]> git.mxchange.org Git - friendica.git/blob - src/Util/Proxy.php
Profile update and some more is now added
[friendica.git] / src / Util / Proxy.php
1 <?php
2
3 namespace Friendica\Util;
4
5 use Friendica\BaseModule;
6 use Friendica\BaseObject;
7 use Friendica\Core\Config;
8 use Friendica\Core\System;
9
10 require_once 'include/security.php';
11
12 /**
13  * @brief Proxy utilities class
14  */
15 class Proxy
16 {
17
18         /**
19          * Default time to keep images in proxy storage
20          */
21         const DEFAULT_TIME = 86400; // 1 Day
22
23         /**
24          * Sizes constants
25          */
26         const SIZE_MICRO  = 'micro';
27         const SIZE_THUMB  = 'thumb';
28         const SIZE_SMALL  = 'small';
29         const SIZE_MEDIUM = 'medium';
30         const SIZE_LARGE  = 'large';
31
32         /**
33          * Accepted extensions
34          *
35          * @var array
36          * @todo Make this configurable?
37          */
38         private static $extensions = [
39                 'jpg',
40                 'jpeg',
41                 'gif',
42                 'png',
43         ];
44
45         /**
46          * @brief Private constructor
47          */
48         private function __construct () {
49                 // No instances from utilities classes
50         }
51
52         /**
53          * @brief Transform a remote URL into a local one.
54          *
55          * This function only performs the URL replacement on http URL and if the
56          * provided URL isn't local, "the isn't deactivated" (sic) and if the config
57          * system.proxy_disabled is set to false.
58          *
59          * @param string $url       The URL to proxyfy
60          * @param bool   $writemode Returns a local path the remote URL should be saved to
61          * @param string $size      One of the ProxyUtils::SIZE_* constants
62          *
63          * @return string The proxyfied URL or relative path
64          */
65         public static function proxifyUrl($url, $writemode = false, $size = '')
66         {
67                 // Get application instance
68                 $a = BaseObject::getApp();
69
70                 // Trim URL first
71                 $url = trim($url);
72
73                 // Is no http in front of it?
74                 /// @TODO To weak test for being a valid URL
75                 if (substr($url, 0, 4) !== 'http') {
76                         return $url;
77                 }
78
79                 // Only continue if it isn't a local image and the isn't deactivated
80                 if (self::isLocalImage($url)) {
81                         $url = str_replace(normalise_link(System::baseUrl()) . '/', System::baseUrl() . '/', $url);
82                         return $url;
83                 }
84
85                 // Is the proxy disabled?
86                 if (Config::get('system', 'proxy_disabled')) {
87                         return $url;
88                 }
89
90                 // Image URL may have encoded ampersands for display which aren't desirable for proxy
91                 $url = html_entity_decode($url, ENT_NOQUOTES, 'utf-8');
92
93                 // Creating a sub directory to reduce the amount of files in the cache directory
94                 $basepath = $a->get_basepath() . '/proxy';
95
96                 $shortpath = hash('md5', $url);
97                 $longpath = substr($shortpath, 0, 2);
98
99                 if (is_dir($basepath) && $writemode && !is_dir($basepath . '/' . $longpath)) {
100                         mkdir($basepath . '/' . $longpath);
101                         chmod($basepath . '/' . $longpath, 0777);
102                 }
103
104                 $longpath .= '/' . strtr(base64_encode($url), '+/', '-_');
105
106                 // Extract the URL extension
107                 $extension = pathinfo(parse_url($url, PHP_URL_PATH), PATHINFO_EXTENSION);
108
109                 if (in_array($extension, self::$extensions)) {
110                         $shortpath .= '.' . $extension;
111                         $longpath .= '.' . $extension;
112                 }
113
114                 $proxypath = System::baseUrl() . '/proxy/' . $longpath;
115
116                 if ($size != '') {
117                         $size = ':' . $size;
118                 }
119
120                 // Too long files aren't supported by Apache
121                 // Writemode in combination with long files shouldn't be possible
122                 if ((strlen($proxypath) > 250) && $writemode) {
123                         return $shortpath;
124                 } elseif (strlen($proxypath) > 250) {
125                         return System::baseUrl() . '/proxy/' . $shortpath . '?url=' . urlencode($url);
126                 } elseif ($writemode) {
127                         return $longpath;
128                 } else {
129                         return $proxypath . $size;
130                 }
131         }
132
133         /**
134          * @brief "Proxifies" HTML code's image tags
135          *
136          * "Proxifies", means replaces image URLs in given HTML code with those from
137          * proxy storage directory.
138          *
139          * @param string $html Un-proxified HTML code
140          *
141          * @return string Proxified HTML code
142          */
143         public static function proxifyHtml($html)
144         {
145                 $html = str_replace(normalise_link(System::baseUrl()) . '/', System::baseUrl() . '/', $html);
146
147                 return preg_replace_callback('/(<img [^>]*src *= *["\'])([^"\']+)(["\'][^>]*>)/siU', 'self::replaceUrl', $html);
148         }
149
150         /**
151          * @brief Checks if the URL is a local URL.
152          *
153          * @param string $url
154          * @return boolean
155          */
156         private static function isLocalImage($url)
157         {
158                 if (substr($url, 0, 1) == '/') {
159                         return true;
160                 }
161
162                 if (strtolower(substr($url, 0, 5)) == 'data:') {
163                         return true;
164                 }
165
166                 // links normalised - bug #431
167                 $baseurl = normalise_link(System::baseUrl());
168                 $url = normalise_link($url);
169
170                 return (substr($url, 0, strlen($baseurl)) == $baseurl);
171         }
172
173         /**
174          * @brief Return the array of query string parameters from a URL
175          *
176          * @param string $url URL to parse
177          * @return array Associative array of query string parameters
178          */
179         private static function parseQuery($url)
180         {
181                 $query = parse_url($url, PHP_URL_QUERY);
182                 $query = html_entity_decode($query);
183
184                 parse_str($query, $arr);
185
186                 return $arr;
187         }
188
189         /**
190          * @brief Call-back method to replace the UR
191          *
192          * @param array $matches Matches from preg_replace_callback()
193          * @return string Proxified HTML image tag
194          */
195         private static function replaceUrl(array $matches)
196         {
197                 // if the picture seems to be from another picture cache then take the original source
198                 $queryvar = self::parseQuery($matches[2]);
199
200                 if (!empty($queryvar['url']) && substr($queryvar['url'], 0, 4) == 'http') {
201                         $matches[2] = urldecode($queryvar['url']);
202                 }
203
204                 // Following line changed per bug #431
205                 if (self::isLocalImage($matches[2])) {
206                         return $matches[1] . $matches[2] . $matches[3];
207                 }
208
209                 // Return proxified HTML
210                 return $matches[1] . self::proxifyUrl(htmlspecialchars_decode($matches[2])) . $matches[3];
211         }
212
213 }