Advertisement
Guest User

Untitled

a guest
Jan 28th, 2017
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 31.45 KB | None | 0 0
  1. <?php
  2. /**
  3. * Plugin Uploader 1.2.1
  4.  
  5. * Copyright 2016 Matthew Rogowski
  6.  
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10.  
  11. ** http://www.apache.org/licenses/LICENSE-2.0
  12.  
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. **/
  19.  
  20. if(!defined("IN_MYBB"))
  21. {
  22. header("HTTP/1.0 404 Not Found");
  23. exit;
  24. }
  25.  
  26. define('PLUGINUPLOADER_VERSION', '1.2.1');
  27.  
  28. $plugins->add_hook("admin_config_plugins_activate_commit", "pluginuploader_admin_config_plugins_activate_commit");
  29. $plugins->add_hook("admin_config_permissions", "pluginuploader_admin_config_permissions");
  30. $plugins->add_hook("admin_config_plugins_tabs", "pluginuploader_add_pluginuploader_tab");
  31. $plugins->add_hook("admin_page_output_nav_tabs_start", "pluginuploader_add_pluginuploader_tab");
  32. $plugins->add_hook("admin_config_plugins_begin", "pluginuploader_admin_config_plugins_begin");
  33. $plugins->add_hook("admin_config_plugins_plugin_list", "pluginuploader_admin_config_plugins_plugin_list");
  34. $plugins->add_hook("admin_config_plugins_begin", "pluginuploader_admin_config_plugins_check_browse");
  35. $plugins->add_hook("admin_page_output_footer", "pluginuploader_admin_page_output_footer");
  36.  
  37. function pluginuploader_info()
  38. {
  39. return array(
  40. 'name' => 'Plugin Uploader',
  41. 'description' => 'Allows you to import .zip plugin archives directly and have the files extracted to their correct locations automatically.',
  42. 'website' => 'https://github.com/MattRogowski/Plugin-Uploader',
  43. 'author' => 'Matt Rogowski',
  44. 'authorsite' => 'https://matt.rogow.ski',
  45. 'version' => PLUGINUPLOADER_VERSION,
  46. 'compatibility' => '18*',
  47. 'codename' => 'pluginuploader'
  48. );
  49. }
  50.  
  51. function pluginuploader_install()
  52. {
  53. global $db, $plugins, $pluginuploader_uninstall_confirm_override;
  54.  
  55. // this is so we override the confirmation when trying to uninstall, so we can just run the uninstall code
  56. $pluginuploader_uninstall_confirm_override = true;
  57. pluginuploader_uninstall();
  58.  
  59. if(!$db->table_exists("pluginuploader"))
  60. {
  61. $db->write_query("
  62. CREATE TABLE " . TABLE_PREFIX . "pluginuploader (
  63. `pid` SMALLINT(5) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
  64. `name` VARCHAR(255) NOT NULL UNIQUE KEY,
  65. `version` VARCHAR(25) NOT NULL ,
  66. `files` TEXT NOT NULL
  67. ) ENGINE = MYISAM ;
  68. ");
  69. }
  70.  
  71. if(!$db->field_exists("pluginuploader_key", "users"))
  72. {
  73. $db->add_column("users", "pluginuploader_key", "VARCHAR(120)");
  74. }
  75.  
  76. chdir(MYBB_ROOT . "inc/plugins/");
  77. $plugin_files = glob("*.php");
  78.  
  79. if(!empty($plugin_files))
  80. {
  81. foreach($plugin_files as $plugin_file)
  82. {
  83. $plugin_name = substr($plugin_file, 0, -4);
  84. $info_func = $plugin_name . "_info";
  85.  
  86. if(!function_exists($info_func))
  87. {
  88. require_once MYBB_ROOT . "inc/plugins/" . $plugin_file;
  89. }
  90. if(!function_exists($info_func))
  91. {
  92. continue;
  93. }
  94.  
  95. $info = $info_func();
  96.  
  97. $insert = array(
  98. "name" => $db->escape_string($plugin_name),
  99. "version" => $db->escape_string($info['version'])
  100. );
  101. $db->insert_query("pluginuploader", $insert);
  102. }
  103. }
  104.  
  105. change_admin_permission("config", "pluginuploader", 0);
  106. }
  107.  
  108. function pluginuploader_is_installed()
  109. {
  110. global $db;
  111.  
  112. return $db->table_exists("pluginuploader");
  113. }
  114.  
  115. function pluginuploader_uninstall()
  116. {
  117. global $mybb, $db, $lang, $page, $pluginuploader_uninstall_confirm_override;
  118.  
  119. $lang->load("config_pluginuploader");
  120.  
  121. if($mybb->request_method == "post" || $pluginuploader_uninstall_confirm_override === true)
  122. {
  123. if(!$pluginuploader_uninstall_confirm_override)
  124. {
  125. $query = $db->simple_select("pluginuploader", "version AS salt, files AS password", "name = '_password'");
  126. $password = $db->fetch_array($query);
  127.  
  128. if(md5(md5($mybb->input['password']) . md5($password['salt'])) != $password['password'])
  129. {
  130. flash_message($lang->pluginuploader_uninstall_password_incorrect, 'error');
  131. admin_redirect("index.php?module=config-plugins&action=deactivate&uninstall=1&plugin=pluginuploader&my_post_key={$mybb->post_code}");
  132. }
  133. }
  134.  
  135. if($db->table_exists("pluginuploader"))
  136. {
  137. $db->drop_table("pluginuploader");
  138. }
  139.  
  140. if($db->field_exists("pluginuploader_key", "users"))
  141. {
  142. $db->drop_column("users", "pluginuploader_key");
  143. }
  144. }
  145. else
  146. {
  147. $page->output_header($lang->pluginuploader);
  148.  
  149. $form = new Form("index.php?module=config-plugins&action=deactivate&uninstall=1&plugin=pluginuploader", "post");
  150. $form_container = new FormContainer($lang->pluginuploader_uninstall_message_title);
  151.  
  152. $form_container->output_row("", "", $lang->pluginuploader_uninstall_warning);
  153. $form_container->output_row($lang->pluginuploader_password . " <em>*</em>", $lang->pluginuploader_password_desc, $form->generate_password_box("password"));
  154. $form_container->end();
  155.  
  156. $buttons[] = $form->generate_submit_button($lang->submit);
  157. $form->output_submit_wrapper($buttons);
  158. $form->end();
  159.  
  160. $page->output_footer();
  161. exit;
  162. }
  163. }
  164.  
  165. function pluginuploader_activate()
  166. {
  167.  
  168. }
  169.  
  170. function pluginuploader_deactivate()
  171. {
  172. my_unsetcookie("mybb_pluginuploader_key");
  173. }
  174.  
  175. function pluginuploader_admin_config_plugins_activate_commit()
  176. {
  177. global $codename, $install_uninstall;
  178.  
  179. if($codename == "pluginuploader" && $install_uninstall)
  180. {
  181. admin_redirect("index.php?module=config-plugins&action=pluginuploader");
  182. }
  183. }
  184.  
  185. function pluginuploader_admin_config_permissions($admin_permissions)
  186. {
  187. global $lang;
  188.  
  189. $lang->load("config_pluginuploader");
  190.  
  191. $admin_permissions['pluginuploader'] = $lang->can_upload_plugins;
  192.  
  193. return $admin_permissions;
  194. }
  195.  
  196. function pluginuploader_add_pluginuploader_tab(&$tabs)
  197. {
  198. global $lang;
  199.  
  200. $lang->load("config_pluginuploader");
  201.  
  202. if(array_key_exists("plugins", $tabs) && array_key_exists("update_plugins", $tabs) && array_key_exists("browse_plugins", $tabs) && !array_key_exists("upload_plugin", $tabs))
  203. {
  204. $tabs['upload_plugin'] = array(
  205. 'title' => $lang->pluginuploader_upload_plugin,
  206. 'link' => "index.php?module=config-plugins&action=pluginuploader",
  207. 'description' => $lang->pluginuploader_upload_plugin_desc
  208. );
  209. }
  210. }
  211.  
  212. function pluginuploader_admin_config_plugins_begin()
  213. {
  214. global $mybb, $db, $cache, $lang, $plugins, $page, $pluginuploader;
  215.  
  216. $lang->load("config_pluginuploader");
  217.  
  218. if($mybb->input['action'] == "pluginuploader")
  219. {
  220. check_admin_permissions(array("module" => "config", "action" => "pluginuploader"));
  221.  
  222. require_once MYBB_ADMIN_DIR . "modules/config/pluginuploader.php";
  223. }
  224. elseif($mybb->input['action'] == "do_delete")
  225. {
  226. check_admin_permissions(array("module" => "config", "action" => "pluginuploader"));
  227.  
  228. if(!verify_post_check($mybb->input['my_post_key']))
  229. {
  230. flash_message($lang->invalid_post_verify_key2, 'error');
  231. admin_redirect("index.php?module=config-plugins");
  232. }
  233.  
  234. if($mybb->input['no'])
  235. {
  236. admin_redirect("index.php?module=config-plugins");
  237. }
  238.  
  239. $plugin_name = $mybb->input['plugin'];
  240. if($plugin_name)
  241. {
  242. $query = $db->simple_select("pluginuploader", "files", "name = '" . $db->escape_string($plugin_name) . "'");
  243. if($db->num_rows($query) == 1 || file_exists(MYBB_ROOT . "inc/plugins/" . $plugin_name . ".php"))
  244. {
  245. $info_func = $plugin_name . "_info";
  246. $deactivate_func = $plugin_name . "_deactivate";
  247. $uninstall_func = $plugin_name . "_uninstall";
  248. if(!function_exists($info_func))
  249. {
  250. // plugin isn't currently active, otherwise the info function would be available, but include it anyway to check for an uninstall function
  251. require_once MYBB_ROOT . "inc/plugins/" . $plugin_name . ".php";
  252. }
  253.  
  254. if(function_exists($deactivate_func))
  255. {
  256. $deactivate_func();
  257. }
  258. if(function_exists($uninstall_func))
  259. {
  260. $uninstall_func();
  261. }
  262. $plugins_cache = $cache->read("plugins");
  263. $active_plugins = $plugins_cache['active'];
  264. unset($active_plugins[$plugin_name]);
  265. $plugins_cache['active'] = $active_plugins;
  266. $cache->update("plugins", $plugins_cache);
  267.  
  268. $errors = array();
  269. if($db->num_rows($query) == 1)
  270. {
  271. $files = $db->fetch_field($query, "files");
  272. $files = unserialize($files);
  273. foreach($files as $file)
  274. {
  275. $file = $pluginuploader->replace_admin_dir($file);
  276. if(@is_dir(MYBB_ROOT . $file))
  277. {
  278. @$pluginuploader->rmdir(MYBB_ROOT . $file);
  279. if(@is_dir(MYBB_ROOT . $file))
  280. {
  281. $errors[] = "./" . $file;
  282. }
  283. }
  284. else
  285. {
  286. if(@file_exists(MYBB_ROOT . $file))
  287. {
  288. @$pluginuploader->unlink(MYBB_ROOT . $file);
  289. if(@file_exists(MYBB_ROOT . $file))
  290. {
  291. $errors[] = "./" . $file;
  292. }
  293. }
  294. }
  295. }
  296. }
  297. elseif(@file_exists(MYBB_ROOT . "inc/plugins/" . $plugin_name . ".php"))
  298. {
  299. if(!@$pluginuploader->unlink(MYBB_ROOT . "inc/plugins/" . $plugin_name . ".php"))
  300. {
  301. $errors[] = "./inc/plugins/" . $plugin_name . ".php";
  302. }
  303. }
  304.  
  305. if(!empty($errors))
  306. {
  307. $errors = "<li>" . str_replace("MYBB_ADMIN_DIR", $mybb->config['admin_dir'], implode("</li><li>", $errors)) . "</li>";
  308. flash_message($lang->sprintf($lang->pluginuploader_delete_errors, $errors), 'error');
  309. admin_redirect("index.php?module=config-plugins");
  310. }
  311. else
  312. {
  313. $db->delete_query("pluginuploader", "name = '" . $db->escape_string($plugin_name) . "'");
  314. flash_message($lang->pluginuploader_delete_success, 'success');
  315. admin_redirect("index.php?module=config-plugins");
  316. }
  317. }
  318. else
  319. {
  320. flash_message($lang->pluginuploader_delete_invalid_plugin, 'error');
  321. admin_redirect("index.php?module=config-plugins");
  322. }
  323. }
  324. else
  325. {
  326. flash_message($lang->pluginuploader_delete_invalid_plugin, 'error');
  327. admin_redirect("index.php?module=config-plugins");
  328. }
  329. }
  330. elseif($mybb->input['action'] == "delete")
  331. {
  332. check_admin_permissions(array("module" => "config", "action" => "pluginuploader"));
  333.  
  334. $lang->load("config_pluginuploader");
  335.  
  336. $plugin = $mybb->input['plugin'];
  337. $delete_message = "";
  338.  
  339. $query = $db->simple_select("pluginuploader", "files", "name = '" . $db->escape_string($plugin) . "'");
  340. if($db->num_rows($query) == 1)
  341. {
  342. $files = $db->fetch_field($query, "files");
  343. if(!empty($files))
  344. {
  345. $files = unserialize($files);
  346. foreach($files as &$file)
  347. {
  348. $file = $pluginuploader->replace_admin_dir($file);
  349. $file = "./" . $file;
  350. if(is_dir(MYBB_ROOT . $file))
  351. {
  352. $file .= "/";
  353. }
  354. }
  355. $files = "<li>" . str_replace("MYBB_ADMIN_DIR", $mybb->config['admin_dir'], implode("</li><li>", $files)) . "</li>";
  356. $delete_message = $lang->sprintf($lang->pluginuploader_delete_warning, $files);
  357. }
  358. }
  359. if(!$delete_message)
  360. {
  361. $delete_message = $lang->pluginuploader_delete_warning_no_files;
  362. }
  363.  
  364. $page->output_confirm_action("index.php?module=config-plugins&action=do_delete&plugin=" . $mybb->input['plugin'] . "&my_post_key={$mybb->post_code}", $delete_message);
  365. }
  366. }
  367.  
  368. function pluginuploader_admin_config_plugins_plugin_list()
  369. {
  370. global $mybb, $lang, $plugins, $plugin_urls, $pluginuploader_js;
  371.  
  372. $plugins_list = get_plugins_list();
  373. $plugin_codenames = $info = array();
  374.  
  375. if($plugins_list)
  376. {
  377. $active_hooks = $plugins->hooks;
  378. foreach($plugins_list as $plugin_file)
  379. {
  380. require_once MYBB_ROOT."inc/plugins/".$plugin_file;
  381. $codename = str_replace(".php", "", $plugin_file);
  382. $plugin_codenames[] = $codename;
  383. $infofunc = $codename."_info";
  384. if(!function_exists($infofunc))
  385. {
  386. continue;
  387. }
  388. $plugininfo = $infofunc();
  389. $plugininfo['guid'] = trim($plugininfo['guid']);
  390. $plugininfo['codename'] = trim($plugininfo['codename']);
  391.  
  392. if($plugininfo['codename'] != "")
  393. {
  394. $info[] = $plugininfo['codename'];
  395. $names[$plugininfo['codename']] = array('name' => $plugininfo['name'], 'version' => $plugininfo['version']);
  396. }
  397. elseif($plugininfo['guid'] != "")
  398. {
  399. $info[] = $plugininfo['guid'];
  400. $names[$plugininfo['guid']] = array('name' => $plugininfo['name'], 'version' => $plugininfo['version']);
  401. }
  402. }
  403. $plugins->hooks = $active_hooks;
  404. }
  405.  
  406. if(empty($info))
  407. {
  408. return;
  409. }
  410.  
  411. $url = "https://community.mybb.com/version_check.php?";
  412. $url .= http_build_query(array("info" => $info))."&";
  413. require_once MYBB_ROOT."inc/class_xml.php";
  414. $contents = fetch_remote_file($url);
  415.  
  416. if(!$contents)
  417. {
  418. return;
  419. }
  420.  
  421. $parser = new XMLParser($contents);
  422. $tree = $parser->get_tree();
  423.  
  424. if(!is_array($tree) || !isset($tree['plugins']) || array_key_exists('error', $tree['plugins']))
  425. {
  426. return;
  427. }
  428.  
  429. $lang->load("config_pluginuploader");
  430.  
  431. $plugins_info = $tree['plugins']['plugin'];
  432. $plugin_urls = array();
  433. if(!empty($plugins_info))
  434. {
  435. if(isset($plugins_info[0]))
  436. {
  437. foreach($plugins_info as $item)
  438. {
  439. $plugin_urls[$names[$item['attributes']['codename']]['name']] = array('codename' => $item['attributes']['codename'], 'url' => $item['download_url']['value'], 'version' => $item['version']['value']);
  440. }
  441. }
  442. else
  443. {
  444. $plugin_urls[$names[$plugins_info['attributes']['codename']]['name']] = array('codename' => $item['attributes']['codename'], 'url' => $plugins_info['download_url']['value'], 'version' => $item['version']['value']);
  445. }
  446. }
  447.  
  448. foreach($plugin_urls as $name => &$info)
  449. {
  450. $info['update_available'] = false;
  451. if(in_array($info['codename'], $plugin_codenames))
  452. {
  453. $infofunc = $info['codename']."_info";
  454. if(!function_exists($infofunc))
  455. {
  456. continue;
  457. }
  458. $plugininfo = $infofunc();
  459. if(version_compare($plugininfo['version'], $info['version']))
  460. {
  461. $info['update_available'] = true;
  462. }
  463. }
  464. }
  465.  
  466. $pluginuploader_js = '<script src="jscripts/pluginuploader.js?version='.PLUGINUPLOADER_VERSION.'"></script>';
  467. $pluginuploader_js .= '<script>
  468. var pluginuploader_section = \'list\';
  469. var plugin_download_urls = '.json_encode($plugin_urls).';
  470. var can_use_mods_site = '.(int)pluginuploader_can_use_mods_site().';
  471. var mybb_post_key = \''.$mybb->post_code.'\';
  472. var lang_delete = \''.$lang->delete.'\';
  473. var lang_pluginuploader_reimport = \''.$lang->pluginuploader_reimport.'\';
  474. var lang_pluginuploader_reimport_update = \''.$lang->pluginuploader_reimport_update.'\';
  475. </script>';
  476. }
  477.  
  478. function pluginuploader_admin_config_plugins_check_browse()
  479. {
  480. global $mybb, $lang, $pluginuploader_js;
  481.  
  482. $lang->load("config_pluginuploader");
  483.  
  484. switch($mybb->input['action'])
  485. {
  486. case 'check':
  487. $lang_key = $lang->pluginuploader_upgrade;
  488. break;
  489. case 'browse':
  490. $lang_key = $lang->pluginuploader_install;
  491. break;
  492. }
  493.  
  494. $pluginuploader_js = '<script src="jscripts/pluginuploader.js?version='.PLUGINUPLOADER_VERSION.'"></script>';
  495. $pluginuploader_js .= '<script>
  496. var pluginuploader_section = \''.$mybb->input['action'].'\';
  497. var mybb_post_key = \''.$mybb->post_code.'\';
  498. var lang_upgrade = \''.$lang_key.'\';
  499. </script>';
  500. }
  501.  
  502. function pluginuploader_admin_page_output_footer(&$args)
  503. {
  504. global $pluginuploader_js;
  505.  
  506. if($pluginuploader_js)
  507. {
  508. echo $pluginuploader_js;
  509. }
  510. }
  511.  
  512. function pluginuploader_can_use_mods_site()
  513. {
  514. if(function_exists('curl_init'))
  515. {
  516. return true;
  517. }
  518. else
  519. {
  520. return false;
  521. }
  522. }
  523.  
  524. global $pluginuploader;
  525. if(defined('IN_ADMINCP'))
  526. {
  527. $pluginuploader = new PluginUploader;
  528. }
  529. class PluginUploader
  530. {
  531. public $use_ftp = false;
  532. public $ftp_connected = false;
  533. private $ftp_connection;
  534. private $ftp_host;
  535. private $ftp_user;
  536. private $ftp_password;
  537. public $using_ssl = false;
  538. public $details_storage_location;
  539. public $changing_details = false;
  540.  
  541. public function __construct()
  542. {
  543. global $mybb, $db, $cache;
  544.  
  545. $plugins_cache = $cache->read('plugins');
  546. if(!is_array($plugins_cache['active']) || !in_array('pluginuploader', $plugins_cache['active']))
  547. {
  548. return;
  549. }
  550.  
  551. if($mybb->cookies['mybb_pluginuploader_ftp'])
  552. {
  553. $this->details_storage_location = 'cookie';
  554. $ftp_details = unserialize(base64_decode($mybb->cookies['mybb_pluginuploader_ftp']));
  555. $this->set_ftp_details($this->decrypt($ftp_details['ftp_host']), $this->decrypt($ftp_details['ftp_user']), $this->decrypt($ftp_details['ftp_password']));
  556. }
  557. else
  558. {
  559. $this->details_storage_location = 'database';
  560. $query = $db->simple_select("pluginuploader", "files AS ftp_details", "name = '_ftp'");
  561. if($db->num_rows($query) == 1)
  562. {
  563. $ftp_details = $db->fetch_field($query, "ftp_details");
  564. $ftp_details = unserialize(base64_decode($ftp_details));
  565. $this->set_ftp_details($this->decrypt($ftp_details['ftp_host']), $this->decrypt($ftp_details['ftp_user']), $this->decrypt($ftp_details['ftp_password']));
  566. }
  567. }
  568.  
  569. if(!$this->pluginuploader_copy_test() || $mybb->cookies['mybb_pluginuploader_use_ftp'])
  570. {
  571. $this->use_ftp = true;
  572. }
  573. else
  574. {
  575. $this->use_ftp = false;
  576. }
  577. }
  578.  
  579. public function set_ftp_details($host, $user, $password)
  580. {
  581. $this->ftp_host = $host;
  582. $this->ftp_user = $user;
  583. $this->ftp_password = $password;
  584. }
  585.  
  586. public function clear_ftp_details($what = 'all')
  587. {
  588. global $db;
  589.  
  590. if($what == 'cookie' || $what == 'all')
  591. {
  592. my_unsetcookie("mybb_pluginuploader_ftp");
  593. my_unsetcookie("mybb_pluginuploader_ftp_test");
  594. }
  595. if($what == 'database' || $what == 'all')
  596. {
  597. $db->delete_query("pluginuploader", "name = '_ftp'");
  598. $db->delete_query("pluginuploader", "name = '_ftp_test'");
  599. }
  600. }
  601.  
  602. public function ftp_connect($return_error = false)
  603. {
  604. global $mybb, $db;
  605.  
  606. if($this->ftp_connected)
  607. {
  608. return true;
  609. }
  610.  
  611. if(is_resource($this->ftp_connection))
  612. {
  613. $this->ftp_connected = true;
  614. return true;
  615. }
  616.  
  617. if(!function_exists("ftp_connect"))
  618. {
  619. if($return_error)
  620. {
  621. return "no_ftp";
  622. }
  623. return false;
  624. }
  625.  
  626. // check if the FTP key exists; if not, try and add it automatically
  627. if(!$mybb->config['pluginuploader_ftp_key'])
  628. {
  629. $this->add_config_ftp_key();
  630. }
  631. // if it's still not there, then error
  632. if(!$mybb->config['pluginuploader_ftp_key'])
  633. {
  634. if($return_error)
  635. {
  636. return "missing_config";
  637. }
  638. return false;
  639. }
  640. else
  641. {
  642. if(!$this->changing_details)
  643. {
  644. // now we have to check if the encryption key used to encrypt the FTP details hasn't been changed
  645. // if it has, we can't decrypt the details
  646. $test_string = '';
  647. if($this->details_storage_location == 'cookie')
  648. {
  649. $test_string = $mybb->cookies['mybb_pluginuploader_ftp_test'];
  650. }
  651. elseif($this->details_storage_location == 'database')
  652. {
  653. $query = $db->simple_select("pluginuploader", "files AS ftp_test", "name = '_ftp_test'");
  654. if($db->num_rows($query) == 1)
  655. {
  656. $test_string = $db->fetch_field($query, "ftp_test");
  657. }
  658. }
  659.  
  660. if($test_string)
  661. {
  662. if($this->decrypt(base64_decode($test_string)) != 'test')
  663. {
  664. if($return_error)
  665. {
  666. return "config_wrong";
  667. }
  668. return false;
  669. }
  670. }
  671. }
  672. }
  673.  
  674. if(!$this->ftp_host || !$this->ftp_user || !$this->ftp_password)
  675. {
  676. if($return_error)
  677. {
  678. return "missing_details";
  679. }
  680. return false;
  681. }
  682.  
  683. if(function_exists('ftp_ssl_connect'))
  684. {
  685. // we need to connect twice because if the server is not configured to understand the SSL encryption, the FTP login will fail, even though ftp_ssl_connect() is available and returns a valid connection
  686. // just helps the flow a bit if the backup connection is made here
  687. // http://uk.php.net/manual/en/function.ftp-ssl-connect.php#106931
  688. $ftp_connection = @ftp_ssl_connect($this->ftp_host);
  689. $ftp_connection_standard = @ftp_connect($this->ftp_host);
  690. $this->using_ssl = true;
  691. }
  692. else
  693. {
  694. $ftp_connection = @ftp_connect($this->ftp_host);
  695. }
  696.  
  697. if($ftp_connection)
  698. {
  699. // we need the second bit of this condition because even though ftp_ssl_connect() is available and returns a valid connection, the login will fail if the server is not configured to understand the SSL encryption
  700. // instead, a standard FTP connection is made at the same time as the SSL connection, and if the SSL one can't login it tries to login with the standard one
  701. // http://uk.php.net/manual/en/function.ftp-ssl-connect.php#106931
  702. if(@ftp_login($ftp_connection, $this->ftp_user, $this->ftp_password))
  703. {
  704. $this->ftp_connection = $ftp_connection;
  705. $this->ftp_connected = true;
  706. return true;
  707. }
  708. elseif($this->using_ssl && @ftp_login($ftp_connection_standard, $this->ftp_user, $this->ftp_password))
  709. {
  710. $this->ftp_connection = $ftp_connection_standard;
  711. $this->ftp_connected = true;
  712. return true;
  713. }
  714. else
  715. {
  716. if($return_error)
  717. {
  718. return "failed_login";
  719. }
  720. return false;
  721. }
  722. }
  723. else
  724. {
  725. if($return_error)
  726. {
  727. return "failed_host";
  728. }
  729. return false;
  730. }
  731.  
  732. return false;
  733. }
  734.  
  735. /**
  736. * This is a version of glob() that overcomes a stupid piece of PHP behaviour. If open_basedir is enabled, glob() may return false when there are no matches, instead of the expected empty array.
  737. * This can cause problems as code like count(glob("*")) will misbehave; if glob("*") returns false, then it'll be running count(false), which will return 1, so the code will think it found a match when it actually didn't.
  738. * Instead, this function simply checks if the return value of glob() is an array, and if it's not, it returns an empty array like it should so the code knows there weren't any matches.
  739. *
  740. * @param string The pattern to search for
  741. * @param Any flags to pass to glob()
  742. * @return array Array of files/folders or empty array if no matches
  743. **/
  744. public function glob($pattern, $flags = 0)
  745. {
  746. $glob = glob($pattern, $flags);
  747. if(is_array($glob))
  748. {
  749. return $glob;
  750. }
  751. else
  752. {
  753. return array();
  754. }
  755. }
  756.  
  757. /**
  758. * Function to attempt to copy a file from the temporary folder to it's proper destination. Tries numerous methods if previous methods fail.
  759. *
  760. * @param string The path of the source file
  761. * @param string The path of the destination file
  762. * @return bool Whether or not the file was copied successfully
  763. **/
  764. public function copy($from, $to)
  765. {
  766. global $pluginuploader;
  767.  
  768. $to = $this->replace_admin_dir($to);
  769.  
  770. if(!$this->use_ftp)
  771. {
  772. if($this->do_copy_php($from, $to))
  773. {
  774. return true;
  775. }
  776. else
  777. {
  778. $return = false;
  779. if(@chmod('path', 0777))
  780. {
  781. if($this->do_copy_php($from, $to))
  782. {
  783. $return = true;
  784. }
  785. @chmod('path', 0755);
  786. }
  787.  
  788. return $return;
  789. }
  790. }
  791. else
  792. {
  793. if($this->ftp_connect())
  794. {
  795. //echo MYBB_ROOT . "<br />";
  796. //echo $from . "<br />";
  797. //echo $to . "<br />";
  798. //echo ftp_pwd($ftp) . "<br />";
  799. $ftp_dir = MYBB_ROOT;
  800. $ftp_to = $to;
  801. $ftp_from = $from;
  802. while(!empty($ftp_dir) && !@ftp_chdir($this->ftp_connection, $ftp_dir))
  803. {
  804. $ftp_dir = strstr(ltrim($ftp_dir, "/"), "/");
  805. $ftp_from = strstr(ltrim($ftp_from, "/"), "/");
  806. $ftp_to = strstr(ltrim($ftp_to, "/"), "/");
  807. //echo $ftp_dir . "<br />";
  808. }
  809. if(empty($ftp_dir))
  810. {
  811. return false;
  812. }
  813. //echo ftp_pwd($ftp) . "<br />";
  814. //echo $ftp_from . "<br />";
  815. //echo $ftp_to . "<br />";
  816. $ftp_to_info = pathinfo($ftp_to);
  817. $ftp_to_dir = $ftp_to_info['dirname'];
  818. //exit;
  819.  
  820. if($this->do_copy_ftp($ftp_from, $ftp_to, $from, $to))
  821. {
  822. return true;
  823. }
  824. else
  825. {
  826. $return = false;
  827. if(@ftp_chmod($this->ftp_connection, $this->get_ftp_chmod(777), $ftp_to_dir))
  828. {
  829. if($this->do_copy_ftp($ftp_from, $ftp_to, $from, $to))
  830. {
  831. $return = true;
  832. }
  833. @ftp_chmod($this->ftp_connection, $this->get_ftp_chmod(755), $ftp_to_dir);
  834. }
  835.  
  836. return $return;
  837. }
  838. }
  839. }
  840.  
  841. return false;
  842. }
  843.  
  844. public function do_copy_php($from, $to)
  845. {
  846. if(copy($from, $to))
  847. {
  848. if(@file_exists($to))
  849. {
  850. return true;
  851. }
  852. }
  853.  
  854. // copy() has failed, try rename()
  855. if(@rename($from, $to))
  856. {
  857. if(@file_exists($to))
  858. {
  859. return true;
  860. }
  861. }
  862.  
  863. // rename() has failed, try fopen()
  864. $file = @fopen($to, "w");
  865. if($file)
  866. {
  867. $contents = @file_get_contents($from);
  868. if($contents)
  869. {
  870. if(@fwrite($file, $contents) || @file_put_contents($file, $contents))
  871. {
  872. @fclose($file);
  873. if(@file_exists($to))
  874. {
  875. return true;
  876. }
  877. }
  878. }
  879. }
  880. }
  881.  
  882. public function do_copy_ftp($ftp_from, $ftp_to, $from, $to)
  883. {
  884. if(@ftp_rename($this->ftp_connection, $ftp_from, $ftp_to))
  885. {
  886. if(@file_exists($to))
  887. {
  888. return true;
  889. }
  890. }
  891.  
  892. if(@ftp_put($this->ftp_connection, $ftp_to, $from, FTP_BINARY))
  893. {
  894. if(@file_exists($to))
  895. {
  896. return true;
  897. }
  898. }
  899.  
  900. if(@ftp_fput($this->ftp_connection, $ftp_to, fopen($from, 'r'), FTP_BINARY))
  901. {
  902. if(@file_exists($to))
  903. {
  904. return true;
  905. }
  906. }
  907. }
  908.  
  909. /**
  910. * Function to attempt to create a directory.
  911. *
  912. * @param string The path of the new directory
  913. * @return bool Whether or not the directory was created successfully
  914. **/
  915. public function mkdir($name)
  916. {
  917. global $pluginuploader;
  918.  
  919. $name = $this->replace_admin_dir($name);
  920.  
  921. if(@mkdir($name))
  922. {
  923. @chmod($name, 0755);
  924. if(is_dir($name))
  925. {
  926. return true;
  927. }
  928. }
  929.  
  930. if($this->ftp_connect())
  931. {
  932. $ftp_name = $name;
  933. while(!empty($ftp_name) && !@ftp_mkdir($this->ftp_connection, $ftp_name))
  934. {
  935. $ftp_name = strstr(ltrim($ftp_name, "/"), "/");
  936. }
  937. if(empty($ftp_name))
  938. {
  939. return false;
  940. }
  941. @ftp_chmod($this->ftp_connection, $this->get_ftp_chmod(755), $ftp_name);
  942. if(is_dir($ftp_name))
  943. {
  944. return true;
  945. }
  946. }
  947. return false;
  948. }
  949.  
  950. public function unlink($file)
  951. {
  952. $file = $this->replace_admin_dir($file);
  953.  
  954. if(file_exists($file))
  955. {
  956. if(@unlink($file))
  957. {
  958. if(!file_exists($file))
  959. {
  960. return true;
  961. }
  962. }
  963.  
  964. if($this->ftp_connect())
  965. {
  966. $ftp_file = $file;
  967. while(!empty($ftp_file) && !@ftp_delete($this->ftp_connection, $ftp_file))
  968. {
  969. $ftp_file = strstr(ltrim($ftp_file, "/"), "/");
  970. }
  971. if(empty($ftp_file))
  972. {
  973. return false;
  974. }
  975. if(!file_exists($ftp_file))
  976. {
  977. return true;
  978. }
  979. }
  980.  
  981. return false;
  982. }
  983.  
  984. return false;
  985. }
  986.  
  987. public function rmdir($dir)
  988. {
  989. $dir = $this->replace_admin_dir($dir);
  990.  
  991. if(is_dir($dir))
  992. {
  993. $objects = @scandir($dir);
  994. if(!empty($objects))
  995. {
  996. foreach($objects as $object)
  997. {
  998. if($object != "." && $object != "..")
  999. {
  1000. if(is_dir($dir . "/" . $object))
  1001. {
  1002. @$this->rmdir($dir . "/" . $object);
  1003. }
  1004. else
  1005. {
  1006. @$this->unlink($dir . "/" . $object);
  1007. }
  1008. }
  1009. reset($objects);
  1010. }
  1011. }
  1012.  
  1013. if(@rmdir($dir))
  1014. {
  1015. if(!is_dir($dir))
  1016. {
  1017. return true;
  1018. }
  1019. }
  1020.  
  1021. if($this->ftp_connect())
  1022. {
  1023. $ftp_dir = $dir;
  1024. while(!empty($ftp_dir) && !@ftp_rmdir($this->ftp_connection, $ftp_dir))
  1025. {
  1026. $ftp_dir = strstr(ltrim($ftp_dir, "/"), "/");
  1027. }
  1028. if(empty($ftp_dir))
  1029. {
  1030. return false;
  1031. }
  1032. if(!is_dir($ftp_dir))
  1033. {
  1034. return true;
  1035. }
  1036. }
  1037.  
  1038. return false;
  1039. }
  1040.  
  1041. return false;
  1042. }
  1043.  
  1044. /**
  1045. * Generate an FTP key
  1046. **/
  1047. public function generate_config_ftp_key()
  1048. {
  1049. return random_str(32);
  1050. }
  1051.  
  1052. /**
  1053. * Tries to add the FTP key to config.php automatically
  1054. **/
  1055. public function add_config_ftp_key()
  1056. {
  1057. global $mybb;
  1058.  
  1059. if(!is_writable(MYBB_ROOT.'inc/config.php'))
  1060. {
  1061. return false;
  1062. }
  1063.  
  1064. $ftp_key = $this->generate_config_ftp_key();
  1065.  
  1066. $config_lines = explode("\n", file_get_contents(MYBB_ROOT.'inc/config.php'));
  1067. foreach($config_lines as $i => &$line)
  1068. {
  1069. if(strpos($line, 'pluginuploader_ftp_key') !== false)
  1070. {
  1071. $line = '$config[\'pluginuploader_ftp_key\'] = \''.$ftp_key.'\';';
  1072. break;
  1073. }
  1074. elseif(++$i == count($config_lines))
  1075. {
  1076. $config_lines[] = '';
  1077. $config_lines[] = '/* Plugin Uploader - FTP details encryption key */';
  1078. $config_lines[] = '$config[\'pluginuploader_ftp_key\'] = \''.$ftp_key.'\';';
  1079. }
  1080. }
  1081. if(file_put_contents(MYBB_ROOT.'inc/config.php', implode("\n", $config_lines)))
  1082. {
  1083. $mybb->config['pluginuploader_ftp_key'] = $ftp_key;
  1084. return true;
  1085. }
  1086.  
  1087. return false;
  1088. }
  1089.  
  1090. /**
  1091. * Replace 'admin' in the file path to compensate for renamed admin folders
  1092. **/
  1093. public function replace_admin_dir($name, $placeholder = false)
  1094. {
  1095. global $mybb;
  1096.  
  1097. $name = str_replace("MYBB_ADMIN_DIR", "admin", $name);
  1098.  
  1099. if($mybb->config['admin_dir'] == "admin")
  1100. {
  1101. return $name;
  1102. }
  1103.  
  1104. if($placeholder)
  1105. {
  1106. $replace = "MYBB_ADMIN_DIR";
  1107. }
  1108. else
  1109. {
  1110. $replace = $mybb->config['admin_dir'];
  1111. }
  1112.  
  1113. $remove_mybb_root = false;
  1114. if(strpos($name, MYBB_ROOT) !== false)
  1115. {
  1116. $name = str_replace(MYBB_ROOT, "", $name);
  1117. $remove_mybb_root = true;
  1118. }
  1119.  
  1120. $in_admin_dir = false;
  1121. if(strpos($name, "/") === false)
  1122. {
  1123. if($name == "admin")
  1124. {
  1125. $in_admin_dir = true;
  1126. }
  1127. }
  1128. else
  1129. {
  1130. if(substr($name, 0, strpos($name, "/")) == "admin")
  1131. {
  1132. $in_admin_dir = true;
  1133. }
  1134. }
  1135.  
  1136. if($in_admin_dir)
  1137. {
  1138. $name = preg_replace("#admin#", $replace, $name, 1);
  1139. }
  1140.  
  1141. if($remove_mybb_root)
  1142. {
  1143. $name = MYBB_ROOT . $name;
  1144. }
  1145.  
  1146. return $name;
  1147. }
  1148.  
  1149. /**
  1150. * Tests whether or not PHP is able to copy files in the file system. If it can't, files will have to be moved with FTP.
  1151. * This check will be performed on the plugin upload page, and request an FTP password for a pre-stored FTP account.
  1152. **/
  1153. public function pluginuploader_copy_test()
  1154. {
  1155. if(!@file_exists(MYBB_ROOT . "inc/plugins/temp/test.php"))
  1156. {
  1157. if(!@fopen(MYBB_ROOT . "inc/plugins/temp/test.php", "r"))
  1158. {
  1159. return false;
  1160. }
  1161. }
  1162.  
  1163. if(@file_exists(MYBB_ROOT . "inc/plugins/plugin_uploader_test.php"))
  1164. {
  1165. @$this->unlink(MYBB_ROOT . "inc/plugins/plugin_uploader_test.php");
  1166. }
  1167.  
  1168. if(!@copy(MYBB_ROOT . "inc/plugins/temp/test.php", MYBB_ROOT . "inc/plugins/plugin_uploader_test.php"))
  1169. {
  1170. return false;
  1171. }
  1172.  
  1173. if(@file_exists(MYBB_ROOT . "inc/plugins/plugin_uploader_test.php"))
  1174. {
  1175. @$this->unlink(MYBB_ROOT . "inc/plugins/plugin_uploader_test.php");
  1176. }
  1177.  
  1178. return true;
  1179. }
  1180.  
  1181. public function user_is_nobody($file)
  1182. {
  1183. $fileowner = @fileowner($file);
  1184. if($fileowner === false)
  1185. {
  1186. return false;
  1187. }
  1188. $userinfo = @posix_getpwuid($fileowner);
  1189. if(!$userinfo)
  1190. {
  1191. return false;
  1192. }
  1193. if($userinfo['name'] == "nobody" || !$userinfo['name'])
  1194. {
  1195. return true;
  1196. }
  1197. return false;
  1198. }
  1199.  
  1200. public function get_ftp_chmod($perm)
  1201. {
  1202. return (int)octdec(str_pad($perm, 4, '0', STR_PAD_LEFT));
  1203. }
  1204.  
  1205. /*
  1206. * Encrypt a string - credit: http://stackoverflow.com/a/1289114
  1207. */
  1208. public function encrypt($string)
  1209. {
  1210. global $mybb;
  1211.  
  1212. $key = $mybb->config['pluginuploader_ftp_key'];
  1213.  
  1214. return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), $string, MCRYPT_MODE_CBC, md5(md5($key))));
  1215. }
  1216.  
  1217. /*
  1218. * Decrypt a string - credit: http://stackoverflow.com/a/1289114
  1219. */
  1220. public function decrypt($string)
  1221. {
  1222. global $mybb;
  1223.  
  1224. $key = $mybb->config['pluginuploader_ftp_key'];
  1225.  
  1226. return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($key), base64_decode($string), MCRYPT_MODE_CBC, md5(md5($key))), "\0");
  1227. }
  1228.  
  1229. public function __destruct()
  1230. {
  1231. @ftp_close($this->ftp_connection);
  1232. }
  1233. }
  1234. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement