]> git.mxchange.org Git - friendica.git/blob - src/Core/System.php
Update type hint of System::jsonExit parameter to mixed
[friendica.git] / src / Core / System.php
1 <?php
2 /**
3  * @file src/Core/System.php
4  */
5 namespace Friendica\Core;
6
7 use Friendica\App\BaseURL;
8 use Friendica\BaseObject;
9 use Friendica\Network\HTTPException\InternalServerErrorException;
10 use Friendica\Util\XML;
11
12 /**
13  * @file include/Core/System.php
14  *
15  * @brief Contains the class with system relevant stuff
16  */
17
18
19 /**
20  * @brief System methods
21  */
22 class System extends BaseObject
23 {
24         /**
25          * @brief Retrieves the Friendica instance base URL
26          *
27          * @param bool $ssl Whether to append http or https under BaseURL::SSL_POLICY_SELFSIGN
28          * @return string Friendica server base URL
29          * @throws InternalServerErrorException
30          */
31         public static function baseUrl($ssl = false)
32         {
33                 return self::getClass(BaseURL::class)->get($ssl);
34         }
35
36         /**
37          * @brief Removes the baseurl from an url. This avoids some mixed content problems.
38          *
39          * @param string $orig_url The url to be cleaned
40          *
41          * @return string The cleaned url
42          * @throws \Exception
43          */
44         public static function removedBaseUrl($orig_url)
45         {
46                 return self::getApp()->removeBaseURL($orig_url);
47         }
48
49         /**
50          * @brief Returns a string with a callstack. Can be used for logging.
51          * @param integer $depth optional, default 4
52          * @return string
53          */
54         public static function callstack($depth = 4)
55         {
56                 $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
57
58                 // We remove the first two items from the list since they contain data that we don't need.
59                 array_shift($trace);
60                 array_shift($trace);
61
62                 $callstack = [];
63                 $previous = ['class' => '', 'function' => ''];
64
65                 // The ignore list contains all functions that are only wrapper functions
66                 $ignore = ['fetchUrl', 'call_user_func_array'];
67
68                 while ($func = array_pop($trace)) {
69                         if (!empty($func['class'])) {
70                                 // Don't show multiple calls from the "dba" class to show the essential parts of the callstack
71                                 if ((($previous['class'] != $func['class']) || ($func['class'] != 'Friendica\Database\DBA')) && ($previous['function'] != 'q')) {
72                                         $classparts = explode("\\", $func['class']);
73                                         $callstack[] = array_pop($classparts).'::'.$func['function'];
74                                         $previous = $func;
75                                 }
76                         } elseif (!in_array($func['function'], $ignore)) {
77                                 $callstack[] = $func['function'];
78                                 $func['class'] = '';
79                                 $previous = $func;
80                         }
81                 }
82
83                 $callstack2 = [];
84                 while ((count($callstack2) < $depth) && (count($callstack) > 0)) {
85                         $callstack2[] = array_pop($callstack);
86                 }
87
88                 return implode(', ', $callstack2);
89         }
90
91         /**
92          * Generic XML return
93          * Outputs a basic dfrn XML status structure to STDOUT, with a <status> variable
94          * of $st and an optional text <message> of $message and terminates the current process.
95          *
96          * @param        $st
97          * @param string $message
98          * @throws \Exception
99          */
100         public static function xmlExit($st, $message = '')
101         {
102                 $result = ['status' => $st];
103
104                 if ($message != '') {
105                         $result['message'] = $message;
106                 }
107
108                 if ($st) {
109                         Logger::log('xml_status returning non_zero: ' . $st . " message=" . $message);
110                 }
111
112                 header("Content-type: text/xml");
113
114                 $xmldata = ["result" => $result];
115
116                 echo XML::fromArray($xmldata, $xml);
117
118                 exit();
119         }
120
121         /**
122          * @brief Send HTTP status header and exit.
123          *
124          * @param integer $val     HTTP status result value
125          * @param string  $message Error message. Optional.
126          * @param string  $content Response body. Optional.
127          * @throws \Exception
128          */
129         public static function httpExit($val, $message = '', $content = '')
130         {
131                 Logger::log('http_status_exit ' . $val);
132                 header($_SERVER["SERVER_PROTOCOL"] . ' ' . $val . ' ' . $message);
133
134                 echo $content;
135
136                 exit();
137         }
138
139         public static function jsonError($httpCode, $data, $content_type = 'application/json')
140         {
141                 header($_SERVER["SERVER_PROTOCOL"] . ' ' . $httpCode);
142                 self::jsonExit($data, $content_type);
143         }
144
145         /**
146          * @brief Encodes content to json.
147          *
148          * This function encodes an array to json format
149          * and adds an application/json HTTP header to the output.
150          * After finishing the process is getting killed.
151          *
152          * @param mixed  $x The input content.
153          * @param string $content_type Type of the input (Default: 'application/json').
154          */
155         public static function jsonExit($x, $content_type = 'application/json') {
156                 header("Content-type: $content_type");
157                 echo json_encode($x);
158                 exit();
159         }
160
161         /**
162          * Generates a random string in the UUID format
163          *
164          * @param bool|string $prefix A given prefix (default is empty)
165          * @return string a generated UUID
166          * @throws \Exception
167          */
168         public static function createUUID($prefix = '')
169         {
170                 $guid = System::createGUID(32, $prefix);
171                 return substr($guid, 0, 8) . '-' . substr($guid, 8, 4) . '-' . substr($guid, 12, 4) . '-' . substr($guid, 16, 4) . '-' . substr($guid, 20, 12);
172         }
173
174         /**
175          * Generates a GUID with the given parameters
176          *
177          * @param int         $size   The size of the GUID (default is 16)
178          * @param bool|string $prefix A given prefix (default is empty)
179          * @return string a generated GUID
180          * @throws \Exception
181          */
182         public static function createGUID($size = 16, $prefix = '')
183         {
184                 if (is_bool($prefix) && !$prefix) {
185                         $prefix = '';
186                 } elseif (empty($prefix)) {
187                         $prefix = hash('crc32', self::getApp()->getHostName());
188                 }
189
190                 while (strlen($prefix) < ($size - 13)) {
191                         $prefix .= mt_rand();
192                 }
193
194                 if ($size >= 24) {
195                         $prefix = substr($prefix, 0, $size - 22);
196                         return str_replace('.', '', uniqid($prefix, true));
197                 } else {
198                         $prefix = substr($prefix, 0, max($size - 13, 0));
199                         return uniqid($prefix);
200                 }
201         }
202
203         /**
204          * Returns the current Load of the System
205          *
206          * @return integer
207          */
208         public static function currentLoad()
209         {
210                 if (!function_exists('sys_getloadavg')) {
211                         return false;
212                 }
213
214                 $load_arr = sys_getloadavg();
215
216                 if (!is_array($load_arr)) {
217                         return false;
218                 }
219
220                 return max($load_arr[0], $load_arr[1]);
221         }
222
223         /**
224          * Redirects to an external URL (fully qualified URL)
225          * If you want to route relative to the current Friendica base, use App->internalRedirect()
226          *
227          * @param string $url  The new Location to redirect
228          * @param int    $code The redirection code, which is used (Default is 302)
229          *
230          * @throws InternalServerErrorException If the URL is not fully qualified
231          */
232         public static function externalRedirect($url, $code = 302)
233         {
234                 if (empty(parse_url($url, PHP_URL_SCHEME))) {
235                         throw new InternalServerErrorException("'$url' is not a fully qualified URL, please use App->internalRedirect() instead");
236                 }
237
238                 switch ($code) {
239                         case 302:
240                                 // this is the default code for a REDIRECT
241                                 // We don't need a extra header here
242                                 break;
243                         case 301:
244                                 header('HTTP/1.1 301 Moved Permanently');
245                                 break;
246                         case 307:
247                                 header('HTTP/1.1 307 Temporary Redirect');
248                                 break;
249                 }
250
251                 header("Location: $url");
252                 exit();
253         }
254
255         /**
256          * @brief Returns the system user that is executing the script
257          *
258          * This mostly returns something like "www-data".
259          *
260          * @return string system username
261          */
262         public static function getUser()
263         {
264                 if (!function_exists('posix_getpwuid') || !function_exists('posix_geteuid')) {
265                         return '';
266                 }
267
268                 $processUser = posix_getpwuid(posix_geteuid());
269                 return $processUser['name'];
270         }
271
272         /**
273          * @brief Checks if a given directory is usable for the system
274          *
275          * @param      $directory
276          * @param bool $check_writable
277          *
278          * @return boolean the directory is usable
279          */
280         public static function isDirectoryUsable($directory, $check_writable = true)
281         {
282                 if ($directory == '') {
283                         Logger::log('Directory is empty. This shouldn\'t happen.', Logger::DEBUG);
284                         return false;
285                 }
286
287                 if (!file_exists($directory)) {
288                         Logger::log('Path "' . $directory . '" does not exist for user ' . static::getUser(), Logger::DEBUG);
289                         return false;
290                 }
291
292                 if (is_file($directory)) {
293                         Logger::log('Path "' . $directory . '" is a file for user ' . static::getUser(), Logger::DEBUG);
294                         return false;
295                 }
296
297                 if (!is_dir($directory)) {
298                         Logger::log('Path "' . $directory . '" is not a directory for user ' . static::getUser(), Logger::DEBUG);
299                         return false;
300                 }
301
302                 if ($check_writable && !is_writable($directory)) {
303                         Logger::log('Path "' . $directory . '" is not writable for user ' . static::getUser(), Logger::DEBUG);
304                         return false;
305                 }
306
307                 return true;
308         }
309
310         /// @todo Move the following functions from boot.php
311         /*
312         function killme()
313         function local_user()
314         function public_contact()
315         function remote_user()
316         function notice($s)
317         function info($s)
318         function is_site_admin()
319         function get_server()
320         function get_temppath()
321         function get_cachefile($file, $writemode = true)
322         function get_itemcachepath()
323         function get_spoolpath()
324         */
325 }