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