Converts all relative hrefs and image srcs to absolute

@param string $string
@param string $base
@return string
542571
public function relativeToAbsolute($string, $base)
    {
        $matches = preg_split('#(<(a|img)\b[^>]+>)#', $string, -1, PREG_SPLIT_DELIM_CAPTURE);
        $old     = $matches;

        foreach ($matches as &$match) {
            if (preg_match('/<(a|img)\b/', $match) && !preg_match('/(?:http|#|mailto)/', $match)) {
                $match = preg_replace('/^([^"]+")([^"]+)/', '$1' . $base . '$2', $match);
            }
        }

        $string = str_replace($old, $matches, $string);
        return $string;
    }
1077035
public static function extractFilename($string) {
    if (mb_strlen($string) == 0) 
      throw new Exception('Cannot extract filename from empty string');
    
    $file = basename($string);

    if (mb_strlen($file) == 0) 
      throw new Exception('PHP could not extract the basename of the file: '.$file);
    
    return $file;
  }
560321
public function qualify($url, $base)
    {
        if(!parse_url($url, PHP_URL_SCHEME))
        {
            if ($url[0] != '/')
            {
                //Relative path
                $url = dirname($base) . '/' . $url;
            }
            else
            {
                //Absolute path
                $url = parse_url($base, PHP_URL_SCHEME) . ':/' . $url;
            }
        }

        return $this->normalise($url);
    }
329036
def make_absolute(base, relative):
        

        # Python 3.4 and lower do not remove folder traversal strings.
        # This was fixed in 3.5 (https://docs.python.org/3/whatsnew/3.5.html#urllib)
        while relative.startswith('/../') or relative.startswith('../'):
            relative = relative[3:]

            base_parsed = urlparse(base)
            new_path = base_parsed.path.rsplit('/', 1)[0]
            base_parsed = base_parsed._replace(path=new_path)
            base = base_parsed.geturl()

        return urljoin(base, relative)
1158421
private function addBaseurl2ImageSource(&$filtered, $baseurl)
    {
        $textf  = $this->di->get("textfilter");
        $url    = $this->di->get("url");

        // Use callback to url->create() instead of string concat
        $callback = function ($route) use ($url, $baseurl) {
            return $url->asset($route, $baseurl);
        };

        $filtered->text =
            $textf->addBaseurlToImageSource($filtered->text, $baseurl, $callback);
    }
1205126
public function absolute($relativePath = null)
    {
        if ($this->isEmptyPath($relativePath)) {
            return $this->basePath;
        }

        if ($this->startsWithBasePath($relativePath)) {
            return $relativePath;
        }

        if (!$baseUrl = $this->getBaseUrl()) {
            return $this->basePath.'/'.trim($relativePath, '/');
        }

        if ($this->startsWithBaseUrl($relativePath)) {
            return $this->absolute($this->relative($relativePath));
        }

        return $this->basePath.'/'.trim($relativePath, '/');
    }
727904
public function getBase($length, $base = 62)
    {
        $str = '';

        $bytes = $this->getByte($length);
        /** @noinspection ForeachInvariantsInspection */
        for ($i = 0; $i < $length; $i++) {
            $r = ord($bytes[$i]) % $base;

            if ($r < 10) {
                $str .= chr(ord('0') + $r);
            } elseif ($r < 36) {
                $str .= chr(ord('a') + $r - 10);
            } else {
                $str .= chr(ord('A') + $r - 36);
            }
        }

        return $str;
    }
1196623
public static function absolute_url($path, $base_url)
    {
        // check if path is an absolute URL
        if (preg_match('/^[fhtps]+:\/\//', $path)) {
            return $path;
        }

        // check if path is a content-id scheme
        if (strpos($path, 'cid:') === 0) {
            return $path;
        }

        $host_url = $base_url;
        $abs_path = $path;

        // cut base_url to the last directory
        if (strrpos($base_url, '/') > 7) {
            $host_url = substr($base_url, 0, strpos($base_url, '/', 7));
            $base_url = substr($base_url, 0, strrpos($base_url, '/'));
        }

        // $path is absolute
        if ($path[0] == '/') {
            $abs_path = $host_url.$path;
        }
        else {
            // strip './' because its the same as ''
            $path = preg_replace('/^\.\//', '', $path);

            if (preg_match_all('/\.\.\//', $path, $matches, PREG_SET_ORDER)) {
                $cnt = count($matches);
                while ($cnt--) {
                    if ($pos = strrpos($base_url, '/')) {
                        $base_url = substr($base_url, 0, $pos);
                    }
                    $path = substr($path, 3);
                }
            }

            $abs_path = $base_url.'/'.$path;
        }

        return $abs_path;
    }
1007886
def _make_links_absolute(html, base_url):
    
    url_changes = []

    soup = BeautifulSoup(html)
    for tag in soup.find_all('a', href=True):
        old = tag['href']
        fixed = urljoin(base_url, old)
        if old != fixed:
            url_changes.append((old, fixed))
            tag['href'] = fixed

    for tag in soup.find_all('img', src=True):
        old = tag['src']
        fixed = urljoin(base_url, old)
        if old != fixed:
            url_changes.append((old, fixed))
            tag['src'] = fixed

    return mark_safe(six.text_type(soup)), url_changes
504481
public static function getBaseUrl() : string
    {
        $https = (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') ? 'https://' : 'http://';

        return $https . rtrim(rtrim($_SERVER['HTTP_HOST'], '\\/') . dirname($_SERVER['PHP_SELF']), '\\/');
    }
192934
public static function relativepath(String $string) : String
    {
        return str_replace(REAL_BASE_DIR, NULL, self::originpath($string));
    }
375914
public function absolute($baseUrl)
    {
        $url = $this->url;

        $pos = strpos($url, '://');
        if ($pos === false || $pos > 10) {
            $parsed = parse_url($baseUrl) + array(
                    'path' => '',
                );
            if (!isset($parsed['scheme'], $parsed['host']))
                throw new \Exception('Invalid base url "' . $baseUrl . '": scheme not found.');

            if (empty($url))
                return $baseUrl;

            if (strncmp($url, '//', 2) == 0) {
                return $parsed['scheme'] . ':' . $url;
            }

            $fullHost = $parsed['scheme'] . '://' . $parsed['host'];

            if (substr($url, 0, 1) == '?') {
                return $fullHost . $parsed['path'] . $url;
            }

            if (substr($url, 0, 1) == '/') {
                return $fullHost . $url;
            }

            $pathParts = explode('/', $parsed['path']);
            array_pop($pathParts);

            while (substr($url, 0, 3) == '../') {
                array_pop($pathParts);
                $url = substr($url, 3);
            }

            return $fullHost . implode('/', $pathParts) . '/' . $url;
        }

        return $url;
    }
451269
public static String toAbsoluteUrl(String absoluteBasePath, String relativePath) {
		try {
			URL absoluteUrl = new URL(absoluteBasePath);
			return new URL(absoluteUrl, relativePath).toString();
		} catch (Exception e) {
			throw new UtilException(e, "To absolute url [{}] base [{}] error!", relativePath, absoluteBasePath);
		}
	}
1351476
public static function clean($string, $isImage = false)
    {
        // Is the string an array?
        if (is_array($string)) {
            while (list($key) = each($string)) {
                $string[ $key ] = self::clean($string[ $key ]);
            }

            return $string;
        }

        // Remove Invisible Characters
        $string = remove_invisible_characters($string);

        /*
         * URL Decode
         *
         * Just in case stuff like this is submitted:
         *
         * <a href="http://%77%77%77%2E%67%6F%6F%67%6C%65%2E%63%6F%6D">Google</a>
         *
         * Note: Use rawurldecode() so it does not remove plus signs
         */
        do {
            $string = rawurldecode($string);
        } while (preg_match('/%[0-9a-f]{2,}/i', $string));

        /*
         * Convert character entities to ASCII
         *
         * This permits our tests below to work reliably.
         * We only convert entities that are within tags since
         * these are the ones that will pose security problems.
         */
        $string = preg_replace_callback(
            "/[^a-z0-9>]+[a-z0-9]+=([\'\"]).*?\\1/si",
            [self::class, 'convertAttribute'],
            $string
        );

        $string = preg_replace_callback('/<\w+.*/si', [self::class, 'decodeEntity'], $string);

        // Remove Invisible Characters Again!
        $string = remove_invisible_characters($string);

        /*
         * Convert all tabs to spaces
         *
         * This prevents strings like this: ja  vascript
         * NOTE: we deal with spaces between characters later.
         * NOTE: preg_replace was found to be amazingly slow here on
         * large blocks of data, so we use str_replace.
         */
        $string = str_replace("\t", ' ', $string);

        // Capture converted string for later comparison
        $convertedString = $string;

        // Remove Strings that are never allowed
        $string = self::doNeverAllowed($string);

        /*
         * Makes PHP tags safe
         *
         * Note: XML tags are inadvertently replaced too:
         *
         * <?xml
         *
         * But it doesn't seem to pose a problem.
         */
        if ($isImage === true) {
            // Images have a tendency to have the PHP short opening and
            // closing tags every so often so we skip those and only
            // do the long opening tags.
            $string = preg_replace('/<\?(php)/i', '&lt;?\\1', $string);
        } else {
            $string = str_replace(['<?', '?' . '>'], ['&lt;?', '?&gt;'], $string);
        }

        /*
         * Compact any exploded words
         *
         * This corrects words like:  j a v a s c r i p t
         * These words are compacted back to their correct state.
         */
        $words = [
            'javascript',
            'expression',
            'vbscript',
            'jscript',
            'wscript',
            'vbs',
            'script',
            'base64',
            'applet',
            'alert',
            'document',
            'write',
            'cookie',
            'window',
            'confirm',
            'prompt',
            'eval',
        ];

        foreach ($words as $word) {
            $word = implode('\s*', str_split($word)) . '\s*';

            // We only want to do this when it is followed by a non-word character
            // That way valid stuff like "dealer to" does not become "dealerto"
            $string = preg_replace_callback(
                '#(' . substr($word, 0, -3) . ')(\W)#is',
                [self::class, 'compactExplodedWords'],
                $string
            );
        }

        /*
         * Remove disallowed Javascript in links or img tags
         * We used to do some version comparisons and use of stripos(),
         * but it is dog slow compared to these simplified non-capturing
         * preg_match(), especially if the pattern exists in the string
         *
         * Note: It was reported that not only space characters, but all in
         * the following pattern can be parsed as separators between a tag name
         * and its attributes: [\d\s"\'`;,\/\=\(\x00\x0B\x09\x0C]
         * ... however, remove_invisible_characters() above already strips the
         * hex-encoded ones, so we'll skip them below.
         */
        do {
            $original = $string;
            if (preg_match('/<a/i', $string)) {
                $string = preg_replace_callback(
                    '#<a[^a-z0-9>]+([^>]*?)(?:>|$)#si',
                    [self::class, 'jsLinkRemoval'],
                    $string
                );
            }
            if (preg_match('/<img/i', $string)) {
                $string = preg_replace_callback(
                    '#<img[^a-z0-9]+([^>]*?)(?:\s?/?>|$)#si',
                    [self::class, 'jsImgRemoval'],
                    $string
                );
            }
            if (preg_match('/script|xss/i', $string)) {
                $string = preg_replace('#</*(?:script|xss).*?>#si', '[removed]', $string);
            }
        } while ($original !== $string);
        unset($original);

        /*
         * Sanitize naughty HTML elements
         *
         * If a tag containing any of the words in the list
         * below is found, the tag gets converted to entities.
         *
         * So this: <blink>
         * Becomes: &lt;blink&gt;
         */
        $pattern = '#'
            . '<((?<slash>/*\s*)(?<tagName>[a-z0-9]+)(?=[^a-z0-9]|$)'
            // tag start and name, followed by a non-tag character
            . '[^\s\042\047a-z0-9>/=]*'
            // a valid attribute character immediately after the tag would count as a separator
            // optional attributes
            . '(?<attributes>(?:[\s\042\047/=]*'
            // non-attribute characters, excluding > (tag close) for obvious reasons
            . '[^\s\042\047>/=]+'
            // attribute characters
            // optional attribute-value
            . '(?:\s*='
            // attribute-value separator
            . '(?:[^\s\042\047=><`]+|\s*\042[^\042]*\042|\s*\047[^\047]*\047|\s*(?U:[^\s\042\047=><`]*))'
            // single, double or non-quoted value
            . ')?'
            // end optional attribute-value group
            . ')*)'
            // end optional attributes group
            . '[^>]*)(?<closeTag>\>)?#isS';
        // Note: It would be nice to optimize this for speed, BUT
        //       only matching the naughty elements here results in
        //       false positives and in turn - vulnerabilities!
        do {
            $oldString = $string;
            $string = preg_replace_callback($pattern, [self::class, 'sanitizeNaughtyHTML'], $string);
        } while ($oldString !== $string);

        unset($oldString);

        /*
         * Sanitize naughty scripting elements
         *
         * Similar to above, only instead of looking for
         * tags it looks for PHP and JavaScript commands
         * that are disallowed. Rather than removing the
         * code, it simply converts the parenthesis to entities
         * rendering the code un-executable.
         *
         * For example: eval('some code')
         * Becomes: eval&#40;'some code'&#41;
         */
        $string = preg_replace(
            '#(alert|prompt|confirm|cmd|passthru|eval|exec|expression|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(\s*)\((.*?)\)#si',
            '\\1\\2&#40;\\3&#41;',
            $string
        );

        // Final clean up
        // This adds a bit of extra precaution in case
        // something got through the above filters
        $string = self::doNeverAllowed($string);

        /*
         * Images are Handled in a Special Way
         * - Essentially, we want to know that after all of the character
         * conversion is done whether any unwanted, likely XSS, code was found.
         * If not, we return TRUE, as the image is clean.
         * However, if the string post-conversion does not matched the
         * string post-removal of XSS, then it fails, as there was unwanted XSS
         * code found and removed/changed during processing.
         */
        if ($isImage === true) {
            return ($string === $convertedString);
        }

        return $string;
    }
500489
static function basic($string, $filterIn = array("Tidy","Dom","Striptags"), $filterOut = "none") {
        $string = self::tidyUp($string, $filterIn);
        $string = str_replace(array("&amp;", "&lt;", "&gt;"), array("&amp;amp;", "&amp;lt;", "&amp;gt;"), $string);
        
        // fix &entitiy\n;
        $string = preg_replace('#(&\#*\w+)[\x00-\x20]+;#u', "$1;", $string);
        $string = preg_replace('#(&\#x*)([0-9A-F]+);*#iu', "$1$2;", $string);

        $string = html_entity_decode($string, ENT_COMPAT, "UTF-8");
        
        // remove any attribute starting with "on" or xmlns
        $string = preg_replace('#(<[^>]+[\x00-\x20\"\'\/])(on|xmlns)[^>]*>#iUu', "$1>", $string);
        
        // remove javascript: and vbscript: protocol
        $string = preg_replace('#([a-z]*)[\x00-\x20\/]*=[\x00-\x20\/]*([\`\'\"]*)[\x00-\x20\/]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iUu', '$1=$2nojavascript...', $string);
        $string = preg_replace('#([a-z]*)[\x00-\x20\/]*=[\x00-\x20\/]*([\`\'\"]*)[\x00-\x20\/]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iUu', '$1=$2novbscript...', $string);
        $string = preg_replace('#([a-z]*)[\x00-\x20\/]*=[\x00-\x20\/]*([\`\'\"]*)[\x00-\x20\/]*-moz-binding[\x00-\x20]*:#Uu', '$1=$2nomozbinding...', $string);
        $string = preg_replace('#([a-z]*)[\x00-\x20\/]*=[\x00-\x20\/]*([\`\'\"]*)[\x00-\x20\/]*data[\x00-\x20]*:#Uu', '$1=$2nodata...', $string);
        
        //remove any style attributes, IE allows too much stupid things in them, eg.
        //<span style="width: expression(alert('Ping!'));"></span> 
        // and in general you really don't want style declarations in your UGC

        $string = preg_replace('#(<[^>]+[\x00-\x20\"\'\/])style[^>]*>#iUu', "$1>", $string);

        //remove namespaced elements (we do not need them...)
        $string = preg_replace('#</*\w+:\w[^>]*>#i', "", $string);
        
        //remove really unwanted tags
        do {
            $oldstring = $string;
            $string = preg_replace('#</*(applet|meta|xml|blink|link|style|script|embed|object|iframe|frame|frameset|ilayer|layer|bgsound|title|base)[^>]*>#i', "", $string);
        } while ($oldstring != $string);
        
        return self::tidyUp($string, $filterOut);
    }
821300
public function getImageDataUri($string, $size = 64, $color = null, $backgroundColor = null)
    {
        return sprintf('data:%s;base64,%s', $this->generator->getMimeType(), base64_encode($this->getImageData($string, $size, $color, $backgroundColor)));
    }
985357
public function clean($string)
    {
        if (!empty($string)) {
            $string = preg_replace('#<script(.*?)>(.*?)</script>#is', '', $string);
            $string = htmlspecialchars(strip_tags($string, $this->_allowableTags));
            $string = str_replace('href=', 'rel="nofollow" href=', $string);

            return $string;
        }
        return false;
    }