PluginProbe
Softaculous / trunk
Softaculous vtrunk
2.4.1 2.4.0 trunk 2.0.7 2.2.1 2.2.2 2.2.4 2.2.7 2.3.9
softaculous / functions.php

functions.php in Softaculous trunk, at functions.php

3,159 lines 85.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('ABSPATH')){
4 exit;
5 }
6
7 /* function softaculous_died(){
8 print_r(error_get_last());
9 }
10 register_shutdown_function('softaculous_died'); */
11
12 include_once('soft_lang.php');
13
14 /*
15 * Fetch the value of option name from options table
16 *
17 * @param string $option_name option_name to retrieve from table.
18 * @param mixed $default_value Default value to return when the option does not exist.
19 * @param int $site_id Site ID to update. Used for multisite installations only.
20 * @param bool $use_cache Whether to use cache or not. Used for multisite installations only.
21 * @returns string The option value based on $option_name
22 * @since 1.0
23 *
24 * @refer get_option()
25 * @link https://developer.wordpress.org/reference/functions/get_option/
26 */
27 function softaculous_get_option($option_name, $default_value = false, $site_id = null){
28
29 if($site_id !== null && is_multisite()){
30 return get_site_option($option_name, $default_value);
31 }
32 return get_option($option_name, $default_value);
33 }
34
35 /*
36 * Generate a random string for the given length
37 *
38 * @param int $length The number of charactes that should be returned
39 * @return string Randomly geterated string of the given number of charaters
40 * @since 1.0
41 */
42 function softaculous_srandstr($length){
43 $randstr = "";
44 for($i = 0; $i < $length; $i++){
45 $randnum = mt_rand(0,61);
46 if($randnum < 10){
47 $randstr .= chr($randnum+48);
48 }elseif($randnum < 36){
49 $randstr .= chr($randnum+55);
50 }else{
51 $randstr .= chr($randnum+61);
52 }
53 }
54 return strtolower($randstr);
55 }
56
57 /*
58 * A function to display preformatted array. Basically adds the <pre> before and after the print_r() output.
59 *
60 * @param array $array
61 * @return string Best for HTML dump of an array.
62 * @since 1.0
63 */
64 function softaculous_print($array){
65 echo '<pre>';
66 print_r($array);
67 echo '</pre>';
68 }
69
70 /**
71 * A function to return all the installed plugins and their description.
72 *
73 * @since 1.0
74 */
75 function softaculous_get_plugins(){
76 return get_plugins();
77 }
78
79 /**
80 * A function to check if the plugin is active or not.
81 *
82 * @param string $pluginBasename slug of the plugin
83 * @since 1.0
84 */
85 function softaculous_is_plugin_active($pluginBasename){
86 return is_plugin_active($pluginBasename);
87 }
88
89 /**
90 * A function to check if the plugin is installed.
91 *
92 * @param string $plslug slug of the plugin
93 * @since 1.0
94 */
95 function softaculous_is_plugin_installed($plslug){
96
97 $all_installed_plugins = softaculous_get_plugins();
98 $slugs = array_keys($all_installed_plugins);
99
100 $is_installed = 0;
101 foreach($all_installed_plugins as $key => $val){
102 if(strpos($key, $plslug) !== false){
103 $is_installed = true;
104 break;
105 }
106 }
107
108 return $is_installed;
109 }
110
111 /**
112 * Activates the plugins on the website
113 *
114 * @param array $plugin_slug array of plugin's slug values
115 * @since 1.0
116 */
117 function softaculous_activate_plugin($plugin_slugs = array()){
118
119 $result = activate_plugins($plugin_slugs);
120
121 if(is_wp_error($result)){
122 return false;
123 }
124
125 return true;
126
127 }
128
129 /**
130 * Fetch the plugin's main file to generate the plugin slug
131 *
132 * @param string $path path of the plugin directory
133 * @param string $slug directory name of the plugin
134 * @since 1.3
135 */
136 function softaculous_get_plugin_path($path, $slug){
137
138 $path = softaculous_cleanpath($path);
139
140 if(softaculous_sfile_exists(ABSPATH.'wp-content/plugins/'.$slug.'/'.$slug.'.php')){
141 return $plugin_path = $slug.'/'.$slug.'.php';
142 }
143
144 $list = softaculous_filelist($path, 0);
145 $plugin_files = array();
146
147 foreach($list as $lk => $lv){
148 if(!is_dir($lk)){
149 $plugin_files[basename($lk)] = $lk;
150 }
151 }
152
153 foreach($plugin_files as $pk => $pv){
154 $data = softaculous_sfile($pv);
155 if(preg_match('/\n(\s*?)(\*?)(\s*?)Plugin(\s*?)Name:(.*?)\n/is',$data)){
156 return $plugin_path = $slug.'/'.$pk;
157 break;
158 }
159 }
160
161 return $plugin_path = $slug.'/'.$slug.'.php';
162 }
163
164 /**
165 * Replaces '\\' with '/' and Truncates / at the end.
166 * e.g. E:\\path is converted to E:/path
167 *
168 * @param string $path
169 * @returns string The new path which works everywhere !
170 * @since 1.3
171 */
172 function softaculous_cleanpath($path){
173
174 $path = str_replace('\\\\', '/', $path);
175 $path = str_replace('\\', '/', $path);
176 return rtrim($path, '/');
177 }
178
179 /* The below function will list all folders and files within a directory
180 *
181 * @param string $startdir specify the directory to start from; format: must end in a "/"
182 * @param bool $searchSubdirs True if you want to search subdirectories
183 * @param bool $directoriesonly True if you want to only return directories
184 * @param $maxlevel "all" or a number; specifies the number of directories down that you want to search
185 * @param integer $level directory level that the function is currently searching
186 * @since 1.3
187 */
188 function softaculous_filelist($startdir="./", $searchSubdirs=1, $directoriesonly=0, $maxlevel="all", $level=1, $reset = 1) {
189 //list the directory/file names that you want to ignore
190 $ignoredDirectory = array();
191 $ignoredDirectory[] = ".";
192 $ignoredDirectory[] = "..";
193 $ignoredDirectory[] = "_vti_cnf";
194 global $softaculous_directorylist; //initialize global array
195
196 if(substr($startdir, -1) != '/'){
197 $startdir = $startdir.'/';
198 }
199
200 if (is_dir($startdir)) {
201 if ($dh = opendir($startdir)) {
202 while (($file = readdir($dh)) !== false) {
203 if (!(array_search($file,$ignoredDirectory) > -1)) {
204 if (@filetype($startdir . $file) == "dir") {
205
206 //build your directory array however you choose;
207 //add other file details that you want.
208
209 $softaculous_directorylist[$startdir . $file]['level'] = $level;
210 $softaculous_directorylist[$startdir . $file]['dir'] = 1;
211 $softaculous_directorylist[$startdir . $file]['name'] = $file;
212 $softaculous_directorylist[$startdir . $file]['path'] = $startdir;
213 if ($searchSubdirs) {
214 if ((($maxlevel) == "all") or ($maxlevel > $level)) {
215 softaculous_filelist($startdir . $file . "/", $searchSubdirs, $directoriesonly, $maxlevel, ($level + 1), 0);
216 }
217 }
218
219
220 } else {
221 if (!$directoriesonly) {
222
223 // echo substr(strrchr($file, "."), 1);
224 //if you want to include files; build your file array
225 //however you choose; add other file details that you want.
226 $softaculous_directorylist[$startdir . $file]['level'] = $level;
227 $softaculous_directorylist[$startdir . $file]['dir'] = 0;
228 $softaculous_directorylist[$startdir . $file]['name'] = $file;
229 $softaculous_directorylist[$startdir . $file]['path'] = $startdir;
230 }
231 }
232 }
233 }
234 closedir($dh);
235 }
236 }
237
238 if(!empty($reset)){
239 $r = $softaculous_directorylist;
240 $softaculous_directorylist = array();
241 return($r);
242 }
243 }
244
245 /**
246 * De-activates the plugins on the website
247 *
248 * @param array $plugin_slug array of plugin's slug values
249 * @since 1.0
250 */
251 function softaculous_deactivate_plugin($plugin_slugs = array()){
252
253 $result = deactivate_plugins($plugin_slugs);
254
255 if(is_wp_error($result)){
256 return false;
257 }
258
259 return true;
260 }
261
262 /**
263 * Fetch the list of outdated plugins on the website
264 *
265 * @since 1.0
266 */
267 function softaculous_get_outdated_plugins(){
268 global $softaculous_wp_config, $softaculous_error;
269
270 // Get the list of active plugins
271 $squery = 'SELECT `option_value` FROM `'.$softaculous_wp_config['dbprefix'].'options` WHERE `option_name` = "active_plugins";';
272 $sresult = softaculous_sdb_query($squery, $softaculous_wp_config['softdbhost'], $softaculous_wp_config['softdbuser'], $softaculous_wp_config['softdbpass'], $softaculous_wp_config['softdb']);
273
274 $active = array();
275 $active = unserialize($sresult[0]['option_value']);
276
277 foreach($active as $plugin_file){
278 $plugin_data = array();
279 if (!softaculous_sfile_exists($softaculous_wp_config['plugins_root_dir'].'/'.$plugin_file)){
280 continue;
281 }
282
283 $plugin_data = softaculous_get_plugin_data($softaculous_wp_config['plugins_root_dir'].'/'.$plugin_file);
284
285 if(empty($plugin_data['Plugin Name'])){
286 continue;
287 }else{
288 $plugin_data['Name'] = $plugin_data['Plugin Name'];
289 }
290
291 $plugins[$plugin_file] = $plugin_data;
292 }
293
294 uasort($plugins, 'softaculous_sort_uname_callback');
295
296 $to_send = (object) compact('plugins', 'active');
297 $options = array('plugins' => serialize($to_send));
298
299 // Check the WordPress API to get the list of outdated plugins
300 $raw_response = wp_remote_post('http://api.wordpress.org/plugins/update-check/1.0/', array('body' => $options));
301 $body = wp_remote_retrieve_body($raw_response);
302 $outdated_plugins = unserialize($body);
303
304 // We need the Plugin name to send via email
305 foreach($outdated_plugins as $plugin_file => $p_data){
306 if(!empty($plugins[$plugin_file]['Name'])){
307 $outdated_plugins[$plugin_file]->Name = $plugins[$plugin_file]['Name'];
308 }
309 }
310
311 return $outdated_plugins;
312 }
313
314 /**
315 * This is to extract the plugin details from the plugin file
316 *
317 * @param string $pluginPath directory path of the installed plugin
318 * @since 1.0
319 */
320 function softaculous_get_plugin_data($pluginPath = ''){
321 global $softaculous_plugin_details;
322
323 $softaculous_plugin_details = array();
324
325 if(empty($pluginPath)){
326 return false;
327 }
328
329 $tmp_data = array();
330 $data = array();
331 $data = softaculous_sfile($pluginPath);
332 preg_replace_callback('/\n(\s*?)(\*?)(\s*?)Plugin(\s*?)Name:(.*?)\n/is', 'softaculous_plugin_callback', $data, 1);
333 preg_replace_callback('/\n(\s*?)(\*?)(\s*?)Plugin(\s*?)URI:(.*?)\n/is', 'softaculous_plugin_callback', $data, 1);
334 preg_replace_callback('/\n(\s*?)(\*?)(\s*?)Description:(.*?)\n/is', 'softaculous_plugin_callback', $data, 1);
335 preg_replace_callback('/\n(\s*?)(\*?)(\s*?)Version:(.*?)\n/is', 'softaculous_plugin_callback', $data, 1);
336
337 return $softaculous_plugin_details;
338 }
339
340 // This is a callback function for preg_replace in softaculous_get_plugin_data
341 function softaculous_plugin_callback($matches){
342 global $softaculous_plugin_details;
343 $tmp_data = explode(':', $matches[0], 2);
344 $tmp_data[0] = str_replace('*', '', $tmp_data[0]);
345 $key = trim($tmp_data[0]);
346 $value = trim($tmp_data[1]);
347 $softaculous_plugin_details[$key] = $value;
348 }
349
350 /**
351 * A function to check if the theme is installed.
352 *
353 * @param string $thslug slug of the theme
354 * @since 1.0
355 */
356 function softaculous_is_theme_installed($thslug){
357
358 $all_installed_themes = wp_get_themes();
359 $slugs = array_keys($all_installed_themes);
360
361 if(isset($all_installed_themes[$thslug])){
362 return true;
363 }
364
365 return false;
366 }
367
368 /**
369 * Returns active theme for the website.
370 *
371 * @since 1.0
372 */
373 function softaculous_get_active_theme(){
374 $raw_list = wp_get_theme();
375 return softaculous_get_themes_details(array($raw_list->stylesheet));
376 }
377
378 /**
379 * A function to return all the installed themes and their description.
380 *
381 * @since 1.0
382 */
383 function softaculous_get_installed_themes(){
384 $raw_list = wp_get_themes();
385 $theme_slugs = array_keys($raw_list);
386
387 return softaculous_get_themes_details($theme_slugs);
388 }
389
390 /**
391 * Returns details of the themes from wordPress.org.
392 *
393 * @param array $themes array of themes
394 * @since 1.0
395 */
396 function softaculous_get_themes_details($themes = array()){
397 global $softaculous_wp_config, $softaculous_error;
398
399 $apiurl ='http://api.wordpress.org/themes/info/1.0/';
400 $softaculous_theme_details = array();
401 foreach($themes as $current_theme){
402 $theme_data = softaculous_get_theme_data($softaculous_wp_config['themes_root_dir'].'/'.$current_theme.'/style.css');
403
404 $post_data = array(
405 'action' => 'theme_information',
406 'request' => serialize( (object) array( 'slug' => $current_theme )));
407
408 $raw_response = wp_remote_post($apiurl, array('body' => $post_data));
409 $body = wp_remote_retrieve_body($raw_response);
410 $api_data = unserialize($body);
411
412 $softaculous_theme_details[$current_theme] = $api_data;
413 $softaculous_theme_details[$current_theme]->installed_version = $theme_data['Version'];
414
415 if(softaculous_sversion_compare($theme_data['Version'], $api_data->version, '<')){
416 $softaculous_theme_details[$current_theme]->new_version = $api_data->version;
417 }
418 }
419 return $softaculous_theme_details;
420 }
421
422 /**
423 * This is to extract the theme details from the theme file
424 *
425 * @param string $themePath directory path of the installed theme
426 * @since 1.0
427 */
428 function softaculous_get_theme_data($themePath = ''){
429
430 global $softaculous_theme_details;
431
432 $softaculous_theme_details = array();
433
434 if(empty($themePath)){
435 return false;
436 }
437
438 $tmp_data = array();
439 $data = array();
440 $data = softaculous_sfile($themePath);
441 preg_replace_callback('/\n(\s*?)(\*?)(\s*?)Theme(\s*?)Name:(.*?)\n/is', 'softaculous_theme_callback', $data, 1);
442 preg_replace_callback('/\n(\s*?)(\*?)(\s*?)Theme(\s*?)URI:(.*?)\n/is', 'softaculous_theme_callback', $data, 1);
443 preg_replace_callback('/\n(\s*?)(\*?)(\s*?)Description:(.*?)\n/is', 'softaculous_theme_callback', $data, 1);
444 preg_replace_callback('/\n(\s*?)(\*?)(\s*?)Version:(.*?)\n/is', 'softaculous_theme_callback', $data, 1);
445 preg_replace_callback('/\n(\s*?)(\*?)(\s*?)Author:(.*?)\n/is', 'softaculous_theme_callback', $data, 1);
446 preg_replace_callback('/\n(\s*?)(\*?)(\s*?)Author(\s*?)URI:(.*?)\n/is', 'softaculous_theme_callback', $data, 1);
447
448 return $softaculous_theme_details;
449 }
450
451 // This is a callback function for preg_replace used in softaculous_get_theme_data
452 function softaculous_theme_callback($matches){
453 global $softaculous_theme_details;
454 $tmp_data = explode(':', $matches[0], 2);
455 $tmp_data[0] = str_replace('*', '', $tmp_data[0]);
456 $key = trim($tmp_data[0]);
457 $value = trim($tmp_data[1]);
458 $softaculous_theme_details[$key] = $value;
459 }
460
461 /**
462 * Activates the theme on the website
463 *
464 * @param string $theme_slug slug of the theme
465 * @since 1.0
466 */
467 function softaculous_activate_theme($theme_slug = array()){
468 global $softaculous_error, $softaculous_lang;
469
470 $theme_root = $softaculous_wp_config['themes_root_dir'].'/'.$theme_slug[0];
471
472 $res = switch_theme($theme_root, $theme_slug[0]);
473
474 if(is_wp_error($res)) {
475 $softaculous_error = $res->get_error_message();
476 }elseif($res === false) {
477 $softaculous_error = $softaculous_lang['action_failed'];
478 }
479
480 if(!empty($softaculous_error)){
481 return false;
482 }
483
484 return true;
485 }
486
487 /**
488 * Function to delete a theme
489 *
490 * @param string $theme_slug slug of the theme
491 * @since 1.0
492 */
493 function softaculous_delete_theme($theme_slug = array()){
494 global $softaculous_error, $softaculous_lang;
495
496 foreach($theme_slug as $slug){
497 $res = delete_theme($slug);
498 }
499
500 if(is_wp_error($res)) {
501 $softaculous_error = $res->get_error_message();
502
503 }elseif($res === false) {
504 $softaculous_error = $softaculous_lang['action_failed'];
505 }
506
507 if(!empty($softaculous_error)){
508 return false;
509 }
510
511 return true;
512 }
513
514 /**
515 * Takes care of Slashes
516 *
517 * @param string $string The string that will be processed
518 * @return string A string that is safe to use for Database Queries, etc
519 * @since 1.0
520 */
521 function softaculous_inputsec($string){
522
523 //get_magic_quotes_gpc is depricated in php 7.4
524 if(softaculous_sversion_compare(PHP_VERSION, '7.4', '<')){
525 if(!get_magic_quotes_gpc()){
526
527 $string = addslashes($string);
528
529 }else{
530
531 $string = stripslashes($string);
532 $string = addslashes($string);
533
534 }
535 }else{
536 $string = addslashes($string);
537 }
538
539 // This is to replace ` which can cause the command to be executed in exec()
540 $string = str_replace('`', '\`', $string);
541
542 return $string;
543
544 }
545
546 /**
547 * Converts Special characters to html entities
548 *
549 * @param string $string The string containing special characters
550 * @return string A string containing special characters replaced by html entities of the format &#ASCIICODE;
551 * @since 1.0
552 */
553 function softaculous_htmlizer($string){
554
555 $string = htmlentities($string, ENT_QUOTES, 'UTF-8');
556
557 preg_match_all('/(&amp;#(\d{1,7}|x[0-9a-fA-F]{1,6});)/', $string, $matches);
558
559 foreach($matches[1] as $mk => $mv){
560 $tmp_m = softaculous_entity_check($matches[2][$mk]);
561 $string = str_replace($matches[1][$mk], $tmp_m, $string);
562 }
563
564 return $string;
565
566 }
567
568 /**
569 * Used in function htmlizer()
570 *
571 * @param string $string
572 * @return string
573 * @since 1.0
574 */
575 function softaculous_entity_check($string){
576
577 //Convert Hexadecimal to Decimal
578 $num = ((substr($string, 0, 1) === 'x') ? hexdec(substr($string, 1)) : (int) $string);
579
580 //Squares and Spaces - return nothing
581 $string = (($num > 0x10FFFF || ($num >= 0xD800 && $num <= 0xDFFF) || $num < 0x20) ? '' : '&#'.$num.';');
582
583 return $string;
584
585 }
586
587 /**
588 * OPTIONAL REQUEST of the given REQUEST Key
589 *
590 * @param string $name The key of the $_REQUEST array i.e. the name of the input / textarea text
591 * @param string $default The value to return if the $_REQUEST[$name] is NOT SET
592 * @return string Returns the string if the REQUEST is there otherwise the default value given.
593 * @since 1.0
594 */
595 function softaculous_optREQ($name, $default = ''){
596
597 global $softaculous_error;
598
599 //Check the POSTED NAME was posted
600 if(isset($_REQUEST[$name])){
601
602 return trim(sanitize_text_field($_REQUEST[$name]));
603
604 }else{
605 return $default;
606 }
607 }
608
609 /**
610 * OPTIONAL POST of the given POST Key
611 *
612 * @param string $name The key of the $_POST array i.e. the name of the input / textarea text
613 * @param string $default The value to return if the $_POST[$name] is NOT SET
614 * @return string Returns the string if the POST is there otherwise the default value given.
615 * @since 1.4.6
616 */
617 function softaculous_optPOST($name, $default = ''){
618
619 global $softaculous_error;
620
621 //Check the POSTED NAME was posted
622 if(isset($_POST[$name])){
623
624 return trim(sanitize_text_field($_POST[$name]));
625
626 }else{
627 return $default;
628 }
629
630 }
631
632 /**
633 * OPTIONAL GET of the given GET Key i.e. dont throw a error if not there
634 *
635 * @param string $name The key of the $_GET array i.e. the name of the input / textarea text
636 * @param string $default The value to return if the $_GET[$name] is NOT SET
637 * @return string Returns the string if the GET is there otherwise the default value given.
638 * @since 1.0
639 */
640 function softaculous_optGET($name, $default = ''){
641
642 global $softaculous_error;
643
644 //Check the GETED NAME was GETed
645 if(isset($_GET[$name])){
646
647 return trim(sanitize_text_field($_GET[$name]));
648
649 }else{
650 return $default;
651 }
652
653 }
654
655 /**
656 * A function to load a file from the net
657 *
658 * @param string $url The URL to read
659 * @param string $writefilename Instead of returning the data save it to the path given
660 * @return string The data fetched
661 * @since 1.0
662 */
663 function softaculous_get_web_file($url, $writefilename = ''){
664
665 $response = wp_remote_get($url);
666 $file = wp_remote_retrieve_body($response);
667
668 //Are we to store the file
669 if(empty($writefilename)){
670 return $file;
671
672 //Store the file
673 }else{
674 $fp = @fopen($writefilename, "wb"); //This opens the file
675
676 //If its opened then proceed
677 if($fp){
678 if(@fwrite($fp, $file) === FALSE){
679 return false;
680 //Wrote the file
681 }else{
682 @fclose($fp);
683 return true;
684 }
685 }
686 }
687 return false;
688 }
689
690 /**
691 * A Function to unzip a ZIP file
692 *
693 * @param string $file The ZIP File
694 * @param string $destination The Final destination where the file will be unzipped
695 * @param int $overwrite Whether to Overwrite existing files
696 * @param array $include include files of the given pattern
697 * @param array $exclude exclude files of the given pattern
698 * @return boolean
699 * @since 1.0
700 */
701 function softaculous_unzip($file, $destination, $overwrite = 0, $include = array(), $exclude = array()){
702
703 include_once('soft_pclzip.php');
704 $archive = new softaculous_pclzip($file);
705
706 $result = $archive->_extract(PCLZIP_OPT_PATH, $destination,
707 PCLZIP_CB_PRE_EXTRACT, 'softaculous_inc_exc',
708 PCLZIP_OPT_REPLACE_NEWER);
709
710 if($result == 0){
711 return false;
712 }
713 return true;
714 }
715
716 /**
717 * Process includes and excludes of function unzip
718 *
719 * @param $p_event
720 * @param $v
721 * @return Returns boolean
722 * @since 1.0
723 */
724 function softaculous_inc_exc($p_event, &$v){
725 return 1;
726 }
727
728 /**
729 * Checks if a file is symlink or hardlink
730 *
731 * @returns bool false if file is a symlink or a hardlink else true
732 * @since 1.0
733 */
734 function softaculous_is_safe_file($path){
735
736 // Is it a symlink ?
737 if(is_link($path)) return false;
738
739 // Is it a file and is a link ?
740 $stat = @stat($path);
741 if(!is_dir($path) && $stat['nlink'] > 1) return false;
742
743 return true;
744 }
745
746 /**
747 * Read file contents from the DESTINATION. Should be used when an installations file is to be fetched.
748 * For local package file, use the PHP file() function. The main usage of sfile is for import or upgrade !
749 *
750 * @package files
751 * @param string $path The path of the file
752 * @returns bool
753 * @since 1.0
754 */
755 function softaculous_sfile($path){
756
757 // Is it safe to read this file ?
758 if(!softaculous_is_safe_file($path)){
759 return false;
760 }
761
762 return @file_get_contents($path);
763 }
764
765 /**
766 * Fetch website's configuration details from the config file
767 *
768 * @since 1.0
769 */
770 function softaculous_fetch_wp_config(){
771
772 global $wpdb;
773
774 $r = array();
775
776 $r['softdbhost'] = $wpdb->dbhost;
777 $r['softdbuser'] = $wpdb->dbuser;
778 $r['softdbpass'] = $wpdb->dbpassword;
779 $r['softdb'] = $wpdb->dbname;
780 $r['dbprefix'] = $wpdb->prefix;
781
782 $r['ver'] = softaculous_version_wp();
783
784 //No trailing slash
785 $updir = wp_upload_dir();
786 $r['uploads_dir'] = realpath($updir['basedir']);
787 $r['themes_root_dir'] = realpath(get_theme_root());
788 $r['plugins_root_dir'] = realpath(plugin_dir_path( __DIR__ ));
789
790 return $r;
791 }
792
793 /**
794 * Fetch website's currently installed version
795 *
796 * @since 1.0
797 */
798 function softaculous_version_wp(){
799
800 $file = softaculous_sfile(get_home_path().'wp-includes/version.php');
801
802 if(!empty($file)){
803 softaculous_preg_replace('/\$wp_version(\s*?)=(\s*?)("|\')(.*?)("|\');/is', $file, $ver, 4);
804 }
805
806 return $ver;
807 }
808
809 /**
810 * This function will preg_match the pattern and return the respective values in $var
811 *
812 * @param $pattern This should be the pattern to be matched
813 * @param $file This should have the data to search from
814 * @param $var This will be the variable which will have the preg matched data
815 * @param $valuenum This should be the no of regular expression to be returned in $var
816 * @param $stripslashes 0 or 1 depending upon whether the stripslashes function is to be applied (1) or not (0)
817 * @return string Will pass value by reference in $var
818 * @since 1.0
819 */
820 function softaculous_preg_replace($pattern, $file, &$var, $valuenum){
821 preg_match($pattern, $file, $matches);
822 $var = trim($matches[$valuenum]);
823 }
824
825 /**
826 * Unserialize a string and also fixes any broken serialized string before unserializing
827 *
828 * @param string $str
829 * @return array Returns an array if successful otherwise false
830 * @since 1.0
831 */
832 function softaculous_unserialize($str){
833
834 $var = @unserialize($str);
835
836 if(empty($var)){
837
838 preg_match_all('!s:(\d+):"(.*?)";!s', $str, $matches);
839 foreach($matches[2] as $mk => $mv){
840 $tmp_str = 's:'.strlen($mv).':"'.$mv.'";';
841 $str = str_replace($matches[0][$mk], $tmp_str, $str);
842 }
843 $var = @unserialize($str);
844 }
845
846 //If it is still empty false
847 if($var === false){
848 return false;
849 }else{
850 return $var;
851 }
852
853 }
854
855 ////////////////////////////////////////////
856 // Custom MySQL functions for Softaculous
857 ///////////////////////////////////////////
858
859 /**
860 * Connect to mysqli if exists else mysql
861 *
862 * @param string $host database host to be connected
863 * @param string $user db username to be used to connect
864 * @param string $pass db password to be used to connect
865 * @param string $newlink create a new link (mysql only)
866 * @returns string $conn returns resource link on success or FALSE on failure
867 * @since 1.0
868 */
869 function softaculous_mysql_connect($host, $user, $pass, $newlink = false){
870
871 if(extension_loaded('mysqli')){
872 //echo 'mysqli';
873 //To handle connection if user passes a custom port along with the host as 127.0.0.1:6446.
874 //For testing, use port 127.0.0.1 instead of localhost as 127.0.0.1:6446 http://php.net/manual/en/mysqli.construct.php#112328
875 $exh = explode(':', $host);
876 if(!empty($exh[1])){
877 $sconn = @mysqli_connect($exh[0], $user, $pass, '', $exh[1]);
878 }else{
879 $sconn = @mysqli_connect($host, $user, $pass);
880 }
881 }else{
882 //echo 'mysql';
883 $sconn = @mysql_connect($host, $user, $pass, $newlink);
884 }
885
886 return $sconn;
887 }
888
889 /**
890 * Set the database character set
891 *
892 * @param string $conn database connection string
893 * @param string $charset character set to convert to
894 * @returns bool true if character set is set
895 * @since 1.0
896 */
897 function softaculous_mysql_set_charset($conn, $charset){
898
899 if(extension_loaded('mysqli')){
900 //echo 'mysqli';
901 $return = @mysqli_set_charset($conn, $charset);
902 }else{
903 //echo 'mysql';
904 $return = @mysql_set_charset($charset, $conn);
905 }
906
907 return $return;
908 }
909
910 /**
911 * Selects database mysqli if exists else mysql
912 *
913 * @param string $db database to be selected
914 * @param string $conn Resource Link
915 * @returns bool TRUE on success or FALSE on failure
916 * @since 1.0
917 */
918 function softaculous_mysql_select_db($db, $conn){
919
920 if(extension_loaded('mysqli')){
921 $return = @mysqli_select_db($conn, $db);
922 }else{
923 $return = @mysql_select_db($db, $conn);
924 }
925
926 return $return;
927 }
928
929 /**
930 * Executes the query mysqli if exists else mysql
931 *
932 * @param string $db database to be selected
933 * @param string $conn Resource Link
934 * @returns bool TRUE on success or FALSE on failure
935 * @since 1.0
936 */
937 function softaculous_mysql_query($query, $conn){
938
939 if(extension_loaded('mysqli')){
940 $return = @mysqli_query($conn, $query);
941 }else{
942 $return = @mysql_query($query, $conn);
943 }
944
945 return $return;
946 }
947
948 /**
949 * Fetches the result from a result link mysqli if exists else mysql
950 *
951 * @param string $result result to fetch the data from
952 * @returns mixed Returns an array of strings that corresponds to the fetched row, or FALSE if there are no more rows
953 * @since 1.0
954 */
955 function softaculous_mysql_fetch_array($result){
956
957 if(extension_loaded('mysqli')){
958 $return = @mysqli_fetch_array($result);
959 }else{
960 $return = @mysql_fetch_array($result);
961 }
962
963 return $return;
964 }
965
966 /**
967 * Fetches the result into associative array from a result link mysqli if exists else mysql
968 *
969 * @param string $result result to fetch the data from
970 * @returns mixed Returns an associative array of strings that corresponds to the fetched row, or FALSE if there are no more rows
971 * @since 1.0
972 */
973 function softaculous_mysql_fetch_assoc($result){
974
975 if(extension_loaded('mysqli')){
976 $return = @mysqli_fetch_assoc($result);
977 }else{
978 $return = @mysql_fetch_assoc($result);
979 }
980
981 return $return;
982 }
983
984 /**
985 * Get a result row as an enumerated array mysqli if exists else mysql
986 *
987 * @param string $result result to fetch the data from
988 * @returns mixed returns an array of strings that corresponds to the fetched row or FALSE if there are no more rows
989 * @since 1.0
990 */
991 function softaculous_mysql_fetch_row($result){
992
993 if(extension_loaded('mysqli')){
994 $return = @mysqli_fetch_row($result);
995 }else{
996 $return = @mysql_fetch_row($result);
997 }
998
999 return $return;
1000 }
1001
1002 /**
1003 * Get column information from a result and return as an object
1004 *
1005 * @param string $result result to fetch the data from
1006 * @param string $field The numerical field offset
1007 * @returns object Returns the definition of one column of a result set as an object.
1008 * @since 1.0
1009 */
1010 function softaculous_mysql_fetch_field($result, $field){
1011
1012 if(extension_loaded('mysqli')){
1013 $return = @mysqli_fetch_field_direct($result, $field);
1014 }else{
1015 $return = @mysql_fetch_field($result, $field);
1016 }
1017
1018 return $return;
1019 }
1020
1021 /**
1022 * Gets the fields meta
1023 *
1024 * @param string $result result to fetch the data from
1025 * @returns object returns object of fields meta
1026 * @since 1.0
1027 */
1028 function softaculous_getFieldsMeta($result){
1029 // Build an associative array for a type look up
1030
1031 if(!defined('SOFTACULOUS_MYSQLI_TYPE_VARCHAR')){
1032 define('SOFTACULOUS_MYSQLI_TYPE_VARCHAR', 15);
1033 }
1034
1035 $typeAr = array();
1036 $typeAr[MYSQLI_TYPE_DECIMAL] = 'real';
1037 $typeAr[MYSQLI_TYPE_NEWDECIMAL] = 'real';
1038 $typeAr[MYSQLI_TYPE_BIT] = 'int';
1039 $typeAr[MYSQLI_TYPE_TINY] = 'int';
1040 $typeAr[MYSQLI_TYPE_SHORT] = 'int';
1041 $typeAr[MYSQLI_TYPE_LONG] = 'int';
1042 $typeAr[MYSQLI_TYPE_FLOAT] = 'real';
1043 $typeAr[MYSQLI_TYPE_DOUBLE] = 'real';
1044 $typeAr[MYSQLI_TYPE_NULL] = 'null';
1045 $typeAr[MYSQLI_TYPE_TIMESTAMP] = 'timestamp';
1046 $typeAr[MYSQLI_TYPE_LONGLONG] = 'int';
1047 $typeAr[MYSQLI_TYPE_INT24] = 'int';
1048 $typeAr[MYSQLI_TYPE_DATE] = 'date';
1049 $typeAr[MYSQLI_TYPE_TIME] = 'time';
1050 $typeAr[MYSQLI_TYPE_DATETIME] = 'datetime';
1051 $typeAr[MYSQLI_TYPE_YEAR] = 'year';
1052 $typeAr[MYSQLI_TYPE_NEWDATE] = 'date';
1053 $typeAr[MYSQLI_TYPE_ENUM] = 'unknown';
1054 $typeAr[MYSQLI_TYPE_SET] = 'unknown';
1055 $typeAr[MYSQLI_TYPE_TINY_BLOB] = 'blob';
1056 $typeAr[MYSQLI_TYPE_MEDIUM_BLOB] = 'blob';
1057 $typeAr[MYSQLI_TYPE_LONG_BLOB] = 'blob';
1058 $typeAr[MYSQLI_TYPE_BLOB] = 'blob';
1059 $typeAr[MYSQLI_TYPE_VAR_STRING] = 'string';
1060 $typeAr[MYSQLI_TYPE_STRING] = 'string';
1061 $typeAr[SOFTACULOUS_MYSQLI_TYPE_VARCHAR] = 'string'; // for Drizzle
1062 // MySQL returns MYSQLI_TYPE_STRING for CHAR
1063 // and MYSQLI_TYPE_CHAR === MYSQLI_TYPE_TINY
1064 // so this would override TINYINT and mark all TINYINT as string
1065 // https://sourceforge.net/p/phpmyadmin/bugs/2205/
1066 //$typeAr[MYSQLI_TYPE_CHAR] = 'string';
1067 $typeAr[MYSQLI_TYPE_GEOMETRY] = 'geometry';
1068 $typeAr[MYSQLI_TYPE_BIT] = 'bit';
1069
1070 $fields = mysqli_fetch_fields($result);
1071
1072 // this happens sometimes (seen under MySQL 4.0.25)
1073 if (!is_array($fields)) {
1074 return false;
1075 }
1076
1077 foreach ($fields as $k => $field) {
1078 $fields[$k]->_type = $field->type;
1079 $fields[$k]->type = $typeAr[$field->type];
1080 $fields[$k]->_flags = $field->flags;
1081 $fields[$k]->flags = softaculous_mysql_field_flags($result, $k);
1082
1083 // Enhance the field objects for mysql-extension compatibilty
1084 //$flags = explode(' ', $fields[$k]->flags);
1085 //array_unshift($flags, 'dummy');
1086 $fields[$k]->multiple_key
1087 = (int) (bool) ($fields[$k]->_flags & MYSQLI_MULTIPLE_KEY_FLAG);
1088 $fields[$k]->primary_key
1089 = (int) (bool) ($fields[$k]->_flags & MYSQLI_PRI_KEY_FLAG);
1090 $fields[$k]->unique_key
1091 = (int) (bool) ($fields[$k]->_flags & MYSQLI_UNIQUE_KEY_FLAG);
1092 $fields[$k]->not_null
1093 = (int) (bool) ($fields[$k]->_flags & MYSQLI_NOT_NULL_FLAG);
1094 $fields[$k]->unsigned
1095 = (int) (bool) ($fields[$k]->_flags & MYSQLI_UNSIGNED_FLAG);
1096 $fields[$k]->zerofill
1097 = (int) (bool) ($fields[$k]->_flags & MYSQLI_ZEROFILL_FLAG);
1098 $fields[$k]->numeric
1099 = (int) (bool) ($fields[$k]->_flags & MYSQLI_NUM_FLAG);
1100 $fields[$k]->blob
1101 = (int) (bool) ($fields[$k]->_flags & MYSQLI_BLOB_FLAG);
1102 }
1103 return $fields;
1104 }
1105
1106 /**
1107 * Returns the field flags of the field in text format
1108 *
1109 * @param string $result result to fetch the data from
1110 * @param string $field The numerical field offset
1111 * @returns string Returns the field flags of the field in text format
1112 * @since 1.0
1113 */
1114 function softaculous_mysql_field_flags($result, $i){
1115
1116 if(!extension_loaded('mysqli')){
1117 return mysql_field_flags($result, $i);
1118 }
1119
1120 $f = mysqli_fetch_field_direct($result, $i);
1121 $type = $f->type;
1122 $charsetnr = $f->charsetnr;
1123 $f = $f->flags;
1124 $flags = '';
1125 if ($f & MYSQLI_UNIQUE_KEY_FLAG) {
1126 $flags .= 'unique ';
1127 }
1128 if ($f & MYSQLI_NUM_FLAG) {
1129 $flags .= 'num ';
1130 }
1131 if ($f & MYSQLI_PART_KEY_FLAG) {
1132 $flags .= 'part_key ';
1133 }
1134 if ($f & MYSQLI_SET_FLAG) {
1135 $flags .= 'set ';
1136 }
1137 if ($f & MYSQLI_TIMESTAMP_FLAG) {
1138 $flags .= 'timestamp ';
1139 }
1140 if ($f & MYSQLI_AUTO_INCREMENT_FLAG) {
1141 $flags .= 'auto_increment ';
1142 }
1143 if ($f & MYSQLI_ENUM_FLAG) {
1144 $flags .= 'enum ';
1145 }
1146 // See http://dev.mysql.com/doc/refman/6.0/en/c-api-datatypes.html:
1147 // to determine if a string is binary, we should not use MYSQLI_BINARY_FLAG
1148 // but instead the charsetnr member of the MYSQL_FIELD
1149 // structure. Watch out: some types like DATE returns 63 in charsetnr
1150 // so we have to check also the type.
1151 // Unfortunately there is no equivalent in the mysql extension.
1152 if (($type == MYSQLI_TYPE_TINY_BLOB || $type == MYSQLI_TYPE_BLOB
1153 || $type == MYSQLI_TYPE_MEDIUM_BLOB || $type == MYSQLI_TYPE_LONG_BLOB
1154 || $type == MYSQLI_TYPE_VAR_STRING || $type == MYSQLI_TYPE_STRING)
1155 && 63 == $charsetnr
1156 ) {
1157 $flags .= 'binary ';
1158 }
1159 if ($f & MYSQLI_ZEROFILL_FLAG) {
1160 $flags .= 'zerofill ';
1161 }
1162 if ($f & MYSQLI_UNSIGNED_FLAG) {
1163 $flags .= 'unsigned ';
1164 }
1165 if ($f & MYSQLI_BLOB_FLAG) {
1166 $flags .= 'blob ';
1167 }
1168 if ($f & MYSQLI_MULTIPLE_KEY_FLAG) {
1169 $flags .= 'multiple_key ';
1170 }
1171 if ($f & MYSQLI_UNIQUE_KEY_FLAG) {
1172 $flags .= 'unique_key ';
1173 }
1174 if ($f & MYSQLI_PRI_KEY_FLAG) {
1175 $flags .= 'primary_key ';
1176 }
1177 if ($f & MYSQLI_NOT_NULL_FLAG) {
1178 $flags .= 'not_null ';
1179 }
1180 return trim($flags);
1181 }
1182
1183 /**
1184 * Returns the text of the error message from previous MySQL/MySQLi operation
1185 *
1186 * @param string $conn MySQL/MySQLi connection
1187 * @returns string Returns the error text from the last MySQL function
1188 * @since 1.0
1189 */
1190 function softaculous_mysql_error($conn){
1191
1192 if(extension_loaded('mysqli')){
1193 $return = @mysqli_error($conn);
1194
1195 // In mysqli if connection is not made then we will get connection error using the following function.
1196 if(empty($conn)){
1197 $return = @mysqli_connect_error();
1198 }
1199
1200 }else{
1201 $return = @mysql_error($conn);
1202 }
1203
1204 return $return;
1205 }
1206
1207 /**
1208 * Returns the numerical value of the error message from previous MySQL operation
1209 *
1210 * @param string $conn MySQL/MySQLi connection
1211 * @returns int Returns the error number from the last MySQL function
1212 * @since 1.0
1213 */
1214 function softaculous_mysql_errno($conn){
1215
1216 if(extension_loaded('mysqli')){
1217 $return = @mysqli_errno($conn);
1218 }else{
1219 $return = @mysql_errno($conn);
1220 }
1221
1222 return $return;
1223 }
1224
1225 /**
1226 * Retrieves the number of rows from a result set
1227 *
1228 * @param string $result result resource that is being evaluated
1229 * @returns string The number of rows in a result set on success or FALSE on failure
1230 * @since 1.0
1231 */
1232 function softaculous_mysql_num_rows($result){
1233
1234 if(extension_loaded('mysqli')){
1235 $return = @mysqli_num_rows($result);
1236 }else{
1237 $return = @mysql_num_rows($result);
1238 }
1239
1240 return $return;
1241 }
1242
1243 /**
1244 * Get number of affected rows in previous MySQL/MySQLi operation
1245 *
1246 * @param string $conn MySQL/MySQLi connection
1247 * @returns int Returns the number of affected rows on success, Zero indicates that no records were updated and -1 if the last query failed.
1248 * @since 1.0
1249 */
1250 function softaculous_mysql_affected_rows($conn){
1251
1252 if(extension_loaded('mysqli')){
1253 $return = @mysqli_affected_rows($conn);
1254 }else{
1255 $return = @mysql_affected_rows($conn);
1256 }
1257
1258 return $return;
1259 }
1260
1261 /**
1262 * Get the ID generated in the last query
1263 *
1264 * @param string $conn MySQL/MySQLi connection
1265 * @returns int The ID generated for an AUTO_INCREMENT column by the previous query on success, 0 if the previous query does not generate an AUTO_INCREMENT value, or FALSE if * no MySQL connection was established.
1266 * @since 1.0
1267 */
1268 function softaculous_mysql_insert_id($conn){
1269
1270 if(extension_loaded('mysqli')){
1271 $return = @mysqli_insert_id($conn);
1272 }else{
1273 $return = @mysql_insert_id($conn);
1274 }
1275
1276 return $return;
1277 }
1278
1279 /**
1280 * Get number of fields in result
1281 *
1282 * @param string $result result resource that is being evaluated (Required by MySQL)
1283 * @returns string Returns the number of fields in the result set on success or FALSE on failure
1284 * @since 1.0
1285 */
1286 function softaculous_mysql_num_fields($result){
1287
1288 if(extension_loaded('mysqli')){
1289 $return = @mysqli_num_fields($result);
1290 }else{
1291 $return = @mysql_num_fields($result);
1292 }
1293
1294 return $return;
1295 }
1296
1297 /**
1298 * Will free all memory associated with the result identifier
1299 *
1300 * @param string $result result resource that is being evaluated
1301 * @returns bool Returns TRUE on success or FALSE on failure
1302 * @since 1.0
1303 */
1304 function softaculous_mysql_free_result($result){
1305
1306 if(extension_loaded('mysqli')){
1307 $return = @mysqli_free_result($result);
1308 }else{
1309 $return = @mysql_free_result($result);
1310 }
1311
1312 return $return;
1313 }
1314
1315 /**
1316 * Close MySQL/MySQLi connection
1317 *
1318 * @param string $conn MySQL/MySQLi connection
1319 * @returns bool Returns TRUE on success or FALSE on failure
1320 * @since 1.0
1321 */
1322 function softaculous_mysql_close($conn){
1323
1324 if(extension_loaded('mysqli')){
1325 $return = @mysqli_close($conn);
1326 }else{
1327 $return = @mysql_close($conn);
1328 }
1329
1330 return $return;
1331 }
1332
1333 /**
1334 * Get MySQL/MySQLi client info
1335 *
1336 * @returns string Returns a string that represents the MySQL client library version
1337 * @since 1.0
1338 */
1339 function softaculous_mysql_get_client_info(){
1340
1341 if(extension_loaded('mysqli')){
1342 $return = @mysqli_get_client_info();
1343 }else{
1344 $return = @mysql_get_client_info();
1345 }
1346
1347 return $return;
1348 }
1349
1350 /**
1351 * Get MySQL/MySQLi server info
1352 *
1353 * @param string $conn MySQL/MySQLi connection
1354 * @returns string Returns a string that represents the MySQL server version
1355 * @since 1.0
1356 */
1357 function softaculous_mysql_get_server_info($conn){
1358
1359 if(extension_loaded('mysqli')){
1360 $return = @mysqli_get_server_info($conn);
1361 }else{
1362 $return = @mysql_get_server_info($conn);
1363 }
1364
1365 return $return;
1366 }
1367
1368 /**
1369 * Execute Database queries
1370 *
1371 * @param string $queries The Database Queries seperated by a SEMI COLON (;)
1372 * @param string $host The Database HOST
1373 * @param string $db The Database Name
1374 * @param string $user The Database User Name
1375 * @param string $pass The Database User Password
1376 * @param string $conn The Database Connection
1377 * @returns bool
1378 * @since 1.0
1379 */
1380 function softaculous_sdb_query($queries, $host, $user, $pass, $db, $conn = '', $no_strict = 0){
1381 return softaculous_mysqlfile($queries, $host, $user, $pass, $db, $conn);
1382
1383 }
1384
1385 /**
1386 * Dump SQL Data ($raw) into the given database.
1387 *
1388 * @param string $raw The RAW SQL Data
1389 * @param string $host The MySQL Host
1390 * @param string $user The MySQL User
1391 * @param string $pass The MySQL User password
1392 * @param string $db The Database Name
1393 * @param string $__conn Connection link to the database
1394 * @return bool If there is an error $softaculous_error is filled with the error
1395 * @since 1.0
1396 */
1397 function softaculous_mysqlfile($raw, $host, $user, $pass, $db, $__conn = ""){
1398
1399 global $softaculous_error, $softaculous_lang;
1400
1401 $queries = softaculous_sqlsplit($raw);
1402
1403 //Make the Connection
1404 if(empty($__conn)){
1405 $__conn = @softaculous_mysql_connect($host, $user, $pass, true);
1406 }
1407
1408 //CHECK Errors and SELECT DATABASE
1409 if(!empty($__conn)){
1410 if(!(@softaculous_mysql_select_db($db, $__conn))){
1411 $softaculous_error[] = $softaculous_lang['err_selectmy'].(!empty($_GET['debug']) ? softaculous_mysql_error($__conn) : '');
1412 return false;
1413 }
1414 }else{
1415 $softaculous_error[] = $softaculous_lang['err_myconn'].(!empty($_GET['debug']) ? softaculous_mysql_error($__conn) : '');
1416 return false;
1417 }
1418
1419 $num = count($queries);
1420
1421 //Start the Queries
1422 foreach($queries as $k => $q){
1423
1424 //PARSE the String and make the QUERY
1425 $result = softaculous_mysql_query($q, $__conn);
1426
1427 //Looks like there was an error
1428 if(!$result){
1429 $softaculous_error[] = $softaculous_lang['err_makequery'].' : '.$k.'<br />'.$softaculous_lang['err_mynum'].' : '.softaculous_mysql_errno($__conn).'<br />'.$softaculous_lang['err_myerr'].' : '.softaculous_mysql_error($__conn).(softaculous_sdebug('errquery') ? ' Query : '.$q : '');
1430 return false;
1431 }
1432
1433 // Is there only one query ?
1434 if($num == 1){
1435
1436 // Is it a SELECT query ?
1437 if(preg_match('/^(SELECT|SHOW|DESCRIBE)/is', $q)){ // CHECKSUM|OPTIMIZE|ANALYZE|CHECK|EXPLAIN
1438
1439 // Accumulate the data !
1440 for($i = 0; $i < softaculous_mysql_num_rows($result); $i++){
1441 $return[] = softaculous_mysql_fetch_assoc($result);
1442 }
1443
1444 }
1445
1446 // Is it a INSERT query ? Then we will have to return insert id
1447 if(preg_match('/^INSERT/is', $q)){
1448 $return[] = softaculous_mysql_insert_id($__conn);
1449 }
1450 }
1451
1452 }
1453
1454 // Are we to return the data ?
1455 if(!empty($return)){
1456 return $return;
1457 }
1458
1459 return true;
1460
1461 }
1462
1463 /**
1464 * Is debugging ON for the given key ?
1465 *
1466 * @param string $key The Key to search for debugging
1467 * @return int True on success
1468 * @since 1.0
1469 */
1470 function softaculous_sdebug($key){
1471 if(@in_array($key, @$_GET['debug']) || @$_GET['debug'] == $key){
1472 return true;
1473 }
1474 }
1475
1476 /**
1477 * phpMyAdmin SPLIT SQL function which splits the SQL data into seperate chunks that can be passed as QUERIES.
1478 *
1479 * @param string $data The SQL RAW data
1480 * @returns array The chunks of SQL Queries
1481 * @since 1.0
1482 */
1483 function softaculous_sqlsplit($data){
1484
1485 $ret = array();
1486 $buffer = '';
1487 // Defaults for parser
1488 $sql = '';
1489 $start_pos = 0;
1490 $i = 0;
1491 $len= 0;
1492 $big_value = 200000000;
1493 $sql_delimiter = ';';
1494
1495 $finished = false;
1496
1497 while (!($finished && $i >= $len)) {
1498
1499 if ($data === FALSE) {
1500 // subtract data we didn't handle yet and stop processing
1501 //$offset -= strlen($buffer);
1502 break;
1503 } elseif ($data === TRUE) {
1504 // Handle rest of buffer
1505 } else {
1506 // Append new data to buffer
1507 $buffer .= $data;
1508 // free memory
1509 $data = false;
1510 // Do not parse string when we're not at the end and don't have ; inside
1511 if ((strpos($buffer, $sql_delimiter, $i) === FALSE) && !$finished) {
1512 continue;
1513 }
1514 }
1515 // Current length of our buffer
1516 $len = strlen($buffer);
1517
1518 // Grab some SQL queries out of it
1519 while ($i < $len) {
1520 $found_delimiter = false;
1521 // Find first interesting character
1522 $old_i = $i;
1523 // this is about 7 times faster that looking for each sequence i
1524 // one by one with strpos()
1525 if (preg_match('/(\'|"|#|-- |\/\*|`|(?i)DELIMITER)/', $buffer, $matches, PREG_OFFSET_CAPTURE, $i)) {
1526 // in $matches, index 0 contains the match for the complete
1527 // expression but we don't use it
1528 $first_position = $matches[1][1];
1529 } else {
1530 $first_position = $big_value;
1531 }
1532 /**
1533 * @todo we should not look for a delimiter that might be
1534 * inside quotes (or even double-quotes)
1535 */
1536 // the cost of doing this one with preg_match() would be too high
1537 $first_sql_delimiter = strpos($buffer, $sql_delimiter, $i);
1538 if ($first_sql_delimiter === FALSE) {
1539 $first_sql_delimiter = $big_value;
1540 } else {
1541 $found_delimiter = true;
1542 }
1543
1544 // set $i to the position of the first quote, comment.start or delimiter found
1545 $i = min($first_position, $first_sql_delimiter);
1546
1547 if ($i == $big_value) {
1548 // none of the above was found in the string
1549
1550 $i = $old_i;
1551 if (!$finished) {
1552 break;
1553 }
1554 // at the end there might be some whitespace...
1555 if (trim($buffer) == '') {
1556 $buffer = '';
1557 $len = 0;
1558 break;
1559 }
1560 // We hit end of query, go there!
1561 $i = strlen($buffer) - 1;
1562 }
1563
1564 // Grab current character
1565 $ch = $buffer[$i];
1566
1567 // Quotes
1568 if (strpos('\'"`', $ch) !== FALSE) {
1569 $quote = $ch;
1570 $endq = FALSE;
1571 while (!$endq) {
1572 // Find next quote
1573 $pos = strpos($buffer, $quote, $i + 1);
1574 // No quote? Too short string
1575 if ($pos === FALSE) {
1576 // We hit end of string => unclosed quote, but we handle it as end of query
1577 if ($finished) {
1578 $endq = TRUE;
1579 $i = $len - 1;
1580 }
1581 $found_delimiter = false;
1582 break;
1583 }
1584 // Was not the quote escaped?
1585 $j = $pos - 1;
1586 while ($buffer[$j] == '\\') $j--;
1587 // Even count means it was not escaped
1588 $endq = (((($pos - 1) - $j) % 2) == 0);
1589 // Skip the string
1590 $i = $pos;
1591
1592 if ($first_sql_delimiter < $pos) {
1593 $found_delimiter = false;
1594 }
1595 }
1596 if (!$endq) {
1597 break;
1598 }
1599 $i++;
1600 // Aren't we at the end?
1601 if ($finished && $i == $len) {
1602 $i--;
1603 } else {
1604 continue;
1605 }
1606 }
1607
1608 // Not enough data to decide
1609 if ((($i == ($len - 1) && ($ch == '-' || $ch == '/'))
1610 || ($i == ($len - 2) && (($ch == '-' && $buffer[$i + 1] == '-')
1611 || ($ch == '/' && $buffer[$i + 1] == '*')))) && !$finished) {
1612 break;
1613 }
1614
1615 // Comments
1616 if ($ch == '#'
1617 || ($i < ($len - 1) && $ch == '-' && $buffer[$i + 1] == '-'
1618 && (($i < ($len - 2) && $buffer[$i + 2] <= ' ')
1619 || ($i == ($len - 1) && $finished)))
1620 || ($i < ($len - 1) && $ch == '/' && $buffer[$i + 1] == '*')
1621 ) {
1622 // Copy current string to SQL
1623 if ($start_pos != $i) {
1624 $sql .= substr($buffer, $start_pos, $i - $start_pos);
1625 }
1626 // Skip the rest
1627 $j = $i;
1628 $i = strpos($buffer, $ch == '/' ? '*/' : "\n", $i);
1629 // didn't we hit end of string?
1630 if ($i === FALSE) {
1631 if ($finished) {
1632 $i = $len - 1;
1633 } else {
1634 break;
1635 }
1636 }
1637 // Skip *
1638 if ($ch == '/') {
1639 // Check for MySQL conditional comments and include them as-is
1640 if ($buffer[$j + 2] == '!') {
1641 $comment = substr($buffer, $j + 3, $i - $j - 3);
1642 if (preg_match('/^[0-9]{5}/', $comment, $version)) {
1643 if ($version[0] <= 50000000) {
1644 $sql .= substr($comment, 5);
1645 }
1646 } else {
1647 $sql .= $comment;
1648 }
1649 }
1650 $i++;
1651 }
1652 // Skip last char
1653 $i++;
1654 // Next query part will start here
1655 $start_pos = $i;
1656 // Aren't we at the end?
1657 if ($i == $len) {
1658 $i--;
1659 } else {
1660 continue;
1661 }
1662 }
1663 // Change delimiter, if redefined, and skip it (don't send to server!)
1664 if (strtoupper(substr($buffer, $i, 9)) == "DELIMITER"
1665 && ($buffer[$i + 9] <= ' ')
1666 && ($i < $len - 11)
1667 && strpos($buffer, "\n", $i + 11) !== FALSE) {
1668 $new_line_pos = strpos($buffer, "\n", $i + 10);
1669 $sql_delimiter = substr($buffer, $i + 10, $new_line_pos - $i - 10);
1670 $i = $new_line_pos + 1;
1671 // Next query part will start here
1672 $start_pos = $i;
1673 continue;
1674 }
1675
1676 // End of SQL
1677 if ($found_delimiter || ($finished && ($i == $len - 1))) {
1678 $tmp_sql = $sql;
1679 if ($start_pos < $len) {
1680 $length_to_grab = $i - $start_pos;
1681
1682 if (! $found_delimiter) {
1683 $length_to_grab++;
1684 }
1685 $tmp_sql .= substr($buffer, $start_pos, $length_to_grab);
1686 unset($length_to_grab);
1687 }
1688 // Do not try to execute empty SQL
1689 if (! preg_match('/^([\s]*;)*$/', trim($tmp_sql))) {
1690 $sql = $tmp_sql;
1691 $ret[] = $sql;
1692
1693 $buffer = substr($buffer, $i + strlen($sql_delimiter));
1694 // Reset parser:
1695 $len = strlen($buffer);
1696 $sql = '';
1697 $i = 0;
1698 $start_pos = 0;
1699 // Any chance we will get a complete query?
1700 //if ((strpos($buffer, ';') === FALSE) && !$finished) {
1701 if ((strpos($buffer, $sql_delimiter) === FALSE) && !$finished) {
1702 break;
1703 }
1704 } else {
1705 $i++;
1706 $start_pos = $i;
1707 }
1708 }
1709 } // End of parser loop
1710 } // End of import loop
1711
1712 return $ret;
1713
1714 }
1715
1716
1717 /**
1718 * Read the SQL file in parts and Dump the data into the given database
1719 *
1720 * @param string $file The Path to SQL file
1721 * @param string $host The MySQL Host
1722 * @param string $user The MySQL User
1723 * @param string $pass The MySQL User password
1724 * @param string $db The Database Name
1725 * @param string $__conn Connection link to the database
1726 * @return bool If there is an error $softaculous_error is filled with the error
1727 * @since 1.0
1728 */
1729 function softaculous_softaculous_mysql_parts($file, $host, $user, $pass, $db, $__conn = "", $delimiter = ';', $replace_data = array()){
1730
1731 global $softaculous_error, $softaculous_lang;
1732
1733 if(is_file($file) === true){
1734
1735 //Make the Connection
1736 if(empty($__conn)){
1737 $__conn = @softaculous_mysql_connect($host, $user, $pass, true);
1738 }
1739
1740 //CHECK Errors and SELECT DATABASE
1741 if(!empty($__conn)){
1742 if(!(@softaculous_mysql_select_db($db, $__conn))){
1743 $softaculous_error[] = $softaculous_lang['err_selectmy'].(!empty($_GET['debug']) ? softaculous_mysql_error($__conn) : '');
1744 return false;
1745 }
1746 }else{
1747 $softaculous_error[] = $softaculous_lang['err_myconn'].(!empty($_GET['debug']) ? softaculous_mysql_error($__conn) : '');
1748 return false;
1749 }
1750
1751 $file = fopen($file, 'r');
1752
1753 if(is_resource($file) === true){
1754 $query = array();
1755 $num = 0;
1756 while(feof($file) === false){
1757
1758 if(is_string($query) === true){
1759 $query = array();
1760 }
1761
1762 $query[] = fgets($file);
1763
1764 if(preg_match('~' . preg_quote($delimiter, '~') . '\s*$~iS', end($query)) === 1){
1765 $query = trim(implode('', $query));
1766
1767 if(!empty($replace_data)){
1768 $query = strtr($query, $replace_data);
1769 }
1770
1771 $result = softaculous_mysql_query($query, $__conn);
1772 if(!$result){
1773 $softaculous_error[] = $softaculous_lang['err_makequery'].' <br />'.$softaculous_lang['err_mynum'].' : '.softaculous_mysql_errno($__conn).'<br />'.$softaculous_lang['err_myerr'].' : '.softaculous_mysql_error($__conn).(softaculous_sdebug('errquery') ? ' Query : '.$query : '');
1774 return false;
1775 }else{
1776 $num++;
1777 }
1778 }
1779 }
1780
1781 fclose($file);
1782
1783 // Is there only one query ?
1784 if($num == 1){
1785
1786 // Is it a SELECT query ?
1787 if(preg_match('/^(SELECT|SHOW|DESCRIBE)/is', $query)){ // CHECKSUM|OPTIMIZE|ANALYZE|CHECK|EXPLAIN
1788
1789 // Accumulate the data !
1790 for($i = 0; $i < softaculous_mysql_num_rows($result); $i++){
1791 $return[] = softaculous_mysql_fetch_assoc($result);
1792 }
1793
1794 }
1795
1796 // Is it a INSERT query ? Then we will have to return insert id
1797 if(preg_match('/^INSERT/is', $query)){
1798 $return[] = softaculous_mysql_insert_id($__conn);
1799 }
1800 }
1801
1802 // Are we to return the data ?
1803 if(!empty($return)){
1804 return $return;
1805 }
1806 }else{
1807 $softaculous_error['err_no_open_db_file'] = $softaculous_lang['err_no_open_db_file'];
1808 return false;
1809 }
1810 }else{
1811 $softaculous_error['err_no_db_file'] = $softaculous_lang['err_no_db_file'];
1812 return false;
1813 }
1814
1815 return true;
1816 }
1817
1818 /**
1819 * Check whether a file or directory exists at the INSTALLATION level ONLY, not in the PACKAGE
1820 *
1821 * @param string $path The path of the file or directory
1822 * @returns bool
1823 * @since 1.0
1824 */
1825 function softaculous_sfile_exists($path){
1826 return file_exists($path);
1827 }
1828
1829 /**
1830 * Softaculous Version Compare, fixes a bug with '+' as the last character
1831 *
1832 * @param string $ver1 The first version
1833 * @param string $ver2 The second version
1834 * @param string $oper By default NULL or operators of the original version_compare() function
1835 * @param string $vr By default Empty Array or An array which will contain alphabetic version and to be replace version (For handling alphabatic versions)
1836 * @return int values as per the original version_compare() function
1837 * @since 1.0
1838 */
1839 function softaculous_sversion_compare($ver1, $ver2, $oper = NULL, $vr = array()){
1840
1841 if(!empty($vr)){
1842 $ver2 = str_replace($vr['search'], $vr['replace'], $ver2);
1843 }
1844
1845 $last1 = substr($ver1, -1);
1846 $last2 = substr($ver2, -1);
1847
1848 if(!preg_match('/[0-9a-zA-Z]/is', $last1)){
1849 $ver1 = substr($ver1, 0, -1).'.0'.$last1.'0';
1850 }
1851
1852 if(!preg_match('/[0-9a-zA-Z]/is', $last2)){
1853 $ver2 = substr($ver2, 0, -1).'.0'.$last2.'0';
1854 }
1855
1856 if(is_null($oper)){
1857 return version_compare($ver1, $ver2);
1858 }else{
1859 return version_compare($ver1, $ver2, $oper);
1860 }
1861 }
1862
1863 /**
1864 * Deletes a file.
1865 *
1866 * @param string $path
1867 * @returns bool
1868 * @since 1.0
1869 */
1870 function softaculous_sunlink($path){
1871 return @unlink($path);
1872 }
1873
1874 /**
1875 * Check whether the path is a directory
1876 *
1877 * @param string $path The path of the file or directory
1878 * @returns bool
1879 * @since 1.0
1880 */
1881 function softaculous_is_dir($path){
1882 return is_dir($path);
1883 }
1884
1885 /**
1886 * Creates a directory. This is meant to be used by install.php, upgrade.php, etc.
1887 * NOTE : Folder permissions cannot exceed 0755 in MKDIR. You must use schmod if necessary to give 0777
1888 *
1889 * @param string $path
1890 * @param octal $mode
1891 * @param bool $rec Recurse into the directory and apply the changes
1892 * @returns bool
1893 * @since 1.0
1894 */
1895 function softaculous_mkdir($path, $mode = 0755, $rec = 0){
1896 if(!is_dir($path)){
1897 $ret = mkdir($path, $mode, $rec);
1898 return $ret;
1899 }
1900 return true;
1901 }
1902
1903 /**
1904 * Changes the permissions (chmod) of the given path. This is meant to be used by install.php, upgrade.php, etc.
1905 *
1906 * @param string $path The path of the file or directory
1907 * @param octal $oct The new permission e.g. 0644
1908 * @returns bool
1909 * @since 1.0
1910 */
1911 function softaculous_chmod($path, $mode){
1912 return chmod($path, $mode);
1913 }
1914
1915 /**
1916 * Writes data to a file
1917 *
1918 * @param string $file The path of the file or directory
1919 * @param string $data Data to write to the file
1920 * @returns bool
1921 * @since 1.0
1922 */
1923 function softaculous_put($file, $data){
1924
1925 $fp = @fopen($file, "wb");
1926 if($fp){
1927 if(@fwrite($fp, $data) === FALSE){
1928 return false;
1929 }else{
1930 @fclose($fp);
1931 return true;
1932 }
1933 }
1934 return false;
1935 }
1936
1937 /**
1938 * Deletes a file.
1939 *
1940 * @param string $filename
1941 * @returns bool
1942 * @since 1.0
1943 */
1944 function softaculous_delete($filename){
1945 return softaculous_sunlink($filename);
1946 }
1947
1948 /**
1949 * Removes a directory
1950 *
1951 * @param string $directory path
1952 * @returns bool
1953 * @since 1.4.3
1954 */
1955 function softaculous_srm($path){
1956
1957 if(is_dir($path)){
1958 return softaculous_rmdir_recursive($path);
1959 }
1960 // So its a file !
1961 return softaculous_sunlink($path);
1962 }
1963
1964 /**
1965 * Used in file_functions to perform backup
1966 *
1967 * @param string $filename
1968 * @returns bool
1969 * @since 1.0
1970 */
1971 function softaculous_chdir($dir){
1972 return softaculous_is_dir($dir);
1973 }
1974
1975 /**
1976 * Check whether a file or directory exists
1977 *
1978 * @param string $file The path of the file or directory
1979 * @returns bool
1980 * @since 1.0
1981 */
1982 function softaculous_file_exists($file){
1983 return file_exists($file);
1984 }
1985
1986 /**
1987 * Renames a file/folder.
1988 *
1989 * @param string $from oldname
1990 * @param string $to newname
1991 * @returns bool
1992 * @since 1.4.2
1993 */
1994 function softaculous_rename($from, $to){
1995 return rename($from, $to);
1996 }
1997
1998 /**
1999 * Fetch the connection key for the Softaculous plugin to add the website in Softaculous panel
2000 *
2001 * @param bool $force Whether to generate a new key forcefully or fetch the prev generated key
2002 * @returns string $conn_key
2003 * @since 1.0
2004 */
2005 function softaculous_get_connection_key($force = ''){
2006
2007 $conn_key = softaculous_get_option('softaculous_auth_key');
2008
2009 if(empty($conn_key) || (!empty($conn_key) && strlen($conn_key) != 128) || $force){
2010 $conn_key = softaculous_srandstr(128);
2011 update_option('softaculous_auth_key', $conn_key, true);
2012 }
2013
2014 return $conn_key;
2015 }
2016
2017 /**
2018 * Generate the connection key on plugin activation
2019 *
2020 * @returns string $conn_key
2021 * @since 1.0
2022 */
2023 function softaculous_activation_hook(){
2024
2025 softaculous_get_connection_key(1);
2026
2027 // Get Softaculous settings and convert to Softaculous settings
2028 $deprecated_settings = array('wpcentral_auth_key' => 'softaculous_auth_key', 'wpcentral_allowed_ips' => 'softaculous_allowed_ips', 'wpcentral_connected' => 'softaculous_connected', 'wpcentral_promo_time' => 'softaculous_promo_time', 'wpcentral_signonkey' => 'softaculous_signonkey', 'wpcentral_signonkey_time' => 'softaculous_signonkey_time', 'wpc_dismiss_notice_date' => 'softaculous_dismiss_notice_date');
2029
2030 foreach($deprecated_settings as $old_name => $new_name){
2031 $cur = get_option($old_name, NULL);
2032 if(!is_null($cur)){
2033 update_option($new_name, $cur);
2034 delete_option($old_name);
2035 }
2036 }
2037
2038 delete_option('wpcentral_version');
2039
2040 return true;
2041 }
2042
2043 /**
2044 * Generate the connection key when the plugin loads after its activation.
2045 *
2046 * @returns string $conn_key
2047 * @since 1.2
2048 */
2049 function softaculous_load_plugin(){
2050
2051 // Enqueues scripts and styles
2052 add_action('admin_enqueue_scripts', 'softaculous_enqueue_scripts');
2053
2054 // Show key details in Plugins data
2055 add_filter('plugin_row_meta', 'softaculous_add_connection_link', 10, 2);
2056
2057 softaculous_update_check();
2058
2059 // Set the key if not already set
2060 softaculous_get_connection_key();
2061
2062 // All non-privilige actions including those called by cloud.softaculous.com
2063 // We must check with softaculous_authorize in these actions
2064 add_action('wp_ajax_nopriv_my_wpc_actions', 'softaculous_actions_init');
2065
2066 // If we are to login the user
2067 // We must authorize with the softaculous_signonkey_authorization() function in these actions
2068 add_action('wp_ajax_nopriv_wpcentral_login_and_act', 'softaculous_login_and_act');
2069
2070 // Are you the Admin ?
2071 if(current_user_can('administrator')){
2072
2073 // If we are to login the user
2074 // We must authorize with the softaculous_signonkey_authorization() function in these actions
2075 add_action('wp_ajax_wpcentral_login_and_act', 'softaculous_login_and_act');
2076
2077 if(softaculous_is_display_notice()){
2078 add_action('admin_notices', 'softaculous_admin_notice');
2079 }
2080
2081 add_action('wp_ajax_softaculous_dismissnotice', 'softaculous_dismiss_notice');
2082
2083 // This adds the left menu in WordPress Admin page
2084 add_action('admin_menu', 'softaculous_admin_menu', 5);
2085
2086 add_action('wp_ajax_my_softaculous_fetch_authkey', 'softaculous_fetch_authkey');
2087
2088 // Backward compatible. To be deprecated
2089 add_action('wp_ajax_my_wpc_fetch_authkey', 'softaculous_fetch_authkey');
2090
2091 // Show Softaculous ratings notice
2092 softaculous_maybe_promo(array(
2093 'after' => 1,// In days
2094 'interval' => 120,// In days
2095 'rating' => 'https://wordpress.org/plugins/softaculous/#reviews',
2096 'twitter' => 'https://twitter.com/softaculous?status='.rawurlencode('I love #Softaculous for managing my #WordPress site - '.home_url()),
2097 'facebook' => 'https://www.facebook.com/softaculous',
2098 'website' => 'https://softaculous.com',
2099 'image' => SOFTACULOUS_PLUGIN_URL . 'assets/images/logo.gif',
2100 'support' => 'https://softaculous.deskuss.com'
2101 ));
2102
2103 }
2104
2105 return true;
2106 }
2107
2108 // Shows the admin menu of Softaculous
2109 function softaculous_admin_menu() {
2110
2111 $capability = 'activate_plugins';// TODO : Capability for accessing this page
2112
2113 // Add the menu page
2114 add_menu_page(__('Softaculous Manager'), __('Softaculous', 'softaculous'), $capability, 'softaculous', 'softaculous_page_handler', SOFTACULOUS_PLUGIN_URL .'assets/images/soft_logo_22.svg');
2115 }
2116
2117 function softaculous_enqueue_scripts(){
2118
2119 wp_enqueue_style('soft-style', SOFTACULOUS_PLUGIN_URL . '/assets/css/admin.css', array(), SOFTACULOUS_VERSION);
2120
2121 wp_enqueue_script('soft-script', SOFTACULOUS_PLUGIN_URL . '/assets/js/admin.js', array(), SOFTACULOUS_VERSION, true);
2122
2123 wp_localize_script('soft-script', 'soft_obj', array(
2124 'admin_url' => admin_url(),
2125 'nonce' => wp_create_nonce('softaculous_js_nonce'),
2126 'ajax_url' => admin_url('admin-ajax.php')
2127 ));
2128 }
2129
2130 // The Softaculous Settings Page
2131 function softaculous_page_handler(){
2132
2133 if(!current_user_can('manage_options')){
2134 wp_die('Sorry, but you do not have permissions to change settings.');
2135 }
2136
2137 include_once(dirname(__FILE__).'/settings.php');
2138 }
2139
2140 /**
2141 * Fetch the connection key and the site details when the plugin is installed and activated from Softaculous panel.
2142 *
2143 * @since 1.2
2144 */
2145 function softaculous_fetch_authkey(){
2146 global $softaculous_lang, $softaculous_error, $softaculous_wp_config, $wpdb;
2147
2148 //Fetch WP Configuration details
2149 $softaculous_wp_config = softaculous_fetch_wp_config();
2150
2151 $softaculous_authkey = softaculous_get_connection_key();
2152
2153 include_once('verify.php');
2154 softaculous_verify($softaculous_authkey);
2155 }
2156
2157 /**
2158 * Deletes the connection key on plugin deactivation
2159 *
2160 * @returns bool
2161 * @since 1.0
2162 */
2163 function softaculous_deactivation_hook(){
2164 delete_option('softaculous_auth_key');
2165 delete_option('softaculous_connected');
2166 delete_option('softaculous_dismiss_notice_date');
2167 delete_option('softaculous_promo_time');
2168 return true;
2169 }
2170
2171 /**
2172 * Add plugin's metadata in the plugin list table
2173 *
2174 * @param string $links
2175 * @param string $slug plugin's slug value
2176 * @returns array $links
2177 * @since 1.0
2178 */
2179 function softaculous_add_connection_link($links, $slug) {
2180
2181 if(is_multisite() && is_network_admin()){
2182 return $links;
2183 }
2184
2185 if ($slug !== SOFTACULOUS_BASE) {
2186 return $links;
2187 }
2188
2189 if(!current_user_can('activate_plugins')){
2190 return $links;
2191 }
2192
2193 wp_enqueue_script('jquery');
2194 wp_enqueue_script('jquery-ui-core');
2195 wp_enqueue_script('jquery-ui-dialog');
2196 wp_enqueue_style('wp-jquery-ui');
2197 wp_enqueue_style('wp-jquery-ui-dialog');
2198
2199 $mdialog = '
2200 <div id="soft_connection_key_dialog" style="display: none;">
2201
2202 <p style="display:inline-block; padding:0 20px; font-size:13px;"><a class="button button-primary action" href="'.softaculous_get_addsite_link().'" target="_blank">1-Click Connect Website</a></p>
2203
2204 <h2 style="margin-left:5%;">OR</h2>
2205 <p>Follow the steps here to connect your website to Softaculous dashboard:</p>
2206 <ol>
2207 <li>Copy the connection key below</li>
2208 <li>Log into your <a href="https://cloud.softaculous.com/" target="_blank">Softaculous</a> account</li>
2209 <li>Click on <a href="'.softaculous_get_addsite_link().'" target="_blank">Add Website</a> to add your website to the Softaculous panel</li>
2210 <li>Enter this website\'s URL and paste the Connection key given below</li>
2211 <li>You can also follow our guide for the same <a href="https://www.softaculous.com/docs/wordpress-plugin/adding-website-in-panel/" target="_blank">here</a></li>
2212 </ol>
2213
2214 <div style="text-align:center; font-weight:bold;"><p style="margin-bottom: 4px;margin-top: 10px;">Softaculous Connection Key</p></div>
2215 <div class="display_connection_key" style="padding: 10px;background-color: #fafafa;border: 1px solid black;border-radius: 10px;font-weight: bold;font-size: 14px;text-align: center;">'.softaculous_get_connection_key().'</div>
2216
2217 <p style="font-weight:bold;">Note: Contact Softaculous Team at <a href="mailto:support@softaculous.com">support@softaculous.com</a> for any issues</p>
2218 </div>';
2219
2220 $new_links = array(
2221 'doc' => '<a href="#" id="soft_connection_key">View Connection Key</a>'.$mdialog,
2222 'settings' => '<a href="admin.php?page=softaculous">Settings</a>'
2223 );
2224
2225 $links = array_merge($links, $new_links);
2226
2227 return $links;
2228 }
2229
2230 /**
2231 * Deletes the connection key on plugin deactivation
2232 *
2233 * @returns bool
2234 * @since 1.0
2235 */
2236 function softaculous_deactivate(){
2237 delete_option('softaculous_auth_key');
2238 delete_option('softaculous_connected');
2239 delete_option('softaculous_dismiss_notice_date');
2240 }
2241
2242 // Get the client IP
2243 function softaculous_getip(){
2244
2245 if(isset($_SERVER["REMOTE_ADDR"])){
2246 $ip_addr = sanitize_text_field($_SERVER["REMOTE_ADDR"]);
2247 }elseif(isset($_SERVER["HTTP_X_FORWARDED_FOR"])){
2248 $ip_addr = sanitize_text_field($_SERVER["HTTP_X_FORWARDED_FOR"]);
2249 }elseif(isset($_SERVER["HTTP_CLIENT_IP"])){
2250 $ip_addr = sanitize_text_field($_SERVER["HTTP_CLIENT_IP"]);
2251 }
2252
2253 // Fast path: no CF header present — skip CF check entirely.
2254 if(empty($_SERVER['HTTP_CF_CONNECTING_IP'])){
2255 return $ip_addr;
2256 }
2257
2258 // Validate that REMOTE_ADDR (the actual TCP peer) is a Cloudflare IP.
2259 // If it is, the CF header is trustworthy; otherwise ignore it.
2260 if(softaculous_is_cloudflare_ip($ip_addr)){
2261 $cf_ip = sanitize_text_field($_SERVER['HTTP_CF_CONNECTING_IP']);
2262 if(filter_var($cf_ip, FILTER_VALIDATE_IP)){
2263 return $cf_ip;
2264 }
2265 }
2266
2267 return $ip_addr;
2268 }
2269
2270 /**
2271 * Returns true if $ip falls inside any of the published Cloudflare IP ranges
2272 *
2273 * @internal Used only by softaculous_getip().
2274 */
2275 function softaculous_is_cloudflare_ip($ip){
2276
2277 $ranges = softaculous_get_cloudflare_cidrs();
2278 if(empty($ranges)){
2279 return false; // fetch failed — do not trust CF header
2280 }
2281
2282 foreach($ranges as $cidr){
2283 if(softaculous_ip_in_cidr($ip, $cidr)){
2284 return true;
2285 }
2286 }
2287
2288 return false;
2289 }
2290
2291 /**
2292 * Fetch (and cache) Cloudflare's published IP ranges.
2293 * Returns a flat array of CIDR strings, e.g. ['103.21.244.0/22', ...].
2294 *
2295 * Cache location: options table (24-hour TTL).
2296 * Falls back to an empty array on any network or parse error.
2297 *
2298 * @internal
2299 */
2300 function softaculous_get_cloudflare_cidrs() {
2301
2302 $cache_ttl = 7 * DAY_IN_SECONDS;
2303
2304 $cache = get_option('softaculous_cloudflare_ips', array(
2305 'updated' => 0,
2306 'cidrs' => array(),
2307 ));
2308
2309 // Return cached data if still fresh.
2310 if(!empty($cache['cidrs']) && (time() - (int) $cache['updated']) < $cache_ttl){
2311 return $cache['cidrs'];
2312 }
2313
2314 $sources = array(
2315 'https://www.cloudflare.com/ips-v4',
2316 'https://www.cloudflare.com/ips-v6',
2317 );
2318
2319 $cidrs = array();
2320
2321 foreach ($sources as $url) {
2322
2323 $response = wp_remote_get($url, array(
2324 'timeout' => 5,
2325 'redirection' => 3,
2326 'user-agent' => 'WordPress/' . get_bloginfo('version') . '; ' . home_url('/'),
2327 ));
2328
2329 if(is_wp_error($response)){
2330 continue;
2331 }
2332
2333 if(wp_remote_retrieve_response_code($response) !== 200){
2334 continue;
2335 }
2336
2337 $body = wp_remote_retrieve_body($response);
2338
2339 foreach(explode("\n", trim($body)) as $line){
2340 $line = trim($line);
2341
2342 // Basic sanity check.
2343 if($line !== '' && strpos($line, '/') !== false){
2344 $cidrs[] = $line;
2345 }
2346 }
2347 }
2348
2349 // Save only if we successfully fetched data.
2350 if(!empty($cidrs)){
2351 update_option(
2352 'softaculous_cloudflare_ips',
2353 array(
2354 'updated' => time(),
2355 'cidrs' => array_unique($cidrs),
2356 ),
2357 false
2358 );
2359
2360 return array_unique($cidrs);
2361 }
2362
2363 // Return stale cache if refresh failed.
2364 return !empty($cache['cidrs']) ? $cache['cidrs'] : array();
2365 }
2366
2367 /**
2368 * Check whether a given IP address falls within a CIDR block.
2369 * Supports both IPv4 and IPv6.
2370 *
2371 * @internal
2372 */
2373 function softaculous_ip_in_cidr($ip, $cidr){
2374
2375 list($subnet, $bits) = explode('/', $cidr, 2);
2376 $bits = (int)$bits;
2377
2378 // Detect address family by presence of ':'
2379 $isIPv6 = strpos($ip, ':') !== false;
2380
2381 if ($isIPv6) {
2382 // IPv6 comparison using inet_pton packed binary
2383 $ipPacked = @inet_pton($ip);
2384 $subnetPacked = @inet_pton($subnet);
2385 if ($ipPacked === false || $subnetPacked === false) return false;
2386 if (strlen($ipPacked) !== 16 || strlen($subnetPacked) !== 16) return false;
2387
2388 // Build a bitmask of $bits ones followed by zeros, across 128 bits
2389 $mask = str_repeat("\xff", (int)($bits / 8));
2390 $rem = $bits % 8;
2391 if ($rem) $mask .= chr(0xff & (0xff << (8 - $rem)));
2392 $mask = str_pad($mask, 16, "\x00");
2393
2394 return ($ipPacked & $mask) === ($subnetPacked & $mask);
2395 } else {
2396 // IPv4 comparison using 32-bit integers
2397 $ipLong = ip2long($ip);
2398 $subnetLong = ip2long($subnet);
2399 if ($ipLong === false || $subnetLong === false) return false;
2400
2401 $mask = $bits === 0 ? 0 : (~0 << (32 - $bits));
2402 return ($ipLong & $mask) === ($subnetLong & $mask);
2403 }
2404 }
2405
2406 /**
2407 * Check for the authorization of the request using the auth key
2408 *
2409 * @returns bool
2410 * @since 1.0
2411 */
2412 function softaculous_authorize(){
2413 global $softaculous_lang, $softaculous_error;
2414
2415 $return = array();
2416
2417 $auth_key = softaculous_optREQ('auth_key');
2418 if(empty($auth_key)){
2419 $return['error'] = 'Unauthorized Access!!';
2420 echo wp_json_encode($return);
2421 die();
2422 }
2423
2424 $verify_authkey = softaculous_get_option('softaculous_auth_key');
2425 if($auth_key != $verify_authkey){
2426 $return['error'] = $softaculous_lang['invalid_auth_key'];
2427 echo wp_json_encode($return);
2428 die();
2429 }
2430
2431 $allowed_ips = softaculous_get_allowed_ips();
2432 $remote_ip = softaculous_getip();
2433
2434 // We allow requests from allowed panels only
2435 if(!in_array($remote_ip, $allowed_ips)){
2436 // The static allowed IPs did not match. As a fallback resolve the IP for
2437 // the Softaculous panel hostname (cached for 1 hour) and accept the
2438 // request if it matches. This avoids the user having to manually update
2439 // their plugin whenever cloud.softaculous.com's IP changes.
2440 $panel_host_ips = softaculous_get_panel_host_ips();
2441
2442 if(empty($panel_host_ips) || !in_array($remote_ip, $panel_host_ips, true)){
2443 $return['error'] = 'Unauthorized Access from an unknown IP '.esc_html($remote_ip).'. Allowed IPs - '.esc_html(implode(',', $allowed_ips)).'!!';
2444 echo wp_json_encode($return);
2445 die();
2446 }
2447 }
2448 }
2449
2450 /**
2451 * Resolve and cache the IP address of the Softaculous panel hostname.
2452 *
2453 * The DNS lookup is cached in the WordPress options table for 1 hour so that
2454 * the plugin does not need to perform a DNS query on every request. The cache
2455 * is only refreshed when it is older than 1 hour or when no cache exists yet.
2456 *
2457 * @since 2.3.9
2458 * @return array List of resolved IPs for the panel hostname (empty array on failure).
2459 */
2460 function softaculous_get_panel_host_ips(){
2461
2462 $cached_ips = get_option('softaculous_panel_host_ips');
2463 $cached_time = get_option('softaculous_panel_host_ips_time');
2464
2465 // Use the fresh cache if available (less than 1 hour old)
2466 if(!empty($cached_ips) && !empty($cached_time) && ((time() - (int) $cached_time) < 3600)){
2467 return is_array($cached_ips) ? array_values($cached_ips) : array($cached_ips);
2468 }
2469
2470 // Resolve the IP for the panel hostname
2471 $resolved_ip = '';
2472 if(function_exists('gethostbyname')){
2473 $resolved_ip = gethostbyname(SOFTACULOUS_PANEL);
2474 }
2475
2476 // gethostbyname() returns the hostname itself on failure
2477 if(empty($resolved_ip) || $resolved_ip === SOFTACULOUS_PANEL){
2478 // Fall back to the stale cache (if any) if resolution failed
2479 if(!empty($cached_ips)){
2480 return is_array($cached_ips) ? array_values($cached_ips) : array($cached_ips);
2481 }
2482 return array();
2483 }
2484
2485 $ips = array($resolved_ip);
2486
2487 update_option('softaculous_panel_host_ips', $ips, false);
2488 update_option('softaculous_panel_host_ips_time', time(), false);
2489
2490 return $ips;
2491
2492 }
2493
2494 // Gets the list of allowed IPs
2495 function softaculous_get_allowed_ips(){
2496
2497 $ips = get_option('softaculous_allowed_ips');
2498
2499 if(empty($ips)){
2500 update_option('softaculous_allowed_ips', array(SOFTACULOUS_PANEL_IP));
2501 $ips = get_option('softaculous_allowed_ips');
2502 }
2503
2504 foreach($ips as $k => $ip){
2505 if(empty($ip)){
2506 unset($ips[$k]);
2507 }
2508 }
2509
2510 return $ips;
2511
2512 }
2513
2514 /**
2515 * Update the database if the website is added in Softaculous panel
2516 *
2517 * @returns bool
2518 * @since 1.1
2519 */
2520 function softaculous_connectok(){
2521 $connected = softaculous_get_option('softaculous_connected');
2522
2523 if(empty($connected)){
2524 update_option('softaculous_connected', '1', true);
2525 }
2526
2527 return true;
2528 }
2529
2530 /**
2531 * Deactivate Softaculous plugin and delete the database entries if the website is removed in Softaculous panel
2532 *
2533 * @returns bool
2534 * @since 1.1
2535 */
2536 function softaculous_self_deactivate(){
2537
2538 softaculous_deactivate_plugin(array(SOFTACULOUS_BASE));
2539 softaculous_deactivate();
2540
2541 return true;
2542 }
2543
2544 /**
2545 * Test if we are able to create a directory
2546 *
2547 * @returns bool
2548 * @since 1.4
2549 */
2550 function softaculous_test_createdir($path){
2551
2552 softaculous_mkdir($path);
2553
2554 if(softaculous_is_dir($path)){
2555 return true;
2556 }
2557
2558 return true;
2559 }
2560
2561 /**
2562 * Softaculous action handler when we need to LOGIN and then redirect
2563 *
2564 * @since 1.0
2565 */
2566 function softaculous_login_and_act(){
2567 global $softaculous_lang, $softaculous_error;
2568
2569 // Authorize with a TEMP KEY or DIE !
2570 softaculous_signonkey_authorization();
2571
2572 // At this point we are authorized and we can login
2573 softaculous_signon();
2574
2575 //Execute the Request
2576 $softaculous_act = softaculous_optREQ('wpc_act');
2577
2578 switch($softaculous_act){
2579
2580 // Edit or Preview Post
2581 case 'edit_post':
2582 case 'preview_post':
2583 softaculous_post_redirect($softaculous_act);
2584 break;
2585
2586 // Default case to login
2587 default:
2588 case '':
2589 $redirect_to = user_admin_url();
2590 wp_safe_redirect($redirect_to);
2591 exit();
2592 break;
2593 }
2594
2595 }
2596
2597 /**
2598 * Softaculous action handler
2599 *
2600 * @since 1.0
2601 */
2602 function softaculous_actions_init(){
2603 global $softaculous_lang, $softaculous_error, $softaculous_wp_config;
2604
2605 //Authorize
2606 softaculous_authorize();
2607
2608 //Fetch WP Configuration details
2609 $softaculous_wp_config = softaculous_fetch_wp_config();
2610
2611 //Execute the Request
2612 $softaculous_act = softaculous_optREQ('wpc_act');
2613
2614 switch($softaculous_act){
2615
2616 case 'verifyconnect':
2617 include_once('verify.php');
2618 softaculous_verify();
2619 break;
2620
2621 case 'wpcdeactivate':
2622 softaculous_self_deactivate();
2623 break;
2624
2625 case 'getsitedata':
2626 include_once('get_site_data.php');
2627 softaculous_get_site_data();
2628 break;
2629
2630 case 'siteactions':
2631 include_once('actions.php');
2632 softaculous_site_actions();
2633 break;
2634
2635 case 'fileactions':
2636 include_once('file_actions.php');
2637 softaculous_file_actions();
2638 break;
2639
2640 case 'connectok':
2641 softaculous_connectok();
2642 break;
2643
2644 case 'can_createdir':
2645 softaculous_can_createdir();
2646 break;
2647
2648 case 'wpcentral_version':
2649 softaculous_fetch_version();
2650 break;
2651
2652 case 'getsignonkey':
2653 softaculous_getsignonkey();
2654 break;
2655
2656 //The DEFAULT Page
2657 default:
2658 // Nothing to do
2659 break;
2660 }
2661 }
2662
2663 /**
2664 * Directs to the edit/preview post page of the specified post
2665 *
2666 * @since 1.4.6
2667 */
2668 function softaculous_post_redirect($post_act){
2669 global $softaculous_lang, $softaculous_error;
2670
2671 $post_id = softaculous_optREQ('post_id');
2672
2673 if($post_act == 'edit_post'){
2674 $redirect_to = get_edit_post_link($post_id, '');
2675
2676 }elseif($post_act == 'preview_post'){
2677 $redirect_to = get_preview_post_link($post_id);
2678 }
2679
2680 wp_safe_redirect($redirect_to);
2681
2682 exit();
2683 }
2684
2685 /**
2686 * Check if we have the permission to create a directory on the user server
2687 *
2688 * @returns bool
2689 * @since 1.4.1
2690 */
2691 function softaculous_can_createdir($path = ''){
2692 global $softaculous_wp_config;
2693
2694 if(empty($path)){
2695 $path = $softaculous_wp_config['plugins_root_dir'].'/softaculous/'.softaculous_optREQ('testpath');
2696 }
2697
2698 if(softaculous_is_dir($path)){
2699 $path = $softaculous_wp_config['plugins_root_dir'].'/softaculous/'.softaculous_srandstr(16);
2700 }
2701
2702 softaculous_mkdir($path, 0700, 1);
2703
2704 $resp = 0;
2705 if(softaculous_is_dir($path)){
2706 $resp = 1;
2707 }
2708
2709 @rmdir($path);
2710
2711 if(isset($_GET['testpath'])){
2712 $return = array();
2713 $return['can_create'] = $resp;
2714
2715 echo wp_json_encode($return);
2716 }
2717
2718 return $resp;
2719 }
2720
2721 /**
2722 * Fetch the installed version of softaculous plugin in the website
2723 *
2724 * @returns string softaculous version number
2725 * @since 1.4.3
2726 */
2727 function softaculous_fetch_version(){
2728 global $softaculous_wp_config;
2729
2730 $plugin_data = softaculous_get_plugin_data($softaculous_wp_config['plugins_root_dir'].'/softaculous/softaculous.php');
2731
2732 $softaculous_version = $plugin_data['Version'];
2733
2734 if(isset($_GET['callfetch'])){
2735 $return = array();
2736 $return['wpc_ver'] = $softaculous_version;
2737
2738 echo wp_json_encode($return);
2739 }
2740
2741 return $softaculous_version;
2742 }
2743
2744 /**
2745 * Provides access to the website's admin panel
2746 *
2747 * @returns bool
2748 * @since 1.0
2749 */
2750 function softaculous_signon(){
2751
2752 global $softaculous_lang, $softaculous_error;
2753
2754 // Query the users
2755 $users_query = new WP_User_Query( array(
2756 'role' => 'administrator',
2757 'orderby' => 'ID',
2758 'number' => 1
2759 ) );
2760
2761 // Get the results and the row
2762 $results = $users_query->get_results();
2763 $tmp = current($results);
2764
2765 $user_info = get_userdata($tmp->ID);
2766
2767 // Automatic login //
2768 $username = $user_info->user_login;
2769 $user = get_user_by('login', $username );
2770
2771 // Redirect URL //
2772 if (!is_wp_error($user)){
2773 wp_clear_auth_cookie();
2774 wp_set_current_user($user->ID);
2775 wp_set_auth_cookie($user->ID);
2776 }
2777 }
2778
2779 /**
2780 * Return the role of the current user.
2781 *
2782 * @since 1.1
2783 */
2784 function softaculous_get_curr_user_role(){
2785 return wp_get_current_user()->roles[0];
2786 }
2787
2788 /**
2789 * Dismiss Softaculous notice and save the dismiss date.
2790 *
2791 * @since 1.4.3
2792 */
2793 function softaculous_dismiss_notice(){
2794
2795 if(!isset($_POST['softaculous_security']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['softaculous_security'])), 'softaculous_js_nonce')){
2796 wp_send_json_error('Security Check Failed!');
2797 }
2798
2799 $soft_dismissable_notice_date = get_option('softaculous_dismiss_notice_date');
2800
2801 if(empty($soft_dismissable_notice_date)){
2802 add_option('softaculous_dismiss_notice_date', date('Y-m-d'));
2803 }else{
2804 update_option('softaculous_dismiss_notice_date', date('Y-m-d'));
2805 }
2806
2807 }
2808
2809 /**
2810 * Display Softaculous notice on the basis of last dismiss date. When user manually dismisses the notice, it remains for 1 month
2811 *
2812 * @since 1.4.3
2813 */
2814 function softaculous_is_display_notice(){
2815
2816 $soft_dismissable_notice_date = get_option('softaculous_dismiss_notice_date');
2817
2818 if(empty($soft_dismissable_notice_date)){
2819 return true;
2820 }
2821
2822 $soft_dismissable_notice_date2 = new DateTime($soft_dismissable_notice_date);
2823 $current_date = new DateTime(date('Y-m-d'));
2824 $date_diff_month = $soft_dismissable_notice_date2->diff($current_date);
2825
2826 //Do not display notice again for a month
2827 if($date_diff_month->m < 1){
2828 return false;
2829 }
2830
2831 return true;
2832 }
2833 /**
2834 * Display Softaculous notice in dashboard
2835 *
2836 * @since 1.0
2837 */
2838 function softaculous_admin_notice($force = 0){
2839
2840 if(!empty($_GET['page']) && $_GET['page'] == 'softaculous' && empty($force)){
2841 return '';
2842 }
2843
2844 $role = softaculous_get_curr_user_role();
2845
2846 if($role == 'administrator' && !softaculous_get_option('softaculous_connected')){
2847
2848 echo '<div class="soft_notice notice notice-success my-soft-dismiss-notice is-dismissible" style="padding-bottom:10px;">
2849 <div style="width:100%; padding-top:10px;">
2850 <table cellpadding="1" cellspacing="5">
2851 <tr>
2852 <td colspan="3" class="soft_sitehead">
2853 <span class="">Connect your site with Softaculous Cloud panel for easy management</span>
2854 </td>
2855 </tr>
2856 <tr>
2857 <td style="padding: 0 10px;">
2858 <img src="'.esc_attr(SOFTACULOUS_PLUGIN_URL) .'assets/images/logo.gif" alt="softaculous" title="softaculous" style="height:50px; padding:5px 0;">
2859 </td>
2860 <td>
2861 <table cellpadding="1" cellspacing="5">
2862 <tr>
2863 <td><b>Website URL</b></td>
2864 <td><span class="soft_siteurl">'.esc_html(get_option('siteurl')).'</span></td>
2865 </tr>
2866 <tr>
2867 <td><b>Softaculous Connection Key</b></td>
2868 <td><span class="soft_siteurl">'.esc_html(softaculous_get_connection_key()).'</span></td>
2869 </tr>
2870 <tr>
2871 <td colspan="2">
2872 <p style="display:inline-block; padding-right:20px; font-size:13px;"><a class="soft_button soft_button1" href="'.esc_attr(softaculous_get_addsite_link()).'" target="_blank">1-Click Connect</a></p>
2873
2874 <p style="display:inline-block; padding:0 10px; font-size:13px;"><a class="soft_button soft_button3" href="https://www.softaculous.com/docs/wordpress-plugin/1-click-website-connection/" target="_blank" style="padding: 6px 12px; font-size:14px;">1-Click Connection Guide</a></p>
2875
2876 <p style="display:inline-block; padding-right:20px; font-size:13px;"><a class="soft_button soft_button3" href="https://www.softaculous.com/docs/wordpress-plugin/adding-website-in-panel/" target="_blank" style="padding: 6px 12px; font-size:14px;">Connect Website Guide</a></p>
2877
2878 <p style="display:inline-block; padding:0 10px; font-size:13px;"><a class="soft_button soft_button4" href="mailto:support@softaculous.com" target="_blank" style="padding: 6px 12px; font-size:14px;">Contact Us</a></p>
2879
2880 <p style="display:inline-block; padding-right:20px; font-size:13px;"><a class="soft_button soft_button4" href="https://www.softaculous.com/" target="_blank" style="padding: 6px 12px; font-size:14px;">Visit Website</a></p>
2881 </td>
2882 </tr>
2883 </table>
2884 </td>
2885 </tr>
2886 </table>
2887
2888 <div style="text-align: left;">
2889 </div>
2890 </div>
2891 </div>';
2892 }
2893 }
2894
2895 /* Removes a Directory Recursively
2896 *
2897 * @param string $path The path of the folder to be removed
2898 * @return boolean
2899 * @since 1.4.3
2900 */
2901 function softaculous_rmdir_recursive($path){
2902 if(!softaculous_is_safe_file($path)) return false;
2903
2904 $path = (substr($path, -1) == '/' || substr($path, -1) == '\\' ? $path : $path.'/');
2905
2906 softaculous_resetfilelist();
2907
2908 $files = softaculous_filelist($path, 1, 0, 'all');
2909 $files = (!is_array($files) ? array() : $files);
2910
2911 //First delete the files only
2912 foreach($files as $k => $v){
2913 if(softaculous_is_safe_file($k)){
2914 @chmod($k, 0777);
2915 }
2916 if(file_exists($k) && is_file($k) && @filetype($k) == "file"){
2917 @unlink($k);
2918 }
2919 }
2920
2921 @clearstatcache();
2922
2923 $folders = softaculous_filelist($path, 1, 1, 'all');
2924 $folders = (!is_array($folders) ? array() : $folders);
2925 @krsort($folders);
2926
2927 //Now Delete the FOLDERS
2928 foreach($folders as $k => $v){
2929 if(softaculous_is_safe_file($k)){
2930 @chmod($k, 0777);
2931 }
2932 if(is_dir($k)){
2933 @rmdir($k);
2934 }
2935 }
2936
2937 @rmdir($path);
2938
2939 @clearstatcache();
2940
2941 return true;
2942 }
2943
2944 /* A Function that reset lists files
2945 *
2946 * @since 1.4.3
2947 */
2948 function softaculous_resetfilelist(){
2949 global $softaculous_directorylist;
2950 $softaculous_directorylist = array();
2951 }
2952
2953 /* Ratings Notice HTML
2954 *
2955 * @since 1.4.4
2956 */
2957 function softaculous_show_promo(){
2958 global $softaculous_promo_opts;
2959 $opts = $softaculous_promo_opts;
2960
2961 echo '<div class="notice notice-success" id="soft_promo" style="min-height:90px">
2962 <a class="soft_promo-close" href="javascript:" aria-label="Dismiss this Notice">
2963 <span class="dashicons dashicons-dismiss"></span> Dismiss
2964 </a>';
2965
2966 if(!empty($opts['image'])){
2967 echo '<a href="'.esc_attr($opts['website']).'"><img src="'.esc_attr($opts['image']).'" style="float:left; margin:15px 20px 10px 10px" width="150" /></a>';
2968 }
2969
2970 echo '
2971 <p style="font-size:13px">We are glad you like <a href="'.esc_attr($opts['website']).'"><b>Softaculous</b></a> and have been using it since the past few days. It is time to take the next step !</p>
2972 <p>
2973 '.(empty($opts['rating']) ? '' : '<a class="soft_promo_button soft_promo_button2" target="_blank" href="'.esc_attr($opts['rating']).'">Rate it 5�
2974 \'s</a>').'
2975 '.(empty($opts['facebook']) ? '' : '<a class="soft_promo_button soft_promo_button3" target="_blank" href="'.esc_attr($opts['facebook']).'"><span class="dashicons dashicons-thumbs-up"></span> Facebook</a>').'
2976 '.(empty($opts['twitter']) ? '' : '<a class="soft_promo_button soft_promo_button4" target="_blank" href="'.esc_attr($opts['twitter']).'"><span class="dashicons dashicons-twitter"></span> Tweet</a>').'
2977 '.(empty($opts['website']) ? '' : '<a class="soft_promo_button soft_promo_button4" target="_blank" href="'.esc_attr($opts['website']).'">Visit our website</a>').'
2978 '.(empty($opts['support']) ? '' : '<a class="soft_promo_button soft_promo_button4" target="_blank" href="'.esc_attr($opts['support']).'">Softaculous Support</a>').'
2979 </p>
2980 </div>';
2981 }
2982
2983 /* Show Ratings Notice
2984 *
2985 * @since 1.4.4
2986 */
2987 function softaculous_maybe_promo($opts){
2988
2989 global $softaculous_promo_opts;
2990
2991 // There must be an interval after which the notice will appear again
2992 if(empty($opts['interval'])){
2993 return false;
2994 }
2995
2996 // Are we to show a promo
2997 $opt_name = 'softaculous_promo_time';
2998 $promo_time = softaculous_get_option($opt_name);
2999
3000 //Check if it is connected to Softaculous panel
3001 $connected = softaculous_get_option('softaculous_connected');
3002
3003 //Display only if the website is connected to Softaculous panel and a day has passed since the connection or 3 months have passed since the last dismissal
3004 if(!empty($connected)){
3005 if(empty($promo_time)){
3006 update_option($opt_name, time() + (!empty($opts['after']) ? $opts['after'] * 86400 : 0));
3007 $promo_time = softaculous_get_option($opt_name);
3008 }
3009
3010 // Is there interval elapsed
3011 if(time() > $promo_time){
3012 $softaculous_promo_opts = $opts;
3013 add_action('admin_notices', 'softaculous_show_promo');
3014 }
3015 }
3016
3017 // Are we to disable the promo
3018
3019
3020 if(isset($_GET['softaculous_promo']) && (int)$_GET['softaculous_promo'] == 0 && isset($_POST['softaculous_security']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['softaculous_security'])), 'softaculous_js_nonce')){
3021 update_option($opt_name, time() + ($opts['interval'] * 86400));
3022 die('DONE');
3023 }
3024 }
3025
3026 // Update check
3027 function softaculous_update_check(){
3028
3029 $current_version = get_option('softaculous_version');
3030 $version = (int) str_replace('.', '', $current_version);
3031
3032 if($current_version == SOFTACULOUS_VERSION){
3033 return true;
3034 }
3035
3036 if(version_compare($current_version, '2.2.7', '<')){
3037
3038 $softaculous_allowed_ips = get_option('softaculous_allowed_ips', array());
3039
3040 // Softaculous Cloud IP needs to be updated in allowed list
3041 foreach($softaculous_allowed_ips as $sk => $soft_ip){
3042 if(trim($soft_ip) == '138.201.40.162'){
3043 $softaculous_allowed_ips[$sk] = SOFTACULOUS_PANEL_IP;
3044 update_option('softaculous_allowed_ips', $softaculous_allowed_ips);
3045 break;
3046 }
3047 }
3048 }
3049
3050 if(version_compare($current_version, '2.3.9', '<')){
3051
3052 $softaculous_allowed_ips = get_option('softaculous_allowed_ips', array());
3053
3054 // Softaculous Cloud IP needs to be updated in allowed list
3055 foreach($softaculous_allowed_ips as $sk => $soft_ip){
3056 if(trim($soft_ip) == '15.204.134.15'){
3057 $softaculous_allowed_ips[$sk] = SOFTACULOUS_PANEL_IP;
3058 update_option('softaculous_allowed_ips', $softaculous_allowed_ips);
3059 break;
3060 }
3061 }
3062 }
3063
3064 // Save the new Version
3065 update_option('softaculous_version', SOFTACULOUS_VERSION);
3066 }
3067
3068 function softaculous_reset_conn_key(){
3069 $return['conn_key'] = softaculous_get_connection_key(1);
3070 delete_option('softaculous_connected');
3071 return $return;
3072 }
3073
3074
3075 /**
3076 * Generate validation key to allow user to sign in
3077 *
3078 * @returns bool
3079 * @since 1.1
3080 */
3081 function softaculous_getsignonkey(){
3082
3083 $signon_key = softaculous_srandstr(64);
3084 update_option('softaculous_signonkey', $signon_key);
3085 update_option('softaculous_signonkey_time', time());
3086
3087 if(isset($_GET['get_wpcsignonkey'])){
3088 $return = array();
3089 $return['softaculous_signonkey'] = $signon_key;
3090 echo wp_json_encode($return);
3091 }
3092
3093 return $signon_key;
3094 }
3095
3096 /**
3097 * Check for the authorization of the request using the temporary validation key
3098 *
3099 * @returns bool
3100 * @since 1.0
3101 */
3102 function softaculous_signonkey_authorization(){
3103 global $softaculous_lang, $softaculous_error;
3104
3105 $return = array();
3106
3107 $validate_key = softaculous_optREQ('softaculous_signonkey');
3108 if(empty($validate_key)){
3109 $return['error'] = 'Unauthorized Access!!';
3110 echo wp_json_encode($return);
3111 die();
3112 }
3113
3114 $verify_authkey = softaculous_get_option('softaculous_signonkey');
3115 if($validate_key !== $verify_authkey){
3116 $return['error'] = $softaculous_lang['invalid_signon_key'];
3117 echo wp_json_encode($return);
3118 die();
3119 }
3120
3121 // Is the key within 5 minutes of creation ?
3122 if((time() - softaculous_get_option('softaculous_signonkey_time')) > 300){
3123 $return['error'] = 'The Authorization Key has expired';
3124 echo wp_json_encode($return);
3125 die();
3126 }
3127
3128 delete_option('softaculous_signonkey');
3129 delete_option('softaculous_signonkey_time');
3130
3131 }
3132
3133 function softaculous_sort_uname_callback( $a, $b ) {
3134 return strnatcasecmp( $a['Name'], $b['Name'] );
3135 }
3136
3137 // Validates an IP
3138 function softaculous_valid_ip($ip){
3139 if(!preg_match('/^(\d){1,3}\.(\d){1,3}\.(\d){1,3}\.(\d){1,3}$/is', $ip) || substr_count($ip, '.') != 3){
3140 return false;
3141 }
3142
3143 $r = explode('.', $ip);
3144
3145 foreach($r as $v){
3146 $v = (int) $v;
3147 if($v > 255 || $v < 0){
3148 return false;
3149 }
3150 }
3151
3152 return true;
3153
3154 }
3155
3156 // get add site link
3157 function softaculous_get_addsite_link(){
3158 return SOFTACULOUS_ADDSITE.'&siteurl='.get_option('siteurl').'&conn_key='.softaculous_get_connection_key();
3159 }