2024.8.23
Loading...
Searching...
No Matches
class.core.php
Go to the documentation of this file.
1<?php
2/*
3 * Copyright (c) 2021-2024 Bearsampp
4 * License: GNU General Public License version 3 or later; see LICENSE.txt
5 * Author: Bear
6 * Website: https://bearsampp.com
7 * Github: https://github.com/Bearsampp
8 */
9
10/**
11 * Class Core
12 *
13 * This class provides core functionalities and constants for the Bearsampp application.
14 * It includes methods for retrieving paths, managing application versions, and handling
15 * various executable files and configurations.
16 */
17class Core
18{
19 // Constants for various file names and versions
20 const isRoot_FILE = 'root.php';
21 const PATH_WIN_PLACEHOLDER = '~BEARSAMPP_WIN_PATH~';
22 const PATH_LIN_PLACEHOLDER = '~BEARSAMPP_LIN_PATH~';
23
24 const PHP_VERSION = '5.4.23';
25 const PHP_EXE = 'php-win.exe';
26 const PHP_CONF = 'php.ini';
27
28 const SETENV_VERSION = '1.09';
29 const SETENV_EXE = 'SetEnv.exe';
30
31 const NSSM_VERSION = '2.24';
32 const NSSM_EXE = 'nssm.exe';
33
34 const OPENSSL_VERSION = '1.1.0c';
35 const OPENSSL_EXE = 'openssl.exe';
36 const OPENSSL_CONF = 'openssl.cfg';
37
38 const HOSTSEDITOR_VERSION = '1.3';
39 const HOSTSEDITOR_EXE = 'hEdit_x64.exe';
40
41 const LN_VERSION = '2.928';
42 const LN_EXE = 'ln.exe';
43
44 const PWGEN_VERSION = '3.5.4';
45 const PWGEN_EXE = "PWGenPortable.exe";
46
47 const APP_VERSION = 'version.dat';
48 const LAST_PATH = 'lastPath.dat';
49 const EXEC = 'exec.dat';
50 const LOADING_PID = 'loading.pid';
51
52 const SCRIPT_EXEC_SILENT = 'execSilent.vbs';
53
54 /**
55 * Core constructor.
56 *
57 * Loads the WinBinder extension if available.
58 */
59 public function __construct()
60 {
61 if ( extension_loaded( 'winbinder' ) ) {
62 require_once $this->getLibsPath() . '/winbinder/winbinder.php';
63 }
64 }
65
66 /**
67 * Retrieves the path to the language files.
68 *
69 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
70 *
71 * @return string The path to the language files.
72 */
73 public function getLangsPath($aetrayPath = false)
74 {
75 global $bearsamppRoot;
76
77 return $bearsamppRoot->getCorePath( $aetrayPath ) . '/langs';
78 }
79
80 /**
81 * Retrieves the path to the libraries.
82 *
83 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
84 *
85 * @return string The path to the libraries.
86 */
87 public function getLibsPath($aetrayPath = false)
88 {
89 global $bearsamppRoot;
90
91 return $bearsamppRoot->getCorePath( $aetrayPath ) . '/libs';
92 }
93
94 /**
95 * Retrieves the path to the resources.
96 *
97 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
98 *
99 * @return string The path to the resources.
100 */
101 public function getResourcesPath($aetrayPath = false)
102 {
103 global $bearsamppRoot;
104
105 return $bearsamppRoot->getCorePath( $aetrayPath ) . '/resources';
106 }
107
108 /**
109 * Retrieves the path to the icons.
110 *
111 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
112 *
113 * @return string The path to the icons.
114 */
115 public function getIconsPath($aetrayPath = false)
116 {
117 global $bearsamppCore;
118
119 return $bearsamppCore->getResourcesPath( $aetrayPath ) . '/img/icons';
120 }
121
122 /**
123 * Retrieves the path to the scripts.
124 *
125 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
126 *
127 * @return string The path to the scripts.
128 */
129 public function getScriptsPath($aetrayPath = false)
130 {
131 global $bearsamppRoot;
132
133 return $bearsamppRoot->getCorePath( $aetrayPath ) . '/scripts';
134 }
135
136 public function getHomepagePath($aetrayPath = false)
137 {
138 return $this->getResourcesPath( $aetrayPath ) . '/homepage';
139 }
140
141 public function getAjaxPath($aetrayPath = false)
142 {
143 return $this->getHomepagePath( $aetrayPath ) . '/ajax';
144 }
145
146 /**
147 * Retrieves the path to a specific script.
148 *
149 * @param string $type The type of script.
150 *
151 * @return string The path to the script.
152 */
153 public function getScript($type)
154 {
155 return $this->getScriptsPath() . '/' . $type;
156 }
157
158 /**
159 * Retrieves the path to the temporary directory.
160 *
161 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
162 *
163 * @return string The path to the temporary directory.
164 */
165 public function getTmpPath($aetrayPath = false)
166 {
167 global $bearsamppRoot;
168
169 return $bearsamppRoot->getCorePath( $aetrayPath ) . '/tmp';
170 }
171
172 /**
173 * Retrieves the path to the root file.
174 *
175 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
176 *
177 * @return string The path to the root file.
178 */
179 public function getisRootFilePath($aetrayPath = false)
180 {
181 global $bearsamppRoot;
182
183 return $bearsamppRoot->getCorePath( $aetrayPath ) . '/' . self::isRoot_FILE;
184 }
185
186 /**
187 * Retrieves the application version.
188 *
189 * @return string|null The application version or null if not found.
190 */
191 public function getAppVersion()
192 {
193 global $bearsamppLang;
194
195 $filePath = $this->getResourcesPath() . '/' . self::APP_VERSION;
196 if ( !is_file( $filePath ) ) {
197 Util::logError( sprintf( $bearsamppLang->getValue( Lang::ERROR_CONF_NOT_FOUND ), APP_TITLE, $filePath ) );
198
199 return null;
200 }
201
202 return trim( file_get_contents( $filePath ) );
203 }
204
205 /**
206 * Retrieves the path to the last path file.
207 *
208 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
209 *
210 * @return string The path to the last path file.
211 */
212 public function getLastPath($aetrayPath = false)
213 {
214 return $this->getResourcesPath( $aetrayPath ) . '/' . self::LAST_PATH;
215 }
216
217 /**
218 * Retrieves the content of the last path file.
219 *
220 * @return string|false The content of the last path file or false on failure.
221 */
222 public function getLastPathContent()
223 {
224 return @file_get_contents( $this->getLastPath() );
225 }
226
227 /**
228 * Retrieves the path to the exec file.
229 *
230 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
231 *
232 * @return string The path to the exec file.
233 */
234 public function getExec($aetrayPath = false)
235 {
236 return $this->getTmpPath( $aetrayPath ) . '/' . self::EXEC;
237 }
238
239 /**
240 * Sets the content of the exec file.
241 *
242 * @param string $action The content to set in the exec file.
243 */
244 public function setExec($action)
245 {
246 file_put_contents( $this->getExec(), $action );
247 }
248
249 /**
250 * Retrieves the path to the loading PID file.
251 *
252 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
253 *
254 * @return string The path to the loading PID file.
255 */
256 public function getLoadingPid($aetrayPath = false)
257 {
258 return $this->getResourcesPath( $aetrayPath ) . '/' . self::LOADING_PID;
259 }
260
261 /**
262 * Adds a PID to the loading PID file.
263 *
264 * @param int $pid The PID to add.
265 */
266 public function addLoadingPid($pid)
267 {
268 file_put_contents( $this->getLoadingPid(), $pid . PHP_EOL, FILE_APPEND );
269 }
270
271 /**
272 * Retrieves the path to the PHP directory.
273 *
274 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
275 *
276 * @return string The path to the PHP directory.
277 */
278 public function getPhpPath($aetrayPath = false)
279 {
280 return $this->getLibsPath( $aetrayPath ) . '/php';
281 }
282
283 /**
284 * Retrieves the path to the PHP executable.
285 *
286 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
287 *
288 * @return string The path to the PHP executable.
289 */
290 public function getPhpExe($aetrayPath = false)
291 {
292 return $this->getPhpPath( $aetrayPath ) . '/' . self::PHP_EXE;
293 }
294
295 /**
296 * Retrieves the path to the SetEnv directory.
297 *
298 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
299 *
300 * @return string The path to the SetEnv directory.
301 */
302 public function getSetEnvPath($aetrayPath = false)
303 {
304 return $this->getLibsPath( $aetrayPath ) . '/setenv';
305 }
306
307 /**
308 * Retrieves the path to the SetEnv executable.
309 *
310 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
311 *
312 * @return string The path to the SetEnv executable.
313 */
314 public function getSetEnvExe($aetrayPath = false)
315 {
316 return $this->getSetEnvPath( $aetrayPath ) . '/' . self::SETENV_EXE;
317 }
318
319 /**
320 * Retrieves the path to the NSSM directory.
321 *
322 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
323 *
324 * @return string The path to the NSSM directory.
325 */
326 public function getNssmPath($aetrayPath = false)
327 {
328 return $this->getLibsPath( $aetrayPath ) . '/nssm';
329 }
330
331 /**
332 * Retrieves the path to the NSSM executable.
333 *
334 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
335 *
336 * @return string The path to the NSSM executable.
337 */
338 public function getNssmExe($aetrayPath = false)
339 {
340 return $this->getNssmPath( $aetrayPath ) . '/' . self::NSSM_EXE;
341 }
342
343 /**
344 * Retrieves the path to the OpenSSL directory.
345 *
346 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
347 *
348 * @return string The path to the OpenSSL directory.
349 */
350 public function getOpenSslPath($aetrayPath = false)
351 {
352 return $this->getLibsPath( $aetrayPath ) . '/openssl';
353 }
354
355 /**
356 * Retrieves the path to the OpenSSL executable.
357 *
358 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
359 *
360 * @return string The path to the OpenSSL executable.
361 */
362 public function getOpenSslExe($aetrayPath = false)
363 {
364 return $this->getOpenSslPath( $aetrayPath ) . '/' . self::OPENSSL_EXE;
365 }
366
367 /**
368 * Retrieves the path to the OpenSSL configuration file.
369 *
370 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
371 *
372 * @return string The path to the OpenSSL configuration file.
373 */
374 public function getOpenSslConf($aetrayPath = false)
375 {
376 return $this->getOpenSslPath( $aetrayPath ) . '/' . self::OPENSSL_CONF;
377 }
378
379 /**
380 * Retrieves the path to the HostsEditor directory.
381 *
382 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
383 *
384 * @return string The path to the HostsEditor directory.
385 */
386 public function getHostsEditorPath($aetrayPath = false)
387 {
388 return $this->getLibsPath( $aetrayPath ) . '/hostseditor';
389 }
390
391 /**
392 * Retrieves the path to the HostsEditor executable.
393 *
394 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
395 *
396 * @return string The path to the HostsEditor executable.
397 */
398 public function getHostsEditorExe($aetrayPath = false)
399 {
400 return $this->getHostsEditorPath( $aetrayPath ) . '/' . self::HOSTSEDITOR_EXE;
401 }
402
403 /**
404 * Retrieves the path to the LN directory.
405 *
406 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
407 *
408 * @return string The path to the LN directory.
409 */
410 public function getLnPath($aetrayPath = false)
411 {
412 return $this->getLibsPath( $aetrayPath ) . '/ln';
413 }
414
415 /**
416 * Retrieves the path to the LN executable.
417 *
418 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
419 *
420 * @return string The path to the LN executable.
421 */
422 public function getLnExe($aetrayPath = false)
423 {
424 return $this->getLnPath( $aetrayPath ) . '/' . self::LN_EXE;
425 }
426
427 /**
428 * Retrieves the path to the PWGen directory.
429 *
430 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
431 *
432 * @return string The path to the PWGen directory.
433 */
434 public function getPwgenPath($aetrayPath = false)
435 {
436 return $this->getLibsPath( $aetrayPath ) . '/pwgen';
437 }
438
439 /**
440 * Retrieves the path to the PWGen executable.
441 *
442 * @param bool $aetrayPath Whether to format the path for AeTrayMenu.
443 *
444 * @return string The path to the PWGen executable.
445 */
446 public function getPwgenExe($aetrayPath = false)
447 {
448 return $this->getPwgenPath( $aetrayPath ) . '/' . self::PWGEN_EXE;
449 }
450
451 /**
452 * Provides a string representation of the core object.
453 *
454 * @return string A string describing the core object.
455 */
456 public function __toString()
457 {
458 return 'core object';
459 }
460
461 /**
462 * Unzips a file to the specified directory and provides progress updates.
463 *
464 * This method uses the 7-Zip command-line tool to extract the contents of a zip file.
465 * It first tests the archive to determine the number of files to be extracted, then
466 * proceeds with the extraction while providing progress updates via a callback function.
467 *
468 * @param string $filePath The path to the zip file.
469 * @param string $destination The directory to extract the files to.
470 * @param callable|null $progressCallback A callback function to report progress. The callback receives two parameters:
471 * - int $currentFile: The current file number being extracted.
472 * - int $totalFiles: The total number of files to be extracted.
473 *
474 * @return array An array containing the result of the extraction:
475 * - 'success' => true and 'numFiles' => int on success.
476 * - 'error' => string and 'numFiles' => int on failure.
477 */
478 public function unzipFile($filePath, $destination, $progressCallback = null)
479 {
480 global $bearsamppRoot;
481
482 $sevenZipPath = $this->getLibsPath() . '/7zip/7za.exe';
483
484 if ( !file_exists( $sevenZipPath ) ) {
485 Util::logError( '7za.exe not found at: ' . $sevenZipPath );
486
487 return false;
488 }
489
490 // Command to test the archive and get the number of files
491 $testCommand = escapeshellarg( $sevenZipPath ) . ' t ' . escapeshellarg( $filePath ) . ' -y -bsp1';
492 $testOutput = shell_exec( $testCommand );
493
494 // Extract the number of files from the test command output
495 preg_match( '/Files: (\d+)/', $testOutput, $matches );
496 $numFiles = isset( $matches[1] ) ? (int) $matches[1] : 0;
497 Util::logDebug( 'Number of files to be extracted: ' . $numFiles );
498
499 // Command to extract the archive
500 $command = escapeshellarg( $sevenZipPath ) . ' x ' . escapeshellarg( $filePath ) . ' -y -bb1 -o' . escapeshellarg( $destination );
501 Util::logTrace( 'Executing command: ' . $command );
502
503 $process = popen( $command, 'rb' );
504
505 if ( $process ) {
506 $filesExtracted = 0;
507 $buffer = '';
508
509 while ( !feof( $process ) ) {
510 $buffer .= fread( $process, 8192 ); // Read in smaller chunks of 4KB
511
512 while ( ($newlinePos = strpos( $buffer, "\n" )) !== false ) {
513 $line = substr( $buffer, 0, $newlinePos + 1 );
514 $buffer = substr( $buffer, $newlinePos + 1 );
515
516 if ( $progressCallback && preg_match( '/^- (.+)$/', $line, $matches ) ) {
517 $fileName = trim( $matches[1] );
518
519 // Check if the extracted item is a file and not a directory
520 if ( substr( $fileName, -1 ) !== '\\' ) {
521 $filesExtracted++;
522 if ( $filesExtracted <= $numFiles ) {
523 call_user_func( $progressCallback, $filesExtracted, $numFiles );
524 }
525 }
526 }
527 }
528 }
529
530 $returnVar = pclose( $process );
531 Util::logDebug( 'Command return value: ' . $returnVar );
532
533 if ( $returnVar === 0 ) {
534 Util::logDebug( 'Successfully unzipped file to: ' . $destination );
535
536 return ['success' => true, 'numFiles' => $numFiles];
537 }
538 else {
539 Util::logError( 'Failed to unzip file. Command return value: ' . $returnVar );
540
541 return ['error' => 'Failed to unzip file', 'numFiles' => $numFiles];
542 }
543 }
544 else {
545 Util::logError( 'Failed to open process for command: ' . $command );
546
547 return ['error' => 'Failed to open process', 'numFiles' => $numFiles];
548 }
549 }
550
551 /**
552 * Fetches a file from a given URL and saves it to a specified file path.
553 *
554 * This method attempts to retrieve the content from the provided URL and save it to the specified file path.
555 * If any error occurs during fetching or saving, it logs the error and returns an error message.
556 * If the operation is successful, it returns the file path.
557 * The method also logs the file size if the input stream is a valid resource.
558 *
559 * @param string $moduleUrl The URL from which to fetch the file content.
560 * @param string $filePath The path where the file content should be saved.
561 * @param bool $progressBar Optional. Whether to display a progress bar during the download process. Default is false.
562 *
563 * @return array Returns the file path if successful, or an array with an error message if an error occurs.
564 */
565 public function getFileFromUrl(string $moduleUrl, string $filePath, $progressBar = false)
566 {
567 // Open the URL for reading
568 $inputStream = @fopen( $moduleUrl, 'rb' );
569 if ( $inputStream === false ) {
570 Util::logError( 'Error fetching content from URL: ' . $moduleUrl );
571
572 return ['error' => 'Error fetching module'];
573 }
574
575 // Open the file for writing
576 $outputStream = @fopen( $filePath, 'wb' );
577 if ( $outputStream === false ) {
578 Util::logError( 'Error opening file for writing: ' . $filePath );
579 fclose( $inputStream );
580
581 return ['error' => 'Error saving module'];
582 }
583
584 // Read and write in chunks to avoid memory overload
585 $bufferSize = 8096; // 8KB
586 $chunksRead = 0;
587
588 while ( !feof( $inputStream ) ) {
589 $buffer = fread( $inputStream, $bufferSize );
590 fwrite( $outputStream, $buffer );
591 $chunksRead++;
592
593 // Send progress update
594 if ( $progressBar ) {
595 $progress = $chunksRead;
596 echo json_encode( ['progress' => $progress] );
597
598 // Check if output buffering is active before calling ob_flush()
599 if ( ob_get_length() !== false ) {
600 ob_flush();
601 }
602 flush();
603 }
604 }
605
606 fclose( $inputStream );
607 fclose( $outputStream );
608
609 return ['success' => true];
610 }
611}
global $bearsamppLang
global $bearsamppRoot
global $bearsamppCore
const SETENV_VERSION
addLoadingPid($pid)
getLnPath($aetrayPath=false)
getAjaxPath($aetrayPath=false)
getNssmPath($aetrayPath=false)
getScriptsPath($aetrayPath=false)
const NSSM_VERSION
const LAST_PATH
const isRoot_FILE
const EXEC
getResourcesPath($aetrayPath=false)
const OPENSSL_VERSION
getSetEnvExe($aetrayPath=false)
getPwgenExe($aetrayPath=false)
getOpenSslPath($aetrayPath=false)
getPhpPath($aetrayPath=false)
const OPENSSL_CONF
getFileFromUrl(string $moduleUrl, string $filePath, $progressBar=false)
const HOSTSEDITOR_VERSION
getHostsEditorExe($aetrayPath=false)
getPwgenPath($aetrayPath=false)
const LN_EXE
const PHP_CONF
const PHP_EXE
setExec($action)
getSetEnvPath($aetrayPath=false)
const LN_VERSION
const NSSM_EXE
getTmpPath($aetrayPath=false)
unzipFile($filePath, $destination, $progressCallback=null)
const HOSTSEDITOR_EXE
getIconsPath($aetrayPath=false)
__toString()
__construct()
const PWGEN_VERSION
const PATH_WIN_PLACEHOLDER
getScript($type)
getHomepagePath($aetrayPath=false)
getNssmExe($aetrayPath=false)
getHostsEditorPath($aetrayPath=false)
const PWGEN_EXE
getAppVersion()
getisRootFilePath($aetrayPath=false)
getLoadingPid($aetrayPath=false)
getLibsPath($aetrayPath=false)
const OPENSSL_EXE
const APP_VERSION
getLnExe($aetrayPath=false)
const SCRIPT_EXEC_SILENT
getOpenSslExe($aetrayPath=false)
const PHP_VERSION
getExec($aetrayPath=false)
getLastPathContent()
getPhpExe($aetrayPath=false)
getLastPath($aetrayPath=false)
getOpenSslConf($aetrayPath=false)
const SETENV_EXE
const PATH_LIN_PLACEHOLDER
getLangsPath($aetrayPath=false)
const LOADING_PID
const ERROR_CONF_NOT_FOUND
static logError($data, $file=null)
static logDebug($data, $file=null)
static logTrace($data, $file=null)
const APP_TITLE
Definition root.php:12