PageRenderTime 48ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/application/libraries/Upgrade.php

https://github.com/Magaz/Ushahidi_Web
PHP | 634 lines | 516 code | 50 blank | 68 comment | 51 complexity | 4608458db0aeded44211e2fc01ac7201 MD5 | raw file
Possible License(s): AGPL-1.0, LGPL-3.0, BSD-3-Clause, GPL-2.0, LGPL-2.1
  1. <?php defined('SYSPATH') OR die('No direct access allowed.');
  2. /**
  3. * Upgrading Library
  4. * Provides the necessary functions to do the automatic upgrade
  5. *
  6. * @package Upgrade
  7. * @author Ushahidi Team
  8. * @copyright (c) 2008 Ushahidi Team
  9. * @license http://www.ushahidi.com/license.html
  10. */
  11. class Upgrade
  12. {
  13. public $notices;
  14. public $errors;
  15. public $success;
  16. public $error_level;
  17. public $session;
  18. public $ftp;
  19. public $ftp_server;
  20. public $ftp_user_name;
  21. public $ftp_user_pass;
  22. public function __construct()
  23. {
  24. $this->log = array();
  25. $this->errors = array();
  26. $this->error_level = ini_get('error_reporting');
  27. $this->session = Session::instance();
  28. if ( ! $this->session->get('upgrade_session'))
  29. {
  30. $this->session->set('upgrade_session', date("Y_m_d-H_i_s"));
  31. }
  32. }
  33. /**
  34. * Fetches ushahidi from download.ushahidi.com
  35. *
  36. * @param String url-- download URL
  37. */
  38. public function download_ushahidi($url) {
  39. $http_client = new HttpClient($url,30);
  40. $results = $http_client->execute();
  41. $this->log[] = "Starting to download the latest ushahidi build...";
  42. if ( $results)
  43. {
  44. $this->log[] = "Download of latest ushahidi went successful.";
  45. $this->success = true;
  46. return $results;
  47. }
  48. else
  49. {
  50. $this->errors[] = sprintf(Kohana::lang('libraries.upgrade_failed').": %d", $http_client->get_error_msg());
  51. $this->success = false;
  52. return $results;
  53. }
  54. }
  55. /**
  56. * FTP files recursively.
  57. *
  58. * @param String source-- the source directory.
  59. * @param String dest -- the destination directory.
  60. * @param $options //folderPermission,filePermission
  61. * @return boolean
  62. */
  63. function ftp_recursively($source, $dest, $options=array('folderPermission'=>0775,'filePermission'=>0664))
  64. {
  65. if ( ! $this->ftp_connect() )
  66. {
  67. $this->success = false;
  68. return false;
  69. }
  70. if ( ! $ftp_base_path = $this->ftp_base_path())
  71. {
  72. $this->success = false;
  73. return false;
  74. }
  75. $this->ftp->chdir($ftp_base_path);
  76. if (is_file($source))
  77. {
  78. $__dest=$dest;
  79. // Turn off error reporting temporarily
  80. error_reporting(0);
  81. $result = $this->ftp_copy($source, $__dest, $options);
  82. if ($result)
  83. {
  84. $this->success = true;
  85. $this->logger("Copied to ".$__dest);
  86. //Turn on error reporting again
  87. error_reporting($this->error_level);
  88. }
  89. else
  90. {
  91. $this->success = false;
  92. $this->logger("** Failed writing ".$__dest);
  93. //Turn on error reporting again
  94. error_reporting($this->error_level);
  95. return false;
  96. }
  97. }
  98. elseif(is_dir($source))
  99. {
  100. if ($dest[strlen($dest)-1] == '/')
  101. {
  102. if ($source[strlen($source)-1] == '/')
  103. {
  104. //Copy only contents
  105. }
  106. else
  107. {
  108. //Change parent itself and its contents
  109. $dest = $dest.basename($source);
  110. if ( ! $this->ftp->mkdir(str_replace(DOCROOT,"",$dest)))
  111. {
  112. $this->logger("** Failed creating directory ".$dest.". It might already exist.");
  113. }
  114. else
  115. {
  116. $this->logger("Created directory ".$dest);
  117. }
  118. $this->ftp->chmod(str_replace(DOCROOT,"",$dest),$options['folderPermission']);
  119. }
  120. }
  121. else
  122. {
  123. if ($source[strlen($source)-1] == '/')
  124. {
  125. //Copy parent directory with new name and all its content
  126. if ( ! $this->ftp->mkdir(str_replace(DOCROOT,"",$dest)))
  127. {
  128. $this->logger("** Failed creating directory ".$dest.". It might already exist.");
  129. }
  130. else
  131. {
  132. $this->logger("Created directory ".$dest);
  133. }
  134. $this->ftp->chmod(str_replace(DOCROOT,"",$dest),$options['folderPermission']);
  135. }
  136. else
  137. {
  138. //Copy parent directory with new name and all its content
  139. if ( ! $this->ftp->mkdir(str_replace(DOCROOT,"",$dest)))
  140. {
  141. $this->logger("** Failed creating directory ".$dest.". It might already exist.");
  142. }
  143. else
  144. {
  145. $this->logger("Created directory ".$dest);
  146. }
  147. $this->ftp->chmod(str_replace(DOCROOT,"",$dest),$options['folderPermission']);
  148. }
  149. }
  150. $dirHandle=opendir($source);
  151. while($file=readdir($dirHandle))
  152. {
  153. if($file != "." AND $file != ".." AND substr($file, 0, 1) != '.')
  154. {
  155. if( ! is_dir($source."/".$file))
  156. {
  157. $__dest=$dest."/".$file;
  158. $__dest=str_replace("//", "/", $__dest);
  159. }
  160. else
  161. {
  162. $__dest=$dest."/".$file;
  163. $__dest=str_replace("//", "/", $__dest);
  164. }
  165. $source_file = $source."/".$file;
  166. $source_file = str_replace("//", "/", $source_file);
  167. $result = $this->ftp_recursively($source_file, $__dest, $options);
  168. }
  169. }
  170. closedir($dirHandle);
  171. }
  172. }
  173. function ftp_connect()
  174. {
  175. //** temporary
  176. $this->ftp_server = $this->session->get('ftp_server');
  177. $this->ftp_user_name = $this->session->get('ftp_user_name');
  178. $this->ftp_user_pass = $this->session->get('ftp_user_pass');
  179. // Turn off error reporting temporarily
  180. //error_reporting(0);
  181. $ftp_init = new PemFtp();
  182. $this->ftp = new ftp();
  183. if ( ! $this->ftp_server OR
  184. ! $this->ftp_user_name OR
  185. ! $this->ftp_user_pass)
  186. {
  187. // Failed Connecting
  188. $this->logger("** Can't connect to FTP Server. Server, Username and/or Password not specified.");
  189. error_reporting($this->error_level);
  190. return false;
  191. }
  192. // Set FTP Server
  193. if ( ! $this->ftp->SetServer($this->ftp_server))
  194. {
  195. // Failed Connecting
  196. $this->logger("** Can't connect to FTP Server");
  197. error_reporting($this->error_level);
  198. return false;
  199. }
  200. // Connect to FTP Server
  201. if ( ! $this->ftp->connect() )
  202. {
  203. // Failed Connecting
  204. $this->logger("** Can't connect to FTP Server");
  205. error_reporting($this->error_level);
  206. return false;
  207. }
  208. // Authenticate at FTP Server
  209. if ( ! $this->ftp->login($this->ftp_user_name, $this->ftp_user_pass) )
  210. {
  211. // Failed Connecting
  212. $this->logger("** Can't connect to FTP Server - Incorrect Username or Password");
  213. error_reporting($this->error_level);
  214. return false;
  215. }
  216. $this->ftp->setTimeout(30);
  217. $this->ftp->SetType(-1);
  218. $this->ftp->Passive(true);
  219. error_reporting($this->error_level);
  220. return true;
  221. }
  222. function ftp_base_path()
  223. {
  224. $absolute_parts = explode('/', DOCROOT);
  225. $ushahidi_folder = end($absolute_parts);
  226. $ftp_parts = $this->ftp->nlist();
  227. // Are we already in the Ushahidi directory?
  228. if ($this->ftp->is_exists("application/config/config.php"))
  229. {
  230. return "./";
  231. }
  232. // We'll cycle through both to find out which
  233. // part of the DOCROOT we're in
  234. $ftp_base = "";
  235. foreach ($absolute_parts as $part)
  236. {
  237. foreach ($ftp_parts as $key => $value)
  238. {
  239. if ($value == $part)
  240. {
  241. $ftp_base .= $value."/";
  242. if ($this->ftp->is_exists($ftp_base."application/config/config.php"))
  243. { // We've arrived at the right folder
  244. break;
  245. }
  246. }
  247. }
  248. }
  249. // Verify once again that we're in the right directory
  250. if ($this->ftp->is_exists($ftp_base."application/config/config.php"))
  251. { // We've arrived at the right folder
  252. return $ftp_base;
  253. }
  254. else
  255. {
  256. return false;
  257. }
  258. }
  259. function ftp_copy($source, $dest, $options)
  260. {
  261. $dest = str_replace(DOCROOT,"",$dest);
  262. if ( ! $this->ftp->put($source, $dest) )
  263. {
  264. return false;
  265. }
  266. $this->ftp->chmod($dest,$options['filePermission']);
  267. return true;
  268. }
  269. /**
  270. * Copy files recursively.
  271. *
  272. * @param String source-- the source directory.
  273. * @param String dest -- the destination directory.
  274. * @param $options //folderPermission,filePermission
  275. * @return boolean
  276. */
  277. function copy_recursively($source, $dest, $options=array('folderPermission'=>0755,'filePermission'=>0755))
  278. {
  279. if (is_file($source)) {
  280. if ($dest[strlen($dest)-1]=='/')
  281. {
  282. if (!file_exists($dest))
  283. {
  284. cmfcDirectory::makeAll($dest,$options['folderPermission'],true);
  285. }
  286. $__dest = $dest."/".basename($source);
  287. }
  288. else
  289. {
  290. $__dest=$dest;
  291. }
  292. // Turn off error reporting temporarily
  293. error_reporting(0);
  294. $result = copy($source, $__dest);
  295. if ($result)
  296. {
  297. chmod($__dest,$options['filePermission']);
  298. $this->success = true;
  299. $this->logger("Copied to ".$__dest);
  300. //Turn on error reporting again
  301. error_reporting($this->error_level);
  302. }
  303. else
  304. {
  305. $this->success = false;
  306. $this->logger("** Failed writing ".$__dest);
  307. //Turn on error reporting again
  308. error_reporting($this->error_level);
  309. return false;
  310. }
  311. }
  312. elseif(is_dir($source))
  313. {
  314. if ($dest[strlen($dest)-1] == '/')
  315. {
  316. if ($source[strlen($source)-1] == '/')
  317. {
  318. //Copy only contents
  319. }
  320. else
  321. {
  322. //Change parent itself and its contents
  323. $dest = $dest.basename($source);
  324. if ( ! is_writable($dest))
  325. {
  326. $this->success = false;
  327. $this->logger("** Can't write to ".$dest);
  328. return false;
  329. }
  330. @mkdir($dest);
  331. chmod($dest,$options['filePermission']);
  332. }
  333. }
  334. else
  335. {
  336. if ( ! is_writable($dest))
  337. {
  338. $this->success = false;
  339. $this->logger("** Can't write to ".$dest);
  340. return false;
  341. }
  342. if ($source[strlen($source)-1] == '/')
  343. {
  344. //Copy parent directory with new name and all its content
  345. @mkdir($dest,$options['folderPermission']);
  346. chmod($dest,$options['filePermission']);
  347. }
  348. else
  349. {
  350. //Copy parent directory with new name and all its content
  351. @mkdir($dest,$options['folderPermission']);
  352. chmod($dest,$options['filePermission']);
  353. }
  354. }
  355. $dirHandle=opendir($source);
  356. while($file=readdir($dirHandle))
  357. {
  358. if($file!="." AND $file!=".." AND substr($file, 0, 1) != '.')
  359. {
  360. if(!is_dir($source."/".$file))
  361. {
  362. $__dest=$dest."/".$file;
  363. }
  364. else
  365. {
  366. $__dest=$dest."/".$file;
  367. }
  368. //echo "$source/$file ||| $__dest<br />";
  369. if ( ! is_writable($__dest))
  370. {
  371. $this->success = false;
  372. $this->logger("** Can't write to - ".$__dest);
  373. return false;
  374. }
  375. $result = $this->copy_recursively($source."/".$file, $__dest, $options);
  376. }
  377. }
  378. closedir($dirHandle);
  379. }
  380. }
  381. /**
  382. * Remove files recursively.
  383. *
  384. * @param String dir-- the directory to delete.
  385. */
  386. public function remove_recursively($dir)
  387. {
  388. if (empty($dir) || !is_dir($dir))
  389. return false;
  390. if (substr($dir,-1) != "/")
  391. $dir .= "/";
  392. if (($dh = opendir($dir)) !== false) {
  393. while (($entry = readdir($dh)) !== false) {
  394. if ($entry != "." && $entry != "..") {
  395. if ( is_file($dir . $entry) ) {
  396. if ( !@unlink($dir . $entry) ) {
  397. $this->errors[] = sprintf(Kohana::lang('libraries.upgrade_file_not_deleted'), $dir.$entry );
  398. $this->success = false;
  399. }
  400. } elseif (is_dir($dir . $entry)) {
  401. $this->remove_recursively($dir . $entry);
  402. $this->success = true;
  403. }
  404. }
  405. }
  406. closedir($dh);
  407. if ( !@rmdir($dir) ) {
  408. $this->errors[] = sprintf(Kohana::lang('libraries.upgrade_directory_not_deleted'), $dir.$entry);
  409. $this->success = false;
  410. }
  411. $this->success = true;
  412. return true;
  413. }
  414. return false;
  415. }
  416. /**
  417. * Unzip the file.
  418. *
  419. * @param String zip_file-- the zip file to be extracted.
  420. * @param String destdir-- destination directory
  421. */
  422. public function unzip_ushahidi($zip_file, $destdir)
  423. {
  424. $archive = new Pclzip($zip_file);
  425. $this->log[] = sprintf("Unpacking %s ",$zip_file);
  426. if (@$archive->extract(PCLZIP_OPT_PATH, $destdir) == 0)
  427. {
  428. $this->errors[] = sprintf(Kohana::lang('libraries.upgrade_extracting_error'),$archive->errorInfo(true) ) ;
  429. return false;
  430. }
  431. $this->log[] = sprintf("Unpacking went successful");
  432. $this->success = true;
  433. return true;
  434. }
  435. /**
  436. * Write the zile file to a file.
  437. *
  438. * @param String zip_file-- the zip file to be written.
  439. * @param String dest_file-- the file to write.
  440. */
  441. public function write_to_file($zip_file, $dest_file)
  442. {
  443. $handler = fopen( $dest_file,'w');
  444. $fwritten = fwrite($handler,$zip_file);
  445. $this->log[] = sprintf("Writting to a file ");
  446. if( !$fwritten ) {
  447. $this->errors[] = sprintf(Kohana::lang('libraries.upgrade_zip_error'),$dest_file);
  448. $this->success = false;
  449. return false;
  450. }
  451. fclose($handler);
  452. $this->success = true;
  453. $this->log[] = sprintf("Zip file successfully written to a file ");
  454. return true;
  455. }
  456. /**
  457. * Fetch latest ushahidi version from a remote instance then
  458. * compare it with local instance version number.
  459. */
  460. public function _fetch_core_release()
  461. {
  462. // Current Version
  463. $current = urlencode(Kohana::config('settings.ushahidi_version'));
  464. // Extra Stats
  465. $url = urlencode(preg_replace("/^https?:\/\/(.+)$/i","\\1",
  466. url::base()));
  467. $ip_address = (isset($_SERVER['REMOTE_ADDR'])) ?
  468. urlencode($_SERVER['REMOTE_ADDR']) : "";
  469. $version_url = "http://version.ushahidi.com/2/?v=".$current.
  470. "&u=".$url."&ip=".$ip_address;
  471. preg_match('/({.*})/', file_get_contents($version_url), $matches);
  472. $version_json_string = false;
  473. if(isset($matches[0]))
  474. {
  475. $version_json_string = $matches[0];
  476. }
  477. // If we didn't get anything back...
  478. if ( ! $version_json_string )
  479. {
  480. return "";
  481. }
  482. $version_details = json_decode($version_json_string);
  483. return $version_details;
  484. }
  485. /**
  486. * Log Messages To File
  487. */
  488. public function logger($message)
  489. {
  490. $filter_crlf = array("\n", "\r");
  491. $message = date("Y-m-d H:i:s")." : ".$message;
  492. $mesg = str_replace($filter_crlf,'',$message);
  493. $mesg .= "\n";
  494. $logfile = DOCROOT."application/logs/upgrade_".$this->session->get('upgrade_session').".txt";
  495. $logfile = fopen($logfile, 'a+');
  496. fwrite($logfile, $mesg);
  497. fclose($logfile);
  498. }
  499. /**
  500. * Delete files that no longer exist in latest version
  501. **/
  502. public function remove_old($file, $base_directory)
  503. {
  504. if ( ! $this->ftp_connect() )
  505. {
  506. $this->success = false;
  507. return false;
  508. }
  509. if ( ! $ftp_base_path = $this->ftp_base_path())
  510. {
  511. $this->success = false;
  512. return false;
  513. }
  514. $this->ftp->chdir($ftp_base_path);
  515. $old_files = file($file, FILE_IGNORE_NEW_LINES);
  516. foreach ($old_files as $old_file)
  517. {
  518. $ftp_filename = str_replace(DOCROOT,"",$old_file);
  519. // Skip removed config files
  520. if (stripos($old_file,'application/config/') !== FALSE) continue;
  521. if (is_file($old_file))
  522. {
  523. // Turn off error reporting temporarily
  524. error_reporting(0);
  525. $result = $this->ftp->delete($ftp_filename);
  526. if ($result)
  527. {
  528. $this->success = true;
  529. $this->logger("Removed ".$old_file);
  530. //Turn on error reporting again
  531. error_reporting($this->error_level);
  532. }
  533. else
  534. {
  535. $this->success = false;
  536. $this->logger("** Failed removing ".$old_file);
  537. //Turn on error reporting again
  538. error_reporting($this->error_level);
  539. return false;
  540. }
  541. }
  542. elseif(is_dir($old_file))
  543. {
  544. error_reporting(0);
  545. $result = $this->ftp->mdel($ftp_filename);
  546. if ($result)
  547. {
  548. $this->success = true;
  549. $this->logger("Removed ".$old_file);
  550. //Turn on error reporting again
  551. error_reporting($this->error_level);
  552. }
  553. else
  554. {
  555. $this->success = false;
  556. $this->logger("** Failed removing ".$old_file);
  557. //Turn on error reporting again
  558. error_reporting($this->error_level);
  559. return false;
  560. }
  561. }
  562. }
  563. // Remove upgrader removed files list
  564. error_reporting(0);
  565. $result = $this->ftp->delete('upgrader_removed_files.txt');
  566. error_reporting($this->error_level);
  567. }
  568. }