1<?php
2
3namespace Sabre\DAV;
4
5/**
6 * URL utility class
7 *
8 * This class provides methods to deal with encoding and decoding url (percent encoded) strings.
9 *
10 * It was not possible to use PHP's built-in methods for this, because some clients don't like
11 * encoding of certain characters.
12 *
13 * Specifically, it was found that GVFS (gnome's webdav client) does not like encoding of ( and
14 * ). Since these are reserved, but don't have a reserved meaning in url, these characters are
15 * kept as-is.
16 *
17 * It was also discovered that versions of the SOGO connector for thunderbird
18 * has issues with urlencoded colons.
19 *
20 * @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/).
21 * @author Evert Pot (http://evertpot.com/)
22 * @license http://sabre.io/license/ Modified BSD License
23 */
24class URLUtil {
25
26    /**
27     * Encodes the path of a url.
28     *
29     * slashes (/) are treated as path-separators.
30     *
31     * @param string $path
32     * @return string
33     */
34    static function encodePath($path) {
35
36        return preg_replace_callback('/([^A-Za-z0-9_\-\.~\(\)\/:@])/',function($match) {
37
38            return '%'.sprintf('%02x',ord($match[0]));
39
40        }, $path);
41
42    }
43
44    /**
45     * Encodes a 1 segment of a path
46     *
47     * Slashes are considered part of the name, and are encoded as %2f
48     *
49     * @param string $pathSegment
50     * @return string
51     */
52    static function encodePathSegment($pathSegment) {
53
54        return preg_replace_callback('/([^A-Za-z0-9_\-\.~\(\):@])/',function($match) {
55
56            return '%'.sprintf('%02x',ord($match[0]));
57
58        }, $pathSegment);
59    }
60
61    /**
62     * Decodes a url-encoded path
63     *
64     * @param string $path
65     * @return string
66     */
67    static function decodePath($path) {
68
69        return self::decodePathSegment($path);
70
71    }
72
73    /**
74     * Decodes a url-encoded path segment
75     *
76     * @param string $path
77     * @return string
78     */
79    static function decodePathSegment($path) {
80
81        $path = rawurldecode($path);
82        $encoding = mb_detect_encoding($path, array('UTF-8','ISO-8859-1'));
83
84        switch($encoding) {
85
86            case 'ISO-8859-1' :
87                $path = utf8_encode($path);
88
89        }
90
91        return $path;
92
93    }
94
95    /**
96     * Returns the 'dirname' and 'basename' for a path.
97     *
98     * The reason there is a custom function for this purpose, is because
99     * basename() is locale aware (behaviour changes if C locale or a UTF-8 locale is used)
100     * and we need a method that just operates on UTF-8 characters.
101     *
102     * In addition basename and dirname are platform aware, and will treat backslash (\) as a
103     * directory separator on windows.
104     *
105     * This method returns the 2 components as an array.
106     *
107     * If there is no dirname, it will return an empty string. Any / appearing at the end of the
108     * string is stripped off.
109     *
110     * @param string $path
111     * @return array
112     */
113    static function splitPath($path) {
114
115        $matches = array();
116        if(preg_match('/^(?:(?:(.*)(?:\/+))?([^\/]+))(?:\/?)$/u',$path,$matches)) {
117            return array($matches[1],$matches[2]);
118        } else {
119            return array(null,null);
120        }
121
122    }
123
124}
125