PageRenderTime 13ms CodeModel.GetById 7ms app.highlight 33ms RepoModel.GetById 1ms app.codeStats 3ms

/kickstart.php

https://github.com/finchiefin/olympian
PHP | 9572 lines | 7194 code | 838 blank | 1540 comment | 847 complexity | a2c20af0fdfc8fd5f81a5213274f83a1 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2
   3/**
   4 * Akeeba Kickstart
   5 * A JSON-powered archive extraction tool
   6 *
   7 * @copyright   2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
   8 * @license     GNU GPL v2 or - at your option - any later version
   9 * @package     akeebabackup
  10 * @subpackage  kickstart
  11 */
  12
  13/*
  14    Akeeba Kickstart - The server-side archive extraction wizard
  15    Copyright (C) 2008-2013  Nicholas K. Dionysopoulos / AkeebaBackup.com
  16
  17    This program is free software: you can redistribute it and/or modify
  18    it under the terms of the GNU General Public License as published by
  19    the Free Software Foundation, either version 3 of the License, or
  20    (at your option) any later version.
  21
  22    This program is distributed in the hope that it will be useful,
  23    but WITHOUT ANY WARRANTY; without even the implied warranty of
  24    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  25    GNU General Public License for more details.
  26
  27    You should have received a copy of the GNU General Public License
  28    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  29 */
  30
  31define('KICKSTART',1);
  32define('VERSION', '3.8.0');
  33define('KICKSTARTPRO', '0');
  34// Uncomment the following line to enable Kickstart's debug mode
  35//define('KSDEBUG', 1);
  36
  37if(!defined('KSROOTDIR'))
  38{
  39	define('KSROOTDIR', dirname(__FILE__));
  40}
  41
  42if(defined('KSDEBUG')) {
  43	ini_set('error_log', KSROOTDIR.'/kickstart_error_log' );
  44	if(file_exists(KSROOTDIR.'/kickstart_error_log')) {
  45		@unlink(KSROOTDIR.'/kickstart_error_log');
  46	}
  47	error_reporting(E_ALL | E_STRICT);
  48} else {
  49	@error_reporting(E_NONE);
  50}
  51
  52// ==========================================================================================
  53// IIS missing REQUEST_URI workaround
  54// ==========================================================================================
  55
  56/*
  57 * Based REQUEST_URI for IIS Servers 1.0 by NeoSmart Technologies
  58 * The proper method to solve IIS problems is to take a look at this:
  59 * http://neosmart.net/dl.php?id=7
  60 */
  61
  62//This file should be located in the same directory as php.exe or php5isapi.dll
  63
  64if (!isset($_SERVER['REQUEST_URI']))
  65{
  66	if (isset($_SERVER['HTTP_REQUEST_URI']))
  67	{
  68		$_SERVER['REQUEST_URI'] = $_SERVER['HTTP_REQUEST_URI'];
  69		//Good to go!
  70	}
  71	else
  72	{
  73		//Someone didn't follow the instructions!
  74		if(isset($_SERVER['SCRIPT_NAME']))
  75		$_SERVER['HTTP_REQUEST_URI'] = $_SERVER['SCRIPT_NAME'];
  76		else
  77		$_SERVER['HTTP_REQUEST_URI'] = $_SERVER['PHP_SELF'];
  78		if($_SERVER['QUERY_STRING']){
  79			$_SERVER['HTTP_REQUEST_URI'] .=  '?' . $_SERVER['QUERY_STRING'];
  80		}
  81		//WARNING: This is a workaround!
  82		//For guaranteed compatibility, HTTP_REQUEST_URI *MUST* be defined!
  83		//See product documentation for instructions!
  84		$_SERVER['REQUEST_URI'] = $_SERVER['HTTP_REQUEST_URI'];
  85	}
  86}
  87
  88// Define the cacert.pem location, if it exists
  89$cacertpem = KSROOTDIR . '/cacert.pem';
  90if(is_file($cacertpem)) {
  91	if(is_readable($cacertpem)) {
  92		define('AKEEBA_CACERT_PEM', $cacertpem);
  93	}
  94}
  95unset($cacertpem);
  96
  97// Loads other PHP files containing extra Kickstart features
  98$dh = @opendir(KSROOTDIR);
  99if($dh === false) return;
 100while($filename = readdir($dh)) {
 101	if(!is_file($filename)) continue;
 102	if(substr($filename, 0, 10) != 'kickstart.') continue;
 103	if(substr($filename, -4) != '.php') continue;
 104	include_once $filename;
 105}
 106
 107
 108
 109/**
 110 * Akeeba Restore
 111 * A JSON-powered JPA, JPS and ZIP archive extraction library
 112 *
 113 * @copyright   2010-2013 Nicholas K. Dionysopoulos / Akeeba Ltd.
 114 * @license     GNU GPL v2 or - at your option - any later version
 115 * @package     akeebabackup
 116 * @subpackage  kickstart
 117 */
 118
 119define('_AKEEBA_RESTORATION', 1);
 120defined('DS') or define('DS', DIRECTORY_SEPARATOR);
 121
 122// Unarchiver run states
 123define('AK_STATE_NOFILE',	0); // File header not read yet
 124define('AK_STATE_HEADER',	1); // File header read; ready to process data
 125define('AK_STATE_DATA',		2); // Processing file data
 126define('AK_STATE_DATAREAD',	3); // Finished processing file data; ready to post-process
 127define('AK_STATE_POSTPROC',	4); // Post-processing
 128define('AK_STATE_DONE',		5); // Done with post-processing
 129
 130/* Windows system detection */
 131if(!defined('_AKEEBA_IS_WINDOWS'))
 132{
 133	if (function_exists('php_uname'))
 134		define('_AKEEBA_IS_WINDOWS', stristr(php_uname(), 'windows'));
 135	else
 136		define('_AKEEBA_IS_WINDOWS', DIRECTORY_SEPARATOR == '\\');
 137}
 138
 139// Get the file's root
 140if(!defined('KSROOTDIR'))
 141{
 142	define('KSROOTDIR', dirname(__FILE__));
 143}
 144if(!defined('KSLANGDIR'))
 145{
 146	define('KSLANGDIR', KSROOTDIR);
 147}
 148
 149// Make sure the locale is correct for basename() to work
 150if(function_exists('setlocale'))
 151{
 152	@setlocale(LC_ALL, 'en_US.UTF8');
 153}
 154
 155// fnmatch not available on non-POSIX systems
 156// Thanks to soywiz@php.net for this usefull alternative function [http://gr2.php.net/fnmatch]
 157if (!function_exists('fnmatch')) {
 158	function fnmatch($pattern, $string) {
 159		return @preg_match(
 160			'/^' . strtr(addcslashes($pattern, '/\\.+^$(){}=!<>|'),
 161		array('*' => '.*', '?' => '.?')) . '$/i', $string
 162		);
 163	}
 164}
 165
 166// Unicode-safe binary data length function
 167if (!function_exists('akstringlen'))
 168{
 169	if(function_exists('mb_strlen')) {
 170		function akstringlen($string) { return mb_strlen($string,'8bit'); }
 171	} else {
 172		function akstringlen($string) { return strlen($string); }
 173	}
 174}
 175
 176/**
 177 * Gets a query parameter from GET or POST data
 178 * @param $key
 179 * @param $default
 180 */
 181function getQueryParam( $key, $default = null )
 182{
 183	$value = null;
 184
 185	if(array_key_exists($key, $_REQUEST)) {
 186		$value = $_REQUEST[$key];
 187	} elseif(array_key_exists($key, $_POST)) {
 188		$value = $_POST[$key];
 189	} elseif(array_key_exists($key, $_GET)) {
 190		$value = $_GET[$key];
 191	} else {
 192		return $default;
 193	}
 194
 195	if(get_magic_quotes_gpc() && !is_null($value)) $value=stripslashes($value);
 196
 197	return $value;
 198}
 199
 200// Debugging function
 201function debugMsg($msg)
 202{
 203	if(!defined('KSDEBUG')) return;
 204	$fp = fopen('debug.txt','at');
 205	fwrite($fp, $msg."\n");
 206	fclose($fp);
 207}
 208
 209/**
 210 * Akeeba Restore
 211 * A JSON-powered JPA, JPS and ZIP archive extraction library
 212 *
 213 * @copyright   2010-2013 Nicholas K. Dionysopoulos / Akeeba Ltd.
 214 * @license     GNU GPL v2 or - at your option - any later version
 215 * @package     akeebabackup
 216 * @subpackage  kickstart
 217 */
 218
 219/**
 220 * Akeeba Backup's JSON compatibility layer
 221 *
 222 * On systems where json_encode and json_decode are not available, Akeeba
 223 * Backup will attempt to use PEAR's Services_JSON library to emulate them.
 224 * A copy of this library is included in this file and will be used if and
 225 * only if it isn't already loaded, e.g. due to PEAR's auto-loading, or a
 226 * 3PD extension loading it for its own purposes.
 227 */
 228
 229/**
 230 * Converts to and from JSON format.
 231 *
 232 * JSON (JavaScript Object Notation) is a lightweight data-interchange
 233 * format. It is easy for humans to read and write. It is easy for machines
 234 * to parse and generate. It is based on a subset of the JavaScript
 235 * Programming Language, Standard ECMA-262 3rd Edition - December 1999.
 236 * This feature can also be found in  Python. JSON is a text format that is
 237 * completely language independent but uses conventions that are familiar
 238 * to programmers of the C-family of languages, including C, C++, C#, Java,
 239 * JavaScript, Perl, TCL, and many others. These properties make JSON an
 240 * ideal data-interchange language.
 241 *
 242 * This package provides a simple encoder and decoder for JSON notation. It
 243 * is intended for use with client-side Javascript applications that make
 244 * use of HTTPRequest to perform server communication functions - data can
 245 * be encoded into JSON notation for use in a client-side javascript, or
 246 * decoded from incoming Javascript requests. JSON format is native to
 247 * Javascript, and can be directly eval()'ed with no further parsing
 248 * overhead
 249 *
 250 * All strings should be in ASCII or UTF-8 format!
 251 *
 252 * LICENSE: Redistribution and use in source and binary forms, with or
 253 * without modification, are permitted provided that the following
 254 * conditions are met: Redistributions of source code must retain the
 255 * above copyright notice, this list of conditions and the following
 256 * disclaimer. Redistributions in binary form must reproduce the above
 257 * copyright notice, this list of conditions and the following disclaimer
 258 * in the documentation and/or other materials provided with the
 259 * distribution.
 260 *
 261 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 262 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 263 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
 264 * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 265 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 266 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 267 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 268 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 269 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 270 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 271 * DAMAGE.
 272 *
 273 * @category
 274 * @package     Services_JSON
 275 * @author      Michal Migurski <mike-json@teczno.com>
 276 * @author      Matt Knapp <mdknapp[at]gmail[dot]com>
 277 * @author      Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
 278 * @copyright   2005 Michal Migurski
 279 * @version     CVS: $Id: restore.php 612 2011-05-19 08:26:26Z nikosdion $
 280 * @license     http://www.opensource.org/licenses/bsd-license.php
 281 * @link        http://pear.php.net/pepr/pepr-proposal-show.php?id=198
 282 */
 283
 284if(!defined('JSON_FORCE_OBJECT'))
 285{
 286	define('JSON_FORCE_OBJECT', 1);
 287}
 288
 289if(!defined('SERVICES_JSON_SLICE'))
 290{
 291	/**
 292	 * Marker constant for Services_JSON::decode(), used to flag stack state
 293	 */
 294	define('SERVICES_JSON_SLICE',   1);
 295
 296	/**
 297	 * Marker constant for Services_JSON::decode(), used to flag stack state
 298	 */
 299	define('SERVICES_JSON_IN_STR',  2);
 300
 301	/**
 302	 * Marker constant for Services_JSON::decode(), used to flag stack state
 303	 */
 304	define('SERVICES_JSON_IN_ARR',  3);
 305
 306	/**
 307	 * Marker constant for Services_JSON::decode(), used to flag stack state
 308	 */
 309	define('SERVICES_JSON_IN_OBJ',  4);
 310
 311	/**
 312	 * Marker constant for Services_JSON::decode(), used to flag stack state
 313	 */
 314	define('SERVICES_JSON_IN_CMT', 5);
 315
 316	/**
 317	 * Behavior switch for Services_JSON::decode()
 318	 */
 319	define('SERVICES_JSON_LOOSE_TYPE', 16);
 320
 321	/**
 322	 * Behavior switch for Services_JSON::decode()
 323	 */
 324	define('SERVICES_JSON_SUPPRESS_ERRORS', 32);
 325}
 326
 327/**
 328 * Converts to and from JSON format.
 329 *
 330 * Brief example of use:
 331 *
 332 * <code>
 333 * // create a new instance of Services_JSON
 334 * $json = new Services_JSON();
 335 *
 336 * // convert a complexe value to JSON notation, and send it to the browser
 337 * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
 338 * $output = $json->encode($value);
 339 *
 340 * print($output);
 341 * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
 342 *
 343 * // accept incoming POST data, assumed to be in JSON notation
 344 * $input = file_get_contents('php://input', 1000000);
 345 * $value = $json->decode($input);
 346 * </code>
 347 */
 348if(!class_exists('Akeeba_Services_JSON'))
 349{
 350	class Akeeba_Services_JSON
 351	{
 352	   /**
 353	    * constructs a new JSON instance
 354	    *
 355	    * @param    int     $use    object behavior flags; combine with boolean-OR
 356	    *
 357	    *                           possible values:
 358	    *                           - SERVICES_JSON_LOOSE_TYPE:  loose typing.
 359	    *                                   "{...}" syntax creates associative arrays
 360	    *                                   instead of objects in decode().
 361	    *                           - SERVICES_JSON_SUPPRESS_ERRORS:  error suppression.
 362	    *                                   Values which can't be encoded (e.g. resources)
 363	    *                                   appear as NULL instead of throwing errors.
 364	    *                                   By default, a deeply-nested resource will
 365	    *                                   bubble up with an error, so all return values
 366	    *                                   from encode() should be checked with isError()
 367	    */
 368	    function Akeeba_Services_JSON($use = 0)
 369	    {
 370	        $this->use = $use;
 371	    }
 372
 373	   /**
 374	    * convert a string from one UTF-16 char to one UTF-8 char
 375	    *
 376	    * Normally should be handled by mb_convert_encoding, but
 377	    * provides a slower PHP-only method for installations
 378	    * that lack the multibye string extension.
 379	    *
 380	    * @param    string  $utf16  UTF-16 character
 381	    * @return   string  UTF-8 character
 382	    * @access   private
 383	    */
 384	    function utf162utf8($utf16)
 385	    {
 386	        // oh please oh please oh please oh please oh please
 387	        if(function_exists('mb_convert_encoding')) {
 388	            return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
 389	        }
 390
 391	        $bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
 392
 393	        switch(true) {
 394	            case ((0x7F & $bytes) == $bytes):
 395	                // this case should never be reached, because we are in ASCII range
 396	                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 397	                return chr(0x7F & $bytes);
 398
 399	            case (0x07FF & $bytes) == $bytes:
 400	                // return a 2-byte UTF-8 character
 401	                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 402	                return chr(0xC0 | (($bytes >> 6) & 0x1F))
 403	                     . chr(0x80 | ($bytes & 0x3F));
 404
 405	            case (0xFFFF & $bytes) == $bytes:
 406	                // return a 3-byte UTF-8 character
 407	                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 408	                return chr(0xE0 | (($bytes >> 12) & 0x0F))
 409	                     . chr(0x80 | (($bytes >> 6) & 0x3F))
 410	                     . chr(0x80 | ($bytes & 0x3F));
 411	        }
 412
 413	        // ignoring UTF-32 for now, sorry
 414	        return '';
 415	    }
 416
 417	   /**
 418	    * convert a string from one UTF-8 char to one UTF-16 char
 419	    *
 420	    * Normally should be handled by mb_convert_encoding, but
 421	    * provides a slower PHP-only method for installations
 422	    * that lack the multibye string extension.
 423	    *
 424	    * @param    string  $utf8   UTF-8 character
 425	    * @return   string  UTF-16 character
 426	    * @access   private
 427	    */
 428	    function utf82utf16($utf8)
 429	    {
 430	        // oh please oh please oh please oh please oh please
 431	        if(function_exists('mb_convert_encoding')) {
 432	            return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
 433	        }
 434
 435	        switch(strlen($utf8)) {
 436	            case 1:
 437	                // this case should never be reached, because we are in ASCII range
 438	                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 439	                return $utf8;
 440
 441	            case 2:
 442	                // return a UTF-16 character from a 2-byte UTF-8 char
 443	                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 444	                return chr(0x07 & (ord($utf8{0}) >> 2))
 445	                     . chr((0xC0 & (ord($utf8{0}) << 6))
 446	                         | (0x3F & ord($utf8{1})));
 447
 448	            case 3:
 449	                // return a UTF-16 character from a 3-byte UTF-8 char
 450	                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 451	                return chr((0xF0 & (ord($utf8{0}) << 4))
 452	                         | (0x0F & (ord($utf8{1}) >> 2)))
 453	                     . chr((0xC0 & (ord($utf8{1}) << 6))
 454	                         | (0x7F & ord($utf8{2})));
 455	        }
 456
 457	        // ignoring UTF-32 for now, sorry
 458	        return '';
 459	    }
 460
 461	   /**
 462	    * encodes an arbitrary variable into JSON format
 463	    *
 464	    * @param    mixed   $var    any number, boolean, string, array, or object to be encoded.
 465	    *                           see argument 1 to Services_JSON() above for array-parsing behavior.
 466	    *                           if var is a strng, note that encode() always expects it
 467	    *                           to be in ASCII or UTF-8 format!
 468	    *
 469	    * @return   mixed   JSON string representation of input var or an error if a problem occurs
 470	    * @access   public
 471	    */
 472	    function encode($var)
 473	    {
 474	        switch (gettype($var)) {
 475	            case 'boolean':
 476	                return $var ? 'true' : 'false';
 477
 478	            case 'NULL':
 479	                return 'null';
 480
 481	            case 'integer':
 482	                return (int) $var;
 483
 484	            case 'double':
 485	            case 'float':
 486	                return (float) $var;
 487
 488	            case 'string':
 489	                // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
 490	                $ascii = '';
 491	                $strlen_var = strlen($var);
 492
 493	               /*
 494	                * Iterate over every character in the string,
 495	                * escaping with a slash or encoding to UTF-8 where necessary
 496	                */
 497	                for ($c = 0; $c < $strlen_var; ++$c) {
 498
 499	                    $ord_var_c = ord($var{$c});
 500
 501	                    switch (true) {
 502	                        case $ord_var_c == 0x08:
 503	                            $ascii .= '\b';
 504	                            break;
 505	                        case $ord_var_c == 0x09:
 506	                            $ascii .= '\t';
 507	                            break;
 508	                        case $ord_var_c == 0x0A:
 509	                            $ascii .= '\n';
 510	                            break;
 511	                        case $ord_var_c == 0x0C:
 512	                            $ascii .= '\f';
 513	                            break;
 514	                        case $ord_var_c == 0x0D:
 515	                            $ascii .= '\r';
 516	                            break;
 517
 518	                        case $ord_var_c == 0x22:
 519	                        case $ord_var_c == 0x2F:
 520	                        case $ord_var_c == 0x5C:
 521	                            // double quote, slash, slosh
 522	                            $ascii .= '\\'.$var{$c};
 523	                            break;
 524
 525	                        case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
 526	                            // characters U-00000000 - U-0000007F (same as ASCII)
 527	                            $ascii .= $var{$c};
 528	                            break;
 529
 530	                        case (($ord_var_c & 0xE0) == 0xC0):
 531	                            // characters U-00000080 - U-000007FF, mask 110XXXXX
 532	                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 533	                            $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
 534	                            $c += 1;
 535	                            $utf16 = $this->utf82utf16($char);
 536	                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
 537	                            break;
 538
 539	                        case (($ord_var_c & 0xF0) == 0xE0):
 540	                            // characters U-00000800 - U-0000FFFF, mask 1110XXXX
 541	                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 542	                            $char = pack('C*', $ord_var_c,
 543	                                         ord($var{$c + 1}),
 544	                                         ord($var{$c + 2}));
 545	                            $c += 2;
 546	                            $utf16 = $this->utf82utf16($char);
 547	                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
 548	                            break;
 549
 550	                        case (($ord_var_c & 0xF8) == 0xF0):
 551	                            // characters U-00010000 - U-001FFFFF, mask 11110XXX
 552	                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 553	                            $char = pack('C*', $ord_var_c,
 554	                                         ord($var{$c + 1}),
 555	                                         ord($var{$c + 2}),
 556	                                         ord($var{$c + 3}));
 557	                            $c += 3;
 558	                            $utf16 = $this->utf82utf16($char);
 559	                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
 560	                            break;
 561
 562	                        case (($ord_var_c & 0xFC) == 0xF8):
 563	                            // characters U-00200000 - U-03FFFFFF, mask 111110XX
 564	                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 565	                            $char = pack('C*', $ord_var_c,
 566	                                         ord($var{$c + 1}),
 567	                                         ord($var{$c + 2}),
 568	                                         ord($var{$c + 3}),
 569	                                         ord($var{$c + 4}));
 570	                            $c += 4;
 571	                            $utf16 = $this->utf82utf16($char);
 572	                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
 573	                            break;
 574
 575	                        case (($ord_var_c & 0xFE) == 0xFC):
 576	                            // characters U-04000000 - U-7FFFFFFF, mask 1111110X
 577	                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 578	                            $char = pack('C*', $ord_var_c,
 579	                                         ord($var{$c + 1}),
 580	                                         ord($var{$c + 2}),
 581	                                         ord($var{$c + 3}),
 582	                                         ord($var{$c + 4}),
 583	                                         ord($var{$c + 5}));
 584	                            $c += 5;
 585	                            $utf16 = $this->utf82utf16($char);
 586	                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
 587	                            break;
 588	                    }
 589	                }
 590
 591	                return '"'.$ascii.'"';
 592
 593	            case 'array':
 594	               /*
 595	                * As per JSON spec if any array key is not an integer
 596	                * we must treat the the whole array as an object. We
 597	                * also try to catch a sparsely populated associative
 598	                * array with numeric keys here because some JS engines
 599	                * will create an array with empty indexes up to
 600	                * max_index which can cause memory issues and because
 601	                * the keys, which may be relevant, will be remapped
 602	                * otherwise.
 603	                *
 604	                * As per the ECMA and JSON specification an object may
 605	                * have any string as a property. Unfortunately due to
 606	                * a hole in the ECMA specification if the key is a
 607	                * ECMA reserved word or starts with a digit the
 608	                * parameter is only accessible using ECMAScript's
 609	                * bracket notation.
 610	                */
 611
 612	                // treat as a JSON object
 613	                if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
 614	                    $properties = array_map(array($this, 'name_value'),
 615	                                            array_keys($var),
 616	                                            array_values($var));
 617
 618	                    foreach($properties as $property) {
 619	                        if(Akeeba_Services_JSON::isError($property)) {
 620	                            return $property;
 621	                        }
 622	                    }
 623
 624	                    return '{' . join(',', $properties) . '}';
 625	                }
 626
 627	                // treat it like a regular array
 628	                $elements = array_map(array($this, 'encode'), $var);
 629
 630	                foreach($elements as $element) {
 631	                    if(Akeeba_Services_JSON::isError($element)) {
 632	                        return $element;
 633	                    }
 634	                }
 635
 636	                return '[' . join(',', $elements) . ']';
 637
 638	            case 'object':
 639	                $vars = get_object_vars($var);
 640
 641	                $properties = array_map(array($this, 'name_value'),
 642	                                        array_keys($vars),
 643	                                        array_values($vars));
 644
 645	                foreach($properties as $property) {
 646	                    if(Akeeba_Services_JSON::isError($property)) {
 647	                        return $property;
 648	                    }
 649	                }
 650
 651	                return '{' . join(',', $properties) . '}';
 652
 653	            default:
 654	                return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS)
 655	                    ? 'null'
 656	                    : new Akeeba_Services_JSON_Error(gettype($var)." can not be encoded as JSON string");
 657	        }
 658	    }
 659
 660	   /**
 661	    * array-walking function for use in generating JSON-formatted name-value pairs
 662	    *
 663	    * @param    string  $name   name of key to use
 664	    * @param    mixed   $value  reference to an array element to be encoded
 665	    *
 666	    * @return   string  JSON-formatted name-value pair, like '"name":value'
 667	    * @access   private
 668	    */
 669	    function name_value($name, $value)
 670	    {
 671	        $encoded_value = $this->encode($value);
 672
 673	        if(Akeeba_Services_JSON::isError($encoded_value)) {
 674	            return $encoded_value;
 675	        }
 676
 677	        return $this->encode(strval($name)) . ':' . $encoded_value;
 678	    }
 679
 680	   /**
 681	    * reduce a string by removing leading and trailing comments and whitespace
 682	    *
 683	    * @param    $str    string      string value to strip of comments and whitespace
 684	    *
 685	    * @return   string  string value stripped of comments and whitespace
 686	    * @access   private
 687	    */
 688	    function reduce_string($str)
 689	    {
 690	        $str = preg_replace(array(
 691
 692	                // eliminate single line comments in '// ...' form
 693	                '#^\s*//(.+)$#m',
 694
 695	                // eliminate multi-line comments in '/* ... */' form, at start of string
 696	                '#^\s*/\*(.+)\*/#Us',
 697
 698	                // eliminate multi-line comments in '/* ... */' form, at end of string
 699	                '#/\*(.+)\*/\s*$#Us'
 700
 701	            ), '', $str);
 702
 703	        // eliminate extraneous space
 704	        return trim($str);
 705	    }
 706
 707	   /**
 708	    * decodes a JSON string into appropriate variable
 709	    *
 710	    * @param    string  $str    JSON-formatted string
 711	    *
 712	    * @return   mixed   number, boolean, string, array, or object
 713	    *                   corresponding to given JSON input string.
 714	    *                   See argument 1 to Akeeba_Services_JSON() above for object-output behavior.
 715	    *                   Note that decode() always returns strings
 716	    *                   in ASCII or UTF-8 format!
 717	    * @access   public
 718	    */
 719	    function decode($str)
 720	    {
 721	        $str = $this->reduce_string($str);
 722
 723	        switch (strtolower($str)) {
 724	            case 'true':
 725	                return true;
 726
 727	            case 'false':
 728	                return false;
 729
 730	            case 'null':
 731	                return null;
 732
 733	            default:
 734	                $m = array();
 735
 736	                if (is_numeric($str)) {
 737	                    // Lookie-loo, it's a number
 738
 739	                    // This would work on its own, but I'm trying to be
 740	                    // good about returning integers where appropriate:
 741	                    // return (float)$str;
 742
 743	                    // Return float or int, as appropriate
 744	                    return ((float)$str == (integer)$str)
 745	                        ? (integer)$str
 746	                        : (float)$str;
 747
 748	                } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
 749	                    // STRINGS RETURNED IN UTF-8 FORMAT
 750	                    $delim = substr($str, 0, 1);
 751	                    $chrs = substr($str, 1, -1);
 752	                    $utf8 = '';
 753	                    $strlen_chrs = strlen($chrs);
 754
 755	                    for ($c = 0; $c < $strlen_chrs; ++$c) {
 756
 757	                        $substr_chrs_c_2 = substr($chrs, $c, 2);
 758	                        $ord_chrs_c = ord($chrs{$c});
 759
 760	                        switch (true) {
 761	                            case $substr_chrs_c_2 == '\b':
 762	                                $utf8 .= chr(0x08);
 763	                                ++$c;
 764	                                break;
 765	                            case $substr_chrs_c_2 == '\t':
 766	                                $utf8 .= chr(0x09);
 767	                                ++$c;
 768	                                break;
 769	                            case $substr_chrs_c_2 == '\n':
 770	                                $utf8 .= chr(0x0A);
 771	                                ++$c;
 772	                                break;
 773	                            case $substr_chrs_c_2 == '\f':
 774	                                $utf8 .= chr(0x0C);
 775	                                ++$c;
 776	                                break;
 777	                            case $substr_chrs_c_2 == '\r':
 778	                                $utf8 .= chr(0x0D);
 779	                                ++$c;
 780	                                break;
 781
 782	                            case $substr_chrs_c_2 == '\\"':
 783	                            case $substr_chrs_c_2 == '\\\'':
 784	                            case $substr_chrs_c_2 == '\\\\':
 785	                            case $substr_chrs_c_2 == '\\/':
 786	                                if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
 787	                                   ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
 788	                                    $utf8 .= $chrs{++$c};
 789	                                }
 790	                                break;
 791
 792	                            case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
 793	                                // single, escaped unicode character
 794	                                $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
 795	                                       . chr(hexdec(substr($chrs, ($c + 4), 2)));
 796	                                $utf8 .= $this->utf162utf8($utf16);
 797	                                $c += 5;
 798	                                break;
 799
 800	                            case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
 801	                                $utf8 .= $chrs{$c};
 802	                                break;
 803
 804	                            case ($ord_chrs_c & 0xE0) == 0xC0:
 805	                                // characters U-00000080 - U-000007FF, mask 110XXXXX
 806	                                //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 807	                                $utf8 .= substr($chrs, $c, 2);
 808	                                ++$c;
 809	                                break;
 810
 811	                            case ($ord_chrs_c & 0xF0) == 0xE0:
 812	                                // characters U-00000800 - U-0000FFFF, mask 1110XXXX
 813	                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 814	                                $utf8 .= substr($chrs, $c, 3);
 815	                                $c += 2;
 816	                                break;
 817
 818	                            case ($ord_chrs_c & 0xF8) == 0xF0:
 819	                                // characters U-00010000 - U-001FFFFF, mask 11110XXX
 820	                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 821	                                $utf8 .= substr($chrs, $c, 4);
 822	                                $c += 3;
 823	                                break;
 824
 825	                            case ($ord_chrs_c & 0xFC) == 0xF8:
 826	                                // characters U-00200000 - U-03FFFFFF, mask 111110XX
 827	                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 828	                                $utf8 .= substr($chrs, $c, 5);
 829	                                $c += 4;
 830	                                break;
 831
 832	                            case ($ord_chrs_c & 0xFE) == 0xFC:
 833	                                // characters U-04000000 - U-7FFFFFFF, mask 1111110X
 834	                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
 835	                                $utf8 .= substr($chrs, $c, 6);
 836	                                $c += 5;
 837	                                break;
 838
 839	                        }
 840
 841	                    }
 842
 843	                    return $utf8;
 844
 845	                } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
 846	                    // array, or object notation
 847
 848	                    if ($str{0} == '[') {
 849	                        $stk = array(SERVICES_JSON_IN_ARR);
 850	                        $arr = array();
 851	                    } else {
 852	                        if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
 853	                            $stk = array(SERVICES_JSON_IN_OBJ);
 854	                            $obj = array();
 855	                        } else {
 856	                            $stk = array(SERVICES_JSON_IN_OBJ);
 857	                            $obj = new stdClass();
 858	                        }
 859	                    }
 860
 861	                    array_push($stk, array('what'  => SERVICES_JSON_SLICE,
 862	                                           'where' => 0,
 863	                                           'delim' => false));
 864
 865	                    $chrs = substr($str, 1, -1);
 866	                    $chrs = $this->reduce_string($chrs);
 867
 868	                    if ($chrs == '') {
 869	                        if (reset($stk) == SERVICES_JSON_IN_ARR) {
 870	                            return $arr;
 871
 872	                        } else {
 873	                            return $obj;
 874
 875	                        }
 876	                    }
 877
 878	                    //print("\nparsing {$chrs}\n");
 879
 880	                    $strlen_chrs = strlen($chrs);
 881
 882	                    for ($c = 0; $c <= $strlen_chrs; ++$c) {
 883
 884	                        $top = end($stk);
 885	                        $substr_chrs_c_2 = substr($chrs, $c, 2);
 886
 887	                        if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
 888	                            // found a comma that is not inside a string, array, etc.,
 889	                            // OR we've reached the end of the character list
 890	                            $slice = substr($chrs, $top['where'], ($c - $top['where']));
 891	                            array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
 892	                            //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
 893
 894	                            if (reset($stk) == SERVICES_JSON_IN_ARR) {
 895	                                // we are in an array, so just push an element onto the stack
 896	                                array_push($arr, $this->decode($slice));
 897
 898	                            } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
 899	                                // we are in an object, so figure
 900	                                // out the property name and set an
 901	                                // element in an associative array,
 902	                                // for now
 903	                                $parts = array();
 904
 905	                                if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
 906	                                    // "name":value pair
 907	                                    $key = $this->decode($parts[1]);
 908	                                    $val = $this->decode($parts[2]);
 909
 910	                                    if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
 911	                                        $obj[$key] = $val;
 912	                                    } else {
 913	                                        $obj->$key = $val;
 914	                                    }
 915	                                } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
 916	                                    // name:value pair, where name is unquoted
 917	                                    $key = $parts[1];
 918	                                    $val = $this->decode($parts[2]);
 919
 920	                                    if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
 921	                                        $obj[$key] = $val;
 922	                                    } else {
 923	                                        $obj->$key = $val;
 924	                                    }
 925	                                }
 926
 927	                            }
 928
 929	                        } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
 930	                            // found a quote, and we are not inside a string
 931	                            array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
 932	                            //print("Found start of string at {$c}\n");
 933
 934	                        } elseif (($chrs{$c} == $top['delim']) &&
 935	                                 ($top['what'] == SERVICES_JSON_IN_STR) &&
 936	                                 ((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) {
 937	                            // found a quote, we're in a string, and it's not escaped
 938	                            // we know that it's not escaped becase there is _not_ an
 939	                            // odd number of backslashes at the end of the string so far
 940	                            array_pop($stk);
 941	                            //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
 942
 943	                        } elseif (($chrs{$c} == '[') &&
 944	                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
 945	                            // found a left-bracket, and we are in an array, object, or slice
 946	                            array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
 947	                            //print("Found start of array at {$c}\n");
 948
 949	                        } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
 950	                            // found a right-bracket, and we're in an array
 951	                            array_pop($stk);
 952	                            //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
 953
 954	                        } elseif (($chrs{$c} == '{') &&
 955	                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
 956	                            // found a left-brace, and we are in an array, object, or slice
 957	                            array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
 958	                            //print("Found start of object at {$c}\n");
 959
 960	                        } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
 961	                            // found a right-brace, and we're in an object
 962	                            array_pop($stk);
 963	                            //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
 964
 965	                        } elseif (($substr_chrs_c_2 == '/*') &&
 966	                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
 967	                            // found a comment start, and we are in an array, object, or slice
 968	                            array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
 969	                            $c++;
 970	                            //print("Found start of comment at {$c}\n");
 971
 972	                        } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
 973	                            // found a comment end, and we're in one now
 974	                            array_pop($stk);
 975	                            $c++;
 976
 977	                            for ($i = $top['where']; $i <= $c; ++$i)
 978	                                $chrs = substr_replace($chrs, ' ', $i, 1);
 979
 980	                            //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
 981
 982	                        }
 983
 984	                    }
 985
 986	                    if (reset($stk) == SERVICES_JSON_IN_ARR) {
 987	                        return $arr;
 988
 989	                    } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
 990	                        return $obj;
 991
 992	                    }
 993
 994	                }
 995	        }
 996	    }
 997
 998	    function isError($data, $code = null)
 999	    {
1000	        if (class_exists('pear')) {
1001	            return PEAR::isError($data, $code);
1002	        } elseif (is_object($data) && (get_class($data) == 'services_json_error' ||
1003	                                 is_subclass_of($data, 'services_json_error'))) {
1004	            return true;
1005	        }
1006
1007	        return false;
1008	    }
1009	}
1010
1011    class Akeeba_Services_JSON_Error
1012    {
1013        function Akeeba_Services_JSON_Error($message = 'unknown error', $code = null,
1014                                     $mode = null, $options = null, $userinfo = null)
1015        {
1016
1017        }
1018    }
1019}
1020
1021if(!function_exists('json_encode'))
1022{
1023	function json_encode($value, $options = 0) {
1024		$flags = SERVICES_JSON_LOOSE_TYPE;
1025		if( $options & JSON_FORCE_OBJECT ) $flags = 0;
1026		$encoder = new Akeeba_Services_JSON($flags);
1027		return $encoder->encode($value);
1028	}
1029}
1030
1031if(!function_exists('json_decode'))
1032{
1033	function json_decode($value, $assoc = false)
1034	{
1035		$flags = 0;
1036		if($assoc) $flags = SERVICES_JSON_LOOSE_TYPE;
1037		$decoder = new Akeeba_Services_JSON($flags);
1038		return $decoder->decode($value);
1039	}
1040}
1041
1042/**
1043 * Akeeba Restore
1044 * A JSON-powered JPA, JPS and ZIP archive extraction library
1045 *
1046 * @copyright   2010-2013 Nicholas K. Dionysopoulos / Akeeba Ltd.
1047 * @license     GNU GPL v2 or - at your option - any later version
1048 * @package     akeebabackup
1049 * @subpackage  kickstart
1050 */
1051
1052/**
1053 * The base class of Akeeba Engine objects. Allows for error and warnings logging
1054 * and propagation. Largely based on the Joomla! 1.5 JObject class.
1055 */
1056abstract class AKAbstractObject
1057{
1058	/** @var	array	An array of errors */
1059	private $_errors = array();
1060
1061	/** @var	array	The queue size of the $_errors array. Set to 0 for infinite size. */
1062	protected $_errors_queue_size = 0;
1063
1064	/** @var	array	An array of warnings */
1065	private $_warnings = array();
1066
1067	/** @var	array	The queue size of the $_warnings array. Set to 0 for infinite size. */
1068	protected $_warnings_queue_size = 0;
1069
1070	/**
1071	 * Public constructor, makes sure we are instanciated only by the factory class
1072	 */
1073	public function __construct()
1074	{
1075		/*
1076		// Assisted Singleton pattern
1077		if(function_exists('debug_backtrace'))
1078		{
1079			$caller=debug_backtrace();
1080			if(
1081				($caller[1]['class'] != 'AKFactory') &&
1082				($caller[2]['class'] != 'AKFactory') &&
1083				($caller[3]['class'] != 'AKFactory') &&
1084				($caller[4]['class'] != 'AKFactory')
1085			) {
1086				var_dump(debug_backtrace());
1087				trigger_error("You can't create direct descendants of ".__CLASS__, E_USER_ERROR);
1088			}
1089		}
1090		*/
1091	}
1092
1093	/**
1094	 * Get the most recent error message
1095	 * @param	integer	$i Optional error index
1096	 * @return	string	Error message
1097	 */
1098	public function getError($i = null)
1099	{
1100		return $this->getItemFromArray($this->_errors, $i);
1101	}
1102
1103	/**
1104	 * Return all errors, if any
1105	 * @return	array	Array of error messages
1106	 */
1107	public function getErrors()
1108	{
1109		return $this->_errors;
1110	}
1111
1112	/**
1113	 * Add an error message
1114	 * @param	string $error Error message
1115	 */
1116	public function setError($error)
1117	{
1118		if($this->_errors_queue_size > 0)
1119		{
1120			if(count($this->_errors) >= $this->_errors_queue_size)
1121			{
1122				array_shift($this->_errors);
1123			}
1124		}
1125		array_push($this->_errors, $error);
1126	}
1127
1128	/**
1129	 * Resets all error messages
1130	 */
1131	public function resetErrors()
1132	{
1133		$this->_errors = array();
1134	}
1135
1136	/**
1137	 * Get the most recent warning message
1138	 * @param	integer	$i Optional warning index
1139	 * @return	string	Error message
1140	 */
1141	public function getWarning($i = null)
1142	{
1143		return $this->getItemFromArray($this->_warnings, $i);
1144	}
1145
1146	/**
1147	 * Return all warnings, if any
1148	 * @return	array	Array of error messages
1149	 */
1150	public function getWarnings()
1151	{
1152		return $this->_warnings;
1153	}
1154
1155	/**
1156	 * Add an error message
1157	 * @param	string $error Error message
1158	 */
1159	public function setWarning($warning)
1160	{
1161		if($this->_warnings_queue_size > 0)
1162		{
1163			if(count($this->_warnings) >= $this->_warnings_queue_size)
1164			{
1165				array_shift($this->_warnings);
1166			}
1167		}
1168
1169		array_push($this->_warnings, $warning);
1170	}
1171
1172	/**
1173	 * Resets all warning messages
1174	 */
1175	public function resetWarnings()
1176	{
1177		$this->_warnings = array();
1178	}
1179
1180	/**
1181	 * Propagates errors and warnings to a foreign object. The foreign object SHOULD
1182	 * implement the setError() and/or setWarning() methods but DOESN'T HAVE TO be of
1183	 * AKAbstractObject type. For example, this can even be used to propagate to a
1184	 * JObject instance in Joomla!. Propagated items will be removed from ourself.
1185	 * @param object $object The object to propagate errors and warnings to.
1186	 */
1187	public function propagateToObject(&$object)
1188	{
1189		// Skip non-objects
1190		if(!is_object($object)) return;
1191
1192		if( method_exists($object,'setError') )
1193		{
1194			if(!empty($this->_errors))
1195			{
1196				foreach($this->_errors as $error)
1197				{
1198					$object->setError($error);
1199				}
1200				$this->_errors = array();
1201			}
1202		}
1203
1204		if( method_exists($object,'setWarning') )
1205		{
1206			if(!empty($this->_warnings))
1207			{
1208				foreach($this->_warnings as $warning)
1209				{
1210					$object->setWarning($warning);
1211				}
1212				$this->_warnings = array();
1213			}
1214		}
1215	}
1216
1217	/**
1218	 * Propagates errors and warnings from a foreign object. Each propagated list is
1219	 * then cleared on the foreign object, as long as it implements resetErrors() and/or
1220	 * resetWarnings() methods.
1221	 * @param object $object The object to propagate errors and warnings from
1222	 */
1223	public function propagateFromObject(&$object)
1224	{
1225		if( method_exists($object,'getErrors') )
1226		{
1227			$errors = $object->getErrors();
1228			if(!empty($errors))
1229			{
1230				foreach($errors as $error)
1231				{
1232					$this->setError($error);
1233				}
1234			}
1235			if(method_exists($object,'resetErrors'))
1236			{
1237				$object->resetErrors();
1238			}
1239		}
1240
1241		if( method_exists($object,'getWarnings') )
1242		{
1243			$warnings = $object->getWarnings();
1244			if(!empty($warnings))
1245			{
1246				foreach($warnings as $warning)
1247				{
1248					$this->setWarning($warning);
1249				}
1250			}
1251			if(method_exists($object,'resetWarnings'))
1252			{
1253				$object->resetWarnings();
1254			}
1255		}
1256	}
1257
1258	/**
1259	 * Sets the size of the error queue (acts like a LIFO buffer)
1260	 * @param int $newSize The new queue size. Set to 0 for infinite length.
1261	 */
1262	protected function setErrorsQueueSize($newSize = 0)
1263	{
1264		$this->_errors_queue_size = (int)$newSize;
1265	}
1266
1267	/**
1268	 * Sets the size of the warnings queue (acts like a LIFO buffer)
1269	 * @param int $newSize The new queue size. Set to 0 for infinite length.
1270	 */
1271	protected function setWarningsQueueSize($newSize = 0)
1272	{
1273		$this->_warnings_queue_size = (int)$newSize;
1274	}
1275
1276	/**
1277	 * Returns the last item of a LIFO string message queue, or a specific item
1278	 * if so specified.
1279	 * @param array $array An array of strings, holding messages
1280	 * @param int $i Optional message index
1281	 * @return mixed The message string, or false if the key doesn't exist
1282	 */
1283	private function getItemFromArray($array, $i = null)
1284	{
1285		// Find the item
1286		if ( $i === null) {
1287			// Default, return the last item
1288			$item = end($array);
1289		}
1290		else
1291		if ( ! array_key_exists($i, $array) ) {
1292			// If $i has been specified but does not exist, return false
1293			return false;
1294		}
1295		else
1296		{
1297			$item	= $array[$i];
1298		}
1299
1300		return $item;
1301	}
1302
1303}
1304
1305/**
1306 * Akeeba Restore
1307 * A JSON-powered JPA, JPS and ZIP archive extraction library
1308 *
1309 * @copyright   2010-2013 Nicholas K. Dionysopoulos / Akeeba Ltd.
1310 * @license     GNU GPL v2 or - at your option - any later version
1311 * @package     akeebabackup
1312 * @subpackage  kickstart
1313 */
1314
1315/**
1316 * The superclass of all Akeeba Kickstart parts. The "parts" are intelligent stateful
1317 * classes which perform a single procedure and have preparation, running and
1318 * finalization phases. The transition between phases is handled automatically by
1319 * this superclass' tick() final public method, which should be the ONLY public API
1320 * exposed to the rest of the Akeeba Engine.
1321 */
1322abstract class AKAbstractPart extends AKAbstractObject
1323{
1324	/**
1325	 * Indicates whether this part has finished its initialisation cycle
1326	 * @var boolean
1327	 */
1328	protected $isPrepared = false;
1329
1330	/**
1331	 * Indicates whether this part has more work to do (it's in running state)
1332	 * @var boolean
1333	 */
1334	protected $isRunning = false;
1335
1336	/**
1337	 * Indicates whether this part has finished its finalization cycle
1338	 * @var boolean
1339	 */
1340	protected $isFinished = false;
1341
1342	/**
1343	 * Indicates whether this part has finished its run cycle
1344	 * @var boolean
1345	 */
1346	protected $hasRan = false;
1347
1348	/**
1349	 * The name of the engine part (a.k.a. Domain), used in return table
1350	 * generation.
1351	 * @var string
1352	 */
1353	protected $active_domain = "";
1354
1355	/**
1356	 * The step this engine part is in. Used verbatim in return table and
1357	 * should be set by the code in the _run() method.
1358	 * @var string
1359	 */
1360	protected $active_step = "";
1361
1362	/**
1363	 * A more detailed description of the step this engine part is in. Used
1364	 * verbatim in return table and should be set by the code in the _run()
1365	 * method.
1366	 * @var string
1367	 */
1368	protected $active_substep = "";
1369
1370	/**
1371	 * Any configuration variables, in the form of an array.
1372	 * @var array
1373	 */
1374	protected $_parametersArray = array();
1375
1376	/** @var string The database root key */
1377	protected $databaseRoot = array();
1378
1379	/** @var int Last reported warnings's position in array */
1380	private $warnings_pointer = -1;
1381
1382	/** @var array An array of observers */
1383	protected $observers = array();
1384
1385	/**
1386	 * Runs the preparation for this part. Should set _isPrepared
1387	 * to true
1388	 */
1389	abstract protected function _prepare();
1390
1391	/**
1392	 * Runs the finalisation process for this part. Should set
1393	 * _isFinished to true.
1394	 */
1395	abstract protected function _finalize();
1396
1397	/**
1398	 * Runs the main functionality loop for this part. Upon calling,
1399	 * should set the _isRunning to true. When it finished, should set
1400	 * the _hasRan to true. If an error is encountered, setError should
1401	 * be used.
1402	 */
1403	abstract protected function _run();
1404
1405	/**
1406	 * Sets the BREAKFLAG, which instructs this engine part that the current step must break immediately,
1407	 * in fear of timing…

Large files files are truncated, but you can click here to view the full file