findFolder(dirname(__FILE__));
$GLOBALS['FileSystemObj']->touch($temp_unzip_dir_file.'/iwp-restore-log.txt');
$GLOBALS['FileSystemObj']->chmod($temp_unzip_dir_file.'/iwp-restore-log.txt', 0777);
}
$GLOBALS['LOG_FILE_HANDLE'] = @fopen($GLOBALS['LOG_FILE_NAME'], "w+");
}
if (!empty($_REQUEST['params']['wp_content_path'])) {
$GLOBALS['wp_content_path'] = $_REQUEST['params']['wp_content_path'];
}
if (!empty($_REQUEST['params']['toIWP'])) {
$GLOBALS['toIWP'] = $_REQUEST['params']['toIWP'];
}
if (!empty($_REQUEST['params']['old_user'])) {
$GLOBALS['old_user'] = $_REQUEST['params']['old_user'];
$old_user = $_REQUEST['params']['old_user'];
}
if (!empty($_REQUEST['params']['childRestore'])) {
$GLOBALS['is_child_restore'] = $_REQUEST['params']['childRestore'];
}
if (!empty($_REQUEST['params']['blogid'])) {
$GLOBALS['blogid'] = $_REQUEST['params']['blogid'];
}
if (!empty($prevMultiCallResponse['toIWP'])) {
$GLOBALS['toIWP'] = $prevMultiCallResponse['toIWP'];
}
if (!empty($prevMultiCallResponse['old_user'])) {
$GLOBALS['old_user'] = $prevMultiCallResponse['old_user'];
$old_user = $prevMultiCallResponse['old_user'];
}
if (!empty($prevMultiCallResponse['wp_content_path'])) {
$GLOBALS['wp_content_path'] = $prevMultiCallResponse['wp_content_path'];
}
if (!empty($prevMultiCallResponse['wp_content_path'])) {
$GLOBALS['table_prefix'] = $prevMultiCallResponse['wp_content_path'];
}
if (!empty($prevMultiCallResponse['table_prefix'])) {
$GLOBALS['table_prefix'] = $prevMultiCallResponse['table_prefix'];
}
if (!empty($prevMultiCallResponse['blogid'])) {
$GLOBALS['blogid'] = $prevMultiCallResponse['blogid'];
}
if (!empty($_REQUEST['params']['isCloudBackup'])) {
$GLOBALS['isCloudBackup'] = $_REQUEST['params']['isCloudBackup'];
status("*********************************** Restore From cloud backup *************************", $success=true, $return=false);
}
if (!empty($prevMultiCallResponse['isCloudBackup'])) {
$GLOBALS['isCloudBackup'] = $prevMultiCallResponse['isCloudBackup'];
status("*********************************** Restore From cloud backup *************************", $success=true, $return=false);
}
if (!empty($prevMultiCallResponse['IWP_encryptionphrase'])) {
$GLOBALS['IWP_encryptionphrase'] = $prevMultiCallResponse['IWP_encryptionphrase'];
}
$GLOBALS['is_new_backup'] = false;
if (!empty($_REQUEST['params']['isNewBackup']) || !empty($prevMultiCallResponse['is_new_backup'])) {
$GLOBALS['is_new_backup'] = true;
status("*********************************** Restore New method backup *************************", $success=true, $return=false);
}else{
status("*********************************** Restore old method backup *************************", $success=true, $return=false);
}
if (isset($_REQUEST['ftpHost']) && $GLOBALS['new_file_path']) {
initFileSystem();
}
$GLOBALS['needFileSystem'] = checkFileSystemRequirement();
if ($isMultiCall==false) {
if ($GLOBALS['needFileSystem']) {
status("*********************************** Restore Will use File system method instead of PHP *************************", $success=true, $return=false);
}
status("*********************************** Restore Test connection started *************************", $success=true, $return=false);
}
//Check access
if (empty($connectionFlag)) {
$connectionFlag = DB::connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME, '3306');
}
if ($connectionFlag !== true) {
$status = "DB verification Failed(".$connectionFlag.")";
die(status($status, $success=false, $return=true));
}elseif($isMultiCall == false){
status("DB connected Successfully", $success=true, $return=false);
}
$query = DB::doQuery("CREATE TABLE IF NOT EXISTS `iwp_clone_stats` (
`optionName` varchar(255) NOT NULL,
`optionValue` longtext
) ;");
if (!$query) {
$status = 'Restore status table creation failed check your database credentials';
die(status($status, $success=false, $return=true));
}elseif($isMultiCall == false){
status("Restore status table created successfully", $success=true, $return=false);
}
if($connectionFlag !== true) {
appUpdateMsg("Error establishing DB : ".$connectionFlag, 1);
return true;
} else{
appUpdateMsg("DB Connected");
status("Database SQLMODE chose", $success=true, $return=false);
DB::doQuery("SET SESSION sql_mode = ' '");
}
if ($isMultiCall == false && ((isset($_REQUEST['emptyTargetDir']) && $_REQUEST['emptyTargetDir']) || isset($_REQUEST['isStaging']))) {
deleteOldFilesFromRootDir($_REQUEST['excludeFolder']);
}
if ($isMultiCall == false) {
status("*********************************** Restore Test connection Ended *************************", $success=true, $return=false);
}
if ($isMultiCall == false) {
$query = "SELECT option_value FROM " . $db_table_prefix . "options WHERE option_name = 'IWP_backup_history' LIMIT 1";
$result = DB::doQuery($query);
if ($result) {
$_result = new DB::$DBResultClass($result);
$info = $_result->nextRow($_result);
$IWP_backup_history = $info['option_value'];
DB::replace("iwp_clone_stats", array('optionName' => 'IWP_backup_history', 'optionValue' => $IWP_backup_history));
}
}
$bkfile = array();
if($isMultiCall && !($isDownloadMultiCall) ){
if(empty($_REQUEST['temp_unzip_dir'])){
$_REQUEST['temp_unzip_dir'] = $prevMultiCallResponse['temp_unzip_dir'];
$_REQUEST['temp_pclzip'] = $prevMultiCallResponse['temp_pclzip'];
$_REQUEST['bkfile'] = $prevMultiCallResponse['temp_pclzip'];
}
$bkfile = $prevMultiCallResponse['bkfile'];
if (!empty($prevMultiCallResponse['dbBkile'])) {
$dbBkile = $prevMultiCallResponse['dbBkile'];
$GLOBALS['dbBkile'] = $dbBkile;
}
}elseif($isMultiCall && $isDownloadMultiCall){
if ($prevMultiCallResponse['backupURL']) {
$WPURL = $prevMultiCallResponse['backupURL'];
$bkfile = $prevMultiCallResponse['bkfile'];
if (!empty($prevMultiCallResponse['dbBkile'])) {
$dbBkile = $prevMultiCallResponse['dbBkile'];
$GLOBALS['dbBkile'] = $dbBkile;
}
$download_result = multiCallDownloadUsingCURL($WPURL, $prevMultiCallResponse['file'], $downloadResponseHeaders, $prevMultiCallResponse);
checkdownloadResponseHeaders($downloadResponseHeaders);
if($download_result['isDownloadMultiCall']){
$download_result['backupURL'] = $WPURL;
$download_result['bkfile'] = $bkfile;
send_multicall_response($download_result);
}
}
}elseif($GLOBALS['is_new_backup']){
$bkfile = array();
$types_to_downlaod = $_REQUEST['params']['types_to_downlaod'];
$backupFileBasename = $_REQUEST['params']['backupFileBasename'];
$backupFileBase = str_replace('.tmp','.php', $backupFileBasename);
copy($backupFileBasename, $backupFileBase);
include $backupFileBase;
if (!empty($backup_meta_files)) {
$backup_meta_files = unserialize($backup_meta_files);
$fileList = getBackupFilesByTaskName($backup_meta_files);
}else{
$fileList = $_REQUEST['params']['backupFiles'];
}
foreach ($fileList as $key => $value) {
if ($key != 'db' && !empty($value) && in_array($key, $types_to_downlaod)) {
$bkfile = array_merge($bkfile, $value);
}elseif ($key == 'db' && in_array($key, $types_to_downlaod)) {
$dbBkile = $value[0];
}
$GLOBALS['dbBkile'] = $dbBkile;
$GLOBALS['IWP_encryptionphrase'] = $backup_meta_files['IWP_encryptionphrase'];
}
if (empty($bkfile)) {
$prevMultiCallResponse['is_extract_over'] = 1;
}
if (!empty($GLOBALS['isCloudBackup'])) {
unlink($backupFileBase);
}
if (in_array('wp', $types_to_downlaod)) {
$meta_pos = strpos($backupFileBasename, 'eta_');
$php_pos = strpos($backupFileBasename, '.tmp');
$sub = substr($backupFileBasename, $meta_pos-$php_pos);
$WPVersion = str_replace('.tmp', '', $sub);
$GLOBALS['WPVersionName'] = 'wordpress-'.$WPVersion.'.zip';
$WPURL = 'https://wordpress.org/wordpress-'.$WPVersion.'.zip';
$WPPath = $GLOBALS['wp_content_path'].'/infinitewp/backups/WPPackage.zip';
$bkfile = array_merge(array($WPPath), $bkfile);
$download_result = multiCallDownloadUsingCURL($WPURL, $WPPath, $downloadResponseHeaders);
checkdownloadResponseHeaders($downloadResponseHeaders);
if($download_result['isDownloadMultiCall']){
$download_result['backupURL'] = $WPURL;
$download_result['bkfile'] = $bkfile;
send_multicall_response($download_result);
}
}
}elseif(empty($prevMultiCallResponse['is_extract_over'])){
$bkfile = $_REQUEST['params']['backupFiles'];
}
transfer($bkfile, $new_url, $newUser, $newPassword, $old_user, $db_table_prefix, $prevMultiCallResponse, $dbBkile);
function transfer($backup_file, $new_url, $newUser, $newPassword, $old_user, $db_table_prefix, $prevMultiCallResponse = array(), $dbBkile=false){
// ***************************************** Extract the ZIP Starts {*************************
if(empty($prevMultiCallResponse['is_extract_over'])){
if(empty($prevMultiCallResponse) || empty($prevMultiCallResponse['next_extract_id'])){
status("*********************************** Backup file extract process started *************************", $success=true, $return=false);
if(!isset($_REQUEST['temp_unzip_dir'])){
if ($GLOBALS['is_new_backup']) {
$temp_unzip_dir = $GLOBALS['wp_content_path'];
}else{
$temp_unzip_dir = dirname(dirname(__FILE__));
// mkdir($temp_unzip_dir);
}
// mkdir($temp_unzip_dir);
$temp_unzip_dir = iwpRemoveTrailingSlash($temp_unzip_dir);
$temp_uniq = md5(microtime(1));
while (is_dir($temp_unzip_dir .'/'. $temp_uniq )) {
$temp_uniq = md5(microtime(1));
}
$temp_pclzip = dirname(__FILE__).'/'.$temp_uniq."_zip_tmp";
mkdir($temp_pclzip);
status("Temp folder created ", $success=true, $return=false);
} else {
$temp_unzip_dir = $_REQUEST['temp_unzip_dir'];
$temp_pclzip = $_REQUEST['temp_pclzip'];
}
if(@is_writable($temp_unzip_dir) && @is_writable($temp_pclzip) || $GLOBALS['new_file_path']) {
status("Using temp working dir:".$temp_unzip_dir, $success=true, $return=false);
define( 'IWP_PCLZIP_TEMPORARY_DIR', $temp_pclzip."/");
if(empty($_REQUEST['temp_unzip_dir'])){
$_REQUEST['temp_unzip_dir'] = $temp_unzip_dir;
$_REQUEST['temp_pclzip'] = $temp_pclzip;
$_REQUEST['bkfile'] = $backup_file;
}
} else {
die(status('Unable to write files to the random directory.', $success=false, $return=true));
}
} else{
//setting old values from response data
$temp_unzip_dir = $_REQUEST['temp_unzip_dir'];
$temp_pclzip = $_REQUEST['temp_pclzip'];
define( 'IWP_PCLZIP_TEMPORARY_DIR', $temp_pclzip."/");
logExtractResponse('', array('status' => 'startingBridgeExtract', 'extractParentHID' => $_REQUEST['extractParentHID']), $_REQUEST);
}
// For unzipping
if(!is_array($backup_file)){
$temp_backup_file = $backup_file;
$backup_file = array();
$backup_file[] = $temp_backup_file;
}
@ini_set('memory_limit', '-1');
definePCLZipConstants();
if (empty($prevMultiCallResponse['is_file_append'])) {
$extract_result = extract_in_multicall($backup_file, $temp_unzip_dir);
}
if(is_array($extract_result) && $extract_result['status'] == 'partiallyCompleted' && empty($prevMultiCallResponse['is_file_append'])){
global $response_arr;
$response_arr = array();
initialize_response_array($response_arr);
$response_arr['next_extract_id'] = $extract_result['next_extract_id'];
$response_arr['is_extract_over'] = false;
$response_arr['status'] = 'partiallyCompleted';
$response_arr['break'] = true;
$response_arr['v_pos_entry'] = $extract_result['v_pos_entry'];
$response_arr['bkfile'] = $extract_result['bkfile'];;
$response_arr['peak_mem_usage'] = (memory_get_peak_usage(true)/1024/1024);
status("Extract will continue next call", $success=true, $return=false);
die(status("multicall", $success=true, $return=false, $response_arr));
return true;
exit;
}else{
status("*********************************** Backup file extract process end *************************", $success=true, $return=false);
}
}
if(empty($temp_unzip_dir) && !isset($temp_unzip_dir)){
$temp_unzip_dir = $_REQUEST['temp_unzip_dir'];
$temp_pclzip = $_REQUEST['temp_pclzip'];
}
if (empty($prevMultiCallResponse['is_file_append']) && empty($prevMultiCallResponse['next_db_insert_id'])) {
// $directFSObj = new filesystemDirect('');
@rmdir($temp_pclzip);
foreach ($backup_file as $key => $file) {
if (is_file($file) && $GLOBALS['isCloudBackup']) {
status("Unlinking file".$file, $success=true, $return=false);
unlink($file);
}
}
global $response_arr;
$response_arr = array();
$is_multicall_break = check_for_clone_break();
//if($key == 10){
if ($GLOBALS['is_new_backup']==false) {
status("*********************************** File appending process started *************************", $success=true, $return=false);
$prevMultiCallResponse['is_file_append']=1;
$prevMultiCallResponse['is_extract_over']= 1;
status("*********************************** File appending *************************".$GLOBALS['is_new_backup'], $success=true, $return=false);
}
if($is_multicall_break){
initialize_response_array($response_arr);
$response_arr['is_file_append'] = true;
$response_arr['status'] = 'partiallyCompleted';
$response_arr['break'] = true;
$response_arr['is_extract_over'] = true;
$response_arr['temp_pclzip'] = $temp_pclzip;
$response_arr['peak_mem_usage'] = (memory_get_peak_usage(true)/1024/1024);
die(status("multicall", $success=true, $return=false, $response_arr));
return $response_arr;
}
}
if(!empty($prevMultiCallResponse['is_extract_over']) && !empty($prevMultiCallResponse['is_file_append']) && $GLOBALS['is_new_backup'] == false){
if (empty($prevMultiCallResponse['appendFileLists'])) {
if (empty($GLOBALS['wp_content_path'])) {
$temp_unzip_dir = dirname(dirname(__FILE__)).'/';
}else{
$temp_unzip_dir = $GLOBALS['wp_content_path']/'uploads/';
}
$appendFileLists = $temp_unzip_dir;
status("File appending locations".$appendFileLists , $success=true, $return=false);
} else{
$appendFileLists = $prevMultiCallResponse['appendFileLists'];
}
status("*********************************** File appending...*************************", $success=true, $return=false);
appendSplitFiles($appendFileLists);
status("*********************************** File appending process Ended *************************", $success=true, $return=false);
status("*********************************** Database dump started *************************", $success=true, $return=false);
}
// @chmod($temp_unzip_dir, 0755);
// discourageSearchEngine($temp_unzip_dir);
if (!empty($GLOBALS['is_new_backup']) && empty($dbBkile)) {
deleteCloneDir();
sendCompleteResponse($newUser, $new_url, $old_user, $db_table_prefix);
return;
}
$paths = check_mysql_paths();
if (!empty($GLOBALS['is_new_backup'])) {
@rmdir($temp_pclzip);
$db_file_path = $GLOBALS['wp_content_path'].'/infinitewp/backups';
}else{
$db_file_path = dirname(dirname(__FILE__)).'/iwp_db';
$file_name = glob($db_file_path . '/*.sql');
$dbBkile = $file_name[0];
}
$db_file = $db_file_path . "/" . basename($dbBkile);
status("DB File Started".$db_file, $success=true, $return=false);
if (is_file_encrypted($db_file)) {
status("DB file encrypted so performing decryption", $success =true, $return=false);
$decrypt = decrypt_db($db_file, $GLOBALS['IWP_encryptionphrase']);
$db_file = $decrypt['fullpath'];
status("DB File decryption completed", $success=true, $return=false);
status("New DB File ".$db_file, $success=true, $return=false);
}
/*if($do_db_clone_basic_requirements){
if(modify_db_dump($db_file, $has_new_prefix)) {
status("Database dump modified url and prefix.", $success=true, $return=false);
} else {
status("Error: Database dump cannot be modified.", $success=false, $return=true);
}
} /* No need to replace URL seperatly it can be done along with while query run */
/*-----Replace URL-ends--------*/
$brace = (substr(PHP_OS, 0, 3) == 'WIN') ? '"' : '';
$command = $brace . $paths['mysql'] . $brace . ' --host="' . DB_HOST . '" --user="' . DB_USER . '" --password="' . DB_PASSWORD . '" --default-character-set="utf8" ' . DB_NAME . ' < ' . $brace . $db_file . $brace;
$result = false;
//$result = cmdExec($command);
iwp_mmb_auto_print('sql_import');
if ($result){
status("Database dump executed using command.", $success=true, $return=false);
} else{
//Else PHP db dump
DB::doQuery("SET FOREIGN_KEY_CHECKS = 0");
DB::doQuery("SET unique_checks=0");
DB::doQuery("SET NAMES 'utf8'");
// Read in entire file
//$lines = file($db_file);
if ($GLOBALS['is_new_backup']) {
status("DB new Started".$db_file, $success=true, $return=false);
$handle = gzopen($db_file, "r");
}else{
status("DB old Started".$db_file, $success=true, $return=false);
$handle = fopen($db_file, "r");
}
global $response_arr;
$response_arr = array();
initialize_response_array($response_arr);
$next_db_insert_id = empty($prevMultiCallResponse['next_db_insert_id']) ? 0 : $prevMultiCallResponse['next_db_insert_id'];
$change_collotion = empty($prevMultiCallResponse['change_collotion']) ? 0 : $prevMultiCallResponse['change_collotion'];
$finalQueryCount = empty($prevMultiCallResponse['finalQueryCount']) ? 0 : $prevMultiCallResponse['finalQueryCount'];
$failedQueryCount = empty($prevMultiCallResponse['failedQueryCount']) ? 0 : $prevMultiCallResponse['failedQueryCount'];
$count = 0;
// Loop through each line
if($handle){
while (!feof($handle)){
if ($GLOBALS['is_new_backup']) {
$line = gzgets($handle);
}else{
$line = fgets($handle);
}
$count ++;
if($count < $next_db_insert_id){
continue;
}
// iwp_mmb_auto_print('php_sql_import');
// Skip it if it's a comment
if(substr($line, 0, 2) == '--' || $line == '' || substr($line, 0, 3) == '/*!' || substr($line, 0, 1) == '#'){
continue;
}
// $line = preg_replace_callback("/(TABLE[S]?|INSERT\ INTO|DROP\ TABLE\ IF\ EXISTS) [`]?([^`\;\ ]+)[`]?/", 'search_and_replace_prefix', $line);// this will replace the old prefix to new one
$current_query .= $line;
if (strlen($current_query) < 10 || $current_query == ";") {
continue;
}
if ($GLOBALS['is_child_restore'] == true /*&& strrpos($current_query, $GLOBALS['table_prefix'].$GLOBALS['blogid']) === false*/) {
preg_match("/(TABLE[S]?|INSERT\ INTO|DROP\ TABLE\ IF\ EXISTS) [`]?([^`\;\ ]+)[`]?/", $current_query, $matches);
$is_true = search_and_find_blog_prefix($matches);
if ($is_true == false) {
$current_query = '';
continue;
}
}
if (substr(trim($line), -1, 1) == ';' && strrpos($current_query,$db_table_prefix.'iwp_backup_status')) {
status("iwp_backup_status table skipped", $success=true, $return=false);
$current_query = '';
continue;
}
if ($change_collotion == true && strrpos($current_query,'utf8mb4_unicode_520_ci')) {
$current_query = str_replace('utf8mb4_unicode_520_ci','utf8mb4_unicode_ci',$current_query);
}
// If it has a semicolon at the end, it's the end of the query
if(substr(trim($line), -1, 1) == ';'){
// Perform the query
$finalQueryCount ++;
$result = DB::doQuery($current_query);
// $result = true;
if (!$result) {
$failedQueryCount++;
//------------Due to big query, error msg is not getting saved in IWP Panel DB due to max packet length and other issues-- this is a fix for it------
$temp_error_replace_text = '...[Big text removed for error]...';
$max_error_query_length = 1500 + strlen($temp_error_replace_text);
$temp_current_query = $current_query;
if(strlen($current_query) > $max_error_query_length){
$temp_current_query = substr_replace($temp_current_query, '...[Big text removed for error]...', 750, -750);
}
$temp_current_query = htmlentities($temp_current_query);
//------------Due to big query, error msg is not getting saved in IWP Panel DB due to max packet length and other issues-- this is a fix for it------
echo "line count".$count;
$db_error = 'Error performing query "' . $temp_current_query . '": ' . DB::error().' Error Number'.DB::errorNo();
status("Failed to restore: " . $db_error, $success=true, $return=false);
if (DB::errorNo()==1273) {
$current_query = str_replace('utf8mb4_unicode_520_ci','utf8mb4_unicode_ci',$current_query);
$result = DB::doQuery($current_query);
$change_collotion = true;
}
clone_error_status_log($db_error);
// break;
}
// Reset temp variable to empty
$current_query = '';
$is_multicall_break = check_for_clone_break();
//if($key == 10){
if($is_multicall_break){
global $response_arr;
$response_arr['next_db_insert_id'] = $count + 1;
$response_arr['is_extract_over'] = true;
$response_arr['is_db_insert_over'] = false;
$response_arr['failedQueryCount'] = $failedQueryCount;
$response_arr['finalQueryCount'] = $finalQueryCount;
$response_arr['change_collotion'] = $change_collotion;
$response_arr['status'] = 'partiallyCompleted';
$response_arr['break'] = true;
$response_arr['peak_mem_usage'] = (memory_get_peak_usage(true)/1024/1024);
break;
}
}
}
} else{
$db_error = 'Cannot open database file.';
if ($GLOBALS['is_new_backup']) {
gzclose($handle);
}else{
fclose($handle);
}
}
if ($GLOBALS['is_new_backup']) {
gzclose($handle);
}else{
fclose($handle);
}
if($response_arr['break'] == true){
//logExtractResponse($_REQUEST['extractParentHID'], array('status' => 'partiallyCompleted', 'sendResponse' => true, 'nextFunc' => 'backupFiles', 'responseParams' => $response_arr));
storeCloningResponse();
status("Query processed : ".$finalQueryCount, $success=true, $return=false);
die(status("multicall", $success=true, $return=false, $response_arr));
exit;
return true;
}
status("Total query executed : ".$finalQueryCount, $success=true, $return=false);
status("Total query failed : ".$failedQueryCount, $success=true, $return=false);
status("***********************************Database dump executed*********************************** ", $success=true, $return=false);
if ($GLOBALS['isCloudBackup']) {
status("Unlinking file DB File ".$file, $success=true, $return=false);
unlink($db_file);
}
deleteCloneDir();
sendCompleteResponse($newUser, $new_url, $old_user, $db_table_prefix);
}
}
function deleteOldFilesFromRootDir($exclude = array()){
$defaultExclude = array('clone_controller');
$exclude = array_merge($exclude, $defaultExclude);
$tempWorkingDirFS = new filesystemDirect('');
$from = dirname(dirname(__FILE__));
$dirList = $tempWorkingDirFS->dirList($from);
initFileSystem();
$from = iwpAddTrailingSlash($from);
$from = $GLOBALS['FileSystemObj']->findFolder($from);
$from = iwpAddTrailingSlash($from);
foreach ((array) $dirList as $filename => $fileinfo ) {
if (!empty($exclude) && in_array($filename, $exclude)) {
continue;
}
$GLOBALS['FileSystemObj']->delete($from. $filename, 1);
}
}
function unset_safe_path($path) {
return str_replace("/", "\\", $path);
}
function extract_in_multicall($backup_file, $temp_unzip_dir){
$backup_file_temp = $backup_file;
foreach($backup_file as $key => $single_backup_file)
{
if (empty($GLOBALS['wp_content_path'])) {
$wp_content_path = dirname(dirname(__FILE__)).'/wp-content';
}else{
$wp_content_path = $GLOBALS['wp_content_path'];
}
$single_backup_file = $wp_content_path.'/infinitewp/backups/'.basename($single_backup_file);
status("Extracting backup file ".$single_backup_file, $success=true, $return=false);
/* iwp_mmb_auto_print('unzipping');
$unzip = cmdExec('which unzip', true);
if (!$unzip) $unzip = "unzip";
$command = "$unzip -d $temp_unzip_dir -o $single_backup_file";
$result = cmdExec($command); */
$type = '';
$result = false;
// $GLOBALS['is_child_restore'] = 1;
if (!$result) {
// initFileSystem(false, $temp_unzip_dir);
// if (strrpos($single_backup_file,'plugins')) {
// $type = 'plugins';
// $temp_unzip_dir =$wp_content_path.'/plugins';
// }elseif (strrpos($single_backup_file,'themes')) {
// $type = 'themes';
// $temp_unzip_dir =$wp_content_path.'/themes';
// }elseif (strrpos($single_backup_file,'uploads')) {
// $type = 'uploads';
// $temp_unzip_dir =$wp_content_path.'/uploads';
// }elseif (strrpos($single_backup_file,'others')) {
// $temp_unzip_dir =$wp_content_path.'/others';
// }else
if (strrpos($single_backup_file,'more') || strrpos($single_backup_file,'WPPackage') !== false || empty($GLOBALS['wp_content_path'])) {
$temp_unzip_dir =dirname(dirname(__FILE__));
}else{
// $temp_unzip_dir = $wp_content_path.'/uploads2';
$temp_unzip_dir = $wp_content_path;
}
// mkdir($temp_unzip_dir.'/uploads');
// mkdir($temp_unzip_dir.'/uploads/sites');
status("Extracting location ".$temp_unzip_dir, $success=true, $return=false);
@mkdir($temp_unzip_dir);
$archive = new IWPPclZip($single_backup_file);
$extracted = $archive->extract(IWP_PCLZIP_OPT_PATH, $temp_unzip_dir, IWP_PCLZIP_OPT_TEMP_FILE_THRESHOLD, 1);
if ($extracted['break']) {
$extracted['bkfile'] = $backup_file_temp;
return $extracted;
}
if (!$extracted || $archive->error_code) {
die(status('Error: Failed to extract backup file (' . $archive->error_string . ').'.$GLOBALS['downloadPossibleError'], $success=false, $return=true));
}
unset($backup_file_temp[$key]);
// if (!empty($type) && $type != 'plugins') {
// rename($wp_content_path.'/'.$type, $wp_content_path.'/'.$type.'_iwp_old');
// rename($wp_content_path.'/'.$type.'_iwp_new/'.$type, $wp_content_path.'/'.$type);
// }elseif (0&&!isset($GLOBALS['is_new_backup'])) {
// // rename($wp_content_path.'/plugins', $wp_content_path.'/_iwp_old');
// // rename(dirname(__FILE__).'/clone_controller/wp-content/plugins', $wp_content_path.'/plugins');
// rename($wp_content_path.'/uploads', $wp_content_path.'/uploads_iwp_old');
// rename(dirname(__FILE__).'/clone_controller/wp-content/uploads', $wp_content_path.'/uploads');
// rename($wp_content_path.'/themes', $wp_content_path.'/themes_iwp_old');
// rename(dirname(__FILE__).'/clone_controller/wp-content/themes', $wp_content_path.'/themes');
// }
if(!empty($GLOBALS['isCloudBackup'])){
status("Unlinking file ".$single_backup_file, $success=true, $return=false);
unlink($single_backup_file);
}
unset($_REQUEST['params']['responseData']['next_extract_id']);
unset($_REQUEST['params']['responseData']['v_pos_entry']);
} else{
status('Native zip is used to unzip.', $success=true, $return=false);
}
}
}
function deleteCloneDir(){
$site_parent_folder = dirname(__FILE__);
initFileSystem(false, $site_parent_folder);
$directFSObj = new filesystemDirect('');
$delete_result = $directFSObj->delete($site_parent_folder, true);//dirname(__FILE__) => clone_controller folder
if (empty($GLOBALS['is_new_backup'])) {
$delete_result = $directFSObj->delete(dirname(dirname(__FILE__)).'/iwp_db', true);//dirname(__FILE__) => clone_controller folder
}
if(!$delete_result){
$delete_result = $GLOBALS['FileSystemObj']->delete(iwpRemoveTrailingSlash(APP_FTP_BASE).'/clone_controller', true);//for those files and folders not delete with direct file system
}
if(!$delete_result){
status("Delete through file system Error.", $success=false, $return=false);
}
echo "
Clone Completed
";
$mem_peak = (memory_get_peak_usage(true)/1024/1024);
status("clone_completed", $success=true, $return=false);//changing success or status will affect result processing in addon controller
return true;
}
function deleteCloneDirWhileError(){
$directFSObj = new filesystemDirect('');
$directFSObj->delete(dirname(__FILE__), true);
echo "Clone folder deleted during error";
}
function sendCompleteResponse($newUser, $new_url, $old_user, $table_prefix){
status("clone_completed", $success=true, $return=false);
$query = "SELECT option_value FROM " . $table_prefix . "options WHERE option_name = 'siteurl' LIMIT 1";
$result = DB::doQuery($query) or die(status('Error getting old site URL' . DB::error(), $success=false, $return=true));
$_result = new DB::$DBResultClass($result);
$info = $_result->nextRow($_result);
$new_url = iwpRemoveTrailingSlash($info['option_value']);
// Issue: client plugin connection error happen when restore old backup (disconnected sites backup) and perform reload data (IWP <=2.15.6)
// Note : we are implementing re-add site for after every successfull restore
$query = "SELECT option_value FROM " . $table_prefix . "options WHERE option_name = 'home' LIMIT 1";
$result = DB::doQuery($query) or die(status('Error getting Home URL' . DB::error(), $success=false, $return=true));
$_result = new DB::$DBResultClass($result);
$info = $_result->nextRow($_result);
$home_url = iwpRemoveTrailingSlash($info['option_value']);
if($new_url == $home_url){
status("Wordpress site home url and site url same.", $success=true, $return=false);
}else{
$new_url = $home_url;
status("Wordpress site home url and site url are different.", $success=true, $return=false);
}
$query = "SELECT optionValue FROM iwp_clone_stats WHERE optionName = 'IWP_backup_history'";
$result = DB::doQuery($query);
$_result = new DB::$DBResultClass($result);
$info = $_result->nextRow($_result);
$IWP_backup_history = $info['optionValue'];
if (!empty($IWP_backup_history)) {
DB::replace($table_prefix."options", array('option_name' => 'IWP_backup_history', 'option_value' => $IWP_backup_history));
}
$query = "DROP TABLE iwp_clone_stats";
$result = DB::doQuery($query);
if (!empty($GLOBALS['toIWP'])) {
$query = "DELETE FROM " . $table_prefix . "options WHERE option_name = 'iwp_client_public_key' OR option_name = 'iwp_client_action_message_id' OR option_name = 'iwp_client_nossl_key'";
DB::doQuery($query) or die(status('Failed to clear old IWP Client Plugin details.' . DB::error(), $success=false, $return=true));
status("Cleared old IWP Client Plugin details.", $success=true, $return=false);
$query = "SELECT option_value FROM " . $table_prefix . "options WHERE option_name='iwp_client_activate_key'";
$temp_user_result = DB::doQuery($query) or die(status('Error: user to replace not found - ' . DB::error(), $success=false, $return=true));
$_result = new DB::$DBResultClass($temp_user_result);
$row = $_result->nextRow($_result);
$iwp_client_activation_key = $row['option_value'];
$old_user_query = "SELECT user_login FROM ".$table_prefix."users where user_login = '".$old_user."'";
$temp_user_result = DB::doQuery($old_user_query);
$_result = new DB::$DBResultClass($temp_user_result);
$row = $_result->nextRow($_result);
$old_user = $row['user_login'];
if(empty($old_user)){
$adminQuery = "SELECT user_id FROM ".$table_prefix."usermeta where meta_key = '".$table_prefix."capabilities' AND meta_value LIKE '%Administrator%' LIMIT 1";
$temp_user_result = DB::doQuery($adminQuery);
$_result = new DB::$DBResultClass($temp_user_result);
$row = $_result->nextRow($_result);
$user_id = $row['user_id'];
$userQuery = "SELECT user_login FROM ".$table_prefix."users where ID = '".$user_id."'";
$temp_user_result = DB::doQuery($userQuery);
$_result = new DB::$DBResultClass($temp_user_result);
$row = $_result->nextRow($_result);
$newUser = $row['user_login'];
status("Datas", $success=true, $return=false, array('URL' => $new_url, 'userName' => $newUser, 'activationKey' => $iwp_client_activation_key));
}else{
status("Datas", $success=true, $return=false, array('URL' => $new_url, 'userName' => $old_user, 'activationKey' => $iwp_client_activation_key));
}
}
}
function initialize_response_array(&$response_arr){
$response_arr['db_table_prefix'] = $_REQUEST['db_table_prefix'];
$response_arr['temp_unzip_dir'] = $_REQUEST['temp_unzip_dir'];
$response_arr['temp_pclzip'] = $_REQUEST['temp_pclzip'];
$response_arr['bkfile'] = $_REQUEST['bkfile'];
$response_arr['extractParentHID'] = $_REQUEST['params']['extractParentHID'];
$response_arr['isDownloadMultiCall'] = false;
$response_arr['is_file_append'] = false;
$response_arr['wp_content_path'] = $GLOBALS['wp_content_path'];
$response_arr['is_child_restore'] = $GLOBALS['is_child_restore'];
$response_arr['table_prefix'] = $GLOBALS['table_prefix'];
$response_arr['blogid'] = $GLOBALS['blogid'];
$response_arr['is_new_backup'] = $GLOBALS['is_new_backup'];
$response_arr['isCloudBackup'] = $GLOBALS['isCloudBackup'];
$response_arr['IWP_encryptionphrase'] = $GLOBALS['IWP_encryptionphrase'];
$response_arr['dbBkile'] = $GLOBALS['dbBkile'];
$response_arr['dbModification'] = false;
$response_arr['oldURLReplacement'] = false;
$response_arr['next_extract_id'] = 0;
$response_arr['next_extract_id'] = 0;
$response_arr['isStaging'] = $_REQUEST['isStaging'];
$response_arr['status'] = 'completed';
$response_arr['break'] = false;
$response_arr['dbHost'] = DB_HOST;
$response_arr['dbName'] = DB_NAME;
$response_arr['dbUser'] = DB_USER;
$response_arr['dbPassword'] = DB_PASSWORD;
$response_arr['db_table_prefix'] = $GLOBALS['db_table_prefix'];
$response_arr['toIWP'] = $GLOBALS['toIWP'];
$response_arr['old_user'] = $GLOBALS['old_user'];
}
function iwp_wp_normalize_path( $path ) {
$path = str_replace( '\\', '/', $path );
$path = preg_replace( '|(?<=.)/+|', '/', $path );
if ( ':' === substr( $path, 1, 1 ) ) {
$path = ucfirst( $path );
}
return $path;
}
function get_files_array_from_iwp_part($backup_file, $manual = ''){
$backup_files_array = array();
if(!is_array(($backup_file)) && strpos($backup_file, '_iwp_part') !== false)
{
$orgName = substr($backup_file, 0, strpos($backup_file, '_iwp_part_'));
if (!empty($manual)) {
$orgName = $orgName;
}
$totalParts = substr($backup_file, strpos($backup_file, '_iwp_part_')+10);
$totalParts = substr($totalParts, 0, strlen($totalParts)-4);
for($i=0; $i<=$totalParts; $i++)
{
iwp_mmb_auto_print('get_files_array_from_iwp_part');
if($i == 0)
{
$backup_files_array[] = $orgName.'.zip';
} else {
$backup_files_array[] = $orgName.'_iwp_part_'.$i.'.zip';
}
}
return $backup_files_array;
} else {
if (!empty($manual)) {
$backup_file = $backup_file;
}
$backup_files_array[] = $backup_file;
return $backup_file;
}
}
function appendSplitFiles($fileToAppend){
// function to join the split files during multicall backup
if (!is_array($fileToAppend)) {
$directory_tree = get_all_files_from_dir($fileToAppend);
$isBreak = check_for_clone_break();
if ($isBreak) {
global $response_arr;
$response_arr = array();
initialize_response_array($response_arr);
$response_arr['is_file_append'] = true;
$response_arr['status'] = 'partiallyCompleted';
$response_arr['break'] = true;
$response_arr['kuppu'] = true;
$response_arr['is_extract_over'] = true;
$response_arr['appendFileLists'] = $directory_tree;
$response_arr['peak_mem_usage'] = (memory_get_peak_usage(true)/1024/1024);
die(status("multicall", $success=true, $return=false, $response_arr));
return $response_arr;
}
} else{
$directory_tree = $fileToAppend;
}
usort($directory_tree, "sortString");
$joinedFilesArray = array();
$orgHashValues = array();
$hashValue = '';
foreach($directory_tree as $k => $v)
{
$contents = '';
$orgFileCount = 0;
$count = 0;
/* $subject = $v;
$pattern = '/iwp_part/i';
preg_match($pattern, $subject, $matches, PREG_OFFSET_CAPTURE);
print_r($matches); */
if (strpos($v, 'infinitewp/backups')) {
continue;
}
$pos = strpos($v, 'iwp_part');
if($pos !== false)
{
$count ++;
$currentFile = explode(".",$v);
$currentFileSize = count($currentFile);
foreach($currentFile as $key => $val)
{
iwp_mmb_auto_print('appendSplitFiles');
if(($key == ($currentFileSize-2))||($currentFileSize == 1))
{
$insPos = strpos($val, '_iwp_part');
$rest = substr_replace($val, '', $insPos);
$currentFile[$key] = $rest;
$insPos2 = strpos($rest, '_iwp_hash');
if($insPos2 != false)
{
$hashValue = substr($rest, -32);
$rest = substr_replace($rest, '', $insPos2);
$currentFile[$key] = $rest;
}
}
}
$orgFileCount++;
$orgFileName = implode(".", $currentFile);
$handle = fopen($v,"r");
$contents = fread($handle, filesize($v));
fclose($handle);
if($orgFileCount == 1)
{
//clearing contents of file intially to prevent appending to already existing file
}
file_put_contents($orgFileName,$contents,FILE_APPEND);
$joinedFilesArray[$orgFileName] = 'hash';
$orgHashValues[$orgFileName] = $hashValue;
echo " orgFileName - ".$orgFileName;
$file_to_ulink = realpath($v);
$resultUnlink = unlink($file_to_ulink);
$resultUnlink = error_get_last();
if(!$resultUnlink)
{
if(is_file($v))
{
unlink($file_to_ulink);
}
}
if (!is_file($v)) {
unset($directory_tree[$k]);
}
}
$isBreak = check_for_clone_break();
if ($isBreak) {
global $response_arr;
$response_arr = array();
initialize_response_array($response_arr);
$response_arr['is_file_append'] = true;
$response_arr['status'] = 'partiallyCompleted';
$response_arr['break'] = true;
$response_arr['kuppu'] = true;
$response_arr['is_extract_over'] = true;
$response_arr['appendFileLists'] = $directory_tree;
$response_arr['peak_mem_usage'] = (memory_get_peak_usage(true)/1024/1024);
die(status("multicall", $success=true, $return=false, $response_arr));
return $response_arr;
}
}
// md5 hash check currently not in use
// $hashValues = array();
// foreach($joinedFilesArray as $key => $value)
// {
// $hashValues[$key] = md5_file($key);
// }
// $totalHashValues = array();
// $totalHashValues['orgHash'] = $orgHashValues;
// $totalHashValues['afterSplitHash'] = $hashValues;
// return $totalHashValues;
}
function sortString($a, $b){
// the uSort CallBack Function used in the appendSplitFiles function
$stringArr = array();
$stringArr[0] = $a;
$stringArr[1] = $b;
$strA = '';
$strB = '';
foreach($stringArr as $strKey => $strVal)
{
$mystring = $strVal;
$findme = '_iwp_part'; //fileNameSplit logic
$pos = strpos($mystring, $findme);
$rest = substr($mystring, $pos);
$pos2 = strrpos($rest, $findme);
$len = strlen($rest);
$actLen = $pos2+strlen($findme);
$actPos = $len - $actLen -1;
$actPartNum = substr($rest, -($actPos));
$actPartNumArray = explode(".",$actPartNum);
foreach($actPartNumArray as $key => $val)
{
if($key == 0)
$actPartNum = $val;
}
if($strKey == 0){
$strA = intval($actPartNum);
}
else{
$strB = intval($actPartNum);
}
}
if ($strA == $strB){return 0;}
return ($strA < $strB) ? -1 : 1;
}
function get_all_files_from_dir($path, $exclude = array()){
if ($path[strlen($path) - 1] === "/") $path = substr($path, 0, -1);
global $directory_tree, $ignore_array;
$directory_tree = array();
foreach ($exclude as $file) {
if (!in_array($file, array('.', '..'))) {
if ($file[0] === "/") $path = substr($file, 1);
$ignore_array[] = "$path/$file";
}
}
get_all_files_from_dir_recursive($path);
return $directory_tree;
}
function get_all_files_from_dir_recursive($path, $ignore_array=array()){
if ($path[strlen($path) - 1] === "/") $path = substr($path, 0, -1);
global $directory_tree, $ignore_array;
$directory_tree_temp = array();
$dh = @opendir($path);
if(empty($ignore_array))
{
$ignore_array = array();
}
while (false !== ($file = @readdir($dh))) {
if (!in_array($file, array('.', '..'))) {
if (!in_array("$path/$file", $ignore_array)) {
if (!is_dir("$path/$file")) {
$pos = strpos("$path/$file", 'iwp_part');
if($pos !== false) {
$directory_tree[] = "$path/$file";
}
} else {
iwp_mmb_auto_print('appendSplitFiles');
get_all_files_from_dir_recursive("$path/$file");
}
}
}
}
@closedir($dh);
}
function change_table_prefix_config_file($file_path, $db_table_prefix){
//select wp-config-sample.php
$wp_config_file = glob($file_path . '/wp-config.php');
if ($GLOBALS['needFileSystem']) {
$temp_unzip_dir_file = $GLOBALS['FileSystemObj']->findFolder($file_path);
$result = $GLOBALS['FileSystemObj']->move($temp_unzip_dir_file.'wp-config.php', $temp_unzip_dir_file.'wp-config-temp.php');
$GLOBALS['FileSystemObj']->chmod($temp_unzip_dir_file.'/wp-config.php', 0777);
}else{
$result = @rename($wp_config_file[0], $file_path.'/wp-config-temp.php');
}
if ($result) {
$lines = file($file_path.'/wp-config-temp.php');
@unlink($file_path.'/wp-config-temp.php');
} else {
$lines = @file($file_path.'/wp-config-sample.php');
}
if ($GLOBALS['needFileSystem']) {
$GLOBALS['FileSystemObj']->delete($temp_unzip_dir_file.'/wp-config.php');
$GLOBALS['FileSystemObj']->touch($temp_unzip_dir_file.'/wp-config.php');
$GLOBALS['FileSystemObj']->chmod($temp_unzip_dir_file.'/wp-config.php', 0777);
}else{
@unlink($file_path.'/wp-config.php');
}
if (empty($lines))
die(status('Error: Cannot recreate wp-config.php file.', $success=false, $return=true));
$file_success = false;
foreach ($lines as $line) {
if ($db_table_prefix && strstr($line, '$table_prefix')) {
$line = "\$table_prefix = '$db_table_prefix';\n";
$file_success = true;
}
$result = file_put_contents($file_path.'/wp-config.php', $line, FILE_APPEND);
if ($result === true)
die(status('Error: Cannot write wp-config.php file.', $success=false, $return=true));
}
return $file_success;
}
function get_table_prefix($temp_unzip_dir){
$lines = file($temp_unzip_dir.'/wp-config.php');
foreach ($lines as $line) {
if (strstr($line, '$table_prefix')) {
$pattern = "/(\'|\")[^(\'|\")]*/";
preg_match($pattern, $line, $matches);
$prefix = substr($matches[0], 1);
return $prefix;
break;
}
}
return 'wp_'; //default
}
function check_mysql_paths(){
$paths = array(
'mysql' => '',
'mysqldump' => ''
);
if (substr(PHP_OS, 0, 3) == 'WIN') {
$mysql_install = DB::doQuery("SHOW VARIABLES LIKE 'basedir'");
$_result = new DB::$DBResultClass($mysql_install);
$mysql_install = $_result->nextRow($_result);
appUpdateMsg("inside-check-mysql-path : ".$mysql_install->Value);
if ($mysql_install) {
$install_path = str_replace('\\', '/', $mysql_install->Value);
$paths['mysql'] = $install_path . 'bin/mysql.exe';
$paths['mysqldump'] = $install_path . 'bin/mysqldump.exe';
} else {
$paths['mysql'] = 'mysql.exe';
$paths['mysqldump'] = 'mysqldump.exe';
}
} else {
$paths['mysql'] = cmdExec('which mysql', true);
if (empty($paths['mysql']))
$paths['mysql'] = 'mysql'; // try anyway
$paths['mysqldump'] = cmdExec('which mysqldump', true);
if (empty($paths['mysqldump']))
$paths['mysqldump'] = 'mysqldump'; // try anyway
}
return $paths;
}
function cmdExec(){
if ($command == ''){
return false;
}
if (checkFunctionExists('exec')) {
$log = @exec($command, $output, $return);
if ($string)
return $log;
return $return ? false : true;
} else if (checkFunctionExists('system')) {
$log = @system($command, $return);
if ($string){
return $log;
}
return $return ? false : true;
} else if (checkFunctionExists('passthru') && !$string) {
$log = passthru($command, $return);
return $return ? false : true;
} else {
return false;
}
}
function checkFunctionExists($function_callback){
if(!function_exists($function_callback)){
return false;
}
$disabled = explode(', ', @ini_get('disable_functions'));
if (in_array($function_callback, $disabled)){
return false;
}
if (extension_loaded('suhosin')) {
$suhosin = @ini_get("suhosin.executor.func.blacklist");
if (empty($suhosin) == false) {
$suhosin = explode(',', $suhosin);
$blacklist = array_map('trim', $suhosin);
$blacklist = array_map('strtolower', $blacklist);
if(in_array($function_callback, $blacklist)){
return false;
}
}
}
return true;
}
function search_and_replace_prefix($matches){
global $old_table_prefix, $table_prefix;
$subject = $matches[0];
$old_table_name = $matches[2];
//$new_table_name = str_replace($old_table_prefix, $table_prefix, $old_table_name);
$new_table_name = preg_replace("/$old_table_prefix/", $table_prefix, $old_table_name, 1);
return str_replace($old_table_name, $new_table_name, $subject);
}
function search_and_find_blog_prefix($matches){
$old_table_prefix = $GLOBALS['table_prefix'];
$table_prefix = $GLOBALS['table_prefix'].$GLOBALS['blogid'].'_';
$subject = $matches[0];
$old_table_name = $matches[2];
if (preg_match('#^'.$table_prefix.'#', $old_table_name) != 1) {
return false;
}
return true;
}
function status($status, $success=true, $return=true, $options='', $multicall=false){
if($success && !empty($options)){
echo '#Status('.base64_encode(serialize(array('success' => $status, 'options' => $options))).')#'; echo "\n".serialize(array('success' => $status, 'options' => $options));
if ($GLOBALS["LOG_FILE_HANDLE"]) {
@fwrite($GLOBALS["LOG_FILE_HANDLE"], 'success : '.$status."\n");
}
} else if($success){
echo '#Status('.base64_encode(serialize(array('success' => $status))).')#'; echo "\n".serialize(array('success' => $status));
if ($GLOBALS["LOG_FILE_HANDLE"])
@fwrite($GLOBALS["LOG_FILE_HANDLE"], 'success : '.$status."\n");
} else if(!$success && $return){
echo '#Status('.base64_encode(serialize(array('error' => $status))).')#'; echo "\n".serialize(array('error' => $status));
if ($GLOBALS["LOG_FILE_HANDLE"])
@fwrite($GLOBALS["LOG_FILE_HANDLE"], 'error : '.$status."\n");
//deleteCloneDirWhileError(); write now it is no need because we cant get log
} else if($return){
echo '#Status('.base64_encode(serialize(array('error' => $status))).')#'; echo "\n".serialize(array('error' => $status));
if ($GLOBALS["LOG_FILE_HANDLE"])
@fwrite($GLOBALS["LOG_FILE_HANDLE"], 'error : '.$status."\n");
}
//if($multicall)){ echo '#Status('.base64_encode(serialize(array('success' => $status, 'options' => $options))).')#'; echo "\n".serialize(array('success' => $status, 'options' => $options)); }
ob_flush(); flush();
$GLOBALS['IWP_MMB_PROFILING']['LAST_PRINT'] = $current_time;
}
function bridge_shutdown(){
$isError = false;
$isWarning = false;
if ($error = error_get_last()){
switch($error['type']){
/*case E_PARSE:*/
case E_ERROR:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_PARSE:
case E_USER_ERROR:
case E_RECOVERABLE_ERROR:
$isError = true;
break;
case E_WARNING:
case E_CORE_WARNING:
case E_USER_WARNING:
case E_NOTICE:
case E_USER_NOTICE:
case E_STRICT:
$isWarning = true;
}
}
if ($isError){
$status = 'PHP Fatal error occured: '.$error['message'].' in '.$error['file'].' on line '.$error['line'].'.';
status($status, $success=false, $return=true);
}elseif($isWarning){
$status = 'PHP Fatal error occured: '.$error['message'].' in '.$error['file'].' on line '.$error['line'].'.';
status($status, $success=false, $return=false);
}
storeCloningResponse();
}
function iwp_mmb_response($response = false, $success = true, $send_serialize_response=false)
{
$return = array();
$GLOBALS['IWP_RESPONSE_SENT'] = true;
// $response = iwp_mmb_convert_wperror_obj_to_arr($response,'initial');
if ((is_array($response) && empty($response)) || (!is_array($response) && strlen($response) == 0)){
$return['error'] = 'Empty response.';
$return['error_code'] = 'empty_response';
}
else if ($success){
$return['success'] = $response;
}
else{
$return['error'] = $response['error'];
$return['error_code'] = $response['error_code'];
}
if( !headers_sent() ){
header('HTTP/1.0 200 OK');
header('Content-Type: text/plain');
}
if (!$send_serialize_response) {
$GLOBALS['IWP_RESPONSE_SENT'] = true;
$response_data = '_IWP_JSON_PREFIX_'.base64_encode(iwp_mmb_json_encode($return));
}else{
$GLOBALS['IWP_RESPONSE_SENT'] = true;
$response_data = base64_encode(serialize($return));
}
exit("" .$response_data."");
}
function storeCloningResponse(){
global $response_arr, $download_result;
if (!empty($response_arr)) {
DB::doQuery("UNLOCK TABLES");
$exit = DB::getExists("iwp_clone_stats", "optionValue", "optionName = 'cloneStatus'");
if ($exit) {
!DB::update("iwp_clone_stats", array('optionName' => 'cloneStatus', 'optionValue' => serialize($response_arr)), "optionName = 'cloneStatus'");
}else{
DB::insert("iwp_clone_stats", array('optionName' => 'cloneStatus', 'optionValue' => serialize($response_arr))) or die(status('Error storing clone status' . DB::error(), $success=false, $return=false));
}
}else{
$exit = DB::getExists("iwp_clone_stats", "optionValue", "optionName = 'cloneStatus'");
if ($exit) {
!DB::update("iwp_clone_stats", array('optionName' => 'cloneStatus', 'optionValue' => serialize($download_result)), "optionName = 'cloneStatus'");
}else{
DB::insert("iwp_clone_stats", array('optionName' => 'cloneStatus', 'optionValue' => serialize($download_result))) or die(status('Error storing clone status' . DB::error(), $success=false, $return=false));
}
}
}
function appUpdateMsg($msg, $isError=0){
if($isError){
die(status($msg, $success=false, $return=true, $options=''));
}
else{
status($msg, $success=true, $return=false, $options='');
}
}
function iwp_mmb_auto_print($unique_task, $task_desc=''){// this will help responding web server, will keep alive the script execution
$print_every_x_secs = 5;
$current_time = microtime(1);
if(!$GLOBALS['IWP_MMB_PROFILING']['TASKS'][$unique_task]['START']){
$GLOBALS['IWP_MMB_PROFILING']['TASKS'][$unique_task]['START'] = $current_time;
}
if(!$GLOBALS['IWP_MMB_PROFILING']['LAST_PRINT'] || ($current_time - $GLOBALS['IWP_MMB_PROFILING']['LAST_PRINT']) > $print_every_x_secs){
//$print_string = "TT:".($current_time - $GLOBALS['IWP_MMB_PROFILING']['ACTION_START'])."\n";
if(!empty($task_desc)){
$print_string = $unique_task." Task Desc :".$task_desc." TT:".($current_time - $GLOBALS['IWP_MMB_PROFILING']['TASKS'][$unique_task]['START']);
}else {
$print_string = $unique_task." TT:".($current_time - $GLOBALS['IWP_MMB_PROFILING']['TASKS'][$unique_task]['START']);
}
iwp_mmb_print_flush($print_string);
$GLOBALS['IWP_MMB_PROFILING']['LAST_PRINT'] = $current_time;
}
}
function iwp_mmb_print_flush($print_string){// this will help responding web server, will keep alive the script execution
echo $print_string." ||| ";
echo "TT:".(microtime(1) - $GLOBALS['IWP_MMB_PROFILING']['ACTION_START'])."\n";
ob_flush();
flush();
}
function logExtractResponse($historyID = '', $statusArray = array(), $params=array()){
return true;
$insertID = '';
if(empty($historyID))
{
$insert = DB::insert($_REQUEST['db_table_prefix'].'iwp_extract_status', array( 'stage' => 'installClone', 'status' => $statusArray['status'], 'action' => 'installClone', 'type' => 'bridge','category' => 'installClone','historyID' => $statusArray['extractParentHID'],'finalStatus' => 'pending','startTime' => microtime(true),'endTime' => '','statusMsg' => 'blah','requestParams' => serialize($params),'taskName' => 'installCloneBridge'));
if($insert)
{
$insertID = $insert;
}
} else if((isset($statusArray['responseParams']))||(isset($statusArray['task_result']))) {
$update = DB::update($_REQUEST['db_table_prefix'].'iwp_extract_status', array( 'responseParams' => serialize($statusArray['responseParams']),'stage' => 'installClone', 'status' => $statusArray['status'],'statusMsg' => 'blah','taskResults' => isset($statusArray['task_result']) ? serialize($statusArray['task_result']) : serialize(array())), "historyID=".$historyID);
} else {
//$responseParams = $this -> getRequiredData($historyID,"responseParams");
$update = DB::update($_REQUEST['db_table_prefix'].'iwp_extract_status', array('stage' => 'installClone', 'status' => $statusArray['status'],'statusMsg' => 'blah' ),"historyID=". $historyID);
}
if( (isset($update)&&($update === false)) || (isset($insert)&&($insert === false)) )
{
die(status("Error: Insert or Update", $success=false, $return=true));
}
if((isset($statusArray['sendResponse']) && $statusArray['sendResponse'] == true) || $statusArray['status'] == 'completed')
{
$returnParams = array();
$returnParams['parentHID'] = $historyID;
$returnParams['backupRowID'] = $insertID;
$returnParams['stage'] = $statusArray['stage'] ;
$returnParams['status'] = $statusArray['status'];
$returnParams['nextFunc'] = isset($statusArray['nextFunc']) ? $statusArray['nextFunc'] : '';
return array('success' => $returnParams);
} else {
if($statusArray['status'] == 'error') {
$returnParams = array();
$returnParams['parentHID'] = $historyID;
$returnParams['backupRowID'] = $insertID;
$returnParams['stage'] = $statusArray['stage'] ;
$returnParams['status'] = $statusArray['status'];
$returnParams['statusMsg'] = $statusArray['statusMsg'];
die(status("Error: Insert or Update status", $success=false, $return=true));
}
}
}
function send_multicall_response($multicall_response){
die(status("multicall", $success=true, $return=false, $multicall_response));
}
function check_for_clone_break(){
global $extract_start_time;
$extract_time_taken = microtime(1) - $extract_start_time;
if($extract_time_taken >= 20){
return true;
}
}
function clone_error_status_log($error){
$data = DB::getField("iwp_clone_stats", "optionValue", "optionName = 'cloneErrorStatus'");
if (!empty($data)) {
!DB::update("iwp_clone_stats", array('optionName' => 'cloneErrorStatus', 'optionValue' => $data.'
'.$error), "optionName = 'cloneErrorStatus'") ;
}else{
DB::insert("iwp_clone_stats", array('optionName' => 'cloneErrorStatus', 'optionValue' => $error));
}
}
function memory_check($memory, $check_using = false) {
$memory_limit = memory_check_current($check_using);
return ($memory_limit >= $memory)?true:false;
}
function memory_check_current($memory_limit = false) {
# Returns in megabytes
if ($memory_limit == false) $memory_limit = ini_get('memory_limit');
$memory_limit = rtrim($memory_limit);
$memory_unit = $memory_limit[strlen($memory_limit)-1];
if ((int)$memory_unit == 0 && $memory_unit !== '0') {
$memory_limit = substr($memory_limit,0,strlen($memory_limit)-1);
} else {
$memory_unit = '';
}
switch($memory_unit) {
case '':
$memory_limit = floor($memory_limit/1048576);
break;
case 'K':
case 'k':
$memory_limit = floor($memory_limit/1024);
break;
case 'G':
$memory_limit = $memory_limit*1024;
break;
case 'M':
//assumed size, no change needed
break;
}
return $memory_limit;
}
function checkFileSystemRequirement(){
return false;
$tempDirName = dirname(__FILE__).time().'_IWP';
if (!mkdir($tempDirName)) {
initFileSystem(false);
$tempDirName = $GLOBALS['FileSystemObj']->findFolder($tempDirName);
$return = $GLOBALS['FileSystemObj']->mkdir($tempDirName);
if (!$return || !$GLOBALS['FileSystemObj']->chmod($tempDirName)) {
die(status("Could not change the File/Directory permission. Please give access to change permissions for your FTP/SFTP user", false ,true));
}
$return = $GLOBALS['FileSystemObj']->rmdir($tempDirName);
return true;
}
@rmdir($tempDirName);
return false;
}
function getBackupFilesByTaskName($backupDetails){
$backupFiles = array();
if (!empty($backupDetails['plugins'])) {
$backupFiles['plugins'] = $backupDetails['plugins'];
}
if (!empty($backupDetails['themes'])) {
$backupFiles['themes'] = $backupDetails['themes'];
}
if (!empty($backupDetails['others'])) {
$backupFiles['others'] = $backupDetails['others'];
}
if (!empty($backupDetails['uploads'])) {
$backupFiles['uploads'] = $backupDetails['uploads'];
}
if (!empty($backupDetails['more'])) {
$backupFiles['more'] = $backupDetails['more'];
}
$backupFiles['db'][] = $backupDetails['db'];
return $backupFiles;
}
function multiCallDownloadUsingCURL($URL, $file, &$downloadResponseHeaders, $prevResult = array(), $wpContentURL= false){
if (!function_exists('curl_init') || !function_exists('curl_exec')){
return false;
}
if(empty($prevResult['file'])){
$fp = fopen ($file, 'wb');
} else{
$file = $prevResult['file'];
$fp = fopen ($file, 'rb+');
fseek($fp, $prevResult['startRange']);
}
if(!$fp){
return false;
}
$isBreak = false;
$isMultiPart = false;
$startRange = (empty($prevResult['startRange']) && empty($prevResult['file']))? 0 : $prevResult['startRange'];
$endRange = (empty($prevResult['endRange']) && empty($prevResult['file']))? 10000000 : $prevResult['endRange'];
$totalFileSize = curl_get_file_size($URL);
$endRange = $totalFileSize;
status("Downloading file ".$URL, $success=true, $return=false);
do{
$ch = curl_init($URL);
curl_setopt($ch, CURLOPT_TIMEOUT, 300);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Connection: Keep-Alive',
'Keep-Alive: 115'
));
$rangeVariable = $startRange . '-' . $endRange;
curl_setopt($ch, CURLOPT_RANGE, $rangeVariable);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false );
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false );
$callResponse = curl_exec($ch);
//write in file
$currentOffest = (empty($startRange)) ? 0 : $startRange;
@fseek($fp, $currentOffest, SEEK_SET);
@fwrite($fp, $callResponse);
$info = curl_getinfo($ch);
curl_close($ch);
if($info['http_code'] == '206'){
//multiCallDownloadUsingCURL($URL, $file, $downloadResponseHeaders);
$isMultiPart = true;
$startRange = ftell($fp);
$endRange = ($startRange + 10000000);
if($endRange >= $totalFileSize){
$endRange = $totalFileSize;
}
if($startRange == $endRange){
$isMultiPart = false;
}
}
$rangeVariable = $startRange . '-' . $endRange;
$isBreak = check_for_clone_break();
}
while(!($isBreak) && $isMultiPart);
fclose($fp);
$currentResult = array();
initialize_response_array($currentResult);
$currentResult['file'] = $file;
$currentResult['startRange'] = $startRange;
$currentResult['endRange'] = $endRange;
if($isBreak == true){
$currentResult['status'] = 'partiallyCompleted';
$currentResult['isDownloadMultiCall'] = true;
}
if(!$isMultiPart){
$currentResult['isDownloadMultiCall'] = false;
}
$downloadResponseHeaders[] = "HTTP/1.1 ".$info['http_code']." SOMETHING";
$downloadResponseHeaders[] = "Content-Type: ".$info['content_type'];
return $currentResult;
}
function checkdownloadResponseHeaders($headers){
$httpCodeChecked = false;
foreach($headers as $line){
if(!$httpCodeChecked && stripos($line, 'HTTP/') !== false){
$matches = array();
preg_match('#HTTP/\d+\.\d+ (\d+)#', $line, $matches);
$httpCode = (int)$matches[1];
if($httpCode != 200 && $httpCode != 206){
die(status("Error while downloading the zip file HTTP error: ".$httpCode.".", false ,true));
}
$httpCodeChecked = true;
}
if(stripos($line, 'Content-Type') !== false){
//$contentType = trim(str_ireplace('Content-Type:', '', $line));
//if(strtolower($contentType) != 'application/zip')
if(stripos($line, 'application/zip') === false){
//die(status("Invalid zip type, please check file is downloadable.", false ,true));
$GLOBALS['downloadPossibleError'] = " Please check file is downloadable.";
}
}
}
return true;
}
function curl_get_file_size($url) {
// Assume failure.
$result = -1;
$curl = curl_init( $url );
// Issue a HEAD request and follow any redirects.
curl_setopt( $curl, CURLOPT_NOBODY, true );
curl_setopt( $curl, CURLOPT_HEADER, true );
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $curl, CURLOPT_FOLLOWLOCATION, true );
curl_setopt( $curl, CURLOPT_SSL_VERIFYHOST, false );
curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:16.0) Gecko Firefox/16.0' );
$data = curl_exec( $curl );
$curlInfo = array();
$curlInfo['info'] = curl_getinfo($curl);
if(curl_errno($curl)){
$curlInfo['errorNo'] = curl_errno($curl);
$curlInfo['error'] = curl_error($curl);
}
curl_close( $curl );
if( $data ) {
$content_length = "unknown";
$status = "unknown";
if( preg_match( "/Content-Length: (\d+)/", $data, $matches ) ) {
$content_length = (int)$matches[1];
}
if ($content_length == 'unknown' && preg_match( "/content-length: (\d+)/", $data, $matches )) {
$content_length = (int)$matches[1];
}
$status = $curlInfo['info']['http_code'];
// http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
if( $status == 200 || ($status > 300 && $status <= 308) ) {
$result = $content_length;
}
}
if ($result == -1) {
$headers = @get_headers($url, 1);
if (!empty($headers["Content-Length"]) && $headers["Content-Length"]>0) {
return $headers["Content-Length"];
}
}
if ($result == -1) {
$content_length = (int)$curlInfo['info']['download_content_length'];
if ($content_length >0) {
return $content_length;
}
}
return $result;
}
// if(!function_exists('iwp_get_file_size')){
function iwp_get_file_size($file)
{
clearstatcache();
$normal_file_size = filesize($file);
if(($normal_file_size !== false)&&($normal_file_size >= 0))
{
return $normal_file_size;
}
else
{
$file = realPath($file);
if(!$file)
{
echo 'iwp_get_file_size_error : realPath error';
}
$ch = curl_init("file://" . $file);
curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_FILE);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
$data = curl_exec($ch);
$curl_error = curl_error($ch);
curl_close($ch);
if ($data !== false && preg_match('/Content-Length: (\d+)/', $data, $matches)) {
return (string) $matches[1];
}
else
{
echo 'iwp_get_file_size_error : '.$curl_error;
return $normal_file_size;
}
}
}
//}
function is_file_encrypted($file) {
return preg_match('/\.crypt$/i', $file);
}
function decrypt_db($fullpath, $key, $to_temporary_file = false) {
// open file to read
if (false === ($file_handle = fopen($fullpath, 'rb'))) return false;
$decrypted_path = dirname($fullpath).'/decrypt_'.basename($fullpath).'.tmp';
// open new file from new path
if (false === ($decrypted_handle = fopen($decrypted_path, 'wb+'))) return false;
// setup encryption
$rijndael = new Crypt_Rijndael();
$rijndael->setKey($key);
$rijndael->disablePadding();
$rijndael->enableContinuousBuffer();
if (defined('IWP_DECRYPTION_ENGINE')) {
if ('openssl' == IWP_DECRYPTION_ENGINE) {
$rijndael->setPreferredEngine(CRYPT_ENGINE_OPENSSL);
} elseif ('mcrypt' == IWP_DECRYPTION_ENGINE) {
$rijndael->setPreferredEngine(CRYPT_ENGINE_MCRYPT);
} elseif ('internal' == IWP_DECRYPTION_ENGINE) {
$rijndael->setPreferredEngine(CRYPT_ENGINE_INTERNAL);
}
}
$file_size = filesize($fullpath);
$bytes_decrypted = 0;
$buffer_size = defined('IWP_CRYPT_BUFFER_SIZE') ? IWP_CRYPT_BUFFER_SIZE : 2097152;
// loop around the file
while ($bytes_decrypted < $file_size) {
// read buffer sized amount from file
if (false === ($file_part = fread($file_handle, $buffer_size))) return false;
// check to ensure padding is needed before decryption
$length = strlen($file_part);
if (0 != $length % 16) {
$pad = 16 - ($length % 16);
$file_part = str_pad($file_part, $length + $pad, chr($pad));
}
$decrypted_data = $rijndael->decrypt($file_part);
if (0 == $bytes_decrypted) {
if (str_ends_with_old($fullpath, '.gz.crypt')) {
// str_ends_with() introduced php8 pre-define function so str_ends_with changed to str_ends_with_old
$first_two_chars = unpack('C*', substr($decrypted_data, 0, 2));
// The first two decrypted bytes of the .gz file should always be 1f 8b
if (31 != $first_two_chars[1] || 139 != $first_two_chars[2]) {
return false;
}
} elseif (str_ends_with_old($fullpath, '.zip.crypt')) {
$first_four_chars = unpack('C*', substr($decrypted_data, 0, 2));
// The first four decrypted bytes of the .zip file should always be 50 4B 03 04 or 50 4B 05 06 or 50 4B 07 08
if (80 != $first_four_chars[1] || 75 != $first_four_chars[2] || !in_array($first_four_chars[3], array(3, 5, 7)) || !in_array($first_four_chars[3], array(4, 6, 8))) {
return false;
}
}
}
$is_last_block = ($bytes_decrypted + strlen($decrypted_data) >= $file_size);
$write_bytes = min($file_size - $bytes_decrypted, strlen($decrypted_data));
if ($is_last_block) {
$is_padding = false;
$last_byte = ord(substr($decrypted_data, -1, 1));
if ($last_byte < 16) {
$is_padding = true;
for ($j = 1; $j<=$last_byte; $j++) {
if (substr($decrypted_data, -$j, 1) != chr($last_byte)) $is_padding = false;
}
}
if ($is_padding) {
$write_bytes -= $last_byte;
}
}
if (false === fwrite($decrypted_handle, $decrypted_data, $write_bytes)) return false;
$bytes_decrypted += $buffer_size;
}
// close the main file handle
fclose($decrypted_handle);
// close original file
fclose($file_handle);
// remove the crypt extension from the end as this causes issues when opening
$fullpath_new = preg_replace('/\.crypt$/', '', $fullpath, 1);
// //need to replace original file with tmp file
$fullpath_basename = basename($fullpath_new);
if ($to_temporary_file) {
return array(
'fullpath' => $decrypted_path,
'basename' => $fullpath_basename
);
}
if (false === rename($decrypted_path, $fullpath_new)) return false;
// need to send back the new decrypted path
$decrypt_return = array(
'fullpath' => $fullpath_new,
'basename' => $fullpath_basename
);
return $decrypt_return;
}
function str_ends_with_old($haystack, $needle) {
if (substr($haystack, - strlen($needle)) == $needle) return true;
return false;
}
function connfigFileProcess(){
if (file_exists(dirname(dirname(__FILE__)).'/wp-config.php')) {
$obj = new IWP_WPConfig();
$configContent = $obj->tokenParser(dirname(dirname(__FILE__)).'/wp-config.php');
iwp_define_constants($configContent);
$GLOBALS['table_prefix'] = get_table_prefix(dirname(dirname(__FILE__)));
}
if(empty($configContent['DB_NAME'])){
require '../wp-load.php';
global $wpdb;
$GLOBALS['table_prefix'] = $wpdb->base_prefix;
}
}
function definePCLZipConstants(){
if (!defined('IWP_PCLZIP_READ_BLOCK_SIZE')) {
define( 'IWP_PCLZIP_READ_BLOCK_SIZE', 2048 );
}
if (!defined('IWP_PCLZIP_SEPARATOR')) {
define( 'IWP_PCLZIP_SEPARATOR', ',' );
}
if (!defined('IWP_PCLZIP_ERROR_EXTERNAL')) {
define( 'IWP_PCLZIP_ERROR_EXTERNAL', 0 );
}
if (!defined('IWP_PCLZIP_TEMPORARY_DIR')) {
define( 'IWP_PCLZIP_TEMPORARY_DIR', '' );
}
if (!defined('IWP_PCLZIP_TEMPORARY_FILE_RATIO')) {
define( 'IWP_PCLZIP_TEMPORARY_FILE_RATIO', 0.47 );
}
$g_pclzip_version = "2.8.2";
define( 'IWP_PCLZIP_ERR_USER_ABORTED', 2 );
define( 'IWP_PCLZIP_ERR_NO_ERROR', 0 );
define( 'IWP_PCLZIP_ERR_WRITE_OPEN_FAIL', -1 );
define( 'IWP_PCLZIP_ERR_READ_OPEN_FAIL', -2 );
define( 'IWP_PCLZIP_ERR_INVALID_PARAMETER', -3 );
define( 'IWP_PCLZIP_ERR_MISSING_FILE', -4 );
define( 'IWP_PCLZIP_ERR_FILENAME_TOO_LONG', -5 );
define( 'IWP_PCLZIP_ERR_INVALID_ZIP', -6 );
define( 'IWP_PCLZIP_ERR_BAD_EXTRACTED_FILE', -7 );
define( 'IWP_PCLZIP_ERR_DIR_CREATE_FAIL', -8 );
define( 'IWP_PCLZIP_ERR_BAD_EXTENSION', -9 );
define( 'IWP_PCLZIP_ERR_BAD_FORMAT', -10 );
define( 'IWP_PCLZIP_ERR_DELETE_FILE_FAIL', -11 );
define( 'IWP_PCLZIP_ERR_RENAME_FILE_FAIL', -12 );
define( 'IWP_PCLZIP_ERR_BAD_CHECKSUM', -13 );
define( 'IWP_PCLZIP_ERR_INVALID_ARCHIVE_ZIP', -14 );
define( 'IWP_PCLZIP_ERR_MISSING_OPTION_VALUE', -15 );
define( 'IWP_PCLZIP_ERR_INVALID_OPTION_VALUE', -16 );
define( 'IWP_PCLZIP_ERR_ALREADY_A_DIRECTORY', -17 );
define( 'IWP_PCLZIP_ERR_UNSUPPORTED_COMPRESSION', -18 );
define( 'IWP_PCLZIP_ERR_UNSUPPORTED_ENCRYPTION', -19 );
define( 'IWP_PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE', -20 );
define( 'IWP_PCLZIP_ERR_DIRECTORY_RESTRICTION', -21 );
// ----- Options values
define( 'IWP_PCLZIP_OPT_PATH', 77001 );
define( 'IWP_PCLZIP_OPT_ADD_PATH', 77002 );
define( 'IWP_PCLZIP_OPT_REMOVE_PATH', 77003 );
define( 'IWP_PCLZIP_OPT_REMOVE_ALL_PATH', 77004 );
define( 'IWP_PCLZIP_OPT_SET_CHMOD', 77005 );
define( 'IWP_PCLZIP_OPT_EXTRACT_AS_STRING', 77006 );
define( 'IWP_PCLZIP_OPT_NO_COMPRESSION', 77007 );
define( 'IWP_PCLZIP_OPT_BY_NAME', 77008 );
define( 'IWP_PCLZIP_OPT_BY_INDEX', 77009 );
define( 'IWP_PCLZIP_OPT_BY_EREG', 77010 );
define( 'IWP_PCLZIP_OPT_BY_PREG', 77011 );
define( 'IWP_PCLZIP_OPT_COMMENT', 77012 );
define( 'IWP_PCLZIP_OPT_ADD_COMMENT', 77013 );
define( 'IWP_PCLZIP_OPT_PREPEND_COMMENT', 77014 );
define( 'IWP_PCLZIP_OPT_EXTRACT_IN_OUTPUT', 77015 );
define( 'IWP_PCLZIP_OPT_REPLACE_NEWER', 77016 );
define( 'IWP_PCLZIP_OPT_STOP_ON_ERROR', 77017 );
// Having big trouble with crypt. Need to multiply 2 long int
// which is not correctly supported by PHP ...
//define( 'IWP_PCLZIP_OPT_CRYPT', 77018 );
define( 'IWP_PCLZIP_OPT_EXTRACT_DIR_RESTRICTION', 77019 );
define( 'IWP_PCLZIP_OPT_CHUNK_BLOCK_SIZE', 78999 ); //darkCode
define( 'IWP_PCLZIP_OPT_HISTORY_ID', 79999 ); //darkCode
define( 'IWP_PCLZIP_OPT_FILE_EXCLUDE_SIZE', 79997 ); //darkCode
define( 'IWP_PCLZIP_OPT_TEMP_FILE_THRESHOLD', 77020 );
define( 'IWP_PCLZIP_OPT_ADD_TEMP_FILE_THRESHOLD', 77020 ); // alias
define( 'IWP_PCLZIP_OPT_TEMP_FILE_ON', 77021 );
define( 'IWP_PCLZIP_OPT_ADD_TEMP_FILE_ON', 77021 ); // alias
define( 'IWP_PCLZIP_OPT_TEMP_FILE_OFF', 77022 );
define( 'IWP_PCLZIP_OPT_ADD_TEMP_FILE_OFF', 77022 ); // alias
define( 'IWP_PCLZIP_OPT_IWP_EXCLUDE', 77999 );//IWP Mod
define( 'IWP_PCLZIP_OPT_IWP_EXCLUDE_EXT', 78998 );//darkCode
// ----- File description attributes
define( 'IWP_PCLZIP_ATT_FILE_NAME', 79001 );
define( 'IWP_PCLZIP_ATT_FILE_NEW_SHORT_NAME', 79002 );
define( 'IWP_PCLZIP_ATT_FILE_NEW_FULL_NAME', 79003 );
define( 'IWP_PCLZIP_ATT_FILE_MTIME', 79004 );
define( 'IWP_PCLZIP_ATT_FILE_CONTENT', 79005 );
define( 'IWP_PCLZIP_ATT_FILE_COMMENT', 79006 );
// ----- Call backs values
define( 'IWP_PCLZIP_CB_PRE_EXTRACT', 78001 );
define( 'IWP_PCLZIP_CB_POST_EXTRACT', 78002 );
define( 'IWP_PCLZIP_CB_PRE_ADD', 78003 );
define( 'IWP_PCLZIP_CB_POST_ADD', 78004 );
}
function iwpAddTrailingSlash($string) {
return iwpRemoveTrailingSlash($string) . '/';
}
function iwpRemoveTrailingSlash($string) {
return rtrim($string, '/');
}
function getTempName($fileName = '', $dir = '') {
if ( empty($dir) )
$dir = getTempDir();
$fileName = basename($fileName);
if ( empty($fileName) )
$fileName = time();
$fileName = preg_replace('|\..*$|', '.tmp', $fileName);
$fileName = $dir . getUniqueFileName($dir, $fileName);
touch($fileName);
return $fileName;
}
function getUniqueFileName( $dir, $fileName) {
// separate the fileName into a name and extension
$info = pathinfo($fileName);
$ext = !empty($info['extension']) ? '.' . $info['extension'] : '';
$name = basename($fileName, $ext);
// edge case: if file is named '.ext', treat as an empty name
if ( $name === $ext )
$name = '';
// Increment the file number until we have a unique file to save in $dir. Use callback if supplied.
$number = '';
// change '.ext' to lower case
if ( $ext && strtolower($ext) != $ext ) {
$ext2 = strtolower($ext);
$fileName2 = preg_replace( '|' . preg_quote($ext) . '$|', $ext2, $fileName );
// check for both lower and upper case extension or image sub-sizes may be overwritten
while ( file_exists($dir . "/$fileName") || file_exists($dir . "/$fileName2") ) {
$newNumber = $number + 1;
$fileName = str_replace( "$number$ext", "$newNumber$ext", $fileName );
$fileName2 = str_replace( "$number$ext2", "$newNumber$ext2", $fileName2 );
$number = $newNumber;
}
return $fileName2;
}
while ( file_exists( $dir . "/$fileName" ) ) {
if ( '' == "$number$ext" )
$fileName = $fileName . ++$number . $ext;
else
$fileName = str_replace( "$number$ext", ++$number . $ext, $fileName );
}
return $fileName;
}
function getTempDir() {
static $temp;
if ( defined('TEMP_DIR') )
return iwpAddTrailingSlash(TEMP_DIR);
if ( $temp )
return iwpAddTrailingSlash($temp);
$temp = dirname(__FILE__).'/clone_temp/';//dirname(__FILE__) = clone_controller folder
if ( is_dir($temp) && @is_writable($temp) )
return $temp;
if ( function_exists('sys_get_temp_dir') ) {
$temp = sys_get_temp_dir();
if ( @is_writable($temp) )
return iwpAddTrailingSlash($temp);
}
$temp = ini_get('upload_tmp_dir');
if ( is_dir($temp) && @is_writable($temp) )
return iwpAddTrailingSlash($temp);
$temp = '/tmp/';
if ( is_dir($temp) && @is_writable($temp) )
return iwpAddTrailingSlash($temp);
die(status('Unable to write files. Please set 777 permission to "/clone_controller/clone_temp" directory in the clone destination and try again.', $success=false, $return=true));
return iwpAddTrailingSlash($temp);
}
function getFileSystemMethod($args = array(), $context = false) {
$method = defined('FS_METHOD') ? FS_METHOD : false; //Please ensure that this is either 'direct', 'ssh', 'FTPExt' or 'ftpsockets'
if ( ! $method && function_exists('getmyuid') && function_exists('fileowner') && 0 ){
if ( !$context )
$context = dirname(dirname(__FILE__));
$context = iwpAddTrailingSlash($context);
$tempFileName = $context . 'tempWriteTest_' . time();
$tempHandle = @fopen($tempFileName, 'w');
if ( $tempHandle ) {
if ( getmyuid() == @fileowner($tempFileName) )
$method = 'direct';
@fclose($tempHandle);
@unlink($tempFileName);
}
}
//if ( ! $method && ($args['use_sftp']==1) && extension_loaded('ssh2') && function_exists('stream_get_contents') ) $method = 'SSH2Ext';
if ( ! $method && defined('APP_FTP_USE_SFTP') && APP_FTP_USE_SFTP == 1 ) {$method = 'SFTPExt'; return $method;}
if ( ! $method && extension_loaded('ftp') ) {$method = 'FTPExt';return $method; }
//if ( ! $method && ( extension_loaded('sockets') || function_exists('fsockopen') ) ) $method = 'ftpsockets'; //Sockets: Socket extension; PHP Mode: FSockopen / fwrite / fread
if( !$method ){
$method = 'direct';//fail safe value
status("No file system method is detected so using direct as a fail safe method.", $success=true, $return=false);
}
//$method = 'SFTPExt';
return $method;
}
function initFileSystem($args = false, $context = false){
if(empty($args)){
$args = array('hostname' => (defined('APP_FTP_HOST') && APP_FTP_HOST) ? APP_FTP_HOST : '',
'port' => (defined('APP_FTP_PORT') && APP_FTP_PORT) ? APP_FTP_PORT : '',
'username' => (defined('APP_FTP_USER') && APP_FTP_USER) ? APP_FTP_USER : '',
'password' => (defined('APP_FTP_PASS') && APP_FTP_PASS) ? APP_FTP_PASS : '',
'base' => (defined('APP_FTP_BASE') && APP_FTP_BASE) ? APP_FTP_BASE : '',
'connectionType' => (defined('APP_FTP_SSL') && APP_FTP_SSL) ? 'ftps' : '',
'passive' => (defined('APP_FTP_PASV') && APP_FTP_PASV) ? APP_FTP_PASV : '',
'hostKey' => (defined('APP_FTP_KEY') && APP_FTP_KEY ) ? APP_FTP_KEY : ''
);
}
$method = getFileSystemMethod($args, $context);
if (!$method)
return false;
$method = "fileSystem".ucfirst($method);
appUpdateMsg('Using '.$method.' file system..');
$GLOBALS['FileSystemObj'] = new $method($args);
//Define the timeouts for the connections. Only available after the construct is called to allow for per-transport overriding of the default.
if ( ! defined('FS_CONNECT_TIMEOUT') )
define('FS_CONNECT_TIMEOUT', 30);
if ( ! defined('FS_TIMEOUT') )
define('FS_TIMEOUT', 30);
//if ( is_error($FileSystemObj->errors) && $FileSystemObj->errors->get_error_code() )
// return false;
if ( !$GLOBALS['FileSystemObj']->connect() )
return false; //There was an error connecting to the server.
// Set the permission constants if not already set.
if ( ! defined('FS_CHMOD_DIR') )
define('FS_CHMOD_DIR', 0755 );
if ( ! defined('FS_CHMOD_FILE') )
define('FS_CHMOD_FILE', 0644 );
return true;
}
function iwp_define_constants($configContent){
if (isset($configContent['DB_NAME'])) {
define('DB_NAME', $configContent['DB_NAME'] );
}
if (isset($configContent['DB_USER'])) {
define('DB_USER', $configContent['DB_USER'] );
}
if (isset($configContent['DB_PASSWORD'])) {
define('DB_PASSWORD', $configContent['DB_PASSWORD'] );
}
if (isset($configContent['DB_HOST'])) {
define('DB_HOST', $configContent['DB_HOST'] );
}
}
class IWP_WPConfig
{
public function tokenParser($wpconfig_path) {
$defines = array();
$wpconfig_file = @file_get_contents($wpconfig_path);
if (!function_exists('token_get_all')) {
return $defines;
}
if ($wpconfig_file === false) {
return $defines;
}
$defines = array();
$tokens = token_get_all($wpconfig_file);
$token = reset($tokens);
while ($token) {
if (is_array($token)) {
if ($token[0] == T_WHITESPACE || $token[0] == T_COMMENT || $token[0] == T_DOC_COMMENT) {
// do nothing
} else if ($token[0] == T_STRING && strtolower($token[1]) == 'define') {
$state = 1;
} else if ($state == 2 && self::isConstant($token[0])) {
$key = $token[1];
$state = 3;
} else if ($state == 4 && self::isConstant($token[0])) {
$value = $token[1];
$state = 5;
}
} else {
$symbol = trim($token);
if ($symbol == '(' && $state == 1) {
$state = 2;
} else if ($symbol == ',' && $state == 3) {
$state = 4;
} else if ($symbol == ')' && $state == 5) {
$defines[self::tokenStrip($key)] = self::tokenStrip($value);
$state = 0;
}
}
$token = next($tokens);
}
return $defines;
}
private static function tokenStrip($value)
{
return preg_replace('!^([\'"])(.*)\1$!', '$2', $value);
}
private static function isConstant($token)
{
return $token == T_CONSTANT_ENCAPSED_STRING || $token == T_STRING || $token == T_LNUMBER || $token == T_DNUMBER;
}
}
class filesystemBase {
var $verbose = false;
var $cache = array();
var $method = '';
function findFolder($folder) {
if (( stripos($this->method, 'ftp') !== false) || 'ssh2' == $this->method || 'sftp' == $this->method ) {
$folder = str_replace(dirname(dirname(__FILE__)), APP_FTP_BASE, $folder);//dirname(dirname(__FILE__)) => one folder up to clone_controller
$folder = str_replace('//', '/', $folder);//removing any // in the path
return iwpAddTrailingSlash($folder);
} elseif ( 'direct' == $this->method ) {
$folder = str_replace('\\', '/', $folder); //Windows path sanitisation
return iwpAddTrailingSlash($folder);
}
return false;
}
function getHChmod($file){
$perms = $this->getChmod($file);
if (($perms & 0xC000) == 0xC000) // Socket
$info = 's';
elseif (($perms & 0xA000) == 0xA000) // Symbolic Link
$info = 'l';
elseif (($perms & 0x8000) == 0x8000) // Regular
$info = '-';
elseif (($perms & 0x6000) == 0x6000) // Block special
$info = 'b';
elseif (($perms & 0x4000) == 0x4000) // Directory
$info = 'd';
elseif (($perms & 0x2000) == 0x2000) // Character special
$info = 'c';
elseif (($perms & 0x1000) == 0x1000) // FIFO pipe
$info = 'p';
else // Unknown
$info = 'u';
// Owner
$info .= (($perms & 0x0100) ? 'r' : '-');
$info .= (($perms & 0x0080) ? 'w' : '-');
$info .= (($perms & 0x0040) ?
(($perms & 0x0800) ? 's' : 'x' ) :
(($perms & 0x0800) ? 'S' : '-'));
// Group
$info .= (($perms & 0x0020) ? 'r' : '-');
$info .= (($perms & 0x0010) ? 'w' : '-');
$info .= (($perms & 0x0008) ?
(($perms & 0x0400) ? 's' : 'x' ) :
(($perms & 0x0400) ? 'S' : '-'));
// World
$info .= (($perms & 0x0004) ? 'r' : '-');
$info .= (($perms & 0x0002) ? 'w' : '-');
$info .= (($perms & 0x0001) ?
(($perms & 0x0200) ? 't' : 'x' ) :
(($perms & 0x0200) ? 'T' : '-'));
return $info;
}
function getNumChmodFromH($mode) {
$realMode = '';
$legal = array('', 'w', 'r', 'x', '-');
$attArray = preg_split('//', $mode);
for ($i=0; $i < count($attArray); $i++)
if ($key = array_search($attArray[$i], $legal))
$realMode .= $legal[$key];
$mode = str_pad($realMode, 9, '-');
$trans = array('-'=>'0', 'r'=>'4', 'w'=>'2', 'x'=>'1');
$mode = strtr($mode,$trans);
$newmode = '';
$newmode .= $mode[0] + $mode[1] + $mode[2];
$newmode .= $mode[3] + $mode[4] + $mode[5];
$newmode .= $mode[6] + $mode[7] + $mode[8];
return $newmode;
}
function copyDir($from, $to, $skipList = array() ) {
//global $GLOBALS['FileSystemObj'];
$dirlist = $GLOBALS['FileSystemObj']->dirList($from);
$from = iwpAddTrailingSlash($from);
$to = iwpAddTrailingSlash($to);
$skipRegex = '';
foreach ( (array)$skipList as $key => $skipFile )
$skipRegex .= preg_quote($skipFile, '!') . '|';
if ( !empty($skipRegex) )
$skipRegex = '!(' . rtrim($skipRegex, '|') . ')$!i';
foreach ( (array) $dirlist as $filename => $fileinfo ) {
if ( !empty($skipRegex) )
if ( preg_match($skipRegex, $from . $filename) )
continue;
if ( 'f' == $fileinfo['type'] ) {
if ( ! $GLOBALS['FileSystemObj']->copy($from . $filename, $to . $filename, true, FS_CHMOD_FILE) ) {
// If copy failed, chmod file to 0644 and try again.
$GLOBALS['FileSystemObj']->chmod($to . $filename, 0644);
if ( ! $GLOBALS['FileSystemObj']->copy($from . $filename, $to . $filename, true, FS_CHMOD_FILE) ){
//return new WP_Error('copy_failed', __('Could not copy file.'), $to . $filename);
appUpdateMsg('Could not copy file '.$to . $file['filename'], true);
return false;
}
}
} elseif ( 'd' == $fileinfo['type'] ) {
if ( !$GLOBALS['FileSystemObj']->isDir($to . $filename) ) {
if ( !$GLOBALS['FileSystemObj']->mkDir($to . $filename, FS_CHMOD_DIR) ){
//return new WP_Error('mkdir_failed', __('Could not create directory.'), $to . $filename);
appUpdateMsg('Could not create directory '.$to . $filename, true);
return false;
}
}
$result = $this->copyDir($from . $filename, $to . $filename, $skipList);
if ( $result == false )
return $result;
}
}
return true;
}
}
class filesystemDirect extends filesystemBase {
function __construct($arg) {
$this->method = 'direct';
//$this->errors = new WP_Error();
}
function connect() {
return true;
}
/**
* Reads entire file into a string
*
* @param string $file Name of the file to read.
* @return string|bool The function returns the read data or false on failure.
*/
function getContents($file) {
return @file_get_contents($file);
}
/**
* Reads entire file into an array
*
* @param string $file Path to the file.
* @return array|bool the file contents in an array or false on failure.
*/
function getContentsArray($file) {
return @file($file);
}
/**
* Write a string to a file
*
* @param string $file Remote path to the file where to write the data.
* @param string $contents The data to write.
* @param int $mode (optional) The file permissions as octal number, usually 0644.
* @return bool False upon failure.
*/
function putContents($file, $contents, $mode = false ) {
if ( ! ($fp = @fopen($file, 'w')) )
return false;
@fwrite($fp, $contents);
@fclose($fp);
$this->chmod($file, $mode);
return true;
}
/**
* Gets the current working directory
*
* @return string|bool the current working directory on success, or false on failure.
*/
function cwd() {
return @getcwd();
}
/**
* Change directory
*
* @param string $dir The new current directory.
* @return bool Returns true on success or false on failure.
*/
function chdir($dir) {
return @chdir($dir);
}
/**
* Changes file group
*
* @param string $file Path to the file.
* @param mixed $group A group name or number.
* @param bool $recursive (optional) If set True changes file group recursively. Defaults to False.
* @return bool Returns true on success or false on failure.
*/
function chgrp($file, $group, $recursive = false) {
if ( ! $this->exists($file) )
return false;
if ( ! $recursive )
return @chgrp($file, $group);
if ( ! $this->isDir($file) )
return @chgrp($file, $group);
//Is a directory, and we want recursive
$file = iwpAddTrailingSlash($file);
$fileList = $this->dirList($file);
foreach ($fileList as $fileName)
$this->chgrp($file . $fileName, $group, $recursive);
return true;
}
/**
* Changes filesystem permissions
*
* @param string $file Path to the file.
* @param int $mode (optional) The permissions as octal number, usually 0644 for files, 0755 for dirs.
* @param bool $recursive (optional) If set True changes file group recursively. Defaults to False.
* @return bool Returns true on success or false on failure.
*/
function chmod($file, $mode = false, $recursive = false) {
if ( ! $mode ) {
if ( $this->isFile($file) )
$mode = FS_CHMOD_FILE;
elseif ( $this->isDir($file) )
$mode = FS_CHMOD_DIR;
else
return false;
}
if ( ! $recursive || ! $this->isDir($file) )
return @chmod($file, $mode);
//Is a directory, and we want recursive
$file = iwpAddTrailingSlash($file);
$fileList = $this->dirList($file);
foreach ( (array)$fileList as $fileName => $filemeta)
$this->chmod($file . $fileName, $mode, $recursive);
return true;
}
/**
* Changes file owner
*
* @param string $file Path to the file.
* @param mixed $owner A user name or number.
* @param bool $recursive (optional) If set True changes file owner recursively. Defaults to False.
* @return bool Returns true on success or false on failure.
*/
function chown($file, $owner, $recursive = false) {
if ( ! $this->exists($file) )
return false;
if ( ! $recursive )
return @chown($file, $owner);
if ( ! $this->isDir($file) )
return @chown($file, $owner);
//Is a directory, and we want recursive
$fileList = $this->dirList($file);
foreach ($fileList as $fileName) {
$this->chown($file . '/' . $fileName, $owner, $recursive);
}
return true;
}
/**
* Gets file owner
*
* @param string $file Path to the file.
* @return string Username of the user.
*/
function owner($file) {
$owneruid = @fileowner($file);
if ( ! $owneruid )
return false;
if ( ! function_exists('posix_getpwuid') )
return $owneruid;
$ownerarray = posix_getpwuid($owneruid);
return $ownerarray['name'];
}
/**
* Gets file permissions
*
* FIXME does not handle errors in fileperms()
*
* @param string $file Path to the file.
* @return string Mode of the file (last 4 digits).
*/
function getChmod($file) {
return substr(decoct(@fileperms($file)),3);
}
function group($file) {
$gid = @filegroup($file);
if ( ! $gid )
return false;
if ( ! function_exists('posix_getgrgid') )
return $gid;
$grouparray = posix_getgrgid($gid);
return $grouparray['name'];
}
function copy($source, $destination, $overwrite = false, $mode = false) {
if ( ! $overwrite && $this->exists($destination) )
return false;
$rtval = copy($source, $destination);
if ( $mode )
$this->chmod($destination, $mode);
return $rtval;
}
function move($source, $destination, $overwrite = false) {
if ( ! $overwrite && $this->exists($destination) )
return false;
// try using rename first. if that fails (for example, source is read only) try copy
if ( @rename($source, $destination) )
return true;
if ( $this->copy($source, $destination, $overwrite) && $this->exists($destination) ) {
$this->delete($source);
return true;
} else {
return false;
}
}
function delete($file, $recursive = false, $type = false) {
if ( empty($file) ) //Some filesystems report this as /, which can cause non-expected recursive deletion of all files in the filesystem.
return false;
$file = str_replace('\\', '/', $file); //for win32, occasional problems deleting files otherwise
if ( 'f' == $type || $this->isFile($file) )
return @unlink($file);
if ( ! $recursive && $this->isDir($file) )
return @rmdir($file);
//At this point its a folder, and we're in recursive mode
$file = iwpAddTrailingSlash($file);
$fileList = $this->dirList($file, true);
$retval = true;
if ( is_array($fileList) ) //false if no files, So check first.
foreach ($fileList as $fileName => $fileinfo){
iwp_mmb_auto_print('recursive_delete');
if ( ! $this->delete($file . $fileName, $recursive, $fileinfo['type']) )
$retval = false;
}
if ( file_exists($file) && ! @rmdir($file) )
$retval = false;
return $retval;
}
function exists($file) {
return @file_exists($file);
}
function isFile($file) {
return @is_file($file);
}
function isDir($path) {
return @is_dir($path);
}
function isReadable($file) {
return @is_readable($file);
}
function isWritable($file) {
return @is_writable($file);
}
function atime($file) {
return @fileatime($file);
}
function mtime($file) {
return @filemtime($file);
}
function size($file) {
return @filesize($file);
}
function touch($file, $time = 0, $atime = 0) {
if ($time == 0)
$time = time();
if ($atime == 0)
$atime = time();
return @touch($file, $time, $atime);
}
function mkDir($path, $chmod = false, $chown = false, $chgrp = false) {
// safe mode fails with a trailing slash under certain PHP versions.
$path = iwpRemoveTrailingSlash($path);
if ( empty($path) )
return false;
if ( ! $chmod )
$chmod = FS_CHMOD_DIR;
if ( ! @mkdir($path) )
return false;
$this->chmod($path, $chmod);
if ( $chown )
$this->chown($path, $chown);
if ( $chgrp )
$this->chgrp($path, $chgrp);
return true;
}
function rmDir($path, $recursive = false) {
return $this->delete($path, $recursive);
}
function dirList($path, $includeHidden = true, $recursive = false) {
if ( $this->isFile($path) ) {
$limitFile = basename($path);
$path = dirname($path);
} else {
$limitFile = false;
}
if ( ! $this->isDir($path) )
return false;
$dir = @dir($path);
if ( ! $dir )
return false;
$ret = array();
while (false !== ($entry = $dir->read()) ) {
$struc = array();
$struc['name'] = $entry;
if ( '.' == $struc['name'] || '..' == $struc['name'] )
continue;
if ( ! $includeHidden && '.' == $struc['name'][0] )
continue;
if ( $limitFile && $struc['name'] != $limitFile)
continue;
$struc['perms'] = $this->getHChmod($path.'/'.$entry);
$struc['permsn'] = $this->getNumChmodFromH($struc['perms']);
$struc['number'] = false;
$struc['owner'] = $this->owner($path.'/'.$entry);
$struc['group'] = $this->group($path.'/'.$entry);
$struc['size'] = $this->size($path.'/'.$entry);
$struc['lastmodunix']= $this->mtime($path.'/'.$entry);
$struc['lastmod'] = @date('M j',$struc['lastmodunix']);
$struc['time'] = @date('h:i:s',$struc['lastmodunix']);
$struc['type'] = $this->isDir($path.'/'.$entry) ? 'd' : 'f';
if ( 'd' == $struc['type'] ) {
if ( $recursive )
$struc['files'] = $this->dirList($path . '/' . $struc['name'], $includeHidden, $recursive);
else
$struc['files'] = array();
}
$ret[ $struc['name'] ] = $struc;
}
$dir->close();
unset($dir);
return $ret;
}
}
class filesystemFTPExt extends filesystemBase {
var $link;
var $errors = null;
var $options = array();
function __construct($opt='') {
$this->method = 'FTPExt';
//$this->errors = new WP_Error();
//Check if possible to use ftp functions.
if ( ! extension_loaded('ftp') ) {
//$this->errors->add('no_ftp_ext', __('The ftp PHP extension is not available'));
appUpdateMsg('The FTP PHP extension is not available', true);
return false;
}
// Set defaults:
//This Class uses the timeout on a per-connection basis, Others use it on a per-action basis.
if ( ! defined('FS_TIMEOUT') )
define('FS_TIMEOUT', 240);
if ( empty($opt['port']) )
$this->options['port'] = 21;
else
$this->options['port'] = $opt['port'];
if ( empty($opt['hostname']) ){
//$this->errors->add('empty_hostname', __('FTP hostname is required'));
appUpdateMsg('FTP hostname is required');
}
else
$this->options['hostname'] = $opt['hostname'];
if ( ! empty($opt['base']) )
$this->baseDir = $opt['base'];
// Check if the options provided are OK.
if ( empty($opt['username']) ){
//$this->errors->add('empty_username', __('FTP username is required'));
appUpdateMsg('FTP username is required');
}
else
$this->options['username'] = $opt['username'];
if ( empty($opt['password']) ){
//$this->errors->add('empty_password', __('FTP password is required'));
appUpdateMsg('FTP password is required');
}
else
$this->options['password'] = $opt['password'];
$this->options['ssl'] = false;
if ( 'ftps' == $opt['connectionType'] )
$this->options['ssl'] = true;
if($opt['passive']){
$this->options['passive'] = $opt['passive'];
}
}
function connect() {
if(!$this->options['hostname'] || !$this->options['username'] || !$this->options['password']){
appUpdateMsg(sprintf('FTP hostname/username/password is missing"'));
return false;
}
if ( isset($this->options['ssl']) && $this->options['ssl'] && function_exists('ftp_ssl_connect') )
$this->link = @ftp_ssl_connect($this->options['hostname'], $this->options['port'], FS_CONNECT_TIMEOUT);
else
$this->link = ftp_connect($this->options['hostname'], $this->options['port'], FS_CONNECT_TIMEOUT);
if ( ! $this->link ) {
//$this->errors->add('connect', sprintf(__('Failed to connect to FTP Server %1$s:%2$s'), $this->options['hostname'], $this->options['port']));
appUpdateMsg(sprintf('Failed to connect to the FTP server "%1$s:%2$s"', $this->options['hostname'], $this->options['port']));
return false;
}
if ( ! @ftp_login($this->link,$this->options['username'], $this->options['password']) ) {
//$this->errors->add('auth', sprintf(__('Username/Password incorrect for %s'), $this->options['username']));
appUpdateMsg(sprintf('FTP username or password incorrect for "%s"', $this->options['username']));
return false;
}
//Set the Connection to use Passive FTP
if($this->options['passive']){
@ftp_pasv( $this->link, true );
}
if ( @ftp_get_option($this->link, FTP_TIMEOUT_SEC) < FS_TIMEOUT )
@ftp_set_option($this->link, FTP_TIMEOUT_SEC, FS_TIMEOUT);
return true;
}
function getContents($file, $type = '', $resumePos = 0 ) {
if ( empty($type) )
$type = FTP_BINARY;
$tempfile = getTempName($file);
$temp = fopen($tempfile, 'w+');
if ( ! $temp )
return false;
if ( ! @ftp_fget($this->link, $temp, $file, $type, $resumePos) )
return false;
fseek($temp, 0); //Skip back to the start of the file being written to
$contents = '';
while ( ! feof($temp) )
$contents .= fread($temp, 8192);
fclose($temp);
unlink($tempfile);
return $contents;
}
function putContents($file, $contents, $mode = false ) {
$tempfile = getTempName($file);
$temp = fopen($tempfile, 'w+');
if ( ! $temp )
return false;
fwrite($temp, $contents);
fseek($temp, 0); //Skip back to the start of the file being written to
$type = isBinary($contents) ? FTP_BINARY : FTP_ASCII;
$ret = @ftp_fput($this->link, $file, $temp, $type);
fclose($temp);
unlink($tempfile);
$this->chmod($file, $mode);
return $ret;
}
function chmod($file, $mode = false, $recursive = false) {
if ( ! $mode ) {
if ( $this->isFile($file) )
$mode = FS_CHMOD_FILE;
elseif ( $this->isDir($file) )
$mode = FS_CHMOD_DIR;
else
return false;
}
// chmod any sub-objects if recursive.
if ( $recursive && $this->isDir($file) ) {
$fileList = $this->dirList($file);
foreach ( (array)$fileList as $fileName => $filemeta )
$this->chmod($file . '/' . $fileName, $mode, $recursive);
}
// chmod the file or directory
if ( ! function_exists('ftp_chmod') )
return (bool)@ftp_site($this->link, sprintf('CHMOD %o %s', $mode, $file));
return (bool)@ftp_chmod($this->link, $mode, $file);
}
function chown($file, $owner, $recursive = false ) {
return false;
}
function copy($source, $destination, $overwrite = false, $mode = false) {
if ( ! $overwrite && $this->exists($destination) )
return false;
$content = $this->getContents($source);
if ( false === $content)
return false;
return $this->putContents($destination, $content, $mode);
}
function move($source, $destination, $overwrite = false) {
if ($overwrite) {
$this->delete($destination, true);
}
return ftp_rename($this->link, $source, $destination);
}
function delete($file, $recursive = false, $type = false) {
if(!$this->link){
return false;
}
if ( empty($file) )
return false;
if ( 'f' == $type || $this->isFile($file) )
return @ftp_delete($this->link, $file);
if ( !$recursive )
return @ftp_rmdir($this->link, $file);
$fileList = $this->dirList( iwpAddTrailingSlash($file) );
if ( !empty($fileList) )
foreach ( $fileList as $deleteFile ){
iwp_mmb_auto_print('recursive_delete');
$this->delete( iwpAddTrailingSlash($file) . $deleteFile['name'], $recursive, $deleteFile['type'] );
}
return @ftp_rmdir($this->link, $file);
}
function exists($file) {
$list = @ftp_nlist($this->link, $file);
return !empty($list); //empty list = no file, so invert.
}
function isFile($file) {
return $this->exists($file) && !$this->isDir($file);
}
function isDir($path) {
$cwd = $this->cwd();
$result = @ftp_chdir($this->link, iwpAddTrailingSlash($path) );
if ( $result && $path == $this->cwd() || $this->cwd() != $cwd ) {
@ftp_chdir($this->link, $cwd);
return true;
}
return false;
}
function isReadable($file) {
//Get dir list, Check if the file is readable by the current user??
return true;
}
function isWritable($file) {
//Get dir list, Check if the file is writable by the current user??
return true;
}
function atime($file) {
return false;
}
function mtime($file) {
return ftp_mdtm($this->link, $file);
}
function size($file) {
return ftp_size($this->link, $file);
}
function touch($file, $time = 0, $atime = 0) {
return false;
}
function mkDir($path, $chmod = false, $chown = false, $chgrp = false) {
$path = iwpRemoveTrailingSlash($path);
if ( empty($path) )
return false;
if ( !@ftp_mkdir($this->link, $path) )
return false;
$this->chmod($path, $chmod);
if ( $chown )
$this->chown($path, $chown);
if ( $chgrp )
$this->chgrp($path, $chgrp);
return true;
}
function rmDir($path, $recursive = false) {
return $this->delete($path, $recursive);
}
function parseListing($line) {
static $isWindows;
if ( is_null($isWindows) )
$isWindows = stripos( ftp_systype($this->link), 'win') !== false;
if ( $isWindows && preg_match('/([0-9]{2})-([0-9]{2})-([0-9]{2}) +([0-9]{2}):([0-9]{2})(AM|PM) +([0-9]+|) +(.+)/', $line, $lucifer) ) {
$b = array();
if ( $lucifer[3] < 70 )
$lucifer[3] +=2000;
else
$lucifer[3] += 1900; // 4digit year fix
$b['isdir'] = ( $lucifer[7] == '');
if ( $b['isdir'] )
$b['type'] = 'd';
else
$b['type'] = 'f';
$b['size'] = $lucifer[7];
$b['month'] = $lucifer[1];
$b['day'] = $lucifer[2];
$b['year'] = $lucifer[3];
$b['hour'] = $lucifer[4];
$b['minute'] = $lucifer[5];
$b['time'] = @mktime($lucifer[4] + (strcasecmp($lucifer[6], "PM") == 0 ? 12 : 0), $lucifer[5], 0, $lucifer[1], $lucifer[2], $lucifer[3]);
$b['am/pm'] = $lucifer[6];
$b['name'] = $lucifer[8];
} elseif ( !$isWindows && $lucifer = preg_split('/[ ]/', $line, 9, PREG_SPLIT_NO_EMPTY)) {
//echo $line."\n";
$lcount = count($lucifer);
if ( $lcount < 8 )
return '';
$b = array();
$b['isdir'] = $lucifer[0][0] === 'd';
$b['islink'] = $lucifer[0][0] === 'l';
if ( $b['isdir'] )
$b['type'] = 'd';
elseif ( $b['islink'] )
$b['type'] = 'l';
else
$b['type'] = 'f';
$b['perms'] = $lucifer[0];
$b['number'] = $lucifer[1];
$b['owner'] = $lucifer[2];
$b['group'] = $lucifer[3];
$b['size'] = $lucifer[4];
if ( $lcount == 8 ) {
sscanf($lucifer[5], '%d-%d-%d', $b['year'], $b['month'], $b['day']);
sscanf($lucifer[6], '%d:%d', $b['hour'], $b['minute']);
$b['time'] = @mktime($b['hour'], $b['minute'], 0, $b['month'], $b['day'], $b['year']);
$b['name'] = $lucifer[7];
} else {
$b['month'] = $lucifer[5];
$b['day'] = $lucifer[6];
if ( preg_match('/([0-9]{2}):([0-9]{2})/', $lucifer[7], $l2) ) {
$b['year'] = @date("Y");
$b['hour'] = $l2[1];
$b['minute'] = $l2[2];
} else {
$b['year'] = $lucifer[7];
$b['hour'] = 0;
$b['minute'] = 0;
}
$b['time'] = strtotime( sprintf('%d %s %d %02d:%02d', $b['day'], $b['month'], $b['year'], $b['hour'], $b['minute']) );
$b['name'] = $lucifer[8];
}
}
return $b;
}
function dirList($path = '.', $includeHidden = true, $recursive = false) {
if ( $this->isFile($path) ) {
$limitFile = basename($path);
$path = dirname($path) . '/';
} else {
$limitFile = false;
}
$pwd = @ftp_pwd($this->link);
if ( ! @ftp_chdir($this->link, $path) ) // Cant change to folder = folder doesn't exist
return false;
$list = @ftp_rawlist($this->link, '-a', false);
@ftp_chdir($this->link, $pwd);
if ( empty($list) ) // Empty array = non-existent folder (real folder will show . at least)
return false;
$dirList = array();
foreach ( $list as $k => $v ) {
$entry = $this->parseListing($v);
if ( empty($entry) )
continue;
if ( '.' == $entry['name'] || '..' == $entry['name'] )
continue;
if ( ! $includeHidden && '.' == $entry['name'][0] )
continue;
if ( $limitFile && $entry['name'] != $limitFile)
continue;
$dirList[ $entry['name'] ] = $entry;
}
$ret = array();
foreach ( (array)$dirList as $struc ) {
if ( 'd' == $struc['type'] ) {
if ( $recursive )
$struc['files'] = $this->dirList($path . '/' . $struc['name'], $includeHidden, $recursive);
else
$struc['files'] = array();
}
$ret[ $struc['name'] ] = $struc;
}
return $ret;
}
function close() {
if ( $this->link )
ftp_close($this->link);
}
function __destruct() {
if ( $this->link )
ftp_close($this->link);
}
}
class filesystemSFTPExt extends filesystemBase {
var $link = false;
var $sftp_link = false;
var $keys = false;
var $options = array();
function __construct($opt='') {
$this->method = 'sftp';
include dirname(__FILE__).'/phpseclib/vendor/autoload.php';
//$this->errors = new WP_Error();
// Set defaults:
if ( empty($opt['port']) )
$this->options['port'] = 22;
else
$this->options['port'] = $opt['port'];
if ( empty($opt['hostname']) )
//$this->errors->add('empty_hostname', __('SSH2 hostname is required'));
appUpdateMsg('SSH2 hostname is required', true);
else
$this->options['hostname'] = $opt['hostname'];
if ( ! empty($opt['base']) )
$this->wp_base = $opt['base'];
if ( empty ($opt['username']) ) {
//$this->errors->add('empty_username', __('SSH2 username is required'));
appUpdateMsg('SFTP username is required', true);
}
if ( !empty($opt['username']) )
$this->options['username'] = $opt['username'];
if ( empty ($opt['password']) && empty ($opt['hostKey'])) {
if ( !$this->keys ) //password can be blank if we are using keys
//$this->errors->add('empty_password', __('SSH2 password is required'));
appUpdateMsg('SSH2 password is required', true);
} else {
if (!empty($opt['password'])) {
$this->options['password'] = $opt['password'];
}
if (!empty($opt['hostKey'])) {
$this->options['hostKey'] = $opt['hostKey'];
}
}
}
function connect() {
$this->link = new \phpseclib\Net\SFTP($this->options['hostname'], $this->options['port']);
if (!empty($this->options['hostKey'])) {
$rsa = new \phpseclib\Crypt\RSA();
if (false === $rsa->loadKey($this->options['hostKey'])) {
appUpdateMsg('The key provided was not in a valid format, or was corrupt', true);
}
$this->options['password'] = $rsa;
}
if ( ! $this->link ) {
//$this->errors->add('connect', sprintf(__('Failed to connect to SSH2 Server %1$s:%2$s'), $this->options['hostname'], $this->options['port']));
appUpdateMsg(sprintf('Failed to connect to SSH2 Server %1$s:%2$s', $this->options['hostname'], $this->options['port']), true);
return false;
}
if ( ! $this->link->login($this->options['username'], $this->options['password']) ) {
appUpdateMsg(sprintf('Username/Password incorrect for %s', $this->options['username']), true);
return false;
}
return true;
}
function runCommand( $command, $returnbool = false) {
$validSFTPCommands = array(
/*
sftp CLI commands:
'cd',
'chgrp',
'chmod',
'chown',
'df',
'get',
'ln',
'ls',
'mkdir',
'put',
'pwd',
'rename',
'rm',
'rmdir',
'symlink'
*/
// Available Net_SFTP commands:
'pwd',
'chmod', // ignored though
'chgrp', // ignored though
'chown' // ignored though
);
if ( ! $this->link )
return false;
$cmdline = preg_split('/[[:blank:]]+/', $command);
if ( ! in_array(($cmd=$cmdline[0]), $validSFTPCommands) )
return false;
if (substr($cmd, 0, 2) == 'ch') return true;
$data = $this->link->$cmd();
if ( $returnbool )
return ( $data === false ) ? false : '' != trim($data);
else
return $data;
}
// strip FTP_BASE part of path; reduce to relative path
function fixPath($file) {
if (defined('FTP_BASE')) {
if (substr($file, 0, ($l=strlen(FTP_BASE))) == FTP_BASE)
$file = ltrim(substr($file, $l), '/');
}
return $file;
}
function getContents( $file ) {
return $this->link->get($this->fixPath($file));
}
function getContentsArray($file) {
return preg_split("/\n+/", $this->getContents($file));
}
function putContents($file, $contents, $mode = 2, $start = -1, $local_start = -1, $progressCallback = null ) {
$file = $this->fixPath($file);
$ret = $this->link->put($file, $contents, $mode, $start, $local_start, $progressCallback);
return false !== $ret;
}
function cwd() {
$cwd = $this->runCommand('pwd');
if ( $cwd )
$cwd = iwpAddTrailingSlash($cwd);
return $cwd;
}
function chdir($dir) {
return $this->link->chdir($this->fixPath($dir));
}
function chgrp($file, $group, $recursive = false ) {
return true; // not supported
}
function chmod($file, $mode = false, $recursive = false) {
return $this->link->chmod($mode, $file, $recursive); // SFTP does support chmod, better though to configure the right (default) permissions on the server side
}
/**
* Change the ownership of a file / folder.
*
* @since Unknown
*
* @param string $file Path to the file.
* @param mixed $owner A user name or number.
* @param bool $recursive Optional. If set True changes file owner recursivly. Defaults to False.
* @return bool Returns true on success or false on failure.
*/
function chown( $file, $owner, $recursive = false ) {
return true; // not supported
}
function stat($file) {
$file = $this->fixPath($file);
$stat = $this->link->stat($file);
if ($stat !== false) {
if (!isset($stat['permissions'])) {
return false;
}
$stat['size'] = $this->link->size($file);
}
else {
}
return $stat;
}
function owner($file) {
$stat = $this->stat($file);
if ( ! $stat )
return false;
if ( ! isset($stat['uid']) )
return false;
$owneruid = $stat['uid'];
if ( ! function_exists('posix_getpwuid') )
return $owneruid;
$ownerarray = posix_getpwuid($owneruid);
return $ownerarray['name'];
}
function getchmod($file) {
$stat = $this->stat($file);
return substr(($stat['permissions'] & 000777), -3);
}
function group($file) {
$stat = $this->stat($file);
if ( ! $stat )
return false;
if ( ! isset($stat['gid']) )
return false;
$ownergid = $stat['gid'];
if ( ! function_exists('posix_getgrgid') )
return $gid;
$grouparray = posix_getgrgid($ownergid);
return $grouparray['name'];
}
function copy($source, $destination, $overwrite = false, $mode = false) {
if ( ! $overwrite && $this->exists($destination) )
return false;
$content = $this->getContents($source);
if ( false === $content)
return false;
return $this->putContents($destination, $content, $mode);
}
function move($source, $destination, $overwrite = false) {
if ($overwrite) {
$this->delete($destination, true);
}
return $this->link->rename($this->fixPath($source), $this->fixPath($destination));
}
function delete($file, $recursive = false, $type = false) {
$file = $this->fixPath($file);
if ( 'f' === $type || $this->isFile($file) ) {
return $this->link->delete($file);
}
if ( ! $recursive ) {
return $this->link->rmdir($file);
}
//At this point its a folder, and we're in recursive mode
$file = iwpAddTrailingSlash($file);
$filelist = $this->dirlist($file, true);
$retval = true;
if ( is_array($filelist) ) //false if no files, So check first.
foreach ($filelist as $filename => $fileinfo){
iwp_mmb_auto_print('recursive_delete');
if ( ! $this->delete($file . $filename, $recursive, $fileinfo['type']) )
$retval = false;
}
if ( $this->exists($file) && ! $this->link->rmdir($file) )
$retval = false;
return $retval;
}
function exists($file) {
return $this->stat($file) !== false;
}
function S_ISDIR($stat) {
return( ($stat['permissions'] & 040000) == 040000 );
}
function S_ISREG($stat) {
return( ($stat['permissions'] & 0100000) == 0100000 );
}
function isFile($file) {
return $this->S_ISREG($this->stat($file));
}
function isDir($path) {
return $this->S_ISDIR($this->stat($path));
}
function isReadable($file) {
$stat = $this->stat($file);
$perms = $stat['permissions'];
return ($perms & 0x000400);
}
function isWritable($file) {
$stat = $this->stat($file);
$perms = $stat['permissions'];
return ($perms & 0x000200);
}
function atime($file) {
$stat = $this->stat($file);
return $stat['atime'];
}
function mtime($file) {
$stat = $this->stat($file);
return $stat['mtime'];
}
function size($file) {
$stat = $this->stat($file);
return $stat['size'];
}
function touch($file, $time = 0, $atime = 0) {
return $this->link->touch($file, $time, $atime);
}
function mkdir($path, $chmod = false, $chown = false, $chgrp = false) {
return $this->link->mkdir($path);
}
function rmdir($path, $recursive = false) {
return $this->delete($path, $recursive);
}
function dirlist($path, $include_hidden = true, $recursive = false) {
if ( $this->isFile($path) ) {
$limit_file = basename($path);
$path = dirname($path);
} else {
$limit_file = false;
}
if ( ! $this->isDir($path) )
return false;
$ret = array();
$curdir = $this->fixPath($path);
$dir = $this->link->nlist($curdir);
if ( ! $dir )
return false;
foreach ($dir as $entry) {
$struc = $this->stat($curdir.'/'.$entry);
$struc['name'] = $entry;
if ( '.' == $struc['name'] || '..' == $struc['name'] )
continue; //Do not care about these folders.
if ( ! $include_hidden && '.' == $struc['name'][0] )
continue;
if ( $limit_file && $struc['name'] != $limit_file )
continue;
$struc['perms'] = $this->gethchmod($path.'/'.$entry);
$struc['permsn'] = $struc['permissions'] & 000777;
$struc['number'] = false;
$struc['owner'] = $this->owner($path.'/'.$entry);
$struc['group'] = $this->group($path.'/'.$entry);
$struc['size'] = $this->size($path.'/'.$entry);
$struc['lastmodunix']= $this->mtime($path.'/'.$entry);
$struc['lastmod'] = date('M j',$struc['lastmodunix']);
$struc['time'] = date('h:i:s',$struc['lastmodunix']);
$struc['type'] = $this->isDir($path.'/'.$entry) ? 'd' : 'f';
if ( 'd' == $struc['type'] ) {
if ( $recursive )
$struc['files'] = $this->dirlist($path . '/' . $struc['name'], $include_hidden, $recursive);
else
$struc['files'] = array();
}
$ret[ $struc['name'] ] = $struc;
}
return $ret;
}
function lastError() {
return $this->link->getLastSFTPError();
}
function getErrors() {
return $this->link->getSFTPErrors();
}
}
class DBMysql{
protected $DBLink;
protected $DBHost;
protected $DBUsername;
protected $DBPassword;
protected $DBName;
protected $DBPort;
function __construct($DBHost, $DBUsername, $DBPassword, $DBName, $DBPort){
$this->DBHost = $DBHost;
$this->DBUsername = $DBUsername;
$this->DBPassword = $DBPassword;
$this->DBName = $DBName;
$this->DBPort = $DBPort;
}
function connect(){
$this->DBLink = mysql_connect($this->DBHost.':'.$this->DBPort, $this->DBUsername, $this->DBPassword);
if (!$this->DBLink) {
return 'Mysql connect error: (' . mysql_error().') '.$this->error();
}
if (!mysql_select_db($this->DBName, $this->DBLink)){
return 'Mysql connect error: (' . $this->errorNo().') '.$this->error();
} else {
return true;
}
}
function query($SQL){
$result = mysql_query($SQL, $this->DBLink);
if(empty($result)){
$errno = $this->errorNo();
if ($errno == 2013 || $errno == 2006){
$this->connect();
return mysql_query($SQL, $this->DBLink);
}
}
return $result;
}
function insertID(){
return mysql_insert_id($this->DBLink);
}
function affectedRows(){
return mysql_affected_rows($this->DBLink);
}
function realEscapeString($val){
return mysql_real_escape_string($val, $this->DBLink);
}
function ping(){
return mysql_ping($this->DBLink);
}
function errorNo(){
return mysql_errno($this->DBLink);
}
function error(){
return mysql_error($this->DBLink);
}
}
class DBMysqlResult{
private $DBResult;
function __construct($newResult)
{
$this->DBResult = $newResult;
}
function numRows()
{
return mysql_num_rows($this->DBResult);
}
function nextRow()
{
return mysql_fetch_assoc($this->DBResult);
}
function rowExists()
{
if (!$this->numRows())
return false;
return true;
}
function free(){
return mysql_free_result($this->DBResult);
}
}
//Code from mysql.php - End
//Code from mysqli.php - Start
class DBMysqli{
protected $DBLink;
protected $DBHost;
protected $DBUsername;
protected $DBPassword;
protected $DBName;
protected $DBPort;
function __construct($DBHost, $DBUsername, $DBPassword, $DBName, $DBPort){
$this->DBHost = $DBHost;
$this->DBUsername = $DBUsername;
$this->DBPassword = $DBPassword;
$this->DBName = $DBName;
$this->DBPort = $DBPort;
}
function connect(){
$this->DBLink = new mysqli($this->DBHost, $this->DBUsername, $this->DBPassword, $this->DBName, $this->DBPort);
if ($this->DBLink->connect_errno) {
return 'Mysql connect error: (' . $this->DBLink->connect_errno.') '.$this->DBLink->connect_error;
} else {
return true;
}
}
function query($SQL){
$result = $this->DBLink->query($SQL);
if(empty($result)){
$errno = $this->errorNo();
if ($errno == 2013 || $errno == 2006){
$this->connect();
return $this->DBLink->query($SQL);
}
}
return $result;
}
function insertID(){
return $this->DBLink->insert_id;
}
function affectedRows(){
return $this->DBLink->affected_rows;
}
function realEscapeString($val){
return $this->DBLink->real_escape_string($val);
}
function ping(){
return $this->DBLink->ping();
}
function errorNo(){
return $this->DBLink->errno;
}
function error(){
return $this->DBLink->error;
}
}
class DBMysqliResult{
private $DBResult;
function __construct($newResult)
{
$this->DBResult = $newResult;
}
function numRows()
{
return $this->DBResult->num_rows;
}
function nextRow()
{
return $this->DBResult->fetch_assoc();
}
function rowExists()
{
if (!$this->numRows())
return false;
return true;
}
function free(){
$this->DBResult->free();
}
}
//Code from mysqli.php - End
//Code from db.php - Start
class DB{
private static $queryString;
private static $printQuery;
private static $printAllQuery;
private static $DBDriver;
public static $DBResultClass;
//private static $showError;
//private static $showSQL;
public static function connect($DBHost, $DBUsername, $DBPassword, $DBName, $DBPort){
$driver = self::getDriver();
if(in_array($driver, array('mysql', 'mysqli'))){
$DBClass = 'DB'.ucfirst($driver);
self::$DBResultClass = $DBClass.'Result';
self::$DBDriver = new $DBClass($DBHost, $DBUsername, $DBPassword, $DBName, $DBPort);
$DBConnect = self::$DBDriver->connect();
if($DBConnect !== true) {
return $DBConnect;
}
} else {
return "PHP has no mysql extension installed";
}
return true;
}
public static function getDriver() {
if(class_exists('mysqli')){
$driver = 'mysqli';
}
elseif(function_exists('mysql_connect')){
$driver = 'mysql';
}
else{
return false;
}
return $driver;
}
private static function get($params, $type){
if(empty($params)) return false;
$result = array();
$query = self::prepareQ('select', $params);
$query_result = self::doQuery($query);
if(!$query_result) return $query_result;
$_result = new self::$DBResultClass($query_result);
if($_result){
if($type == 'array'){
while($row = $_result->nextRow()){
if(!empty($params[3])){//array key hash
$result[ $row[$params[3]] ] = $row;
}
else{
$result[] = $row;
}
}
}
elseif($type == 'row'){
$result = $_result->nextRow();
}
elseif($type == 'exists'){
$result = $_result->rowExists();
}
elseif($type == 'field'){
$row = $_result->nextRow();
$result = ($row && is_array($row)) ? reset($row) : NULL;
}
elseif($type == 'fields'){
while($row = $_result->nextRow()){
if(!empty($params[3])){//array key hash
$result[ $row[$params[3]] ] = reset($row);
}
else{
$result[] = reset($row);
}
}
}
$_result->free();
}
return $result;
}
public static function getArray(){//table, select, conditions
$args = func_get_args();
return self::get($args, 'array');
}
public static function getRow(){//table, select, conditions
$args = func_get_args();
return self::get($args, 'row');
}
public static function getExists(){//table, select, conditions
$args = func_get_args();
return self::get($args, 'exists');
}
public static function getField(){//table, select, conditions
$args = func_get_args();
return self::get($args, 'field');
}
public static function getFields(){//table, select, conditions
$args = func_get_args();
return self::get($args, 'fields');
}
private static function prepareQ($type, $params){
if(!empty($params) && count($params) == 1){
return $params[0];
}
if($type == 'select'){
if(empty($conditions)){ $conditions = 'true'; }
return "SELECT ".$params[1]." FROM ".$params[0]." WHERE ".$params[2];
}
elseif($type == 'insert' || $type == 'replace'){
if(is_array($params[1])) $params[1] = self::array2MysqlSet($params[1]);
return ($type == 'insert' ? "INSERT" : "REPLACE")." INTO ".$params[0]." SET ".$params[1];
}
elseif($type == 'update'){
if(is_array($params[1])) $params[1] = self::array2MysqlSet($params[1]);
return "UPDATE ".$params[0]." SET ".$params[1]." WHERE ".$params[2];
}
elseif($type == 'delete'){
return "DELETE FROM ".$params[0]." WHERE ".$params[1];
}
}
public static function insert(){//table, setCommand
$args=func_get_args();
$query = self::prepareQ('insert', $args);
return self::insertReplace($query);
}
public static function replace(){//table, setCommand
$args=func_get_args();
$query = self::prepareQ('replace', $args);
return self::insertReplace($query);
}
private static function insertReplace($query){
if(self::doQuery($query)){
$lastInsertID = self::lastInsertID();
if(!empty($lastInsertID)) return $lastInsertID;
return true;
}
return false;
}
public static function update(){//table, setCommand, conditions
$args=func_get_args();
$query = self::prepareQ('update', $args);
return self::doQuery($query);
}
public static function delete(){//table, conditions
$args=func_get_args();
$query = self::prepareQ('delete', $args);
return self::doQuery($query);
}
public static function doQuery($queryString){
//$queryString = str_replace('?:', Reg::get('config.SQL_TABLE_NAME_PREFIX'), $queryString);
self::$queryString = $queryString;
if(self::$printAllQuery || self::$printQuery)
echo '
'.self::$queryString.'
';
$query = self::$DBDriver->query(self::$queryString);
if($query)
return $query;
else
{
self::printError(debug_backtrace());
echo "\n".self::$queryString."\n
";
return false;
}
}
public static function getLastQuery(){//avoid using this function, it should be called as soon as query is executed
return self::$queryString;
}
private static function lastInsertID(){
return self::$DBDriver->insertID();
}
public static function errorNo(){
return self::$DBDriver->errorNo();
}
public static function error(){
return self::$DBDriver->error();
}
public static function affectedRows(){
return self::$DBDriver->affectedRows();
}
public static function realEscapeString($val){
return self::$DBDriver->realEscapeString($val);
}
public static function escapse($val){ //same as public static function realEscapeString($val)
return self::$DBDriver->realEscapeString($val);
}
private static function printError($traceback_detail){
echo "Manual SQL Error: [". self::$DBDriver->errorNo()."] " . self::$DBDriver->error() . "
\n
in file " . $_SERVER['PHP_SELF'] ." On line " . $traceback_detail[count($traceback_detail) - 1]['line'] . "
";
}
private static function array2MysqlSet($array){
$mysqlSet='';
$isPrev=false;
foreach($array as $key => $value)
{
if($isPrev) $mysqlSet .= ', ';
if(isset($value) && is_array($value))
$mysqlSet .= $key." = ".self::realEscapeString($value[0]).""; //without quotes
else
$mysqlSet .= $key." = '".self::realEscapeString($value)."'";
$isPrev = true;
}
return $mysqlSet;
}
private static function array2MysqlSelect($array){
$mysqlSet='';
$isPrev=false;
foreach($array as $key => $value)
{
if($isPrev) $mysqlSet .= ', ';
$mysqlSet .= $value;
$isPrev = true;
}
return $mysqlSet;
}
public static function setPrintQuery($var){
self::$printQuery = $var;
}
}
//-------------------------------------------------------------------------------------------------------------------->
# stores a mysql result
class DBResult{
var $DBResult;
function __construct($newResult)
{
$this->DBResult = $newResult;
}
function numRows()
{
return $this->DBResult->num_rows;
}
function nextRow()
{
return $this->DBResult->fetch_assoc();
}
function rowExists()
{
if (!$this->numRows())
return false;
return true;
}
function free(){
$this->DBResult->free();
}
}
//Code from db.php - End
class DBUpdateEngine extends DB
{
public static function getTextColumns($table)
{
$type_where = "type NOT LIKE 'tinyint%' AND ";
$type_where .= "type NOT LIKE 'smallint%' AND ";
$type_where .= "type NOT LIKE 'mediumint%' AND ";
$type_where .= "type NOT LIKE 'int%' AND ";
$type_where .= "type NOT LIKE 'bigint%' AND ";
$type_where .= "type NOT LIKE 'float%' AND ";
$type_where .= "type NOT LIKE 'double%' AND ";
$type_where .= "type NOT LIKE 'decimal%' AND ";
$type_where .= "type NOT LIKE 'numeric%' AND ";
$type_where .= "type NOT LIKE 'date%' AND ";
$type_where .= "type NOT LIKE 'time%' AND ";
$type_where .= "type NOT LIKE 'year%' ";
$result = self::getArray("SHOW COLUMNS FROM `{$table}` WHERE {$type_where}");
if (empty($result)) {
return null;
}
$fields = array();
if (count($result) > 0 ) {
foreach ($result as $key => $row) {
$fields[] = $row['Field'];
}
}
$result = self::getArray("SHOW INDEX FROM `{$table}`");
if (count($result) > 0) {
foreach ($result as $key => $row) {
$fields[] = $row['Column_name'];
}
}
return (count($fields) > 0) ? $fields : null;
}
public static function load($list = array(), $tables = array(), $fullsearch = false)
{
$report = array(
'scan_tables' => 0,
'scan_rows' => 0,
'scan_cells' => 0,
'updt_tables' => 0,
'updt_rows' => 0,
'updt_cells' => 0,
'errsql' => array(),
'errser' => array(),
'errkey' => array(),
'errsql_sum' => 0,
'errser_sum' => 0,
'errkey_sum' => 0,
'time' => '',
'err_all' => 0
);
$walk_function = function(&$str){
$str = "`$str`";
};
if (is_array($tables) && !empty($tables)) {
foreach ($tables as $table)
{
$report['scan_tables']++;
$columns = array();
$fields = self::getArray('DESCRIBE ' . $table);
foreach ($fields as $key => $column) {
$columns[$column['Field']] = $column['Key'] == 'PRI' ? true : false;
}
$row_count = self::getField("SELECT COUNT(*) FROM `{$table}`");
if ($row_count == 0) {
continue;
}
$page_size = 25000;
$offset = ($page_size + 1);
$pages = ceil($row_count / $page_size);
$colList = '*';
$colMsg = '*';
if (! $fullsearch)
{
$colList = self::getTextColumns($table);
if ($colList != null && is_array($colList)) {
array_walk($colList, $walk_function);
$colList = implode(',', $colList);
}
$colMsg = (empty($colList)) ? '*' : '~';
}
if (empty($colList))
{
continue;
}
else
{
}
//Paged Records
for ($page = 0; $page < $pages; $page++)
{
$current_row = 0;
$start = $page * $page_size;
$end = $start + $page_size;
$sql = sprintf("SELECT {$colList} FROM `%s` LIMIT %d, %d", $table, $start, $offset);
$data = self::getArray($sql);
if (empty($data))
//$report['errsql'][] = mysqli_error($conn);
$scan_count = ($row_count < $end) ? $row_count : $end;
foreach ($data as $key => $row) {
$report['scan_rows']++;
$current_row++;
$upd_col = array();
$upd_sql = array();
$where_sql = array();
$upd = false;
$serial_err = 0;
foreach ($columns as $column => $primary_key)
{
$report['scan_cells']++;
$edited_data = $data_to_fix = $row[$column];
$base64coverted = false;
$txt_found = false;
if (!empty($row[$column]) && !is_numeric($row[$column]))
{
//Base 64 detection
if (base64_decode($row[$column], true))
{
$decoded = base64_decode($row[$column], true);
if (self::is_serialized($decoded))
{
$edited_data = $decoded;
$base64coverted = true;
}
}
//Skip table cell if match not found
foreach ($list as $item)
{
if (!empty($item['search']) && strpos($edited_data, $item['search']) !== false) {
$txt_found = true;
break;
}
}
if (! $txt_found) {
continue;
}
//Replace logic - level 1: simple check on any string or serlized strings
foreach ($list as $item) {
$edited_data = self::recursive_unserialize_replace($item['search'], $item['replace'], $edited_data);
}
//Replace logic - level 2: repair serilized strings that have become broken
$serial_check = self::fix_serial_string($edited_data);
if ($serial_check['fixed'])
{
$edited_data = $serial_check['data'];
}
elseif ($serial_check['tried'] && !$serial_check['fixed'])
{
$serial_err++;
}
}
//Change was made
if ($edited_data != $data_to_fix || $serial_err > 0)
{
$report['updt_cells']++;
//Base 64 encode
if ($base64coverted) {
$edited_data = base64_encode($edited_data);
}
$upd_col[] = $column;
$upd_sql[] = $column . ' = "' . self::realEscapeString($edited_data) . '"';
$upd = true;
}
if ($primary_key) {
$where_sql[] = $column . ' = "' . self::realEscapeString($data_to_fix) . '"';
}
}
if ($upd && !empty($where_sql))
{
$sql = "UPDATE `{$table}` SET " . implode(', ', $upd_sql) . ' WHERE ' . implode(' AND ', array_filter($where_sql));
$result = self::doQuery($sql);
if ($result) {
if ($serial_err > 0) {
$report['errser'][] = "SELECT " . implode(', ', $upd_col) . " FROM `{$table}` WHERE " . implode(' AND ', array_filter($where_sql)) . ';';
}
$report['updt_rows']++;
}
} elseif ($upd) {
$report['errkey'][] = sprintf("Row [%s] on Table [%s] requires a manual update.", $current_row, $table);
}
}
}
if ($upd) {
$report['updt_tables']++;
}
}
}
$report['errsql_sum'] = empty($report['errsql']) ? 0 : count($report['errsql']);
$report['errser_sum'] = empty($report['errser']) ? 0 : count($report['errser']);
$report['errkey_sum'] = empty($report['errkey']) ? 0 : count($report['errkey']);
$report['err_all'] = $report['errsql_sum'] + $report['errser_sum'] + $report['errkey_sum'];
return $report;
}
public static function recursive_unserialize_replace($from = '', $to = '', $data = '', $serialised = false)
{
try
{
if (is_string($data) && ($unserialized = @unserialize($data)) !== false)
{
$data = self::recursive_unserialize_replace($from, $to, $unserialized, true);
}
elseif (is_array($data))
{
$_tmp = array();
foreach ($data as $key => $value)
{
$_tmp[$key] = self::recursive_unserialize_replace($from, $to, $value, false);
}
$data = $_tmp;
unset($_tmp);
}
elseif (is_object($data))
{
$_tmp = $data;
$props = get_object_vars( $data );
foreach ($props as $key => $value)
{
$_tmp->$key = self::recursive_unserialize_replace( $from, $to, $value, false );
}
$data = $_tmp;
unset($_tmp);
}
else
{
if (is_string($data)) {
$data = str_replace($from, $to, $data);
}
}
if ($serialised)
return serialize($data);
}
catch (Exception $error)
{
}
return $data;
}
public static function is_serialized($data)
{
$test = @unserialize(($data));
return ($test !== false || $test === 'b:0;') ? true : false;
}
public static function fix_serial_string($data)
{
$result = array('data' => $data, 'fixed' => false, 'tried' => false);
if (preg_match("/s:[0-9]+:/", $data))
{
if (!self::is_serialized($data))
{
$regex = '!(?<=^|;)s:(\d+)(?=:"(.*?)";(?:}|a:|s:|b:|d:|i:|o:|N;))!s';
$serial_string = preg_match('/^s:[0-9]+:"(.*$)/s', trim($data), $matches);
//Nested serial string
if ($serial_string)
{
$inner = preg_replace_callback($regex, 'DBUpdateEngine::fix_string_callback', rtrim($matches[1], '";'));
$serialized_fixed = 's:' . strlen($inner) . ':"' . $inner . '";';
}
else
{
$serialized_fixed = preg_replace_callback($regex, 'DBUpdateEngine::fix_string_callback', $data);
}
if (self::is_serialized($serialized_fixed))
{
$result['data'] = $serialized_fixed;
$result['fixed'] = true;
}
$result['tried'] = true;
}
}
return $result;
}
private static function fix_string_callback($matches)
{
return 's:' . strlen(($matches[2]));
}
}
// --------------------------------------------------------------------------------
// PhpConcept Library - Zip Module 2.8.2
// --------------------------------------------------------------------------------
// License GNU/LGPL - Vincent Blavet - August 2009
// http://www.phpconcept.net
// --------------------------------------------------------------------------------
//
// Presentation :
// PclZip is a PHP library that manage ZIP archives.
// So far tests show that archives generated by PclZip are readable by
// WinZip application and other tools.
//
// Description :
// See readme.txt and http://www.phpconcept.net
//
// Warning :
// This library and the associated files are non commercial, non professional
// work.
// It should not have unexpected results. However if any damage is caused by
// this software the author can not be responsible.
// The use of this software is at the risk of the user.
//
// --------------------------------------------------------------------------------
// $Id: pclzip.lib.php,v 1.60 2009/09/30 21:01:04 vblavet Exp $
// --------------------------------------------------------------------------------
// ----- Constants
/* For futur use
define( 'IWP_PCLZIP_CB_PRE_LIST', 78005 );
define( 'IWP_PCLZIP_CB_POST_LIST', 78006 );
define( 'IWP_PCLZIP_CB_PRE_DELETE', 78007 );
define( 'IWP_PCLZIP_CB_POST_DELETE', 78008 );
*/
// --------------------------------------------------------------------------------
// Class : PclZip
// Description :
// PclZip is the class that represent a Zip archive.
// The public methods allow the manipulation of the archive.
// Attributes :
// Attributes must not be accessed directly.
// Methods :
// PclZip() : Object creator
// create() : Creates the Zip archive
// listContent() : List the content of the Zip archive
// extract() : Extract the content of the archive
// properties() : List the properties of the archive
// --------------------------------------------------------------------------------
class IWPPclZip
{
// ----- Filename of the zip file
var $zipname = '';
// ----- File descriptor of the zip file
var $zip_fd = 0;
// ----- Internal error handling
var $error_code = 1;
var $error_string = '';
// ----- Current status of the magic_quotes_runtime
// This value store the php configuration for magic_quotes
// The class can then disable the magic_quotes and reset it after
var $magic_quotes_status;
// --------------------------------------------------------------------------------
// Function : IWPPclZip() or __construct()
// Description :
// Creates a IWPPclZip object and set the name of the associated Zip archive
// filename.
// Note that no real action is taken, if the archive does not exist it is not
// created. Use create() for that.
// --------------------------------------------------------------------------------
function __construct($p_zipname)
{
// ----- Tests the zlib
if (!function_exists('gzopen'))
{
die('Abort '.basename(__FILE__).' : Missing zlib extensions');
}
// ----- Set the attributes
$this->zipname = $p_zipname;
$this->zip_fd = 0;
$this->magic_quotes_status = -1;
// ----- Return
return;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function :
// create($p_filelist, $p_add_dir="", $p_remove_dir="")
// create($p_filelist, $p_option, $p_option_value, ...)
// Description :
// This method supports two different synopsis. The first one is historical.
// This method creates a Zip Archive. The Zip file is created in the
// filesystem. The files and directories indicated in $p_filelist
// are added in the archive. See the parameters description for the
// supported format of $p_filelist.
// When a directory is in the list, the directory and its content is added
// in the archive.
// In this synopsis, the function takes an optional variable list of
// options. See bellow the supported options.
// Parameters :
// $p_filelist : An array containing file or directory names, or
// a string containing one filename or one directory name, or
// a string containing a list of filenames and/or directory
// names separated by spaces.
// $p_add_dir : A path to add before the real path of the archived file,
// in order to have it memorized in the archive.
// $p_remove_dir : A path to remove from the real path of the file to archive,
// in order to have a shorter path memorized in the archive.
// When $p_add_dir and $p_remove_dir are set, $p_remove_dir
// is removed first, before $p_add_dir is added.
// Options :
// IWP_PCLZIP_OPT_ADD_PATH :
// IWP_PCLZIP_OPT_REMOVE_PATH :
// IWP_PCLZIP_OPT_REMOVE_ALL_PATH :
// IWP_PCLZIP_OPT_COMMENT :
// IWP_PCLZIP_CB_PRE_ADD :
// IWP_PCLZIP_CB_POST_ADD :
// Return Values :
// 0 on failure,
// The list of the added files, with a status of the add action.
// (see IWPPclZip::listContent() for list entry format)
// --------------------------------------------------------------------------------
function create($p_filelist)
{
$v_result=1;
// ----- Reset the error handler
$this->privErrorReset();
// ----- Set default values
$v_options = array();
$v_options[IWP_PCLZIP_OPT_NO_COMPRESSION] = FALSE;
$v_options[IWP_PCLZIP_OPT_CHUNK_BLOCK_SIZE] = 15*1024*1024*1024;
$v_options[IWP_PCLZIP_OPT_FILE_EXCLUDE_SIZE] = 15*1024*1024*1024;
$v_options[IWP_PCLZIP_OPT_IWP_EXCLUDE] = array();
$v_options[IWP_PCLZIP_OPT_IWP_EXCLUDE_EXT] = array();
$v_options[IWP_PCLZIP_OPT_HISTORY_ID] = 0;
// ----- Look for variable options arguments
$v_size = func_num_args();
// ----- Look for arguments
if ($v_size > 1) {
// ----- Get the arguments
$v_arg_list = func_get_args();
// ----- Remove from the options list the first argument
array_shift($v_arg_list);
$v_size--;
// ----- Look for first arg
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
// ----- Parse the options
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
array (IWP_PCLZIP_OPT_REMOVE_PATH => 'optional',
IWP_PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
IWP_PCLZIP_OPT_ADD_PATH => 'optional',
IWP_PCLZIP_CB_PRE_ADD => 'optional',
IWP_PCLZIP_CB_POST_ADD => 'optional',
IWP_PCLZIP_OPT_NO_COMPRESSION => 'optional',
IWP_PCLZIP_OPT_COMMENT => 'optional',
IWP_PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
IWP_PCLZIP_OPT_TEMP_FILE_ON => 'optional',
IWP_PCLZIP_OPT_TEMP_FILE_OFF => 'optional',
IWP_PCLZIP_OPT_CHUNK_BLOCK_SIZE => 'optional',
IWP_PCLZIP_OPT_FILE_EXCLUDE_SIZE => 'optional',
IWP_PCLZIP_OPT_HISTORY_ID => 'optional',
IWP_PCLZIP_OPT_IWP_EXCLUDE => 'optional',
IWP_PCLZIP_OPT_IWP_EXCLUDE_EXT => 'optional',
//, IWP_PCLZIP_OPT_CRYPT => 'optional'
));
if ($v_result != 1) {
return 0;
}
}
// ----- Look for 2 args
// Here we need to support the first historic synopsis of the
// method.
else {
// ----- Get the first argument
$v_options[IWP_PCLZIP_OPT_ADD_PATH] = $v_arg_list[0];
// ----- Look for the optional second argument
if ($v_size == 2) {
$v_options[IWP_PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
}
else if ($v_size > 2) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_PARAMETER,
"Invalid number / type of arguments");
return 0;
}
}
}
// ----- Look for default option values
$this->privOptionDefaultThreshold($v_options);
// ----- Init
$v_string_list = array();
$v_att_list = array();
$v_filedescr_list = array();
$p_result_list = array();
// ----- Look if the $p_filelist is really an array
if (is_array($p_filelist)) {
// ----- Look if the first element is also an array
// This will mean that this is a file description entry
if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
$v_att_list = $p_filelist;
}
// ----- The list is a list of string names
else {
$v_string_list = $p_filelist;
}
}
// ----- Look if the $p_filelist is a string
else if (is_string($p_filelist)) {
// ----- Create a list from the string
$v_string_list = explode(IWP_PCLZIP_SEPARATOR, $p_filelist);
}
// ----- Invalid variable type for $p_filelist
else {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist");
return 0;
}
// ----- Reformat the string list
if (sizeof($v_string_list) != 0) {
foreach ($v_string_list as $v_string) {
if ($v_string != '') {
$v_att_list[][IWP_PCLZIP_ATT_FILE_NAME] = $v_string;
}
else {
}
}
}
// ----- For each file in the list check the attributes
$v_supported_attributes
= array ( IWP_PCLZIP_ATT_FILE_NAME => 'mandatory'
,IWP_PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional'
,IWP_PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional'
,IWP_PCLZIP_ATT_FILE_MTIME => 'optional'
,IWP_PCLZIP_ATT_FILE_CONTENT => 'optional'
,IWP_PCLZIP_ATT_FILE_COMMENT => 'optional'
);
foreach ($v_att_list as $v_entry) {
$v_result = $this->privFileDescrParseAtt($v_entry,
$v_filedescr_list[],
$v_options,
$v_supported_attributes);
if ($v_result != 1) {
return 0;
}
}
// ----- Expand the filelist (expand directories)
$v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
if ($v_result != 1) {
return 0;
}
// ----- Call the create fct
$v_result = $this->privCreate($v_filedescr_list, $p_result_list, $v_options);
if ($v_result != 1) {
return 0;
}
// ----- Return
return $p_result_list;
}
// --------------------------------------------------------------------------------
function getFileList($p_filelist) //own function to get the folder and files List
{
$startTime = microtime(true);
$v_result=1;
// ----- Reset the error handler
$this->privErrorReset();
// ----- Set default values
$v_options = array();
$v_options[IWP_PCLZIP_OPT_NO_COMPRESSION] = FALSE;
$v_options[IWP_PCLZIP_OPT_FILE_EXCLUDE_SIZE] = 15*1024*1024*1024;
// ----- Look for variable options arguments
$v_size = func_num_args();
// ----- Look for arguments
if ($v_size > 1) {
// ----- Get the arguments
$v_arg_list = func_get_args();
// ----- Remove form the options list the first argument
array_shift($v_arg_list);
$v_size--;
// ----- Look for first arg
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
// ----- Parse the options
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
array (IWP_PCLZIP_OPT_REMOVE_PATH => 'optional',
IWP_PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
IWP_PCLZIP_OPT_ADD_PATH => 'optional',
IWP_PCLZIP_CB_PRE_ADD => 'optional',
IWP_PCLZIP_CB_POST_ADD => 'optional',
IWP_PCLZIP_OPT_NO_COMPRESSION => 'optional',
IWP_PCLZIP_OPT_COMMENT => 'optional',
IWP_PCLZIP_OPT_ADD_COMMENT => 'optional',
IWP_PCLZIP_OPT_PREPEND_COMMENT => 'optional',
IWP_PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
IWP_PCLZIP_OPT_TEMP_FILE_ON => 'optional',
IWP_PCLZIP_OPT_TEMP_FILE_OFF => 'optional',
IWP_PCLZIP_OPT_CHUNK_BLOCK_SIZE => 'optional',
IWP_PCLZIP_OPT_FILE_EXCLUDE_SIZE => 'optional',
IWP_PCLZIP_OPT_HISTORY_ID => 'optional',
IWP_PCLZIP_OPT_IWP_EXCLUDE => 'optional',
IWP_PCLZIP_OPT_IWP_EXCLUDE_EXT => 'optional',
//, IWP_PCLZIP_OPT_CRYPT => 'optional'
));
if ($v_result != 1) {
return 0;
}
}
// ----- Look for 2 args
// Here we need to support the first historic synopsis of the
// method.
else {
// ----- Get the first argument
$v_options[IWP_PCLZIP_OPT_ADD_PATH] = $v_add_path = $v_arg_list[0];
// ----- Look for the optional second argument
if ($v_size == 2) {
$v_options[IWP_PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
}
else if ($v_size > 2) {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
// ----- Return
return 0;
}
}
}
// ----- Look for default option values
$this->privOptionDefaultThreshold($v_options);
// ----- Init
$v_string_list = array();
$v_att_list = array();
$v_filedescr_list = array();
$p_result_list = array();
// ----- Look if the $p_filelist is really an array
if (is_array($p_filelist)) {
// ----- Look if the first element is also an array
// This will mean that this is a file description entry
if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
$v_att_list = $p_filelist;
}
// ----- The list is a list of string names
else {
$v_string_list = $p_filelist;
}
}
// ----- Look if the $p_filelist is a string
else if (is_string($p_filelist)) {
// ----- Create a list from the string
$v_string_list = explode(IWP_PCLZIP_SEPARATOR, $p_filelist);
}
// ----- Invalid variable type for $p_filelist
else {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type '".gettype($p_filelist)."' for p_filelist");
return 0;
}
// ----- Reformat the string list
if (sizeof($v_string_list) != 0) {
foreach ($v_string_list as $v_string) {
$v_att_list[][IWP_PCLZIP_ATT_FILE_NAME] = $v_string;
}
}
// ----- For each file in the list check the attributes
$v_supported_attributes
= array ( IWP_PCLZIP_ATT_FILE_NAME => 'mandatory'
,IWP_PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional'
,IWP_PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional'
,IWP_PCLZIP_ATT_FILE_MTIME => 'optional'
,IWP_PCLZIP_ATT_FILE_CONTENT => 'optional'
,IWP_PCLZIP_ATT_FILE_COMMENT => 'optional'
);
foreach ($v_att_list as $v_entry) {
$v_result = $this->privFileDescrParseAtt($v_entry,
$v_filedescr_list[],
$v_options,
$v_supported_attributes);
if ($v_result != 1) {
return 0;
}
}
// ----- Expand the filelist (expand directories)
$startTImeForlist = microtime(true);
$prevFileList = array();
$next_file_index = 0;
$complete_folder_list = array();
$historyID = $v_options[IWP_PCLZIP_OPT_HISTORY_ID];
if($historyID)
{
$backupObj = new IWP_MMB_Backup_Multicall();
$responseParams = $backupObj->getRequiredData($historyID,"responseParams");
}
if(!(empty($responseParams)))
{
$prevFileList = isset($responseParams['response_data']['p_filedescr_list']) ? $responseParams['response_data']['p_filedescr_list'] : array();
$next_file_index = isset($responseParams['response_data']['next_file_index']) ? $responseParams['response_data']['next_file_index'] : 0;
$complete_folder_list = isset($responseParams['response_data']['complete_folder_list']) ? $responseParams['response_data']['complete_folder_list'] : array();
}
else
{
}
if(!($prevFileList))
{
$prevFileList = array();
}
if(!($next_file_index))
{
$next_file_index = 0;
}
if(!($complete_folder_list))
{
$complete_folder_list = array();
}
$new_complete_folder_list = array();
$folder_list_result = array();
manual_debug('', 'pclbeforeGettingFileListFirst', 0);
//if(empty($complete_folder_list))
if(true)
{
global $total_count;
$old_next_file_index = $next_file_index;
/* $folder_list_result = $this->getFolderListManual('F:\\wamp\\www\\plugin_for_bugs/wp-dark/', $v_options, $next_file_index);
if(!empty($folder_list_result) && $folder_list_result['break']){
$next_file_index = $folder_list_result['loop_count'];
} */
//first am getting the number of directories and its list
foreach($v_filedescr_list as $value)
{
$folder_list = array();
if(is_dir($value['filename']))
{
//$folder_list = $this->getFolderList($value['filename']);
$folder_list_result = $this->getFolderListManual($value['filename'], $v_options, $old_next_file_index);
if(!empty($folder_list_result) && $folder_list_result['break']){
$next_file_index = $folder_list_result['loop_count'];
break;
}
}
else
{
global $total_count;
$folder_list_result = $this->fileDetailsExpandManual($value['filename'], $v_options, $next_file_index);
if(!empty($folder_list_result) && $folder_list_result['break']){
$next_file_index = $folder_list_result['loop_count'];
break;
}
}
}
}
if(empty($folder_list_result)){
$next_file_index = 0;
}
$timeTaken65 = microtime(true) - $startTImeForlist;
manual_debug('', 'pclAfterGettingFileListFirst', 0);
//for the file list prepared am doing the pclZip file preparation
//manual_debug('', 'pclbeforeGettingFileListSecond', 0);
$prevlistCount = count($prevFileList);
$current_file_array = array();
$current_file_array = $prevFileList;
$file_list_result = array();
$file_list_result['status'] = 'completed';
$file_list_result['next_file_index'] = $next_file_index;
if(!empty($folder_list_result) && !empty($folder_list_result['break'])){
$file_list_result['status'] = 'partiallyCompleted';
$file_list_result['next_file_index'] = $next_file_index + 1;
}
$file_list_result['p_filedescr_list'] = array();
global $total_FL_count;
$file_list_result['total_FL_count'] = $total_FL_count;
if ($v_result != 1) {
return 0;
}
// ----- Call the create fct
/* $v_result = $this->privAdd($v_filedescr_list, $p_result_list, $v_options);
if ($v_result != 1) {
return 0;
} */
// ----- Return
//return $file_list_iwp;
return $file_list_result;
}
//---------------------------------------------------------------------------------
function getRequiredData($historyID, $field){
global $wpdb;
$backupData = $wpdb->get_row("SELECT ".$field." FROM ".$wpdb->base_prefix."iwp_backup_status WHERE historyID = ".$historyID);
if(($field == 'responseParams')||($field == 'requestParams')||($field == 'taskResults')){
$fieldParams = base64_decode($backupData->$field);
$fieldParams = unserialize($fieldParams);
}
else
{
$fieldParams = $backupData->$field;
}
return $fieldParams;
}
function getFilesListForCurrentDir($dir, &$dirs_iwp, &$files_iwp, $level = 1, $last = 1){
//print $dir." (DIR)\n";
$dp=opendir($dir);
while (false!=($file=readdir($dp)) && $level == $last){
if ($file!="." && $file!="..")
{
if (is_dir($dir."/".$file))
{
$this->getFilesListForCurrentDir($dir."/".$file, $dirs_iwp, $files_iwp, $level+1, $last); // uses recursion
//$dirs_iwp[] = "$dir/$file"; // reads the dir into an array
}
else{
$files_iwp[][]['filename'] = "$dir/$file"; // reads the file into an array
}
}
}
}
//Function : getFolderList()
function getFolderList($dir)
{
static $info = array();
if( is_dir( $dir = rtrim( $dir, "/\\" ) ) ) {
foreach( scandir( $dir) as $item ) {
if( $item != "." && $item != ".." ) {
$info['all'][][]['filename'] = $absPath = $dir . DIRECTORY_SEPARATOR . $item;
$stat = stat( $absPath );
switch( $stat['mode'] & 0170000 ) {
case 0010000: $info['files'][] = $absPath; break;
case 0040000: $info['directories'][] = $absPath; $this->getFolderList( $absPath ); break;
case 0120000: $info['links'][] = $absPath; break;
case 0140000: $info['sockets'][] = $absPath; break;
case 0010000: $info['pipes'][] = $absPath; break;
}
}
}
}
clearstatcache();
return $info['all'];
}
function getFolderListManual($dir, $v_options = array(), $next_file_index = 0)
{
global $total_count;
global $for_every_count;
static $info = array();
static $this_result;
if(empty($this_result)){
if( is_dir( $dir = rtrim( $dir, "/\\" ) ) ) {
foreach( scandir( $dir) as $item ) {
if(true){
if( $item != "." && $item != ".." ) {
$absPath = $dir . DIRECTORY_SEPARATOR . $item;
$this_result = $this->fileDetailsExpandManual($absPath, $v_options, $next_file_index);
if(!empty($this_result) && !empty($this_result['break'])){
return $this_result;
//break;
}
if(empty($this_result)){
$stat = stat( $absPath );
switch( $stat['mode'] & 0170000 ) {
//case 0010000: $info['files'][] = $absPath; break;
case 0040000: $this_result = $this->getFolderListManual($absPath, $v_options, $next_file_index); break;
//case 0120000: $info['links'][] = $absPath; break;
//case 0140000: $info['sockets'][] = $absPath; break;
//case 0010000: $info['pipes'][] = $absPath; break;
}
if(!empty($this_result) && !empty($this_result['break'])){
return $this_result;
//break;
}
}
}
}
}
}
}
clearstatcache();
return $this_result;
}
function fileDetailsExpandManual($absPath, $v_options, $next_file_index = 0){
global $total_FL_count;
global $total_count;
$total_count++;
$this_result = false;
if($total_count >= $next_file_index){
$to_be_expanded_array = array( 0 => array( 'filename' => $absPath ) );
$v_result = $this->privFileDescrExpand($to_be_expanded_array, $v_options, "getFileList");
if($v_result == 1 && !empty($to_be_expanded_array)){
foreach($to_be_expanded_array as $key => $value){
$this_result = save_in_iwp_files_db(0, $value);
if(!empty($this_result) && !empty($this_result['break'])){
$total_count = $total_count - 1;
$this_result['loop_count'] = $total_count;
return $this_result;
}
}
$total_FL_count++;
}
}
return $this_result;
}
//---------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function :
// add($p_filelist, $p_add_dir="", $p_remove_dir="")
// add($p_filelist, $p_option, $p_option_value, ...)
// Description :
// This method supports two synopsis. The first one is historical.
// This methods add the list of files in an existing archive.
// If a file with the same name already exists, it is added at the end of the
// archive, the first one is still present.
// If the archive does not exist, it is created.
// Parameters :
// $p_filelist : An array containing file or directory names, or
// a string containing one filename or one directory name, or
// a string containing a list of filenames and/or directory
// names separated by spaces.
// $p_add_dir : A path to add before the real path of the archived file,
// in order to have it memorized in the archive.
// $p_remove_dir : A path to remove from the real path of the file to archive,
// in order to have a shorter path memorized in the archive.
// When $p_add_dir and $p_remove_dir are set, $p_remove_dir
// is removed first, before $p_add_dir is added.
// Options :
// IWP_PCLZIP_OPT_ADD_PATH :
// IWP_PCLZIP_OPT_REMOVE_PATH :
// IWP_PCLZIP_OPT_REMOVE_ALL_PATH :
// IWP_PCLZIP_OPT_COMMENT :
// IWP_PCLZIP_OPT_ADD_COMMENT :
// IWP_PCLZIP_OPT_PREPEND_COMMENT :
// IWP_PCLZIP_CB_PRE_ADD :
// IWP_PCLZIP_CB_POST_ADD :
// Return Values :
// 0 on failure,
// The list of the added files, with a status of the add action.
// (see IWPPclZip::listContent() for list entry format)
// --------------------------------------------------------------------------------
function add($p_filelist)
{
$v_result=1;
// ----- Reset the error handler
$this->privErrorReset();
// ----- Set default values
$v_options = array();
$v_options[IWP_PCLZIP_OPT_NO_COMPRESSION] = FALSE;
$v_options[IWP_PCLZIP_OPT_CHUNK_BLOCK_SIZE] = 15*1024*1024*1024;
$v_options[IWP_PCLZIP_OPT_FILE_EXCLUDE_SIZE] = 15*1024*1024*1024;
$v_options[IWP_PCLZIP_OPT_IWP_EXCLUDE] = array();
$v_options[IWP_PCLZIP_OPT_IWP_EXCLUDE_EXT] = array();
$v_options[IWP_PCLZIP_OPT_HISTORY_ID] = 0;
// ----- Look for variable options arguments
$v_size = func_num_args();
// ----- Look for arguments
if ($v_size > 1) {
// ----- Get the arguments
$v_arg_list = func_get_args();
// ----- Remove form the options list the first argument
array_shift($v_arg_list);
$v_size--;
// ----- Look for first arg
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
// ----- Parse the options
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
array (IWP_PCLZIP_OPT_REMOVE_PATH => 'optional',
IWP_PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
IWP_PCLZIP_OPT_ADD_PATH => 'optional',
IWP_PCLZIP_CB_PRE_ADD => 'optional',
IWP_PCLZIP_CB_POST_ADD => 'optional',
IWP_PCLZIP_OPT_NO_COMPRESSION => 'optional',
IWP_PCLZIP_OPT_COMMENT => 'optional',
IWP_PCLZIP_OPT_ADD_COMMENT => 'optional',
IWP_PCLZIP_OPT_PREPEND_COMMENT => 'optional',
IWP_PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
IWP_PCLZIP_OPT_TEMP_FILE_ON => 'optional',
IWP_PCLZIP_OPT_CHUNK_BLOCK_SIZE => 'optional',
IWP_PCLZIP_OPT_FILE_EXCLUDE_SIZE => 'optional',
IWP_PCLZIP_OPT_HISTORY_ID => 'optional',
IWP_PCLZIP_OPT_TEMP_FILE_OFF => 'optional',
IWP_PCLZIP_OPT_IWP_EXCLUDE => 'optional',
IWP_PCLZIP_OPT_IWP_EXCLUDE_EXT => 'optional',
//, IWP_PCLZIP_OPT_CRYPT => 'optional'
));
if ($v_result != 1) {
return 0;
}
}
// ----- Look for 2 args
// Here we need to support the first historic synopsis of the
// method.
else {
// ----- Get the first argument
$v_options[IWP_PCLZIP_OPT_ADD_PATH] = $v_add_path = $v_arg_list[0];
// ----- Look for the optional second argument
if ($v_size == 2) {
$v_options[IWP_PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
}
else if ($v_size > 2) {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
// ----- Return
return 0;
}
}
}
// ----- Look for default option values
$this->privOptionDefaultThreshold($v_options);
// ----- Init
$v_string_list = array();
$v_att_list = array();
$v_filedescr_list = array();
$p_result_list = array();
// ----- Look if the $p_filelist is really an array
if (is_array($p_filelist)) {
// ----- Look if the first element is also an array
// This will mean that this is a file description entry
if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
$v_att_list = $p_filelist;
}
// ----- The list is a list of string names
else {
$v_string_list = $p_filelist;
}
}
// ----- Look if the $p_filelist is a string
else if (is_string($p_filelist)) {
// ----- Create a list from the string
$v_string_list = explode(IWP_PCLZIP_SEPARATOR, $p_filelist);
}
// ----- Invalid variable type for $p_filelist
else {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type '".gettype($p_filelist)."' for p_filelist");
return 0;
}
// ----- Reformat the string list
if (sizeof($v_string_list) != 0) {
foreach ($v_string_list as $v_string) {
$v_att_list[][IWP_PCLZIP_ATT_FILE_NAME] = $v_string;
}
}
// ----- For each file in the list check the attributes
$v_supported_attributes
= array ( IWP_PCLZIP_ATT_FILE_NAME => 'mandatory'
,IWP_PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional'
,IWP_PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional'
,IWP_PCLZIP_ATT_FILE_MTIME => 'optional'
,IWP_PCLZIP_ATT_FILE_CONTENT => 'optional'
,IWP_PCLZIP_ATT_FILE_COMMENT => 'optional'
);
foreach ($v_att_list as $v_entry) {
$v_result = $this->privFileDescrParseAtt($v_entry,
$v_filedescr_list[],
$v_options,
$v_supported_attributes);
if ($v_result != 1) {
return 0;
}
}
// ----- Expand the filelist (expand directories)
$v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
if ($v_result != 1) {
return 0;
}
// ----- Call the create fct
$v_result = $this->privAdd($v_filedescr_list, $p_result_list, $v_options);
if ($v_result != 1) {
return 0;
}
// ----- Return
return $p_result_list;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : listContent()
// Description :
// This public method, gives the list of the files and directories, with their
// properties.
// The properties of each entries in the list are (used also in other functions) :
// filename : Name of the file. For a create or add action it is the filename
// given by the user. For an extract function it is the filename
// of the extracted file.
// stored_filename : Name of the file / directory stored in the archive.
// size : Size of the stored file.
// compressed_size : Size of the file's data compressed in the archive
// (without the headers overhead)
// mtime : Last known modification date of the file (UNIX timestamp)
// comment : Comment associated with the file
// folder : true | false
// index : index of the file in the archive
// status : status of the action (depending of the action) :
// Values are :
// ok : OK !
// filtered : the file / dir is not extracted (filtered by user)
// already_a_directory : the file can not be extracted because a
// directory with the same name already exists
// write_protected : the file can not be extracted because a file
// with the same name already exists and is
// write protected
// newer_exist : the file was not extracted because a newer file exists
// path_creation_fail : the file is not extracted because the folder
// does not exist and can not be created
// write_error : the file was not extracted because there was a
// error while writing the file
// read_error : the file was not extracted because there was a error
// while reading the file
// invalid_header : the file was not extracted because of an archive
// format error (bad file header)
// Note that each time a method can continue operating when there
// is an action error on a file, the error is only logged in the file status.
// Return Values :
// 0 on an unrecoverable failure,
// The list of the files in the archive.
// --------------------------------------------------------------------------------
function listContent()
{
$v_result=1;
// ----- Reset the error handler
$this->privErrorReset();
// ----- Check archive
if (!$this->privCheckFormat()) {
return(0);
}
// ----- Call the extracting fct
$p_list = array();
if (($v_result = $this->privList($p_list)) != 1)
{
unset($p_list);
return(0);
}
// ----- Return
return $p_list;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function :
// extract($p_path="./", $p_remove_path="")
// extract([$p_option, $p_option_value, ...])
// Description :
// This method supports two synopsis. The first one is historical.
// This method extract all the files / directories from the archive to the
// folder indicated in $p_path.
// If you want to ignore the 'root' part of path of the memorized files
// you can indicate this in the optional $p_remove_path parameter.
// By default, if a newer file with the same name already exists, the
// file is not extracted.
//
// If both IWP_PCLZIP_OPT_PATH and IWP_PCLZIP_OPT_ADD_PATH aoptions
// are used, the path indicated in IWP_PCLZIP_OPT_ADD_PATH is append
// at the end of the path value of IWP_PCLZIP_OPT_PATH.
// Parameters :
// $p_path : Path where the files and directories are to be extracted
// $p_remove_path : First part ('root' part) of the memorized path
// (if any similar) to remove while extracting.
// Options :
// IWP_PCLZIP_OPT_PATH :
// IWP_PCLZIP_OPT_ADD_PATH :
// IWP_PCLZIP_OPT_REMOVE_PATH :
// IWP_PCLZIP_OPT_REMOVE_ALL_PATH :
// IWP_PCLZIP_CB_PRE_EXTRACT :
// IWP_PCLZIP_CB_POST_EXTRACT :
// Return Values :
// 0 or a negative value on failure,
// The list of the extracted files, with a status of the action.
// (see IWPPclZip::listContent() for list entry format)
// --------------------------------------------------------------------------------
function extract()
{
$v_result=1;
// ----- Reset the error handler
$this->privErrorReset();
// ----- Check archive
if (!$this->privCheckFormat()) {
return(0);
}
// ----- Set default values
$v_options = array();
// $v_path = "./";
$v_path = '';
$v_remove_path = "";
$v_remove_all_path = false;
// ----- Look for variable options arguments
$v_size = func_num_args();
// ----- Default values for option
$v_options[IWP_PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
$v_options[IWP_PCLZIP_OPT_REPLACE_NEWER] = TRUE;
$v_options[IWP_PCLZIP_OPT_CHUNK_BLOCK_SIZE] = 15*1024*1024*1024;
$v_options[IWP_PCLZIP_OPT_FILE_EXCLUDE_SIZE] = 15*1024*1024*1024;
// ----- Look for arguments
if ($v_size > 0) {
// ----- Get the arguments
$v_arg_list = func_get_args();
// ----- Look for first arg
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
// ----- Parse the options
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
array (IWP_PCLZIP_OPT_PATH => 'optional',
IWP_PCLZIP_OPT_REMOVE_PATH => 'optional',
IWP_PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
IWP_PCLZIP_OPT_ADD_PATH => 'optional',
IWP_PCLZIP_CB_PRE_EXTRACT => 'optional',
IWP_PCLZIP_CB_POST_EXTRACT => 'optional',
IWP_PCLZIP_OPT_SET_CHMOD => 'optional',
IWP_PCLZIP_OPT_BY_NAME => 'optional',
IWP_PCLZIP_OPT_BY_EREG => 'optional',
IWP_PCLZIP_OPT_BY_PREG => 'optional',
IWP_PCLZIP_OPT_BY_INDEX => 'optional',
IWP_PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
IWP_PCLZIP_OPT_EXTRACT_IN_OUTPUT => 'optional',
IWP_PCLZIP_OPT_REPLACE_NEWER => 'optional',
IWP_PCLZIP_OPT_STOP_ON_ERROR => 'optional',
IWP_PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional',
IWP_PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
IWP_PCLZIP_OPT_CHUNK_BLOCK_SIZE => 'optional',
IWP_PCLZIP_OPT_FILE_EXCLUDE_SIZE => 'optional',
IWP_PCLZIP_OPT_HISTORY_ID => 'optional',
IWP_PCLZIP_OPT_TEMP_FILE_ON => 'optional',
IWP_PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
));
if ($v_result != 1) {
return 0;
}
// ----- Set the arguments
if (isset($v_options[IWP_PCLZIP_OPT_PATH])) {
$v_path = $v_options[IWP_PCLZIP_OPT_PATH];
}
if (isset($v_options[IWP_PCLZIP_OPT_REMOVE_PATH])) {
$v_remove_path = $v_options[IWP_PCLZIP_OPT_REMOVE_PATH];
}
if (isset($v_options[IWP_PCLZIP_OPT_REMOVE_ALL_PATH])) {
$v_remove_all_path = $v_options[IWP_PCLZIP_OPT_REMOVE_ALL_PATH];
}
if (isset($v_options[IWP_PCLZIP_OPT_ADD_PATH])) {
// ----- Check for '/' in last path char
if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
$v_path .= '/';
}
$v_path .= $v_options[IWP_PCLZIP_OPT_ADD_PATH];
}
}
// ----- Look for 2 args
// Here we need to support the first historic synopsis of the
// method.
else {
// ----- Get the first argument
$v_path = $v_arg_list[0];
// ----- Look for the optional second argument
if ($v_size == 2) {
$v_remove_path = $v_arg_list[1];
}
else if ($v_size > 2) {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments --".$v_size);
// ----- Return
return 0;
}
}
}
// ----- Look for default option values
$this->privOptionDefaultThreshold($v_options);
// ----- Trace
// ----- Call the extracting fct
$p_list = array();
$v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options);
if ($v_result < 1) {
unset($p_list);
return(0);
}
if(is_array($v_result) && $v_result['status'] == 'partiallyCompleted' || $v_result){
return $v_result;
}
// ----- Return
return $p_list;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function :
// extractByIndex($p_index, $p_path="./", $p_remove_path="")
// extractByIndex($p_index, [$p_option, $p_option_value, ...])
// Description :
// This method supports two synopsis. The first one is historical.
// This method is doing a partial extract of the archive.
// The extracted files or folders are identified by their index in the
// archive (from 0 to n).
// Note that if the index identify a folder, only the folder entry is
// extracted, not all the files included in the archive.
// Parameters :
// $p_index : A single index (integer) or a string of indexes of files to
// extract. The form of the string is "0,4-6,8-12" with only numbers
// and '-' for range or ',' to separate ranges. No spaces or ';'
// are allowed.
// $p_path : Path where the files and directories are to be extracted
// $p_remove_path : First part ('root' part) of the memorized path
// (if any similar) to remove while extracting.
// Options :
// IWP_PCLZIP_OPT_PATH :
// IWP_PCLZIP_OPT_ADD_PATH :
// IWP_PCLZIP_OPT_REMOVE_PATH :
// IWP_PCLZIP_OPT_REMOVE_ALL_PATH :
// IWP_PCLZIP_OPT_EXTRACT_AS_STRING : The files are extracted as strings and
// not as files.
// The resulting content is in a new field 'content' in the file
// structure.
// This option must be used alone (any other options are ignored).
// IWP_PCLZIP_CB_PRE_EXTRACT :
// IWP_PCLZIP_CB_POST_EXTRACT :
// Return Values :
// 0 on failure,
// The list of the extracted files, with a status of the action.
// (see IWPPclZip::listContent() for list entry format)
// --------------------------------------------------------------------------------
//function extractByIndex($p_index, options...)
function extractByIndex($p_index)
{
$v_result=1;
// ----- Reset the error handler
$this->privErrorReset();
// ----- Check archive
if (!$this->privCheckFormat()) {
return(0);
}
// ----- Set default values
$v_options = array();
// $v_path = "./";
$v_path = '';
$v_remove_path = "";
$v_remove_all_path = false;
// ----- Look for variable options arguments
$v_size = func_num_args();
// ----- Default values for option
$v_options[IWP_PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
$v_options[IWP_PCLZIP_OPT_CHUNK_BLOCK_SIZE] = 15*1024*1024*1024;
$v_options[IWP_PCLZIP_OPT_FILE_EXCLUDE_SIZE] = 15*1024*1024*1024;
// ----- Look for arguments
if ($v_size > 1) {
// ----- Get the arguments
$v_arg_list = func_get_args();
// ----- Remove form the options list the first argument
array_shift($v_arg_list);
$v_size--;
// ----- Look for first arg
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
// ----- Parse the options
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
array (IWP_PCLZIP_OPT_PATH => 'optional',
IWP_PCLZIP_OPT_REMOVE_PATH => 'optional',
IWP_PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
IWP_PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
IWP_PCLZIP_OPT_ADD_PATH => 'optional',
IWP_PCLZIP_CB_PRE_EXTRACT => 'optional',
IWP_PCLZIP_CB_POST_EXTRACT => 'optional',
IWP_PCLZIP_OPT_SET_CHMOD => 'optional',
IWP_PCLZIP_OPT_REPLACE_NEWER => 'optional',
IWP_PCLZIP_OPT_STOP_ON_ERROR => 'optional',
IWP_PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional',
IWP_PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
IWP_PCLZIP_OPT_CHUNK_BLOCK_SIZE => 'optional',
IWP_PCLZIP_OPT_FILE_EXCLUDE_SIZE => 'optional',
IWP_PCLZIP_OPT_HISTORY_ID => 'optional',
IWP_PCLZIP_OPT_TEMP_FILE_ON => 'optional',
IWP_PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
));
if ($v_result != 1) {
return 0;
}
// ----- Set the arguments
if (isset($v_options[IWP_PCLZIP_OPT_PATH])) {
$v_path = $v_options[IWP_PCLZIP_OPT_PATH];
}
if (isset($v_options[IWP_PCLZIP_OPT_REMOVE_PATH])) {
$v_remove_path = $v_options[IWP_PCLZIP_OPT_REMOVE_PATH];
}
if (isset($v_options[IWP_PCLZIP_OPT_REMOVE_ALL_PATH])) {
$v_remove_all_path = $v_options[IWP_PCLZIP_OPT_REMOVE_ALL_PATH];
}
if (isset($v_options[IWP_PCLZIP_OPT_ADD_PATH])) {
// ----- Check for '/' in last path char
if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
$v_path .= '/';
}
$v_path .= $v_options[IWP_PCLZIP_OPT_ADD_PATH];
}
if (!isset($v_options[IWP_PCLZIP_OPT_EXTRACT_AS_STRING])) {
$v_options[IWP_PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
}
else {
}
}
// ----- Look for 2 args
// Here we need to support the first historic synopsis of the
// method.
else {
// ----- Get the first argument
$v_path = $v_arg_list[0];
// ----- Look for the optional second argument
if ($v_size == 2) {
$v_remove_path = $v_arg_list[1];
}
else if ($v_size > 2) {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
// ----- Return
return 0;
}
}
}
// ----- Trace
// ----- Trick
// Here I want to reuse extractByRule(), so I need to parse the $p_index
// with privParseOptions()
$v_arg_trick = array (IWP_PCLZIP_OPT_BY_INDEX, $p_index);
$v_options_trick = array();
$v_result = $this->privParseOptions($v_arg_trick, sizeof($v_arg_trick), $v_options_trick,
array (IWP_PCLZIP_OPT_BY_INDEX => 'optional' ));
if ($v_result != 1) {
return 0;
}
$v_options[IWP_PCLZIP_OPT_BY_INDEX] = $v_options_trick[IWP_PCLZIP_OPT_BY_INDEX];
// ----- Look for default option values
$this->privOptionDefaultThreshold($v_options);
// ----- Call the extracting fct
if (($v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) < 1) {
return(0);
}
// ----- Return
return $p_list;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function :
// delete([$p_option, $p_option_value, ...])
// Description :
// This method removes files from the archive.
// If no parameters are given, then all the archive is emptied.
// Parameters :
// None or optional arguments.
// Options :
// IWP_PCLZIP_OPT_BY_INDEX :
// IWP_PCLZIP_OPT_BY_NAME :
// IWP_PCLZIP_OPT_BY_EREG :
// IWP_PCLZIP_OPT_BY_PREG :
// Return Values :
// 0 on failure,
// The list of the files which are still present in the archive.
// (see IWPPclZip::listContent() for list entry format)
// --------------------------------------------------------------------------------
function delete()
{
$v_result=1;
// ----- Reset the error handler
$this->privErrorReset();
// ----- Check archive
if (!$this->privCheckFormat()) {
return(0);
}
// ----- Set default values
$v_options = array();
// ----- Look for variable options arguments
$v_size = func_num_args();
// ----- Look for arguments
if ($v_size > 0) {
// ----- Get the arguments
$v_arg_list = func_get_args();
// ----- Parse the options
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
array (IWP_PCLZIP_OPT_BY_NAME => 'optional',
IWP_PCLZIP_OPT_BY_EREG => 'optional',
IWP_PCLZIP_OPT_BY_PREG => 'optional',
IWP_PCLZIP_OPT_BY_INDEX => 'optional' ));
if ($v_result != 1) {
return 0;
}
}
// ----- Magic quotes trick
$this->privDisableMagicQuotes();
// ----- Call the delete fct
$v_list = array();
if (($v_result = $this->privDeleteByRule($v_list, $v_options)) != 1) {
$this->privSwapBackMagicQuotes();
unset($v_list);
return(0);
}
// ----- Magic quotes trick
$this->privSwapBackMagicQuotes();
// ----- Return
return $v_list;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : deleteByIndex()
// Description :
// ***** Deprecated *****
// delete(IWP_PCLZIP_OPT_BY_INDEX, $p_index) should be prefered.
// --------------------------------------------------------------------------------
function deleteByIndex($p_index)
{
$p_list = $this->delete(IWP_PCLZIP_OPT_BY_INDEX, $p_index);
// ----- Return
return $p_list;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : properties()
// Description :
// This method gives the properties of the archive.
// The properties are :
// nb : Number of files in the archive
// comment : Comment associated with the archive file
// status : not_exist, ok
// Parameters :
// None
// Return Values :
// 0 on failure,
// An array with the archive properties.
// --------------------------------------------------------------------------------
function properties()
{
// ----- Reset the error handler
$this->privErrorReset();
// ----- Magic quotes trick
$this->privDisableMagicQuotes();
// ----- Check archive
if (!$this->privCheckFormat()) {
$this->privSwapBackMagicQuotes();
return(0);
}
// ----- Default properties
$v_prop = array();
$v_prop['comment'] = '';
$v_prop['nb'] = 0;
$v_prop['status'] = 'not_exist';
// ----- Look if file exists
if (@is_file($this->zipname))
{
// ----- Open the zip file
if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
{
$this->privSwapBackMagicQuotes();
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
// ----- Return
return 0;
}
// ----- Read the central directory informations
$v_central_dir = array();
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
{
$this->privSwapBackMagicQuotes();
return 0;
}
// ----- Close the zip file
$this->privCloseFd();
// ----- Set the user attributes
$v_prop['comment'] = $v_central_dir['comment'];
$v_prop['nb'] = $v_central_dir['entries'];
$v_prop['status'] = 'ok';
}
// ----- Magic quotes trick
$this->privSwapBackMagicQuotes();
// ----- Return
return $v_prop;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : duplicate()
// Description :
// This method creates an archive by copying the content of an other one. If
// the archive already exist, it is replaced by the new one without any warning.
// Parameters :
// $p_archive : The filename of a valid archive, or
// a valid IWPPclZip object.
// Return Values :
// 1 on success.
// 0 or a negative value on error (error code).
// --------------------------------------------------------------------------------
function duplicate($p_archive)
{
$v_result = 1;
// ----- Reset the error handler
$this->privErrorReset();
// ----- Look if the $p_archive is a IWPPclZip object
if ((is_object($p_archive)) && (get_class($p_archive) == 'pclzip'))
{
// ----- Duplicate the archive
$v_result = $this->privDuplicate($p_archive->zipname);
}
// ----- Look if the $p_archive is a string (so a filename)
else if (is_string($p_archive))
{
// ----- Check that $p_archive is a valid zip file
// TBC : Should also check the archive format
if (!is_file($p_archive)) {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_MISSING_FILE, "No file with filename '".$p_archive."'");
$v_result = IWP_PCLZIP_ERR_MISSING_FILE;
}
else {
// ----- Duplicate the archive
$v_result = $this->privDuplicate($p_archive);
}
}
// ----- Invalid variable
else
{
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
$v_result = IWP_PCLZIP_ERR_INVALID_PARAMETER;
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : merge()
// Description :
// This method merge the $p_archive_to_add archive at the end of the current
// one ($this).
// If the archive ($this) does not exist, the merge becomes a duplicate.
// If the $p_archive_to_add archive does not exist, the merge is a success.
// Parameters :
// $p_archive_to_add : It can be directly the filename of a valid zip archive,
// or a IWPPclZip object archive.
// Return Values :
// 1 on success,
// 0 or negative values on error (see below).
// --------------------------------------------------------------------------------
function merge($p_archive_to_add)
{
$v_result = 1;
// ----- Reset the error handler
$this->privErrorReset();
// ----- Check archive
if (!$this->privCheckFormat()) {
return(0);
}
// ----- Look if the $p_archive_to_add is a IWPPclZip object
if ((is_object($p_archive_to_add)) && (get_class($p_archive_to_add) == 'pclzip'))
{
// ----- Merge the archive
$v_result = $this->privMerge($p_archive_to_add);
}
// ----- Look if the $p_archive_to_add is a string (so a filename)
else if (is_string($p_archive_to_add))
{
// ----- Create a temporary archive
$v_object_archive = new IWPPclZip($p_archive_to_add);
// ----- Merge the archive
$v_result = $this->privMerge($v_object_archive);
}
// ----- Invalid variable
else
{
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
$v_result = IWP_PCLZIP_ERR_INVALID_PARAMETER;
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : errorCode()
// Description :
// Parameters :
// --------------------------------------------------------------------------------
function errorCode()
{
if (IWP_PCLZIP_ERROR_EXTERNAL == 1) {
return(PclErrorCode());
}
else {
return($this->error_code);
}
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : errorName()
// Description :
// Parameters :
// --------------------------------------------------------------------------------
function errorName($p_with_code=false)
{
$v_name = array ( IWP_PCLZIP_ERR_NO_ERROR => 'IWP_PCLZIP_ERR_NO_ERROR',
IWP_PCLZIP_ERR_WRITE_OPEN_FAIL => 'IWP_PCLZIP_ERR_WRITE_OPEN_FAIL',
IWP_PCLZIP_ERR_READ_OPEN_FAIL => 'IWP_PCLZIP_ERR_READ_OPEN_FAIL',
IWP_PCLZIP_ERR_INVALID_PARAMETER => 'IWP_PCLZIP_ERR_INVALID_PARAMETER',
IWP_PCLZIP_ERR_MISSING_FILE => 'IWP_PCLZIP_ERR_MISSING_FILE',
IWP_PCLZIP_ERR_FILENAME_TOO_LONG => 'IWP_PCLZIP_ERR_FILENAME_TOO_LONG',
IWP_PCLZIP_ERR_INVALID_ZIP => 'IWP_PCLZIP_ERR_INVALID_ZIP',
IWP_PCLZIP_ERR_BAD_EXTRACTED_FILE => 'IWP_PCLZIP_ERR_BAD_EXTRACTED_FILE',
IWP_PCLZIP_ERR_DIR_CREATE_FAIL => 'IWP_PCLZIP_ERR_DIR_CREATE_FAIL',
IWP_PCLZIP_ERR_BAD_EXTENSION => 'IWP_PCLZIP_ERR_BAD_EXTENSION',
IWP_PCLZIP_ERR_BAD_FORMAT => 'IWP_PCLZIP_ERR_BAD_FORMAT',
IWP_PCLZIP_ERR_DELETE_FILE_FAIL => 'IWP_PCLZIP_ERR_DELETE_FILE_FAIL',
IWP_PCLZIP_ERR_RENAME_FILE_FAIL => 'IWP_PCLZIP_ERR_RENAME_FILE_FAIL',
IWP_PCLZIP_ERR_BAD_CHECKSUM => 'IWP_PCLZIP_ERR_BAD_CHECKSUM',
IWP_PCLZIP_ERR_INVALID_ARCHIVE_ZIP => 'IWP_PCLZIP_ERR_INVALID_ARCHIVE_ZIP',
IWP_PCLZIP_ERR_MISSING_OPTION_VALUE => 'IWP_PCLZIP_ERR_MISSING_OPTION_VALUE',
IWP_PCLZIP_ERR_INVALID_OPTION_VALUE => 'IWP_PCLZIP_ERR_INVALID_OPTION_VALUE',
IWP_PCLZIP_ERR_UNSUPPORTED_COMPRESSION => 'IWP_PCLZIP_ERR_UNSUPPORTED_COMPRESSION',
IWP_PCLZIP_ERR_UNSUPPORTED_ENCRYPTION => 'IWP_PCLZIP_ERR_UNSUPPORTED_ENCRYPTION'
,IWP_PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE => 'IWP_PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE'
,IWP_PCLZIP_ERR_DIRECTORY_RESTRICTION => 'IWP_PCLZIP_ERR_DIRECTORY_RESTRICTION'
);
if (isset($v_name[$this->error_code])) {
$v_value = $v_name[$this->error_code];
}
else {
$v_value = 'NoName';
}
if ($p_with_code) {
return($v_value.' ('.$this->error_code.')');
}
else {
return($v_value);
}
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : errorInfo()
// Description :
// Parameters :
// --------------------------------------------------------------------------------
function errorInfo($p_full=false)
{
if (IWP_PCLZIP_ERROR_EXTERNAL == 1) {
return(PclErrorString());
}
else {
if ($p_full) {
return($this->errorName(true)." : ".$this->error_string);
}
else {
return($this->error_string." [code ".$this->error_code."]");
}
}
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS *****
// ***** *****
// ***** THESES FUNCTIONS MUST NOT BE USED DIRECTLY *****
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privCheckFormat()
// Description :
// This method check that the archive exists and is a valid zip archive.
// Several level of check exists. (futur)
// Parameters :
// $p_level : Level of check. Default 0.
// 0 : Check the first bytes (magic codes) (default value))
// 1 : 0 + Check the central directory (futur)
// 2 : 1 + Check each file header (futur)
// Return Values :
// true on success,
// false on error, the error code is set.
// --------------------------------------------------------------------------------
function privCheckFormat($p_level=0)
{
$v_result = true;
// ----- Reset the file system cache
clearstatcache();
// ----- Reset the error handler
$this->privErrorReset();
// ----- Look if the file exits
if (!is_file($this->zipname)) {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_MISSING_FILE, "Missing archive file '".$this->zipname."'");
return(false);
}
// ----- Check that the file is readeable
if (!is_readable($this->zipname)) {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '".$this->zipname."'");
return(false);
}
// ----- Check the magic code
// TBC
// ----- Check the central header
// TBC
// ----- Check each file header
// TBC
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privParseOptions()
// Description :
// This internal methods reads the variable list of arguments ($p_options_list,
// $p_size) and generate an array with the options and values ($v_result_list).
// $v_requested_options contains the options that can be present and those that
// must be present.
// $v_requested_options is an array, with the option value as key, and 'optional',
// or 'mandatory' as value.
// Parameters :
// See above.
// Return Values :
// 1 on success.
// 0 on failure.
// --------------------------------------------------------------------------------
function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options=false)
{
$v_result=1;
// ----- Read the options
$i=0;
while ($i<$p_size) {
// ----- Check if the option is supported
if (!isset($v_requested_options[$p_options_list[$i]])) {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_PARAMETER, "Invalid optional parameter '".$p_options_list[$i]."' for this method");
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Look for next option
switch ($p_options_list[$i]) {
// ----- Look for options that request a path value
case IWP_PCLZIP_OPT_IWP_EXCLUDE :
if (is_array($p_options_list[$i+1])) {
$v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
}
$i++;
break;
case IWP_PCLZIP_OPT_IWP_EXCLUDE_EXT :
if (is_array($p_options_list[$i+1])) {
$v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
}
$i++;
break;
case IWP_PCLZIP_OPT_PATH :
case IWP_PCLZIP_OPT_REMOVE_PATH :
case IWP_PCLZIP_OPT_ADD_PATH :
// ----- Check the number of parameters
if (($i+1) >= $p_size) {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".IWPPclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Get the value
$v_result_list[$p_options_list[$i]] = IWPPclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE);
$i++;
break;
case IWP_PCLZIP_OPT_TEMP_FILE_THRESHOLD :
// ----- Check the number of parameters
if (($i+1) >= $p_size) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".IWPPclZipUtilOptionText($p_options_list[$i])."'");
return IWPPclZip::errorCode();
}
// ----- Check for incompatible options
if (isset($v_result_list[IWP_PCLZIP_OPT_TEMP_FILE_OFF])) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_PARAMETER, "Option '".IWPPclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'IWP_PCLZIP_OPT_TEMP_FILE_OFF'");
return IWPPclZip::errorCode();
}
// ----- Check the value
$v_value = $p_options_list[$i+1];
if ((!is_integer($v_value)) || ($v_value<0)) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_OPTION_VALUE, "Integer expected for option '".IWPPclZipUtilOptionText($p_options_list[$i])."'");
return IWPPclZip::errorCode();
}
// ----- Get the value (and convert it in bytes)
$v_result_list[$p_options_list[$i]] = $v_value*1048576;
$i++;
break;
case IWP_PCLZIP_OPT_CHUNK_BLOCK_SIZE :
// ----- Check the number of parameters
if (($i+1) >= $p_size) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".IWPPclZipUtilOptionText($p_options_list[$i])."'");
return IWPPclZip::errorCode();
}
// ----- Check the value
$v_value = $p_options_list[$i+1];
if ((!is_integer($v_value)) || ($v_value<0)) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_OPTION_VALUE, "Integer expected for option '".IWPPclZipUtilOptionText($p_options_list[$i])."'");
return IWPPclZip::errorCode();
}
// ----- Get the value (and convert it in bytes)
$v_result_list[$p_options_list[$i]] = $v_value*1024*1024;
$i++;
break;
case IWP_PCLZIP_OPT_FILE_EXCLUDE_SIZE :
// ----- Check the number of parameters
if (($i+1) >= $p_size) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".IWPPclZipUtilOptionText($p_options_list[$i])."'");
return IWPPclZip::errorCode();
}
// ----- Check the value
$v_value = $p_options_list[$i+1];
if ((!is_integer($v_value)) || ($v_value<0)) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_OPTION_VALUE, "Integer expected for option '".IWPPclZipUtilOptionText($p_options_list[$i])."'");
return IWPPclZip::errorCode();
}
// ----- Get the value (and convert it in bytes)
$v_result_list[$p_options_list[$i]] = $v_value*1024*1024;
$i++;
break;
case IWP_PCLZIP_OPT_HISTORY_ID :
// ----- Check the number of parameters
if (($i+1) >= $p_size) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".IWPPclZipUtilOptionText($p_options_list[$i])."'");
return IWPPclZip::errorCode();
}
// ----- Check the value
$v_value = $p_options_list[$i+1];
/* if ((!is_integer($v_value)) || ($v_value<0)) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_OPTION_VALUE, "Integer expected for option '".IWPPclZipUtilOptionText($p_options_list[$i])."'");
return IWPPclZip::errorCode();
} */
// ----- Get the value (and convert it in bytes)
$v_result_list[$p_options_list[$i]] = $v_value;
$i++;
break;
case IWP_PCLZIP_OPT_TEMP_FILE_ON :
// ----- Check for incompatible options
if (isset($v_result_list[IWP_PCLZIP_OPT_TEMP_FILE_OFF])) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_PARAMETER, "Option '".IWPPclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'IWP_PCLZIP_OPT_TEMP_FILE_OFF'");
return IWPPclZip::errorCode();
}
$v_result_list[$p_options_list[$i]] = true;
break;
case IWP_PCLZIP_OPT_TEMP_FILE_OFF :
// ----- Check for incompatible options
if (isset($v_result_list[IWP_PCLZIP_OPT_TEMP_FILE_ON])) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_PARAMETER, "Option '".IWPPclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'IWP_PCLZIP_OPT_TEMP_FILE_ON'");
return IWPPclZip::errorCode();
}
// ----- Check for incompatible options
if (isset($v_result_list[IWP_PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_PARAMETER, "Option '".IWPPclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'IWP_PCLZIP_OPT_TEMP_FILE_THRESHOLD'");
return IWPPclZip::errorCode();
}
$v_result_list[$p_options_list[$i]] = true;
break;
case IWP_PCLZIP_OPT_EXTRACT_DIR_RESTRICTION :
// ----- Check the number of parameters
if (($i+1) >= $p_size) {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".IWPPclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Get the value
if ( is_string($p_options_list[$i+1])
&& ($p_options_list[$i+1] != '')) {
$v_result_list[$p_options_list[$i]] = IWPPclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE);
$i++;
}
else {
}
break;
// ----- Look for options that request an array of string for value
case IWP_PCLZIP_OPT_BY_NAME :
// ----- Check the number of parameters
if (($i+1) >= $p_size) {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".IWPPclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Get the value
if (is_string($p_options_list[$i+1])) {
$v_result_list[$p_options_list[$i]][0] = $p_options_list[$i+1];
}
else if (is_array($p_options_list[$i+1])) {
$v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
}
else {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".IWPPclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
return IWPPclZip::errorCode();
}
$i++;
break;
// ----- Look for options that request an EREG or PREG expression
case IWP_PCLZIP_OPT_BY_EREG :
// ereg() is deprecated starting with PHP 5.3. Move IWP_PCLZIP_OPT_BY_EREG
// to IWP_PCLZIP_OPT_BY_PREG
$p_options_list[$i] = IWP_PCLZIP_OPT_BY_PREG;
case IWP_PCLZIP_OPT_BY_PREG :
//case IWP_PCLZIP_OPT_CRYPT :
// ----- Check the number of parameters
if (($i+1) >= $p_size) {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".IWPPclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Get the value
if (is_string($p_options_list[$i+1])) {
$v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
}
else {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".IWPPclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
return IWPPclZip::errorCode();
}
$i++;
break;
// ----- Look for options that takes a string
case IWP_PCLZIP_OPT_COMMENT :
case IWP_PCLZIP_OPT_ADD_COMMENT :
case IWP_PCLZIP_OPT_PREPEND_COMMENT :
// ----- Check the number of parameters
if (($i+1) >= $p_size) {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_MISSING_OPTION_VALUE,
"Missing parameter value for option '"
.IWPPclZipUtilOptionText($p_options_list[$i])
."'");
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Get the value
if (is_string($p_options_list[$i+1])) {
$v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
}
else {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_OPTION_VALUE,
"Wrong parameter value for option '"
.IWPPclZipUtilOptionText($p_options_list[$i])
."'");
// ----- Return
return IWPPclZip::errorCode();
}
$i++;
break;
// ----- Look for options that request an array of index
case IWP_PCLZIP_OPT_BY_INDEX :
// ----- Check the number of parameters
if (($i+1) >= $p_size) {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".IWPPclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Get the value
$v_work_list = array();
if (is_string($p_options_list[$i+1])) {
// ----- Remove spaces
$p_options_list[$i+1] = strtr($p_options_list[$i+1], ' ', '');
// ----- Parse items
$v_work_list = explode(",", $p_options_list[$i+1]);
}
else if (is_integer($p_options_list[$i+1])) {
$v_work_list[0] = $p_options_list[$i+1].'-'.$p_options_list[$i+1];
}
else if (is_array($p_options_list[$i+1])) {
$v_work_list = $p_options_list[$i+1];
}
else {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_OPTION_VALUE, "Value must be integer, string or array for option '".IWPPclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Reduce the index list
// each index item in the list must be a couple with a start and
// an end value : [0,3], [5-5], [8-10], ...
// ----- Check the format of each item
$v_sort_flag=false;
$v_sort_value=0;
for ($j=0; $j= $p_size) {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".IWPPclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Get the value
$v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
$i++;
break;
// ----- Look for options that request a call-back
case IWP_PCLZIP_CB_PRE_EXTRACT :
case IWP_PCLZIP_CB_POST_EXTRACT :
case IWP_PCLZIP_CB_PRE_ADD :
case IWP_PCLZIP_CB_POST_ADD :
/* for futur use
case IWP_PCLZIP_CB_PRE_DELETE :
case IWP_PCLZIP_CB_POST_DELETE :
case IWP_PCLZIP_CB_PRE_LIST :
case IWP_PCLZIP_CB_POST_LIST :
*/
// ----- Check the number of parameters
if (($i+1) >= $p_size) {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".IWPPclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Get the value
$v_function_name = $p_options_list[$i+1];
// ----- Check that the value is a valid existing function
if (!function_exists($v_function_name)) {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_OPTION_VALUE, "Function '".$v_function_name."()' is not an existing function for option '".IWPPclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Set the attribute
$v_result_list[$p_options_list[$i]] = $v_function_name;
$i++;
break;
default :
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_PARAMETER,
"Unknown parameter '"
.$p_options_list[$i]."'");
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Next options
$i++;
}
// ----- Look for mandatory options
if ($v_requested_options !== false) {
for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
// ----- Look for mandatory option
if ($v_requested_options[$key] == 'mandatory') {
// ----- Look if present
if (!isset($v_result_list[$key])) {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".IWPPclZipUtilOptionText($key)."(".$key.")");
// ----- Return
return IWPPclZip::errorCode();
}
}
}
}
// ----- Look for default values
if (!isset($v_result_list[IWP_PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privOptionDefaultThreshold()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privOptionDefaultThreshold(&$p_options)
{
$v_result=1;
if (isset($p_options[IWP_PCLZIP_OPT_TEMP_FILE_THRESHOLD])
|| isset($p_options[IWP_PCLZIP_OPT_TEMP_FILE_OFF])) {
return $v_result;
}
// ----- Get 'memory_limit' configuration value
$v_memory_limit = ini_get('memory_limit');
$v_memory_limit = trim($v_memory_limit);
$last = strtolower(substr($v_memory_limit, -1));
if($last == 'g')
//$v_memory_limit = $v_memory_limit*1024*1024*1024;
$v_memory_limit = $v_memory_limit*1073741824;
if($last == 'm')
//$v_memory_limit = $v_memory_limit*1024*1024;
$v_memory_limit = $v_memory_limit*1048576;
if($last == 'k')
$v_memory_limit = $v_memory_limit*1024;
$p_options[IWP_PCLZIP_OPT_TEMP_FILE_THRESHOLD] = floor($v_memory_limit*IWP_PCLZIP_TEMPORARY_FILE_RATIO);
// ----- Sanity check : No threshold if value lower than 1M
if ($p_options[IWP_PCLZIP_OPT_TEMP_FILE_THRESHOLD] < 1048576) {
unset($p_options[IWP_PCLZIP_OPT_TEMP_FILE_THRESHOLD]);
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privFileDescrParseAtt()
// Description :
// Parameters :
// Return Values :
// 1 on success.
// 0 on failure.
// --------------------------------------------------------------------------------
function privFileDescrParseAtt(&$p_file_list, &$p_filedescr, $v_options, $v_requested_options=false)
{
$v_result=1;
// ----- For each file in the list check the attributes
foreach ($p_file_list as $v_key => $v_value) {
// ----- Check if the option is supported
if (!isset($v_requested_options[$v_key])) {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_PARAMETER, "Invalid file attribute '".$v_key."' for this file");
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Look for attribute
switch ($v_key) {
case IWP_PCLZIP_ATT_FILE_NAME :
if (!is_string($v_value)) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".IWPPclZipUtilOptionText($v_key)."'");
return IWPPclZip::errorCode();
}
$p_filedescr['filename'] = IWPPclZipUtilPathReduction($v_value);
if ($p_filedescr['filename'] == '') {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty filename for attribute '".IWPPclZipUtilOptionText($v_key)."'");
return IWPPclZip::errorCode();
}
break;
case IWP_PCLZIP_ATT_FILE_NEW_SHORT_NAME :
if (!is_string($v_value)) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".IWPPclZipUtilOptionText($v_key)."'");
return IWPPclZip::errorCode();
}
$p_filedescr['new_short_name'] = IWPPclZipUtilPathReduction($v_value);
if ($p_filedescr['new_short_name'] == '') {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty short filename for attribute '".IWPPclZipUtilOptionText($v_key)."'");
return IWPPclZip::errorCode();
}
break;
case IWP_PCLZIP_ATT_FILE_NEW_FULL_NAME :
if (!is_string($v_value)) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".IWPPclZipUtilOptionText($v_key)."'");
return IWPPclZip::errorCode();
}
$p_filedescr['new_full_name'] = IWPPclZipUtilPathReduction($v_value);
if ($p_filedescr['new_full_name'] == '') {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty full filename for attribute '".IWPPclZipUtilOptionText($v_key)."'");
return IWPPclZip::errorCode();
}
break;
// ----- Look for options that takes a string
case IWP_PCLZIP_ATT_FILE_COMMENT :
if (!is_string($v_value)) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".IWPPclZipUtilOptionText($v_key)."'");
return IWPPclZip::errorCode();
}
$p_filedescr['comment'] = $v_value;
break;
case IWP_PCLZIP_ATT_FILE_MTIME :
if (!is_integer($v_value)) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". Integer expected for attribute '".IWPPclZipUtilOptionText($v_key)."'");
return IWPPclZip::errorCode();
}
$p_filedescr['mtime'] = $v_value;
break;
case IWP_PCLZIP_ATT_FILE_CONTENT :
$p_filedescr['content'] = $v_value;
break;
default :
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_PARAMETER,
"Unknown parameter '".$v_key."'");
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Look for mandatory options
if ($v_requested_options !== false) {
for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
// ----- Look for mandatory option
if ($v_requested_options[$key] == 'mandatory') {
// ----- Look if present
if (!isset($p_file_list[$key])) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".IWPPclZipUtilOptionText($key)."(".$key.")");
return IWPPclZip::errorCode();
}
}
}
}
// end foreach
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privFileDescrExpand()
// Description :
// This method look for each item of the list to see if its a file, a folder
// or a string to be added as file. For any other type of files (link, other)
// just ignore the item.
// Then prepare the information that will be stored for that file.
// When its a folder, expand the folder with all the files that are in that
// folder (recursively).
// Parameters :
// Return Values :
// 1 on success.
// 0 on failure.
// --------------------------------------------------------------------------------
function privFileDescrExpand(&$p_filedescr_list, &$p_options, $is_get_file_list = 'no')
{
$v_result=1;
$reLoop = '';
$reLoopCount = -1;
$limitSize = $p_options[IWP_PCLZIP_OPT_CHUNK_BLOCK_SIZE];
$excludeFileSize = $p_options[IWP_PCLZIP_OPT_FILE_EXCLUDE_SIZE];
//$limitSize = 15*1024*1024*1024;
// ----- Create a result list
$v_result_list = array();
$startTimeForTHisFile = microtime(true);
// ----- Look each entry
for ($i=0; $iprivCalculateStoredFilename($v_descr, $p_options);
if(strpos($v_descr['stored_filename'], $item) === 0){
$skip_this = true;
break;
}
/* if($v_descr['size'] >= 50*1024*1024)
{
} */
}
}
if($skip_this)
{
$skip_this = false;
continue;
}
}
//to exclude files based on extensions
$this_base_name = basename($v_descr['filename']);
$skip_after_ext = false;
//file extension based exclude
if((!empty($exclude_extensions)) && is_array($exclude_extensions))
{
foreach($exclude_extensions as $ext)
{
$this_pos = strrpos($this_base_name, $ext);
if($this_pos !== false)
{
if(substr($this_base_name, $this_pos) == $ext)
{
//$files_excluded_by_size[] = substr($value, strlen(ABSPATH));
$skip_after_ext = true; //to skip the file exclude by size
break;
}
}
}
}
if($skip_after_ext)
{
continue;
}
//$excludeFileSize = 200;
//exclude the file if the filesize is larger than the specified file size
if(!empty($excludeFileSize) && (iwp_get_file_size($v_descr['filename']) >= $excludeFileSize))
{
continue;
}
if(strpos($v_descr['filename'], "wp-admin/pclzip-") !== false)
{
// ----- Calculate the stored filename
$this->privCalculateStoredFilename($v_descr, $p_options);
echo "temp File - 1".$v_descr['stored_filename'];
if(strpos($v_descr['stored_filename'], "wp-admin/pclzip-") === 0)
{
if(strpos($v_descr['stored_filename'], ".tmp"))
{
$levenSearchVar = "pclzip-*************.tmp";
}
elseif(strpos($v_descr['stored_filename'], ".gz"))
{
$levenSearchVar = "pclzip-*************.gz";
}
$diffInString = levenshtein($v_descr['stored_filename'], "wp-admin/".$levenSearchVar);
if($diffInString == 13)
{
@unlink($v_descr['filename']);
continue;
}
}
}
elseif(strpos($v_descr['filename'], "wp-content/infinitewp/temp/pclzip-") !== false)
{
// ----- Calculate the stored filename
$this->privCalculateStoredFilename($v_descr, $p_options);
echo "temp File - 2".$v_descr['stored_filename'];
if(strpos($v_descr['stored_filename'], "wp-content/infinitewp/temp/pclzip-") === 0)
{
if(strpos($v_descr['stored_filename'], ".tmp"))
{
$levenSearchVar = "pclzip-*************.tmp";
}
elseif(strpos($v_descr['stored_filename'], ".gz"))
{
$levenSearchVar = "pclzip-*************.gz";
}
$diffInString = levenshtein($v_descr['stored_filename'], "wp-content/infinitewp/temp/".$levenSearchVar);
if($diffInString == 13)
{
@unlink($v_descr['filename']);
continue;
}
}
}
elseif(strpos($v_descr['filename'], "pclzip-") !== false)
{
// ----- Calculate the stored filename
$this->privCalculateStoredFilename($v_descr, $p_options);
echo "temp File - 3".$v_descr['stored_filename'];
if(strpos($v_descr['stored_filename'], "pclzip-") === 0)
{
if(strpos($v_descr['stored_filename'], ".tmp"))
{
$levenSearchVar = "pclzip-*************.tmp";
}
elseif(strpos($v_descr['stored_filename'], ".gz"))
{
$levenSearchVar = "pclzip-*************.gz";
}
$diffInString = levenshtein($v_descr['stored_filename'], $levenSearchVar);
if($diffInString == 13)
{
@unlink($v_descr['filename']);
continue;
}
}
}
/* //exclude IWP Mod
if(!empty($exclude)){
foreach($exclude as $item){
if(strpos($v_descr['stored_filename'], $item) === 0){
$skip_this = true;
break;
}
}
if($skip_this){
$skip_this = false;
continue;
}
}
//exclude IWP Mod */
}
$v_descr['type'] = 'file';
$v_descr['size'] = iwp_get_file_size($v_descr['filename']); //adding size parameter
if($v_descr['size'] >= $limitSize) //50MB size
{
$reLoop = 'set';
$reLoopCount++;
$v_descr['sizeLeft'] = (iwp_get_file_size($v_descr['filename']) - ($reLoopCount*$limitSize));
$v_descr['splitFilenameFull'] = $v_descr['filename'].'_iwp_part_'.$reLoopCount;
$v_descr['splitFilename'] = '_iwp_part_'.$reLoopCount;
if($v_descr['sizeLeft'] >= $limitSize)
{
$v_descr['size'] = $limitSize;
$v_descr['splitOffset'] = $reLoopCount*$limitSize;
}
else
{
$v_descr['size'] = $v_descr['sizeLeft'];
$v_descr['splitOffset'] = iwp_get_file_size($v_descr['filename']) - $v_descr['sizeLeft'];
$v_descr['sizeLeft'] = 0;
//$v_descr['fileHash'] = md5_file($v_descr['filename']);
$v_descr['fileHash'] = 'final';
$v_descr['splitFilename'] = "_iwp_hash_".$v_descr['fileHash'] . $v_descr['splitFilename']; //storing hash in the fileName
$reLoop = '';
$reLoopCount = 0;
}
}
$v_descr['fileTime'] = filemtime($v_descr['filename']);
if($reLoop == 'set')
{
$i--;
}
}
else if (@is_dir($v_descr['filename'])) {
$v_descr['type'] = 'folder';
$v_descr['size'] = ''; //adding size parameter
$v_descr['fileTime'] = filemtime($v_descr['filename']);
}
else if (@is_link($v_descr['filename'])) {
// skip
continue;
}
else {
// skip
continue;
}
}
// ----- Look for string added as file
else if (isset($v_descr['content'])) {
$v_descr['type'] = 'virtual_file';
}
// ----- Missing file
else {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_MISSING_FILE, "File '".$v_descr['filename']."' does not exist");
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Calculate the stored filename
$this->privCalculateStoredFilename($v_descr, $p_options);
//exclude IWP Mod
$skip_this = false;
$exclude = isset($p_options[IWP_PCLZIP_OPT_IWP_EXCLUDE]) ? $p_options[IWP_PCLZIP_OPT_IWP_EXCLUDE] : array();
if(!empty($exclude)){
foreach($exclude as $item){
if(strpos($v_descr['stored_filename'], $item) === 0){
$skip_this = true;
break;
}
}
if($skip_this){
$skip_this = false;
continue;
}
}
//exclude IWP Mod
// ----- Add the descriptor in result list
$v_result_list[sizeof($v_result_list)] = $v_descr;
// ----- Look for folder
if (($v_descr['type'] == 'folder')&&($is_get_file_list != 'getFileList')) {
// ----- List of items in folder
$v_dirlist_descr = array();
$v_dirlist_nb = 0;
if ($v_folder_handler = @opendir($v_descr['filename'])) {
while (($v_item_handler = @readdir($v_folder_handler)) !== false) {
// ----- Skip '.' and '..'
if (($v_item_handler == '.') || ($v_item_handler == '..')) {
continue;
}
// ----- Compose the full filename
$v_dirlist_descr[$v_dirlist_nb]['filename'] = $v_descr['filename'].'/'.$v_item_handler;
// ----- Look for different stored filename
// Because the name of the folder was changed, the name of the
// files/sub-folders also change
if (($v_descr['stored_filename'] != $v_descr['filename'])
&& (!isset($p_options[IWP_PCLZIP_OPT_REMOVE_ALL_PATH]))) {
if ($v_descr['stored_filename'] != '') {
$v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_descr['stored_filename'].'/'.$v_item_handler;
}
else {
$v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_item_handler;
}
}
$v_dirlist_nb++;
}
@closedir($v_folder_handler);
}
else {
// TBC : unable to open folder in read mode
}
// ----- Expand each element of the list
if ($v_dirlist_nb != 0) {
// ----- Expand
if (($v_result = $this->privFileDescrExpand($v_dirlist_descr, $p_options)) != 1) {
return $v_result;
}
// ----- Concat the resulting list
$v_result_list = array_merge($v_result_list, $v_dirlist_descr);
}
else {
}
// ----- Free local array
unset($v_dirlist_descr);
}
}
$timeTakenFOrTHisFile = microtime(true) - $startTimeForTHisFile;
// ----- Get the result list
$p_filedescr_list = $v_result_list;
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// Function : privFileDescrExpand()
// Description :
// This method look for each item of the list to see if its a file, a folder
// or a string to be added as file. For any other type of files (link, other)
// just ignore the item.
// Then prepare the information that will be stored for that file.
// When its a folder, expand the folder with all the files that are in that
// folder (recursively).
// Parameters :
// Return Values :
// 1 on success.
// 0 on failure.
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privCreate()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privCreate($p_filedescr_list, &$p_result_list, &$p_options)
{
$v_result=1;
$v_list_detail = array();
// ----- Magic quotes trick
$this->privDisableMagicQuotes();
// ----- Open the file in write mode
if (($v_result = $this->privOpenFd('wb')) != 1)
{
// ----- Return
return $v_result;
}
// ----- Add the list of files
$v_result = $this->privAddList($p_filedescr_list, $p_result_list, $p_options);
// ----- Close
$this->privCloseFd();
// ----- Magic quotes trick
$this->privSwapBackMagicQuotes();
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privAdd()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privAdd($p_filedescr_list, &$p_result_list, &$p_options)
{
$v_result=1;
$v_list_detail = array();
// ----- Look if the archive exists or is empty
if ((!is_file($this->zipname)) || (iwp_get_file_size($this->zipname) == 0))
{
// ----- Do a create
$v_result = $this->privCreate($p_filedescr_list, $p_result_list, $p_options);
// ----- Return
return $v_result;
}
// ----- Magic quotes trick
$this->privDisableMagicQuotes();
// ----- Open the zip file
if (($v_result=$this->privOpenFd('rb')) != 1)
{
// ----- Magic quotes trick
$this->privSwapBackMagicQuotes();
// ----- Return
return $v_result;
}
// ----- Read the central directory informations
$v_central_dir = array();
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
{
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
return $v_result;
}
// ----- Go to beginning of File
@rewind($this->zip_fd);
// ----- Creates a temporay file
$v_zip_temp_name = IWP_PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
// ----- Open the temporary file in write mode
if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
{
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Copy the files from the archive to the temporary file
// TBC : Here I should better append the file and go back to erase the central dir
$v_size = $v_central_dir['offset'];
while ($v_size != 0)
{
$v_read_size = ($v_size < IWP_PCLZIP_READ_BLOCK_SIZE ? $v_size : IWP_PCLZIP_READ_BLOCK_SIZE);
$v_buffer = fread($this->zip_fd, $v_read_size);
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
}
// ----- Swap the file descriptor
// Here is a trick : I swap the temporary fd with the zip fd, in order to use
// the following methods on the temporary fil and not the real archive
$v_swap = $this->zip_fd;
$this->zip_fd = $v_zip_temp_fd;
$v_zip_temp_fd = $v_swap;
// ----- Add the files
$v_header_list = array();
if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1)
{
fclose($v_zip_temp_fd);
$this->privCloseFd();
@unlink($v_zip_temp_name);
$this->privSwapBackMagicQuotes();
// ----- Return
return $v_result;
}
// ----- Store the offset of the central dir
$v_offset = @ftell($this->zip_fd);
// ----- Copy the block of file headers from the old archive
$v_size = $v_central_dir['size'];
while ($v_size != 0)
{
$v_read_size = ($v_size < IWP_PCLZIP_READ_BLOCK_SIZE ? $v_size : IWP_PCLZIP_READ_BLOCK_SIZE);
$v_buffer = @fread($v_zip_temp_fd, $v_read_size);
@fwrite($this->zip_fd, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
}
// ----- Create the Central Dir files header
for ($i=0, $v_count=0; $iprivWriteCentralFileHeader($v_header_list[$i])) != 1) {
fclose($v_zip_temp_fd);
$this->privCloseFd();
@unlink($v_zip_temp_name);
$this->privSwapBackMagicQuotes();
// ----- Return
return $v_result;
}
$v_count++;
}
// ----- Transform the header to a 'usable' info
$this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
}
// ----- Zip file comment
$v_comment = $v_central_dir['comment'];
if (isset($p_options[IWP_PCLZIP_OPT_COMMENT])) {
$v_comment = $p_options[IWP_PCLZIP_OPT_COMMENT];
}
if (isset($p_options[IWP_PCLZIP_OPT_ADD_COMMENT])) {
$v_comment = $v_comment.$p_options[IWP_PCLZIP_OPT_ADD_COMMENT];
}
if (isset($p_options[IWP_PCLZIP_OPT_PREPEND_COMMENT])) {
$v_comment = $p_options[IWP_PCLZIP_OPT_PREPEND_COMMENT].$v_comment;
}
// ----- Calculate the size of the central header
$v_size = @ftell($this->zip_fd)-$v_offset;
// ----- Create the central dir footer
if (($v_result = $this->privWriteCentralHeader($v_count+$v_central_dir['entries'], $v_size, $v_offset, $v_comment)) != 1)
{
// ----- Reset the file list
unset($v_header_list);
$this->privSwapBackMagicQuotes();
// ----- Return
return $v_result;
}
// ----- Swap back the file descriptor
$v_swap = $this->zip_fd;
$this->zip_fd = $v_zip_temp_fd;
$v_zip_temp_fd = $v_swap;
// ----- Close
$this->privCloseFd();
// ----- Close the temporary file
@fclose($v_zip_temp_fd);
// ----- Magic quotes trick
$this->privSwapBackMagicQuotes();
// ----- Delete the zip file
// TBC : I should test the result ...
@unlink($this->zipname);
// ----- Rename the temporary file
// TBC : I should test the result ...
//@rename($v_zip_temp_name, $this->zipname);
IWPPclZipUtilRename($v_zip_temp_name, $this->zipname);
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privOpenFd()
// Description :
// Parameters :
// --------------------------------------------------------------------------------
function privOpenFd($p_mode)
{
$v_result=1;
// ----- Look if already open
if ($this->zip_fd != 0)
{
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \''.$this->zipname.'\' already open');
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Open the zip file
if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0)
{
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in '.$p_mode.' mode');
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privCloseFd()
// Description :
// Parameters :
// --------------------------------------------------------------------------------
function privCloseFd()
{
$v_result=1;
if ($this->zip_fd != 0)
@fclose($this->zip_fd);
$this->zip_fd = 0;
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privAddList()
// Description :
// $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
// different from the real path of the file. This is usefull if you want to have PclTar
// running in any directory, and memorize relative path from an other directory.
// Parameters :
// $p_list : An array containing the file or directory names to add in the tar
// $p_result_list : list of added files with their properties (specially the status field)
// $p_add_dir : Path to add in the filename path archived
// $p_remove_dir : Path to remove in the filename path archived
// Return Values :
// --------------------------------------------------------------------------------
// function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
function privAddList($p_filedescr_list, &$p_result_list, &$p_options)
{
$v_result=1;
// ----- Add the files
$v_header_list = array();
if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1)
{
// ----- Return
return $v_result;
}
// ----- Store the offset of the central dir
$v_offset = @ftell($this->zip_fd);
// ----- Create the Central Dir files header
for ($i=0,$v_count=0; $iprivWriteCentralFileHeader($v_header_list[$i])) != 1) {
// ----- Return
return $v_result;
}
$v_count++;
}
// ----- Transform the header to a 'usable' info
$this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
}
// ----- Zip file comment
$v_comment = '';
if (isset($p_options[IWP_PCLZIP_OPT_COMMENT])) {
$v_comment = $p_options[IWP_PCLZIP_OPT_COMMENT];
}
// ----- Calculate the size of the central header
$v_size = @ftell($this->zip_fd)-$v_offset;
// ----- Create the central dir footer
if (($v_result = $this->privWriteCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1)
{
// ----- Reset the file list
unset($v_header_list);
// ----- Return
return $v_result;
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privAddFileList()
// Description :
// Parameters :
// $p_filedescr_list : An array containing the file description
// or directory names to add in the zip
// $p_result_list : list of added files with their properties (specially the status field)
// Return Values :
// --------------------------------------------------------------------------------
function privAddFileList($p_filedescr_list, &$p_result_list, &$p_options)
{
$v_result=1;
$v_header = array();
// ----- Recuperate the current number of elt in list
$v_nb = sizeof($p_result_list);
// ----- Loop on the files
for ($j=0; ($jprivAddFile($p_filedescr_list[$j], $v_header,
$p_options);
if ($v_result != 1) {
return $v_result;
}
// ----- Store the file infos
$p_result_list[$v_nb++] = $v_header;
}
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privAddFile()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privAddFile($p_filedescr, &$p_header, &$p_options)
{
//echo 'Coming Inside privAddFile';
$v_result=1;
/* echo $p_filedescr['filename'];
echo ' -------------------------------------------------------------------------------- '; */
// ----- Working variable
if($p_filedescr['splitFilename'] != '')
{
$currentFile = explode(".",$p_filedescr['stored_filename']); //making fileName for the split part
$currentFileSize = count($currentFile);
foreach($currentFile as $key => $val)
{
if(($key == (sizeof($currentFile)-2))||($currentFileSize == 1))
{
$currentFile[$key] = $val.$p_filedescr['splitFilename'];
}
}
$orgFileName = implode(".", $currentFile);
$p_filename = $orgFileName;
}
else
{
$p_filename = $p_filedescr['stored_filename'];
if($p_filename == '')
{
$p_filename = $p_filedescr['filename'];
}
}
// TBC : Already done in the fileAtt check ... ?
if ($p_filename == "") {
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)");
// ----- Return
echo "false filename";
return IWPPclZip::errorCode();
}
// ----- Look for a stored different filename
/* TBC : Removed
if (isset($p_filedescr['stored_filename'])) {
$v_stored_filename = $p_filedescr['stored_filename'];
}
else {
$v_stored_filename = $p_filedescr['stored_filename'];
}
*/
// ----- Set the file properties
clearstatcache();
$p_header['version'] = 20;
$p_header['version_extracted'] = 10;
$p_header['flag'] = 0;
$p_header['compression'] = 0;
$p_header['crc'] = 0;
$p_header['compressed_size'] = 0;
$p_header['filename_len'] = strlen($p_filename);
$p_header['extra_len'] = 0;
$p_header['disk'] = 0;
$p_header['internal'] = 0;
$p_header['offset'] = 0;
$p_header['filename'] = $p_filename;
// TBC : Removed $p_header['stored_filename'] = $v_stored_filename;
//$p_header['stored_filename'] = $p_filedescr['stored_filename']; //darkPrince
$p_header['stored_filename'] = $p_filename;
$p_header['extra'] = '';
$p_header['status'] = 'ok';
$p_header['index'] = -1;
// ----- Look for regular file
if ($p_filedescr['type']=='file') {
$p_header['external'] = 0x00000000;
//$p_header['size'] = iwp_get_file_size($p_filename);
$p_header['size'] = $p_filedescr['size']; //darkPrince
}
// ----- Look for regular folder
else if ($p_filedescr['type']=='folder') {
$p_header['external'] = 0x00000010;
/* $p_header['mtime'] = filemtime($p_filename);
$p_header['size'] = iwp_get_file_size($p_filename); */
$p_header['mtime'] = $p_filedescr['fileTime'];
$p_header['size'] = $p_filedescr['size'];
}
// ----- Look for virtual file
else if ($p_filedescr['type'] == 'virtual_file') {
$p_header['external'] = 0x00000000;
$p_header['size'] = strlen($p_filedescr['content']);
}
// ----- Look for filetime
if (isset($p_filedescr['mtime'])) {
$p_header['mtime'] = $p_filedescr['mtime'];
}
else if ($p_filedescr['type'] == 'virtual_file') {
$p_header['mtime'] = time();
}
else {
//$p_header['mtime'] = filemtime($p_filename);
$p_header['mtime'] = $p_filedescr['fileTime']; //darkPrince
}
// ------ Look for file comment
if (isset($p_filedescr['comment'])) {
$p_header['comment_len'] = strlen($p_filedescr['comment']);
$p_header['comment'] = $p_filedescr['comment'];
}
else {
$p_header['comment_len'] = 0;
$p_header['comment'] = '';
}
// ----- Look for pre-add callback
if (isset($p_options[IWP_PCLZIP_CB_PRE_ADD])) {
// ----- Generate a local information
$v_local_header = array();
$this->privConvertHeader2FileInfo($p_header, $v_local_header);
// ----- Call the callback
// Here I do not use call_user_func() because I need to send a reference to the
// header.
// eval('$v_result = '.$p_options[IWP_PCLZIP_CB_PRE_ADD].'(IWP_PCLZIP_CB_PRE_ADD, $v_local_header);');
$v_result = $p_options[IWP_PCLZIP_CB_PRE_ADD](IWP_PCLZIP_CB_PRE_ADD, $v_local_header);
if ($v_result == 0) {
// ----- Change the file status
$p_header['status'] = "skipped";
$v_result = 1;
}
// ----- Update the informations
// Only some fields can be modified
if ($p_header['stored_filename'] != $v_local_header['stored_filename']) {
$p_header['stored_filename'] = IWPPclZipUtilPathReduction($v_local_header['stored_filename']);
}
}
// ----- Look for empty stored filename
if ($p_header['stored_filename'] == "") {
$p_header['status'] = "filtered";
}
// ----- Check the path length
if (strlen($p_header['stored_filename']) > 0xFF) {
$p_header['status'] = 'filename_too_long';
echo 'fileNameTooLong';
}
// ----- Look if no error, or file not skipped
if ($p_header['status'] == 'ok') {
// ----- Look for a file
if ($p_filedescr['type'] == 'file') {
// ----- Look for using temporary file to zip
if ( (!isset($p_options[IWP_PCLZIP_OPT_TEMP_FILE_OFF]))
&& (isset($p_options[IWP_PCLZIP_OPT_TEMP_FILE_ON])
|| (isset($p_options[IWP_PCLZIP_OPT_TEMP_FILE_THRESHOLD])
&& ($p_options[IWP_PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_header['size'])) ) ) {
$v_result = $this->privAddFileUsingTempFile($p_filedescr, $p_header, $p_options);
if ($v_result < IWP_PCLZIP_ERR_NO_ERROR) {
return $v_result;
}
}
// ----- Use "in memory" zip algo
else {
// ----- Open the source file
//if (($v_file = @fopen($p_filename, "rb")) == 0) { //darkPrince
if (($v_file = @fopen($p_filedescr['filename'], "rb")) == 0) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode. Please try changing the file permission to 644 or exclude this file from your backup.");
echo "File Read Error";
return IWPPclZip::errorCode();
}
if($p_filedescr['splitFilename'] != '')
{
@fseek($v_file,$p_filedescr['splitOffset']);
}
// ----- Read the file content
$v_content = @fread($v_file, $p_header['size']);
// ----- Close the file
@fclose($v_file);
// ----- Calculate the CRC
$p_header['crc'] = @crc32($v_content);
// ----- Look for no compression
if ($p_options[IWP_PCLZIP_OPT_NO_COMPRESSION]) {
// ----- Set header parameters
$p_header['compressed_size'] = $p_header['size'];
$p_header['compression'] = 0;
}
// ----- Look for normal compression
else {
// ----- Compress the content
$v_content = @gzdeflate($v_content);
// ----- Set header parameters
$p_header['compressed_size'] = strlen($v_content);
$p_header['compression'] = 8;
}
// ----- Call the header generation
if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
@fclose($v_file);
return $v_result;
}
// ----- Write the compressed (or not) content
@fwrite($this->zip_fd, $v_content, $p_header['compressed_size']);
}
}
// ----- Look for a virtual file (a file from string)
else if ($p_filedescr['type'] == 'virtual_file') {
$v_content = $p_filedescr['content'];
// ----- Calculate the CRC
$p_header['crc'] = @crc32($v_content);
// ----- Look for no compression
if ($p_options[IWP_PCLZIP_OPT_NO_COMPRESSION]) {
// ----- Set header parameters
$p_header['compressed_size'] = $p_header['size'];
$p_header['compression'] = 0;
}
// ----- Look for normal compression
else {
// ----- Compress the content
$v_content = @gzdeflate($v_content);
// ----- Set header parameters
$p_header['compressed_size'] = strlen($v_content);
$p_header['compression'] = 8;
}
// ----- Call the header generation
if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
@fclose($v_file);
return $v_result;
}
// ----- Write the compressed (or not) content
@fwrite($this->zip_fd, $v_content, $p_header['compressed_size']);
}
// ----- Look for a directory
else if ($p_filedescr['type'] == 'folder') {
// ----- Look for directory last '/'
if (@substr($p_header['stored_filename'], -1) != '/') {
$p_header['stored_filename'] .= '/';
}
// ----- Set the file properties
$p_header['size'] = 0;
//$p_header['external'] = 0x41FF0010; // Value for a folder : to be checked
$p_header['external'] = 0x00000010; // Value for a folder : to be checked
// ----- Call the header generation
if (($v_result = $this->privWriteFileHeader($p_header)) != 1)
{
return $v_result;
}
}
}
// ----- Look for post-add callback
if (isset($p_options[IWP_PCLZIP_CB_POST_ADD])) {
// ----- Generate a local information
$v_local_header = array();
$this->privConvertHeader2FileInfo($p_header, $v_local_header);
// ----- Call the callback
// Here I do not use call_user_func() because I need to send a reference to the
// header.
// eval('$v_result = '.$p_options[IWP_PCLZIP_CB_POST_ADD].'(IWP_PCLZIP_CB_POST_ADD, $v_local_header);');
$v_result = $p_options[IWP_PCLZIP_CB_POST_ADD](IWP_PCLZIP_CB_POST_ADD, $v_local_header);
if ($v_result == 0) {
// ----- Ignored
$v_result = 1;
}
// ----- Update the informations
// Nothing can be modified
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privAddFileUsingTempFile()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privAddFileUsingTempFile($p_filedescr, &$p_header, &$p_options)
{
$startTime = microtime(true);
$v_result=IWP_PCLZIP_ERR_NO_ERROR;
// ----- Working variable
$p_filename = $p_filedescr['filename'];
// ----- Open the source file
if (($v_file = @fopen($p_filename, "rb")) == 0) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode. Please try changing the file permission to 644 or exclude this file from your backup.");
//return array( 'error' => "Unable to open file '$p_filename' in binary read mode. Please try changing the file permission to 644 or exclude this file from your backup.");
return IWPPclZip::errorCode();
}
// ----- Creates a compressed temporary file
$v_gzip_temp_name = IWP_PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz';
if (($v_file_compressed = @gzopen($v_gzip_temp_name, "wb")) == 0) {
fclose($v_file);
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode');
//return array( 'error' => 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode');
return IWPPclZip::errorCode();
}
$tempLoopStart = microtime(true);
// ----- Read the file by IWP_PCLZIP_READ_BLOCK_SIZE octets blocks
//$v_size = iwp_get_file_size($p_filename);
$v_size = $p_filedescr['size']; //darkPrince setting fileSize from Array
if($p_filedescr['splitFilename'] != '')
{
@fseek($v_file,$p_filedescr['splitOffset']);
}
while ($v_size != 0) {
$v_read_size = ($v_size < IWP_PCLZIP_READ_BLOCK_SIZE ? $v_size : IWP_PCLZIP_READ_BLOCK_SIZE);
$v_buffer = @fread($v_file, $v_read_size);
//$v_binary_data = pack('a'.$v_read_size, $v_buffer);
@gzputs($v_file_compressed, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
}
// ----- Close the file
@fclose($v_file);
@gzclose($v_file_compressed);
//$timeTak = microtime(true) - $tempLoopStart;
// ----- Check the minimum file size
if (iwp_get_file_size($v_gzip_temp_name) < 18) {
echo "Check the minimum file size error";
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_BAD_FORMAT, 'gzip temporary file \''.$v_gzip_temp_name.'\' has invalid filesize - should be minimum 18 bytes');
//return array( 'error' => 'Zip-error: Error compressing the file "'.$p_filedescr['filename'].'".Try excluding this file and try again.');
return IWPPclZip::errorCode();
}
// ----- Extract the compressed attributes
if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
return IWPPclZip::errorCode();
}
// ----- Read the gzip file header
$v_binary_data = @fread($v_file_compressed, 10);
$v_data_header = unpack('a1id1/a1id2/a1cm/a1flag/Vmtime/a1xfl/a1os', $v_binary_data);
// ----- Check some parameters
$v_data_header['os'] = bin2hex($v_data_header['os']);
// ----- Read the gzip file footer
@fseek($v_file_compressed, iwp_get_file_size($v_gzip_temp_name)-8);
$v_binary_data = @fread($v_file_compressed, 8);
$v_data_footer = unpack('Vcrc/Vcompressed_size', $v_binary_data);
// ----- Set the attributes
$p_header['compression'] = ord($v_data_header['cm']);
//$p_header['mtime'] = $v_data_header['mtime'];
$p_header['crc'] = $v_data_footer['crc'];
$p_header['compressed_size'] = iwp_get_file_size($v_gzip_temp_name)-18;
if($p_filedescr['splitFilename'] != '')
{
$p_header['filename'] = $p_filedescr['stored_filename'].$p_filedescr['splitFilename'];
}
// ----- Close the file
@fclose($v_file_compressed);
// ----- Call the header generation
if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
return $v_result;
}
// ----- Add the compressed data
if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0)
{
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
return IWPPclZip::errorCode();
}
// ----- Read the file by IWP_PCLZIP_READ_BLOCK_SIZE octets blocks
@fseek($v_file_compressed, 10);
$v_size = $p_header['compressed_size'];
while ($v_size != 0)
{
$v_read_size = ($v_size < IWP_PCLZIP_READ_BLOCK_SIZE ? $v_size : IWP_PCLZIP_READ_BLOCK_SIZE);
$v_buffer = @fread($v_file_compressed, $v_read_size);
if($v_buffer === false){
return -1;
}
//$v_binary_data = pack('a'.$v_read_size, $v_buffer);
$wr_result = @fwrite($this->zip_fd, $v_buffer, $v_read_size);
if($wr_result === false){
return -1;
}
$v_size -= $v_read_size;
}
// ----- Close the file
@fclose($v_file_compressed);
// ----- Unlink the temporary file
@unlink($v_gzip_temp_name);
$timeTakenFOrTempAdd = microtime(true) - $startTime;
//echo "TimeTakenFOrTempAdd".$timeTakenFOrTempAdd;
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privCalculateStoredFilename()
// Description :
// Based on file descriptor properties and global options, this method
// calculate the filename that will be stored in the archive.
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privCalculateStoredFilename(&$p_filedescr, &$p_options)
{
$v_result=1;
// ----- Working variables
$p_filename = $p_filedescr['filename'];
if (isset($p_options[IWP_PCLZIP_OPT_ADD_PATH])) {
$p_add_dir = $p_options[IWP_PCLZIP_OPT_ADD_PATH];
}
else {
$p_add_dir = '';
}
if (isset($p_options[IWP_PCLZIP_OPT_REMOVE_PATH])) {
$p_remove_dir = $p_options[IWP_PCLZIP_OPT_REMOVE_PATH];
}
else {
$p_remove_dir = '';
}
if (isset($p_options[IWP_PCLZIP_OPT_REMOVE_ALL_PATH])) {
$p_remove_all_dir = $p_options[IWP_PCLZIP_OPT_REMOVE_ALL_PATH];
}
else {
$p_remove_all_dir = 0;
}
// ----- Look for full name change
if (isset($p_filedescr['new_full_name'])) {
// ----- Remove drive letter if any
$v_stored_filename = IWPPclZipUtilTranslateWinPath($p_filedescr['new_full_name']);
}
// ----- Look for path and/or short name change
else {
// ----- Look for short name change
// Its when we cahnge just the filename but not the path
if (isset($p_filedescr['new_short_name'])) {
$v_path_info = pathinfo($p_filename);
$v_dir = '';
if ($v_path_info['dirname'] != '') {
$v_dir = $v_path_info['dirname'].'/';
}
$v_stored_filename = $v_dir.$p_filedescr['new_short_name'];
}
else {
// ----- Calculate the stored filename
$v_stored_filename = $p_filename;
}
// ----- Look for all path to remove
if ($p_remove_all_dir) {
$v_stored_filename = basename($p_filename);
}
// ----- Look for partial path remove
else if ($p_remove_dir != "") {
if (substr($p_remove_dir, -1) != '/')
$p_remove_dir .= "/";
if ( (substr($p_filename, 0, 2) == "./")
|| (substr($p_remove_dir, 0, 2) == "./")) {
if ( (substr($p_filename, 0, 2) == "./")
&& (substr($p_remove_dir, 0, 2) != "./")) {
$p_remove_dir = "./".$p_remove_dir;
}
if ( (substr($p_filename, 0, 2) != "./")
&& (substr($p_remove_dir, 0, 2) == "./")) {
$p_remove_dir = substr($p_remove_dir, 2);
}
}
$v_compare = IWPPclZipUtilPathInclusion($p_remove_dir,
$v_stored_filename);
if ($v_compare > 0) {
if ($v_compare == 2) {
$v_stored_filename = "";
}
else {
$v_stored_filename = substr($v_stored_filename,
strlen($p_remove_dir));
}
}
}
// ----- Remove drive letter if any
$v_stored_filename = IWPPclZipUtilTranslateWinPath($v_stored_filename);
// ----- Look for path to add
if ($p_add_dir != "") {
if (substr($p_add_dir, -1) == "/")
$v_stored_filename = $p_add_dir.$v_stored_filename;
else
$v_stored_filename = $p_add_dir."/".$v_stored_filename;
}
}
// ----- Filename (reduce the path of stored name)
$v_stored_filename = IWPPclZipUtilPathReduction($v_stored_filename);
$p_filedescr['stored_filename'] = $v_stored_filename;
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privWriteFileHeader()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privWriteFileHeader(&$p_header)
{
$v_result=1;
// ----- Store the offset position of the file
$p_header['offset'] = ftell($this->zip_fd);
// ----- Transform UNIX mtime to DOS format mdate/mtime
$v_date = getdate($p_header['mtime']);
$v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
$v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
// ----- Packed data
$v_binary_data = pack("VvvvvvVVVvv", 0x04034b50,
$p_header['version_extracted'], $p_header['flag'],
$p_header['compression'], $v_mtime, $v_mdate,
$p_header['crc'], $p_header['compressed_size'],
$p_header['size'],
strlen($p_header['stored_filename']),
$p_header['extra_len']);
// ----- Write the first 148 bytes of the header in the archive
fputs($this->zip_fd, $v_binary_data, 30);
// ----- Write the variable fields
if (strlen($p_header['stored_filename']) != 0)
{
fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
}
if ($p_header['extra_len'] != 0)
{
fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privWriteCentralFileHeader()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privWriteCentralFileHeader(&$p_header)
{
$v_result=1;
// TBC
//for(reset($p_header); $key = key($p_header); next($p_header)) {
//}
// ----- Transform UNIX mtime to DOS format mdate/mtime
$v_date = getdate($p_header['mtime']);
$v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
$v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
// ----- Packed data
$v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50,
$p_header['version'], $p_header['version_extracted'],
$p_header['flag'], $p_header['compression'],
$v_mtime, $v_mdate, $p_header['crc'],
$p_header['compressed_size'], $p_header['size'],
strlen($p_header['stored_filename']),
$p_header['extra_len'], $p_header['comment_len'],
$p_header['disk'], $p_header['internal'],
$p_header['external'], $p_header['offset']);
// ----- Write the 42 bytes of the header in the zip file
fputs($this->zip_fd, $v_binary_data, 46);
// ----- Write the variable fields
if (strlen($p_header['stored_filename']) != 0)
{
fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
}
if ($p_header['extra_len'] != 0)
{
fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
}
if ($p_header['comment_len'] != 0)
{
fputs($this->zip_fd, $p_header['comment'], $p_header['comment_len']);
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privWriteCentralHeader()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privWriteCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment)
{
$v_result=1;
// ----- Packed data
$v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries,
$p_nb_entries, $p_size,
$p_offset, strlen($p_comment));
// ----- Write the 22 bytes of the header in the zip file
fputs($this->zip_fd, $v_binary_data, 22);
// ----- Write the variable fields
if (strlen($p_comment) != 0)
{
fputs($this->zip_fd, $p_comment, strlen($p_comment));
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privList()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privList(&$p_list)
{
$v_result=1;
// ----- Magic quotes trick
$this->privDisableMagicQuotes();
// ----- Open the zip file
if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
{
// ----- Magic quotes trick
$this->privSwapBackMagicQuotes();
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Read the central directory informations
$v_central_dir = array();
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
{
$this->privSwapBackMagicQuotes();
return $v_result;
}
// ----- Go to beginning of Central Dir
@rewind($this->zip_fd);
if (@fseek($this->zip_fd, $v_central_dir['offset']))
{
$this->privSwapBackMagicQuotes();
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Read each entry
for ($i=0; $i<$v_central_dir['entries']; $i++)
{
// ----- Read the file header
if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
{
$this->privSwapBackMagicQuotes();
return $v_result;
}
$v_header['index'] = $i;
// ----- Get the only interesting attributes
$this->privConvertHeader2FileInfo($v_header, $p_list[$i]);
unset($v_header);
}
// ----- Close the zip file
$this->privCloseFd();
// ----- Magic quotes trick
$this->privSwapBackMagicQuotes();
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privConvertHeader2FileInfo()
// Description :
// This function takes the file informations from the central directory
// entries and extract the interesting parameters that will be given back.
// The resulting file infos are set in the array $p_info
// $p_info['filename'] : Filename with full path. Given by user (add),
// extracted in the filesystem (extract).
// $p_info['stored_filename'] : Stored filename in the archive.
// $p_info['size'] = Size of the file.
// $p_info['compressed_size'] = Compressed size of the file.
// $p_info['mtime'] = Last modification date of the file.
// $p_info['comment'] = Comment associated with the file.
// $p_info['folder'] = true/false : indicates if the entry is a folder or not.
// $p_info['status'] = status of the action on the file.
// $p_info['crc'] = CRC of the file content.
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privConvertHeader2FileInfo($p_header, &$p_info)
{
$v_result=1;
// ----- Get the interesting attributes
$v_temp_path = IWPPclZipUtilPathReduction($p_header['filename']);
$p_info['filename'] = $v_temp_path;
$v_temp_path = IWPPclZipUtilPathReduction($p_header['stored_filename']);
$p_info['stored_filename'] = $v_temp_path;
$p_info['size'] = $p_header['size'];
$p_info['compressed_size'] = $p_header['compressed_size'];
$p_info['mtime'] = $p_header['mtime'];
$p_info['comment'] = $p_header['comment'];
$p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010);
$p_info['index'] = $p_header['index'];
$p_info['status'] = $p_header['status'];
$p_info['crc'] = $p_header['crc'];
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privExtractByRule()
// Description :
// Extract a file or directory depending of rules (by index, by name, ...)
// Parameters :
// $p_file_list : An array where will be placed the properties of each
// extracted file
// $p_path : Path to add while writing the extracted files
// $p_remove_path : Path to remove (from the file memorized path) while writing the
// extracted files. If the path does not match the file path,
// the file is extracted with its memorized path.
// $p_remove_path does not apply to 'list' mode.
// $p_path and $p_remove_path are commulative.
// Return Values :
// 1 on success,0 or less on error (see error code list)
// --------------------------------------------------------------------------------
function privExtractByRule(&$p_file_list, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
{
$v_result=1;
// ----- Magic quotes trick
$this->privDisableMagicQuotes();
// ----- Check the path
if ( ($p_path == "")
|| ( (substr($p_path, 0, 1) != "/")
&& (substr($p_path, 0, 3) != "../")
&& (substr($p_path,1,2)!=":/")))
$p_path = "./".$p_path;
// ----- Reduce the path last (and duplicated) '/'
if (($p_path != "./") && ($p_path != "/"))
{
// ----- Look for the path end '/'
while (substr($p_path, -1) == "/")
{
$p_path = substr($p_path, 0, strlen($p_path)-1);
}
}
// ----- Look for path to remove format (should end by /)
if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/'))
{
$p_remove_path .= '/';
}
$p_remove_path_size = strlen($p_remove_path);
// ----- Open the zip file
if (($v_result = $this->privOpenFd('rb')) != 1)
{
$this->privSwapBackMagicQuotes();
return $v_result;
}
// ----- Read the central directory informations
$v_central_dir = array();
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
{
// ----- Close the zip file
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
return $v_result;
}
// ----- Start at beginning of Central Dir
$v_pos_entry = $v_central_dir['offset'];
// ----- Read each entry
$j_start = 0;
$next_extract_id = (empty($_REQUEST['params']['responseData']['next_extract_id'])) ? 0 : $_REQUEST['params']['responseData']['next_extract_id'];
$v_pos_entry = (empty($_REQUEST['params']['responseData']['v_pos_entry'])) ? $v_central_dir['offset'] : $_REQUEST['params']['responseData']['v_pos_entry'];
global $response_arr;
$response_arr = array();
initialize_response_array($response_arr);
for ($i=$next_extract_id, $v_nb_extracted=$next_extract_id; $i<$v_central_dir['entries']; $i++)
{
// ----- Read next Central dir entry
@rewind($this->zip_fd);
if (@fseek($this->zip_fd, $v_pos_entry))
{
// ----- Close the zip file
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Read the file header
$v_header = array();
if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
{
// ----- Close the zip file
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
return $v_result;
}
// ----- Store the index
$v_header['index'] = $i;
// ----- Store the file position
$v_pos_entry = ftell($this->zip_fd);
// ----- Look for the specific extract rules
$v_extract = false;
// ----- Look for extract by name rule
if ( (isset($p_options[IWP_PCLZIP_OPT_BY_NAME]))
&& ($p_options[IWP_PCLZIP_OPT_BY_NAME] != 0)) {
// ----- Look if the filename is in the list
for ($j=0; ($j strlen($p_options[IWP_PCLZIP_OPT_BY_NAME][$j]))
&& (substr($v_header['stored_filename'], 0, strlen($p_options[IWP_PCLZIP_OPT_BY_NAME][$j])) == $p_options[IWP_PCLZIP_OPT_BY_NAME][$j])) {
$v_extract = true;
}
}
// ----- Look for a filename
elseif ($v_header['stored_filename'] == $p_options[IWP_PCLZIP_OPT_BY_NAME][$j]) {
$v_extract = true;
}
}
}
// ----- Look for extract by ereg rule
// ereg() is deprecated with PHP 5.3
/*
else if ( (isset($p_options[IWP_PCLZIP_OPT_BY_EREG]))
&& ($p_options[IWP_PCLZIP_OPT_BY_EREG] != "")) {
if (ereg($p_options[IWP_PCLZIP_OPT_BY_EREG], $v_header['stored_filename'])) {
$v_extract = true;
}
}
*/
// ----- Look for extract by preg rule
else if ( (isset($p_options[IWP_PCLZIP_OPT_BY_PREG]))
&& ($p_options[IWP_PCLZIP_OPT_BY_PREG] != "")) {
if (preg_match($p_options[IWP_PCLZIP_OPT_BY_PREG], $v_header['stored_filename'])) {
$v_extract = true;
}
}
// ----- Look for extract by index rule
else if ( (isset($p_options[IWP_PCLZIP_OPT_BY_INDEX]))
&& ($p_options[IWP_PCLZIP_OPT_BY_INDEX] != 0)) {
// ----- Look if the index is in the list
for ($j=$j_start; ($j=$p_options[IWP_PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[IWP_PCLZIP_OPT_BY_INDEX][$j]['end'])) {
$v_extract = true;
}
if ($i>=$p_options[IWP_PCLZIP_OPT_BY_INDEX][$j]['end']) {
$j_start = $j+1;
}
if ($p_options[IWP_PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
break;
}
}
}
// ----- Look for no rule, which means extract all the archive
else {
$v_extract = true;
}
// ----- Check compression method
if ( ($v_extract)
&& ( ($v_header['compression'] != 8)
&& ($v_header['compression'] != 0))) {
$v_header['status'] = 'unsupported_compression';
// ----- Look for IWP_PCLZIP_OPT_STOP_ON_ERROR
if ( (isset($p_options[IWP_PCLZIP_OPT_STOP_ON_ERROR]))
&& ($p_options[IWP_PCLZIP_OPT_STOP_ON_ERROR]===true)) {
$this->privSwapBackMagicQuotes();
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_UNSUPPORTED_COMPRESSION,
"Filename '".$v_header['stored_filename']."' is "
."compressed by an unsupported compression "
."method (".$v_header['compression'].") ");
return IWPPclZip::errorCode();
}
}
// ----- Check encrypted files
if (($v_extract) && (($v_header['flag'] & 1) == 1)) {
$v_header['status'] = 'unsupported_encryption';
// ----- Look for IWP_PCLZIP_OPT_STOP_ON_ERROR
if ( (isset($p_options[IWP_PCLZIP_OPT_STOP_ON_ERROR]))
&& ($p_options[IWP_PCLZIP_OPT_STOP_ON_ERROR]===true)) {
$this->privSwapBackMagicQuotes();
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_UNSUPPORTED_ENCRYPTION,
"Unsupported encryption for "
." filename '".$v_header['stored_filename']
."'");
return IWPPclZip::errorCode();
}
}
// ----- Look for real extraction
if (($v_extract) && ($v_header['status'] != 'ok')) {
$v_result = $this->privConvertHeader2FileInfo($v_header,
$p_file_list[$v_nb_extracted++]);
if ($v_result != 1) {
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
return $v_result;
}
$v_extract = false;
}
// ----- Look for real extraction
if ($v_extract)
{
// ----- Go to the file position
@rewind($this->zip_fd);
if (@fseek($this->zip_fd, $v_header['offset']))
{
// ----- Close the zip file
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Look for extraction as string
if ($p_options[IWP_PCLZIP_OPT_EXTRACT_AS_STRING]) {
$v_string = '';
// ----- Extracting the file
$v_result1 = $this->privExtractFileAsString($v_header, $v_string, $p_options);
if ($v_result1 < 1) {
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
return $v_result1;
}
// ----- Get the only interesting attributes
if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted])) != 1)
{
// ----- Close the zip file
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
return $v_result;
}
// ----- Set the file content
$p_file_list[$v_nb_extracted]['content'] = $v_string;
// ----- Next extracted file
$v_nb_extracted++;
// ----- Look for user callback abort
if ($v_result1 == 2) {
break;
}
}
// ----- Look for extraction in standard output
elseif ( (isset($p_options[IWP_PCLZIP_OPT_EXTRACT_IN_OUTPUT]))
&& ($p_options[IWP_PCLZIP_OPT_EXTRACT_IN_OUTPUT])) {
// ----- Extracting the file in standard output
$v_result1 = $this->privExtractFileInOutput($v_header, $p_options);
if ($v_result1 < 1) {
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
return $v_result1;
}
// ----- Get the only interesting attributes
if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) {
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
return $v_result;
}
// ----- Look for user callback abort
if ($v_result1 == 2) {
break;
}
}
// ----- Look for normal extraction
else {
// ----- Extracting the file
$v_result1 = $this->privExtractFile($v_header,
$p_path, $p_remove_path,
$p_remove_all_path,
$p_options);
if ($v_result1 < 1) {
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
return $v_result1;
}
// ----- Get the only interesting attributes
if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1)
{
// ----- Close the zip file
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
return $v_result;
}
// ----- Look for user callback abort
if ($v_result1 == 2) {
break;
}
}
unset($p_file_list);
$is_multicall_break = check_for_clone_break();
//if($i == 10){
if($is_multicall_break){
global $response_arr;
$response_arr['next_extract_id'] = $i + 1;
$response_arr['is_extract_over'] = false;
$response_arr['status'] = 'partiallyCompleted';
$response_arr['break'] = true;
$response_arr['v_pos_entry'] = $v_pos_entry;
$response_arr['peak_mem_usage'] = (memory_get_peak_usage(true)/1024/1024);
break;
}
}
}
// ----- Close the zip file
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
if($response_arr['break'] == true){
//logExtractResponse($_REQUEST['extractParentHID'], array('status' => 'partiallyCompleted', 'sendResponse' => true, 'nextFunc' => 'backupFiles', 'responseParams' => $response_arr));
return $response_arr;
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privExtractFile()
// Description :
// Parameters :
// Return Values :
//
// 1 : ... ?
// IWP_PCLZIP_ERR_USER_ABORTED(2) : User ask for extraction stop in callback
// --------------------------------------------------------------------------------
function privExtractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
{
$v_result=1;
// ----- Read the file header
if (($v_result = $this->privReadFileHeader($v_header)) != 1)
{
// ----- Return
return $v_result;
}
// ----- Check that the file header is coherent with $p_entry info
if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
// TBC
}
// ----- Look for all path to remove
if ($p_remove_all_path == true) {
// ----- Look for folder entry that not need to be extracted
if (($p_entry['external']&0x00000010)==0x00000010) {
$p_entry['status'] = "filtered";
return $v_result;
}
// ----- Get the basename of the path
$p_entry['filename'] = basename($p_entry['filename']);
}
// ----- Look for path to remove
else if ($p_remove_path != "")
{
if (IWPPclZipUtilPathInclusion($p_remove_path, $p_entry['filename']) == 2)
{
// ----- Change the file status
$p_entry['status'] = "filtered";
// ----- Return
return $v_result;
}
$p_remove_path_size = strlen($p_remove_path);
if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path)
{
// ----- Remove the path
$p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size);
}
}
// ----- Add the path
if ($p_path != '') {
$p_entry['filename'] = $p_path."/".$p_entry['filename'];
}
// ----- Check a base_dir_restriction
if (isset($p_options[IWP_PCLZIP_OPT_EXTRACT_DIR_RESTRICTION])) {
$v_inclusion
= IWPPclZipUtilPathInclusion($p_options[IWP_PCLZIP_OPT_EXTRACT_DIR_RESTRICTION],
$p_entry['filename']);
if ($v_inclusion == 0) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_DIRECTORY_RESTRICTION,
"Filename '".$p_entry['filename']."' is "
."outside IWP_PCLZIP_OPT_EXTRACT_DIR_RESTRICTION");
return IWPPclZip::errorCode();
}
}
// ----- Look for pre-extract callback
if (isset($p_options[IWP_PCLZIP_CB_PRE_EXTRACT])) {
// ----- Generate a local information
$v_local_header = array();
$this->privConvertHeader2FileInfo($p_entry, $v_local_header);
// ----- Call the callback
// Here I do not use call_user_func() because I need to send a reference to the
// header.
// eval('$v_result = '.$p_options[IWP_PCLZIP_CB_PRE_EXTRACT].'(IWP_PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
$v_result = $p_options[IWP_PCLZIP_CB_PRE_EXTRACT](IWP_PCLZIP_CB_PRE_EXTRACT, $v_local_header);
if ($v_result == 0) {
// ----- Change the file status
$p_entry['status'] = "skipped";
$v_result = 1;
}
// ----- Look for abort result
if ($v_result == 2) {
// ----- This status is internal and will be changed in 'skipped'
$p_entry['status'] = "aborted";
$v_result = IWP_PCLZIP_ERR_USER_ABORTED;
}
// ----- Update the informations
// Only some fields can be modified
$p_entry['filename'] = $v_local_header['filename'];
}
// ----- Look if extraction should be done
if ($p_entry['status'] == 'ok') {
// ----- Look for specific actions while the file exist
if (file_exists($p_entry['filename']))
{
// ----- Look if file is a directory
if (is_dir($p_entry['filename']))
{
// ----- Change the file status
$p_entry['status'] = "already_a_directory";
// ----- Look for IWP_PCLZIP_OPT_STOP_ON_ERROR
// For historical reason first IWPPclZip implementation does not stop
// when this kind of error occurs.
if ( (isset($p_options[IWP_PCLZIP_OPT_STOP_ON_ERROR]))
&& ($p_options[IWP_PCLZIP_OPT_STOP_ON_ERROR]===true)) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_ALREADY_A_DIRECTORY,
"Filename '".$p_entry['filename']."' is "
."already used by an existing directory");
return IWPPclZip::errorCode();
}
}
// ----- Look if file is write protected
else if (!is_writeable($p_entry['filename']))
{
// ----- Change the file status
$p_entry['status'] = "write_protected";
// ----- Look for IWP_PCLZIP_OPT_STOP_ON_ERROR
// For historical reason first IWPPclZip implementation does not stop
// when this kind of error occurs.
if ( (isset($p_options[IWP_PCLZIP_OPT_STOP_ON_ERROR]))
&& ($p_options[IWP_PCLZIP_OPT_STOP_ON_ERROR]===true)) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_WRITE_OPEN_FAIL,
"Filename '".$p_entry['filename']."' exists "
."and is write protected");
return IWPPclZip::errorCode();
}
}
// ----- Look if the extracted file is older
else if (filemtime($p_entry['filename']) > $p_entry['mtime'])
{
// ----- Change the file status
if ( (isset($p_options[IWP_PCLZIP_OPT_REPLACE_NEWER]))
&& ($p_options[IWP_PCLZIP_OPT_REPLACE_NEWER]===true)) {
}
else {
$p_entry['status'] = "newer_exist";
// ----- Look for IWP_PCLZIP_OPT_STOP_ON_ERROR
// For historical reason first IWPPclZip implementation does not stop
// when this kind of error occurs.
if ( (isset($p_options[IWP_PCLZIP_OPT_STOP_ON_ERROR]))
&& ($p_options[IWP_PCLZIP_OPT_STOP_ON_ERROR]===true)) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_WRITE_OPEN_FAIL,
"Newer version of '".$p_entry['filename']."' exists "
."and option IWP_PCLZIP_OPT_REPLACE_NEWER is not selected");
return IWPPclZip::errorCode();
}
}
}
else {
}
}
// ----- Check the directory availability and create it if necessary
else {
if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/'))
$v_dir_to_check = $p_entry['filename'];
else if (!strstr($p_entry['filename'], "/"))
$v_dir_to_check = "";
else
$v_dir_to_check = dirname($p_entry['filename']);
if (($v_result = $this->privDirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) {
// ----- Change the file status
$p_entry['status'] = "path_creation_fail";
// ----- Return
//return $v_result;
$v_result = 1;
}
}
}
// ----- Look if extraction should be done
if ($p_entry['status'] == 'ok') {
// ----- Do the extraction (if not a folder)
if (!(($p_entry['external']&0x00000010)==0x00000010))
{
// ----- Look for not compressed file
if ($p_entry['compression'] == 0) {
// ----- Opening destination file
if ($GLOBALS['is_child_restore'] && strrpos($p_entry['filename'], 'uploads/sites/'.$GLOBALS['blogid']) == false) {
return 1;
}
if ($GLOBALS['is_new_backup']){
$homePath = dirname(dirname(__FILE__));
$t_pr = str_replace($homePath, '', $p_entry['filename']);
if(substr($t_pr, 1, 10) == 'wordpress/'){
$p_dir = substr_replace( $t_pr, '' , 1, 10 );
}else{
$p_dir = $t_pr;
}
$p_entry['filename'] = $homePath.$p_dir;
}
if ($GLOBALS['needFileSystem']) {
$p_entry_file = $GLOBALS['FileSystemObj']->findFolder($p_entry['filename']);
$GLOBALS['FileSystemObj']->touch($p_entry_file);
$GLOBALS['FileSystemObj']->chmod($p_entry_file, 0777);
}
if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0)
{
// ----- Change the file status
$p_entry['status'] = "write_error";
// ----- Return
return $v_result;
}
// ----- Read the file by IWP_PCLZIP_READ_BLOCK_SIZE octets blocks
$v_size = $p_entry['compressed_size'];
while ($v_size != 0)
{
$v_read_size = ($v_size < IWP_PCLZIP_READ_BLOCK_SIZE ? $v_size : IWP_PCLZIP_READ_BLOCK_SIZE);
$v_buffer = @fread($this->zip_fd, $v_read_size);
/* Try to speed up the code
$v_binary_data = pack('a'.$v_read_size, $v_buffer);
@fwrite($v_dest_file, $v_binary_data, $v_read_size);
*/
@fwrite($v_dest_file, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
}
// ----- Closing the destination file
fclose($v_dest_file);
if ($GLOBALS['needFileSystem']) {
$GLOBALS['FileSystemObj']->chmod($p_entry_file, 0644);
$GLOBALS['FileSystemObj']->touch($p_entry['filename'], $p_entry['mtime']);
}else{
// ----- Change the file mtime
@touch($p_entry['filename'], $p_entry['mtime']);
}
}
else {
// ----- TBC
// Need to be finished
if (($p_entry['flag'] & 1) == 1) {
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_UNSUPPORTED_ENCRYPTION, 'File \''.$p_entry['filename'].'\' is encrypted. Encrypted files are not supported.');
return IWPPclZip::errorCode();
}
// ----- Look for using temporary file to unzip
if ( (!isset($p_options[IWP_PCLZIP_OPT_TEMP_FILE_OFF]))
&& (isset($p_options[IWP_PCLZIP_OPT_TEMP_FILE_ON])
|| (isset($p_options[IWP_PCLZIP_OPT_TEMP_FILE_THRESHOLD])
&& ($p_options[IWP_PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_entry['size'])) ) ) {
$v_result = $this->privExtractFileUsingTempFile($p_entry, $p_options);
if ($v_result < IWP_PCLZIP_ERR_NO_ERROR) {
return $v_result;
}
}
// ----- Look for extract in memory
else {
// ----- Read the compressed file in a buffer (one shot)
$v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
// ----- Decompress the file
$v_file_content = @gzinflate($v_buffer);
unset($v_buffer);
if ($v_file_content === FALSE) {
// ----- Change the file status
// TBC
$p_entry['status'] = "error";
return $v_result;
}
if ($GLOBALS['is_child_restore'] && strrpos($p_entry['filename'], 'uploads/sites/'.$GLOBALS['blogid']) == false) {
return 1;
}
// ----- Opening destination file
if ($GLOBALS['is_new_backup']){
$homePath = dirname(dirname(__FILE__));
$t_pr = str_replace($homePath, '', $p_entry['filename']);
if(substr($t_pr, 1, 10) == 'wordpress/'){
$p_dir = substr_replace( $t_pr, '' , 1, 10 );
}else{
$p_dir = $t_pr;
}
$p_entry['filename'] = $homePath.$p_dir;
}
if ($GLOBALS['needFileSystem']) {
$p_entry_file = $GLOBALS['FileSystemObj']->findFolder($p_entry['filename']);
$GLOBALS['FileSystemObj']->touch($p_entry_file);
$GLOBALS['FileSystemObj']->chmod($p_entry_file, 0777);
}
if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
// ----- Change the file status
$p_entry['status'] = "write_error";
return $v_result;
}
// ----- Write the uncompressed data
@fwrite($v_dest_file, $v_file_content, $p_entry['size']);
unset($v_file_content);
// ----- Closing the destination file
@fclose($v_dest_file);
if ($GLOBALS['needFileSystem']) {
$GLOBALS['FileSystemObj']->chmod($p_entry_file, 0644);
}
}
// ----- Change the file mtime
@touch($p_entry['filename'], $p_entry['mtime']);
}
// ----- Look for chmod option
if (isset($p_options[IWP_PCLZIP_OPT_SET_CHMOD])) {
// ----- Change the mode of the file
@chmod($p_entry['filename'], $p_options[IWP_PCLZIP_OPT_SET_CHMOD]);
}
}
}
// ----- Change abort status
if ($p_entry['status'] == "aborted") {
$p_entry['status'] = "skipped";
}
// ----- Look for post-extract callback
elseif (isset($p_options[IWP_PCLZIP_CB_POST_EXTRACT])) {
// ----- Generate a local information
$v_local_header = array();
$this->privConvertHeader2FileInfo($p_entry, $v_local_header);
// ----- Call the callback
// Here I do not use call_user_func() because I need to send a reference to the
// header.
// eval('$v_result = '.$p_options[IWP_PCLZIP_CB_POST_EXTRACT].'(IWP_PCLZIP_CB_POST_EXTRACT, $v_local_header);');
$v_result = $p_options[IWP_PCLZIP_CB_POST_EXTRACT](IWP_PCLZIP_CB_POST_EXTRACT, $v_local_header);
// ----- Look for abort result
if ($v_result == 2) {
$v_result = IWP_PCLZIP_ERR_USER_ABORTED;
}
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privExtractFileUsingTempFile()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privExtractFileUsingTempFile(&$p_entry, &$p_options)
{
$v_result=1;
// ----- Creates a temporary file
$v_gzip_temp_name = IWP_PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz';
if (($v_dest_file = @fopen($v_gzip_temp_name, "wb")) == 0) {
fclose($v_file);
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode');
return IWPPclZip::errorCode();
}
// ----- Write gz file format header
$v_binary_data = pack('va1a1Va1a1', 0x8b1f, Chr($p_entry['compression']), Chr(0x00), time(), Chr(0x00), Chr(3));
@fwrite($v_dest_file, $v_binary_data, 10);
// ----- Read the file by IWP_PCLZIP_READ_BLOCK_SIZE octets blocks
$v_size = $p_entry['compressed_size'];
while ($v_size != 0)
{
$v_read_size = ($v_size < IWP_PCLZIP_READ_BLOCK_SIZE ? $v_size : IWP_PCLZIP_READ_BLOCK_SIZE);
$v_buffer = @fread($this->zip_fd, $v_read_size);
//$v_binary_data = pack('a'.$v_read_size, $v_buffer);
@fwrite($v_dest_file, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
}
// ----- Write gz file format footer
$v_binary_data = pack('VV', $p_entry['crc'], $p_entry['size']);
@fwrite($v_dest_file, $v_binary_data, 8);
// ----- Close the temporary file
@fclose($v_dest_file);
// ----- Opening destination file
if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
$p_entry['status'] = "write_error";
return $v_result;
}
// ----- Open the temporary gz file
if (($v_src_file = @gzopen($v_gzip_temp_name, 'rb')) == 0) {
@fclose($v_dest_file);
$p_entry['status'] = "read_error";
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
return IWPPclZip::errorCode();
}
// ----- Read the file by IWP_PCLZIP_READ_BLOCK_SIZE octets blocks
$v_size = $p_entry['size'];
while ($v_size != 0) {
$v_read_size = ($v_size < IWP_PCLZIP_READ_BLOCK_SIZE ? $v_size : IWP_PCLZIP_READ_BLOCK_SIZE);
$v_buffer = @gzread($v_src_file, $v_read_size);
//$v_binary_data = pack('a'.$v_read_size, $v_buffer);
@fwrite($v_dest_file, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
}
@fclose($v_dest_file);
@gzclose($v_src_file);
// ----- Delete the temporary file
@unlink($v_gzip_temp_name);
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privExtractFileInOutput()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privExtractFileInOutput(&$p_entry, &$p_options)
{
$v_result=1;
// ----- Read the file header
if (($v_result = $this->privReadFileHeader($v_header)) != 1) {
return $v_result;
}
// ----- Check that the file header is coherent with $p_entry info
if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
// TBC
}
// ----- Look for pre-extract callback
if (isset($p_options[IWP_PCLZIP_CB_PRE_EXTRACT])) {
// ----- Generate a local information
$v_local_header = array();
$this->privConvertHeader2FileInfo($p_entry, $v_local_header);
// ----- Call the callback
// Here I do not use call_user_func() because I need to send a reference to the
// header.
// eval('$v_result = '.$p_options[IWP_PCLZIP_CB_PRE_EXTRACT].'(IWP_PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
$v_result = $p_options[IWP_PCLZIP_CB_PRE_EXTRACT](IWP_PCLZIP_CB_PRE_EXTRACT, $v_local_header);
if ($v_result == 0) {
// ----- Change the file status
$p_entry['status'] = "skipped";
$v_result = 1;
}
// ----- Look for abort result
if ($v_result == 2) {
// ----- This status is internal and will be changed in 'skipped'
$p_entry['status'] = "aborted";
$v_result = IWP_PCLZIP_ERR_USER_ABORTED;
}
// ----- Update the informations
// Only some fields can be modified
$p_entry['filename'] = $v_local_header['filename'];
}
// ----- Trace
// ----- Look if extraction should be done
if ($p_entry['status'] == 'ok') {
// ----- Do the extraction (if not a folder)
if (!(($p_entry['external']&0x00000010)==0x00000010)) {
// ----- Look for not compressed file
if ($p_entry['compressed_size'] == $p_entry['size']) {
// ----- Read the file in a buffer (one shot)
$v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
// ----- Send the file to the output
echo $v_buffer;
unset($v_buffer);
}
else {
// ----- Read the compressed file in a buffer (one shot)
$v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
// ----- Decompress the file
$v_file_content = gzinflate($v_buffer);
unset($v_buffer);
// ----- Send the file to the output
echo $v_file_content;
unset($v_file_content);
}
}
}
// ----- Change abort status
if ($p_entry['status'] == "aborted") {
$p_entry['status'] = "skipped";
}
// ----- Look for post-extract callback
elseif (isset($p_options[IWP_PCLZIP_CB_POST_EXTRACT])) {
// ----- Generate a local information
$v_local_header = array();
$this->privConvertHeader2FileInfo($p_entry, $v_local_header);
// ----- Call the callback
// Here I do not use call_user_func() because I need to send a reference to the
// header.
// eval('$v_result = '.$p_options[IWP_PCLZIP_CB_POST_EXTRACT].'(IWP_PCLZIP_CB_POST_EXTRACT, $v_local_header);');
$v_result = $p_options[IWP_PCLZIP_CB_POST_EXTRACT](IWP_PCLZIP_CB_POST_EXTRACT, $v_local_header);
// ----- Look for abort result
if ($v_result == 2) {
$v_result = IWP_PCLZIP_ERR_USER_ABORTED;
}
}
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privExtractFileAsString()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privExtractFileAsString(&$p_entry, &$p_string, &$p_options)
{
$v_result=1;
// ----- Read the file header
$v_header = array();
if (($v_result = $this->privReadFileHeader($v_header)) != 1)
{
// ----- Return
return $v_result;
}
// ----- Check that the file header is coherent with $p_entry info
if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
// TBC
}
// ----- Look for pre-extract callback
if (isset($p_options[IWP_PCLZIP_CB_PRE_EXTRACT])) {
// ----- Generate a local information
$v_local_header = array();
$this->privConvertHeader2FileInfo($p_entry, $v_local_header);
// ----- Call the callback
// Here I do not use call_user_func() because I need to send a reference to the
// header.
// eval('$v_result = '.$p_options[IWP_PCLZIP_CB_PRE_EXTRACT].'(IWP_PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
$v_result = $p_options[IWP_PCLZIP_CB_PRE_EXTRACT](IWP_PCLZIP_CB_PRE_EXTRACT, $v_local_header);
if ($v_result == 0) {
// ----- Change the file status
$p_entry['status'] = "skipped";
$v_result = 1;
}
// ----- Look for abort result
if ($v_result == 2) {
// ----- This status is internal and will be changed in 'skipped'
$p_entry['status'] = "aborted";
$v_result = IWP_PCLZIP_ERR_USER_ABORTED;
}
// ----- Update the informations
// Only some fields can be modified
$p_entry['filename'] = $v_local_header['filename'];
}
// ----- Look if extraction should be done
if ($p_entry['status'] == 'ok') {
// ----- Do the extraction (if not a folder)
if (!(($p_entry['external']&0x00000010)==0x00000010)) {
// ----- Look for not compressed file
// if ($p_entry['compressed_size'] == $p_entry['size'])
if ($p_entry['compression'] == 0) {
// ----- Reading the file
$p_string = @fread($this->zip_fd, $p_entry['compressed_size']);
}
else {
// ----- Reading the file
$v_data = @fread($this->zip_fd, $p_entry['compressed_size']);
// ----- Decompress the file
if (($p_string = @gzinflate($v_data)) === FALSE) {
// TBC
}
}
// ----- Trace
}
else {
// TBC : error : can not extract a folder in a string
}
}
// ----- Change abort status
if ($p_entry['status'] == "aborted") {
$p_entry['status'] = "skipped";
}
// ----- Look for post-extract callback
elseif (isset($p_options[IWP_PCLZIP_CB_POST_EXTRACT])) {
// ----- Generate a local information
$v_local_header = array();
$this->privConvertHeader2FileInfo($p_entry, $v_local_header);
// ----- Swap the content to header
$v_local_header['content'] = $p_string;
$p_string = '';
// ----- Call the callback
// Here I do not use call_user_func() because I need to send a reference to the
// header.
// eval('$v_result = '.$p_options[IWP_PCLZIP_CB_POST_EXTRACT].'(IWP_PCLZIP_CB_POST_EXTRACT, $v_local_header);');
$v_result = $p_options[IWP_PCLZIP_CB_POST_EXTRACT](IWP_PCLZIP_CB_POST_EXTRACT, $v_local_header);
// ----- Swap back the content to header
$p_string = $v_local_header['content'];
unset($v_local_header['content']);
// ----- Look for abort result
if ($v_result == 2) {
$v_result = IWP_PCLZIP_ERR_USER_ABORTED;
}
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privReadFileHeader()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privReadFileHeader(&$p_header)
{
$v_result=1;
// ----- Read the 4 bytes signature
$v_binary_data = @fread($this->zip_fd, 4);
$v_data = unpack('Vid', $v_binary_data);
// ----- Check signature
if ($v_data['id'] != 0x04034b50)
{
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Read the first 42 bytes of the header
$v_binary_data = fread($this->zip_fd, 26);
// ----- Look for invalid block size
if (strlen($v_binary_data) != 26)
{
$p_header['filename'] = "";
$p_header['status'] = "invalid_header";
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Extract the values
$v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data);
// ----- Get filename
$p_header['filename'] = fread($this->zip_fd, $v_data['filename_len']);
// ----- Get extra_fields
if ($v_data['extra_len'] != 0) {
$p_header['extra'] = fread($this->zip_fd, $v_data['extra_len']);
}
else {
$p_header['extra'] = '';
}
// ----- Extract properties
$p_header['version_extracted'] = $v_data['version'];
$p_header['compression'] = $v_data['compression'];
$p_header['size'] = $v_data['size'];
$p_header['compressed_size'] = $v_data['compressed_size'];
$p_header['crc'] = $v_data['crc'];
$p_header['flag'] = $v_data['flag'];
$p_header['filename_len'] = $v_data['filename_len'];
// ----- Recuperate date in UNIX format
$p_header['mdate'] = $v_data['mdate'];
$p_header['mtime'] = $v_data['mtime'];
if ($p_header['mdate'] && $p_header['mtime'])
{
// ----- Extract time
$v_hour = ($p_header['mtime'] & 0xF800) >> 11;
$v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
$v_seconde = ($p_header['mtime'] & 0x001F)*2;
// ----- Extract date
$v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
$v_month = ($p_header['mdate'] & 0x01E0) >> 5;
$v_day = $p_header['mdate'] & 0x001F;
// ----- Get UNIX date format
$p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
}
else
{
$p_header['mtime'] = time();
}
// TBC
//for(reset($v_data); $key = key($v_data); next($v_data)) {
//}
// ----- Set the stored filename
$p_header['stored_filename'] = $p_header['filename'];
// ----- Set the status field
$p_header['status'] = "ok";
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privReadCentralFileHeader()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privReadCentralFileHeader(&$p_header)
{
$v_result=1;
// ----- Read the 4 bytes signature
$v_binary_data = @fread($this->zip_fd, 4);
$v_data = unpack('Vid', $v_binary_data);
// ----- Check signature
if ($v_data['id'] != 0x02014b50)
{
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Read the first 42 bytes of the header
$v_binary_data = fread($this->zip_fd, 42);
// ----- Look for invalid block size
if (strlen($v_binary_data) != 42)
{
$p_header['filename'] = "";
$p_header['status'] = "invalid_header";
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Extract the values
$p_header = unpack('vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $v_binary_data);
// ----- Get filename
if ($p_header['filename_len'] != 0)
$p_header['filename'] = fread($this->zip_fd, $p_header['filename_len']);
else
$p_header['filename'] = '';
// ----- Get extra
if ($p_header['extra_len'] != 0)
$p_header['extra'] = fread($this->zip_fd, $p_header['extra_len']);
else
$p_header['extra'] = '';
// ----- Get comment
if ($p_header['comment_len'] != 0)
$p_header['comment'] = fread($this->zip_fd, $p_header['comment_len']);
else
$p_header['comment'] = '';
// ----- Extract properties
// ----- Recuperate date in UNIX format
//if ($p_header['mdate'] && $p_header['mtime'])
// TBC : bug : this was ignoring time with 0/0/0
if (1)
{
// ----- Extract time
$v_hour = ($p_header['mtime'] & 0xF800) >> 11;
$v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
$v_seconde = ($p_header['mtime'] & 0x001F)*2;
// ----- Extract date
$v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
$v_month = ($p_header['mdate'] & 0x01E0) >> 5;
$v_day = $p_header['mdate'] & 0x001F;
// ----- Get UNIX date format
$p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
}
else
{
$p_header['mtime'] = time();
}
// ----- Set the stored filename
$p_header['stored_filename'] = $p_header['filename'];
// ----- Set default status to ok
$p_header['status'] = 'ok';
// ----- Look if it is a directory
if (substr($p_header['filename'], -1) == '/') {
//$p_header['external'] = 0x41FF0010;
$p_header['external'] = 0x00000010;
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privCheckFileHeaders()
// Description :
// Parameters :
// Return Values :
// 1 on success,
// 0 on error;
// --------------------------------------------------------------------------------
function privCheckFileHeaders(&$p_local_header, &$p_central_header)
{
$v_result=1;
// ----- Check the static values
// TBC
if ($p_local_header['filename'] != $p_central_header['filename']) {
}
if ($p_local_header['version_extracted'] != $p_central_header['version_extracted']) {
}
if ($p_local_header['flag'] != $p_central_header['flag']) {
}
if ($p_local_header['compression'] != $p_central_header['compression']) {
}
if ($p_local_header['mtime'] != $p_central_header['mtime']) {
}
if ($p_local_header['filename_len'] != $p_central_header['filename_len']) {
}
// ----- Look for flag bit 3
if (($p_local_header['flag'] & 8) == 8) {
$p_local_header['size'] = $p_central_header['size'];
$p_local_header['compressed_size'] = $p_central_header['compressed_size'];
$p_local_header['crc'] = $p_central_header['crc'];
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privReadEndCentralDir()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privReadEndCentralDir(&$p_central_dir)
{
$v_result=1;
// ----- Go to the end of the zip file
$v_size = iwp_get_file_size($this->zipname);
if($v_size === false)
{
echo "error getting file size";
}
elseif($v_size > 2000)
{
echo "
file size is : ".$v_size;
}
@fseek($this->zip_fd, $v_size);
if (@ftell($this->zip_fd) != $v_size)
{
// ----- Error log
echo "Unable to go to the end of the archive";
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_BAD_FORMAT, 'Unable to go to the end of the archive \''.$this->zipname.'\'');
if(($v_size > 2047999988 )||($v_size == 0)||($v_size < 0))
{
return array('error' => 'Unable to find End of Central Dir Record signature.');
}
// ----- Return
return IWPPclZip::errorCode();
}
// ----- First try : look if this is an archive with no commentaries (most of the time)
// in this case the end of central dir is at 22 bytes of the file end
$v_found = 0;
if ($v_size > 26) {
@fseek($this->zip_fd, $v_size-22);
if (($v_pos = @ftell($this->zip_fd)) != ($v_size-22))
{
echo 'Unable to seek back to the middle of the archive - 5091';
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Read for bytes
$v_binary_data = @fread($this->zip_fd, 4);
$v_data = @unpack('Vid', $v_binary_data);
// ----- Check signature
if ($v_data['id'] == 0x06054b50) {
$v_found = 1;
}
$v_pos = ftell($this->zip_fd);
}
// ----- Go back to the maximum possible size of the Central Dir End Record
if (!$v_found) {
$v_maximum_size = 65557; // 0xFFFF + 22;
if ($v_maximum_size > $v_size)
$v_maximum_size = $v_size;
@fseek($this->zip_fd, $v_size-$v_maximum_size);
if (@ftell($this->zip_fd) != ($v_size-$v_maximum_size))
{
echo "Unable to seek back to the middle of the archive - 5119";
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Read byte per byte in order to find the signature
$v_pos = ftell($this->zip_fd);
$v_bytes = 0x00000000;
while ($v_pos < $v_size)
{
// ----- Read a byte
$v_byte = @fread($this->zip_fd, 1);
// ----- Add the byte
//$v_bytes = ($v_bytes << 8) | Ord($v_byte);
// Note we mask the old value down such that once shifted we can never end up with more than a 32bit number
// Otherwise on systems where we have 64bit integers the check below for the magic number will fail.
$v_bytes = ( ($v_bytes & 0xFFFFFF) << 8) | Ord($v_byte);
// ----- Compare the bytes
if ($v_bytes == 0x504b0506)
{
$v_pos++;
break;
}
$v_pos++;
}
// ----- Look if not found end of central dir
if ($v_pos == $v_size)
{
echo "Unable to find End of Central Dir Record signature ";
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_BAD_FORMAT, "Unable to find End of Central Dir Record signature");
if(($v_size > 2047999988)||($v_size == 0))
{
return array('error' => 'Unable to find End of Central Dir Record signature.');
}
// ----- Return
return IWPPclZip::errorCode();
}
}
// ----- Read the first 18 bytes of the header
$v_binary_data = fread($this->zip_fd, 18);
// ----- Look for invalid block size
if (strlen($v_binary_data) != 18)
{
echo "Invalid End of Central Dir Record size : ";
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_BAD_FORMAT, "Invalid End of Central Dir Record size : ".strlen($v_binary_data));
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Extract the values
$v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data);
// ----- Check the global size
if (($v_pos + $v_data['comment_size'] + 18) != $v_size) {
// ----- Removed in release 2.2 see readme file
// The check of the file size is a little too strict.
// Some bugs where found when a zip is encrypted/decrypted with 'crypt'.
// While decrypted, zip has training 0 bytes
if (0) {
echo "The central dir is not at the end of the archive. Some trailing bytes exists after the archive.";
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_BAD_FORMAT,
'The central dir is not at the end of the archive.'
.' Some trailing bytes exists after the archive.');
// ----- Return
return IWPPclZip::errorCode();
}
}
// ----- Get comment
if ($v_data['comment_size'] != 0) {
$p_central_dir['comment'] = fread($this->zip_fd, $v_data['comment_size']);
}
else
$p_central_dir['comment'] = '';
$p_central_dir['entries'] = $v_data['entries'];
$p_central_dir['disk_entries'] = $v_data['disk_entries'];
$p_central_dir['offset'] = $v_data['offset'];
$p_central_dir['size'] = $v_data['size'];
$p_central_dir['disk'] = $v_data['disk'];
$p_central_dir['disk_start'] = $v_data['disk_start'];
// TBC
//for(reset($p_central_dir); $key = key($p_central_dir); next($p_central_dir)) {
//}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privDeleteByRule()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privDeleteByRule(&$p_result_list, &$p_options)
{
$v_result=1;
$v_list_detail = array();
// ----- Open the zip file
if (($v_result=$this->privOpenFd('rb')) != 1)
{
// ----- Return
return $v_result;
}
// ----- Read the central directory informations
$v_central_dir = array();
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
{
$this->privCloseFd();
return $v_result;
}
// ----- Go to beginning of File
@rewind($this->zip_fd);
// ----- Scan all the files
// ----- Start at beginning of Central Dir
$v_pos_entry = $v_central_dir['offset'];
@rewind($this->zip_fd);
if (@fseek($this->zip_fd, $v_pos_entry))
{
// ----- Close the zip file
$this->privCloseFd();
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Read each entry
$v_header_list = array();
$j_start = 0;
for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
{
// ----- Read the file header
$v_header_list[$v_nb_extracted] = array();
if (($v_result = $this->privReadCentralFileHeader($v_header_list[$v_nb_extracted])) != 1)
{
// ----- Close the zip file
$this->privCloseFd();
return $v_result;
}
// ----- Store the index
$v_header_list[$v_nb_extracted]['index'] = $i;
// ----- Look for the specific extract rules
$v_found = false;
// ----- Look for extract by name rule
if ( (isset($p_options[IWP_PCLZIP_OPT_BY_NAME]))
&& ($p_options[IWP_PCLZIP_OPT_BY_NAME] != 0)) {
// ----- Look if the filename is in the list
for ($j=0; ($j strlen($p_options[IWP_PCLZIP_OPT_BY_NAME][$j]))
&& (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_options[IWP_PCLZIP_OPT_BY_NAME][$j])) == $p_options[IWP_PCLZIP_OPT_BY_NAME][$j])) {
$v_found = true;
}
elseif ( (($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */
&& ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_options[IWP_PCLZIP_OPT_BY_NAME][$j])) {
$v_found = true;
}
}
// ----- Look for a filename
elseif ($v_header_list[$v_nb_extracted]['stored_filename'] == $p_options[IWP_PCLZIP_OPT_BY_NAME][$j]) {
$v_found = true;
}
}
}
// ----- Look for extract by ereg rule
// ereg() is deprecated with PHP 5.3
/*
else if ( (isset($p_options[IWP_PCLZIP_OPT_BY_EREG]))
&& ($p_options[IWP_PCLZIP_OPT_BY_EREG] != "")) {
if (ereg($p_options[IWP_PCLZIP_OPT_BY_EREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
$v_found = true;
}
}
*/
// ----- Look for extract by preg rule
else if ( (isset($p_options[IWP_PCLZIP_OPT_BY_PREG]))
&& ($p_options[IWP_PCLZIP_OPT_BY_PREG] != "")) {
if (preg_match($p_options[IWP_PCLZIP_OPT_BY_PREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
$v_found = true;
}
}
// ----- Look for extract by index rule
else if ( (isset($p_options[IWP_PCLZIP_OPT_BY_INDEX]))
&& ($p_options[IWP_PCLZIP_OPT_BY_INDEX] != 0)) {
// ----- Look if the index is in the list
for ($j=$j_start; ($j=$p_options[IWP_PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[IWP_PCLZIP_OPT_BY_INDEX][$j]['end'])) {
$v_found = true;
}
if ($i>=$p_options[IWP_PCLZIP_OPT_BY_INDEX][$j]['end']) {
$j_start = $j+1;
}
if ($p_options[IWP_PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
break;
}
}
}
else {
$v_found = true;
}
// ----- Look for deletion
if ($v_found)
{
unset($v_header_list[$v_nb_extracted]);
}
else
{
$v_nb_extracted++;
}
}
// ----- Look if something need to be deleted
if ($v_nb_extracted > 0) {
// ----- Creates a temporay file
$v_zip_temp_name = IWP_PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
// ----- Creates a temporary zip archive
$v_temp_zip = new IWPPclZip($v_zip_temp_name);
// ----- Open the temporary zip file in write mode
if (($v_result = $v_temp_zip->privOpenFd('wb')) != 1) {
$this->privCloseFd();
// ----- Return
return $v_result;
}
// ----- Look which file need to be kept
for ($i=0; $izip_fd);
if (@fseek($this->zip_fd, $v_header_list[$i]['offset'])) {
// ----- Close the zip file
$this->privCloseFd();
$v_temp_zip->privCloseFd();
@unlink($v_zip_temp_name);
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Read the file header
$v_local_header = array();
if (($v_result = $this->privReadFileHeader($v_local_header)) != 1) {
// ----- Close the zip file
$this->privCloseFd();
$v_temp_zip->privCloseFd();
@unlink($v_zip_temp_name);
// ----- Return
return $v_result;
}
// ----- Check that local file header is same as central file header
if ($this->privCheckFileHeaders($v_local_header,
$v_header_list[$i]) != 1) {
// TBC
}
unset($v_local_header);
// ----- Write the file header
if (($v_result = $v_temp_zip->privWriteFileHeader($v_header_list[$i])) != 1) {
// ----- Close the zip file
$this->privCloseFd();
$v_temp_zip->privCloseFd();
@unlink($v_zip_temp_name);
// ----- Return
return $v_result;
}
// ----- Read/write the data block
if (($v_result = IWPPclZipUtilCopyBlock($this->zip_fd, $v_temp_zip->zip_fd, $v_header_list[$i]['compressed_size'])) != 1) {
// ----- Close the zip file
$this->privCloseFd();
$v_temp_zip->privCloseFd();
@unlink($v_zip_temp_name);
// ----- Return
return $v_result;
}
}
// ----- Store the offset of the central dir
$v_offset = @ftell($v_temp_zip->zip_fd);
// ----- Re-Create the Central Dir files header
for ($i=0; $iprivWriteCentralFileHeader($v_header_list[$i])) != 1) {
$v_temp_zip->privCloseFd();
$this->privCloseFd();
@unlink($v_zip_temp_name);
// ----- Return
return $v_result;
}
// ----- Transform the header to a 'usable' info
$v_temp_zip->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
}
// ----- Zip file comment
$v_comment = '';
if (isset($p_options[IWP_PCLZIP_OPT_COMMENT])) {
$v_comment = $p_options[IWP_PCLZIP_OPT_COMMENT];
}
// ----- Calculate the size of the central header
$v_size = @ftell($v_temp_zip->zip_fd)-$v_offset;
// ----- Create the central dir footer
if (($v_result = $v_temp_zip->privWriteCentralHeader(sizeof($v_header_list), $v_size, $v_offset, $v_comment)) != 1) {
// ----- Reset the file list
unset($v_header_list);
$v_temp_zip->privCloseFd();
$this->privCloseFd();
@unlink($v_zip_temp_name);
// ----- Return
return $v_result;
}
// ----- Close
$v_temp_zip->privCloseFd();
$this->privCloseFd();
// ----- Delete the zip file
// TBC : I should test the result ...
@unlink($this->zipname);
// ----- Rename the temporary file
// TBC : I should test the result ...
//@rename($v_zip_temp_name, $this->zipname);
IWPPclZipUtilRename($v_zip_temp_name, $this->zipname);
// ----- Destroy the temporary archive
unset($v_temp_zip);
}
// ----- Remove every files : reset the file
else if ($v_central_dir['entries'] != 0) {
$this->privCloseFd();
if (($v_result = $this->privOpenFd('wb')) != 1) {
return $v_result;
}
if (($v_result = $this->privWriteCentralHeader(0, 0, 0, '')) != 1) {
return $v_result;
}
$this->privCloseFd();
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privDirCheck()
// Description :
// Check if a directory exists, if not it creates it and all the parents directory
// which may be useful.
// Parameters :
// $p_dir : Directory path to check.
// Return Values :
// 1 : OK
// -1 : Unable to create directory
// --------------------------------------------------------------------------------
function privDirCheck($p_dir, $p_is_dir=false)
{
$v_result = 1;
// ----- Remove the final '/'
if (($p_is_dir) && (substr($p_dir, -1)=='/'))
{
$p_dir = substr($p_dir, 0, strlen($p_dir)-1);
}
// ----- Check the directory availability
if ((is_dir($p_dir)) || ($p_dir == ""))
{
return 1;
}
// ----- Extract parent directory
$p_parent_dir = dirname($p_dir);
// ----- Just a check
if ($p_parent_dir != $p_dir)
{
// ----- Look for parent directory
if ($p_parent_dir != "")
{
if (($v_result = $this->privDirCheck($p_parent_dir)) != 1)
{
return $v_result;
}
}
}
// ----- Create the directory
if ($GLOBALS['is_child_restore'] && strrpos($p_dir, 'uploads/sites/'.$GLOBALS['blogid']) == false) {
return 1;
}
if ($GLOBALS['is_new_backup']){
$homePath = iwp_wp_normalize_path(dirname(dirname(__FILE__)));
$t_pr = str_replace($homePath, '', $p_dir);
if(substr($t_pr, 1, 10) == 'wordpress/'){
$p_dir = substr_replace( $t_pr, '' , 1, 10 );
}else{
$p_dir = $t_pr;
}
$p_dir = $homePath.$p_dir;
$result = true;
}
if ($GLOBALS['needFileSystem']) {
$p_dir_name = $GLOBALS['FileSystemObj']->findFolder($p_dir);
$result = $GLOBALS['FileSystemObj']->mkdir($p_dir_name, 0755);
}else{
if (!file_exists($p_dir)) {
$result = mkdir($p_dir);
}
}
if (!$result)
{
// ----- Error log
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_DIR_CREATE_FAIL, "Unable to create directory '$p_dir'");
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privMerge()
// Description :
// If $p_archive_to_add does not exist, the function exit with a success result.
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privMerge(&$p_archive_to_add)
{
$v_result=1;
// ----- Look if the archive_to_add exists
if (!is_file($p_archive_to_add->zipname))
{
// ----- Nothing to merge, so merge is a success
$v_result = 1;
// ----- Return
return $v_result;
}
// ----- Look if the archive exists
if (!is_file($this->zipname))
{
// ----- Do a duplicate
$v_result = $this->privDuplicate($p_archive_to_add->zipname);
// ----- Return
return $v_result;
}
// ----- Open the zip file
if (($v_result=$this->privOpenFd('rb')) != 1)
{
// ----- Return
return $v_result;
}
// ----- Read the central directory informations
$v_central_dir = array();
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
{
$this->privCloseFd();
return $v_result;
}
// ----- Go to beginning of File
@rewind($this->zip_fd);
// ----- Open the archive_to_add file
if (($v_result=$p_archive_to_add->privOpenFd('rb')) != 1)
{
$this->privCloseFd();
// ----- Return
return $v_result;
}
// ----- Read the central directory informations
$v_central_dir_to_add = array();
if (($v_result = $p_archive_to_add->privReadEndCentralDir($v_central_dir_to_add)) != 1)
{
$this->privCloseFd();
$p_archive_to_add->privCloseFd();
return $v_result;
}
// ----- Go to beginning of File
@rewind($p_archive_to_add->zip_fd);
// ----- Creates a temporay file
$v_zip_temp_name = IWP_PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
// ----- Open the temporary file in write mode
if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
{
$this->privCloseFd();
$p_archive_to_add->privCloseFd();
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Copy the files from the archive to the temporary file
// TBC : Here I should better append the file and go back to erase the central dir
$v_size = $v_central_dir['offset'];
while ($v_size != 0)
{
$v_read_size = ($v_size < IWP_PCLZIP_READ_BLOCK_SIZE ? $v_size : IWP_PCLZIP_READ_BLOCK_SIZE);
$v_buffer = fread($this->zip_fd, $v_read_size);
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
}
// ----- Copy the files from the archive_to_add into the temporary file
$v_size = $v_central_dir_to_add['offset'];
while ($v_size != 0)
{
$v_read_size = ($v_size < IWP_PCLZIP_READ_BLOCK_SIZE ? $v_size : IWP_PCLZIP_READ_BLOCK_SIZE);
$v_buffer = fread($p_archive_to_add->zip_fd, $v_read_size);
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
}
// ----- Store the offset of the central dir
$v_offset = @ftell($v_zip_temp_fd);
// ----- Copy the block of file headers from the old archive
$v_size = $v_central_dir['size'];
while ($v_size != 0)
{
$v_read_size = ($v_size < IWP_PCLZIP_READ_BLOCK_SIZE ? $v_size : IWP_PCLZIP_READ_BLOCK_SIZE);
$v_buffer = @fread($this->zip_fd, $v_read_size);
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
}
// ----- Copy the block of file headers from the archive_to_add
$v_size = $v_central_dir_to_add['size'];
while ($v_size != 0)
{
$v_read_size = ($v_size < IWP_PCLZIP_READ_BLOCK_SIZE ? $v_size : IWP_PCLZIP_READ_BLOCK_SIZE);
$v_buffer = @fread($p_archive_to_add->zip_fd, $v_read_size);
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
}
// ----- Merge the file comments
$v_comment = $v_central_dir['comment'].' '.$v_central_dir_to_add['comment'];
// ----- Calculate the size of the (new) central header
$v_size = @ftell($v_zip_temp_fd)-$v_offset;
// ----- Swap the file descriptor
// Here is a trick : I swap the temporary fd with the zip fd, in order to use
// the following methods on the temporary fil and not the real archive fd
$v_swap = $this->zip_fd;
$this->zip_fd = $v_zip_temp_fd;
$v_zip_temp_fd = $v_swap;
// ----- Create the central dir footer
if (($v_result = $this->privWriteCentralHeader($v_central_dir['entries']+$v_central_dir_to_add['entries'], $v_size, $v_offset, $v_comment)) != 1)
{
$this->privCloseFd();
$p_archive_to_add->privCloseFd();
@fclose($v_zip_temp_fd);
$this->zip_fd = null;
// ----- Reset the file list
unset($v_header_list);
// ----- Return
return $v_result;
}
// ----- Swap back the file descriptor
$v_swap = $this->zip_fd;
$this->zip_fd = $v_zip_temp_fd;
$v_zip_temp_fd = $v_swap;
// ----- Close
$this->privCloseFd();
$p_archive_to_add->privCloseFd();
// ----- Close the temporary file
@fclose($v_zip_temp_fd);
// ----- Delete the zip file
// TBC : I should test the result ...
@unlink($this->zipname);
// ----- Rename the temporary file
// TBC : I should test the result ...
//@rename($v_zip_temp_name, $this->zipname);
IWPPclZipUtilRename($v_zip_temp_name, $this->zipname);
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privDuplicate()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privDuplicate($p_archive_filename)
{
$v_result=1;
// ----- Look if the $p_archive_filename exists
if (!is_file($p_archive_filename))
{
// ----- Nothing to duplicate, so duplicate is a success.
$v_result = 1;
// ----- Return
return $v_result;
}
// ----- Open the zip file
if (($v_result=$this->privOpenFd('wb')) != 1)
{
// ----- Return
return $v_result;
}
// ----- Open the temporary file in write mode
if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0)
{
$this->privCloseFd();
IWPPclZip::privErrorLog(IWP_PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive file \''.$p_archive_filename.'\' in binary write mode');
// ----- Return
return IWPPclZip::errorCode();
}
// ----- Copy the files from the archive to the temporary file
// TBC : Here I should better append the file and go back to erase the central dir
$v_size = iwp_get_file_size($p_archive_filename);
while ($v_size != 0)
{
$v_read_size = ($v_size < IWP_PCLZIP_READ_BLOCK_SIZE ? $v_size : IWP_PCLZIP_READ_BLOCK_SIZE);
$v_buffer = fread($v_zip_temp_fd, $v_read_size);
@fwrite($this->zip_fd, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
}
// ----- Close
$this->privCloseFd();
// ----- Close the temporary file
@fclose($v_zip_temp_fd);
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privErrorLog()
// Description :
// Parameters :
// --------------------------------------------------------------------------------
function privErrorLog($p_error_code=0, $p_error_string='')
{
if (IWP_PCLZIP_ERROR_EXTERNAL == 1) {
PclError($p_error_code, $p_error_string);
}
else {
$this->error_code = $p_error_code;
$this->error_string = $p_error_string;
}
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privErrorReset()
// Description :
// Parameters :
// --------------------------------------------------------------------------------
function privErrorReset()
{
if (IWP_PCLZIP_ERROR_EXTERNAL == 1) {
PclErrorReset();
}
else {
$this->error_code = 0;
$this->error_string = '';
}
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privDisableMagicQuotes()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privDisableMagicQuotes()
{
$v_result=1;
// ----- Look if function exists
if ( (!function_exists("get_magic_quotes_runtime"))
|| (!function_exists("set_magic_quotes_runtime"))) {
return $v_result;
}
// ----- Look if already done
if ($this->magic_quotes_status != -1) {
return $v_result;
}
// ----- Get and memorize the magic_quote value
$this->magic_quotes_status = @get_magic_quotes_runtime();
// ----- Disable magic_quotes
if ($this->magic_quotes_status == 1) {
@set_magic_quotes_runtime(0);
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privSwapBackMagicQuotes()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function privSwapBackMagicQuotes()
{
$v_result=1;
// ----- Look if function exists
if ( (!function_exists("get_magic_quotes_runtime"))
|| (!function_exists("set_magic_quotes_runtime"))) {
return $v_result;
}
// ----- Look if something to do
if ($this->magic_quotes_status != -1) {
return $v_result;
}
// ----- Swap back magic_quotes
if ($this->magic_quotes_status == 1) {
@set_magic_quotes_runtime($this->magic_quotes_status);
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
}
// End of class
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : IWPPclZipUtilPathReduction()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function IWPPclZipUtilPathReduction($p_dir)
{
$v_result = "";
// ----- Look for not empty path
if ($p_dir != "") {
// ----- Explode path by directory names
$v_list = explode("/", $p_dir);
// ----- Study directories from last to first
$v_skip = 0;
for ($i=sizeof($v_list)-1; $i>=0; $i--) {
// ----- Look for current path
if ($v_list[$i] == ".") {
// ----- Ignore this directory
// Should be the first $i=0, but no check is done
}
else if ($v_list[$i] == "..") {
$v_skip++;
}
else if ($v_list[$i] == "") {
// ----- First '/' i.e. root slash
if ($i == 0) {
$v_result = "/".$v_result;
if ($v_skip > 0) {
// ----- It is an invalid path, so the path is not modified
// TBC
$v_result = $p_dir;
$v_skip = 0;
}
}
// ----- Last '/' i.e. indicates a directory
else if ($i == (sizeof($v_list)-1)) {
$v_result = $v_list[$i];
}
// ----- Double '/' inside the path
else {
// ----- Ignore only the double '//' in path,
// but not the first and last '/'
}
}
else {
// ----- Look for item to skip
if ($v_skip > 0) {
$v_skip--;
}
else {
$v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:"");
}
}
}
// ----- Look for skip
if ($v_skip > 0) {
while ($v_skip > 0) {
$v_result = '../'.$v_result;
$v_skip--;
}
}
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : IWPPclZipUtilPathInclusion()
// Description :
// This function indicates if the path $p_path is under the $p_dir tree. Or,
// said in an other way, if the file or sub-dir $p_path is inside the dir
// $p_dir.
// The function indicates also if the path is exactly the same as the dir.
// This function supports path with duplicated '/' like '//', but does not
// support '.' or '..' statements.
// Parameters :
// Return Values :
// 0 if $p_path is not inside directory $p_dir
// 1 if $p_path is inside directory $p_dir
// 2 if $p_path is exactly the same as $p_dir
// --------------------------------------------------------------------------------
function IWPPclZipUtilPathInclusion($p_dir, $p_path)
{
$v_result = 1;
// ----- Look for path beginning by ./
if ( ($p_dir == '.')
|| ((strlen($p_dir) >=2) && (substr($p_dir, 0, 2) == './'))) {
$p_dir = IWPPclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_dir, 1);
}
if ( ($p_path == '.')
|| ((strlen($p_path) >=2) && (substr($p_path, 0, 2) == './'))) {
$p_path = IWPPclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_path, 1);
}
// ----- Explode dir and path by directory separator
$v_list_dir = explode("/", $p_dir);
$v_list_dir_size = sizeof($v_list_dir);
$v_list_path = explode("/", $p_path);
$v_list_path_size = sizeof($v_list_path);
// ----- Study directories paths
$i = 0;
$j = 0;
while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) {
// ----- Look for empty dir (path reduction)
if ($v_list_dir[$i] == '') {
$i++;
continue;
}
if ($v_list_path[$j] == '') {
$j++;
continue;
}
// ----- Compare the items
if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ( $v_list_path[$j] != '')) {
$v_result = 0;
}
// ----- Next items
$i++;
$j++;
}
// ----- Look if everything seems to be the same
if ($v_result) {
// ----- Skip all the empty items
while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++;
while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++;
if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) {
// ----- There are exactly the same
$v_result = 2;
}
else if ($i < $v_list_dir_size) {
// ----- The path is shorter than the dir
$v_result = 0;
}
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : IWPPclZipUtilCopyBlock()
// Description :
// Parameters :
// $p_mode : read/write compression mode
// 0 : src & dest normal
// 1 : src gzip, dest normal
// 2 : src normal, dest gzip
// 3 : src & dest gzip
// Return Values :
// --------------------------------------------------------------------------------
function IWPPclZipUtilCopyBlock($p_src, $p_dest, $p_size, $p_mode=0)
{
$v_result = 1;
if ($p_mode==0)
{
while ($p_size != 0)
{
$v_read_size = ($p_size < IWP_PCLZIP_READ_BLOCK_SIZE ? $p_size : IWP_PCLZIP_READ_BLOCK_SIZE);
$v_buffer = @fread($p_src, $v_read_size);
@fwrite($p_dest, $v_buffer, $v_read_size);
$p_size -= $v_read_size;
}
}
else if ($p_mode==1)
{
while ($p_size != 0)
{
$v_read_size = ($p_size < IWP_PCLZIP_READ_BLOCK_SIZE ? $p_size : IWP_PCLZIP_READ_BLOCK_SIZE);
$v_buffer = @gzread($p_src, $v_read_size);
@fwrite($p_dest, $v_buffer, $v_read_size);
$p_size -= $v_read_size;
}
}
else if ($p_mode==2)
{
while ($p_size != 0)
{
$v_read_size = ($p_size < IWP_PCLZIP_READ_BLOCK_SIZE ? $p_size : IWP_PCLZIP_READ_BLOCK_SIZE);
$v_buffer = @fread($p_src, $v_read_size);
@gzwrite($p_dest, $v_buffer, $v_read_size);
$p_size -= $v_read_size;
}
}
else if ($p_mode==3)
{
while ($p_size != 0)
{
$v_read_size = ($p_size < IWP_PCLZIP_READ_BLOCK_SIZE ? $p_size : IWP_PCLZIP_READ_BLOCK_SIZE);
$v_buffer = @gzread($p_src, $v_read_size);
@gzwrite($p_dest, $v_buffer, $v_read_size);
$p_size -= $v_read_size;
}
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : IWPPclZipUtilRename()
// Description :
// This function tries to do a simple rename() function. If it fails, it
// tries to copy the $p_src file in a new $p_dest file and then unlink the
// first one.
// Parameters :
// $p_src : Old filename
// $p_dest : New filename
// Return Values :
// 1 on success, 0 on failure.
// --------------------------------------------------------------------------------
function IWPPclZipUtilRename($p_src, $p_dest)
{
$v_result = 1;
// ----- Try to rename the files
if (!@rename($p_src, $p_dest)) {
// ----- Try to copy & unlink the src
if (!@copy($p_src, $p_dest)) {
$v_result = 0;
}
else if (!@unlink($p_src)) {
$v_result = 0;
}
}
// ----- Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : IWPPclZipUtilOptionText()
// Description :
// Translate option value in text. Mainly for debug purpose.
// Parameters :
// $p_option : the option value.
// Return Values :
// The option text value.
// --------------------------------------------------------------------------------
function IWPPclZipUtilOptionText($p_option)
{
$v_list = get_defined_constants();
for (reset($v_list); $v_key = key($v_list); next($v_list)) {
$v_prefix = substr($v_key, 0, 10);
if (( ($v_prefix == 'IWP_PCLZIP_OPT')
|| ($v_prefix == 'IWP_PCLZIP_CB_')
|| ($v_prefix == 'IWP_PCLZIP_ATT'))
&& ($v_list[$v_key] == $p_option)) {
return $v_key;
}
}
$v_result = 'Unknown';
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : IWPPclZipUtilTranslateWinPath()
// Description :
// Translate windows path by replacing '\' by '/' and optionally removing
// drive letter.
// Parameters :
// $p_path : path to translate.
// $p_remove_disk_letter : true | false
// Return Values :
// The path translated.
// --------------------------------------------------------------------------------
function IWPPclZipUtilTranslateWinPath($p_path, $p_remove_disk_letter=true)
{
if (stristr(php_uname(), 'windows')) {
// ----- Look for potential disk letter
if (($p_remove_disk_letter) && (($v_position = strpos($p_path, ':')) != false)) {
$p_path = substr($p_path, $v_position+1);
}
// ----- Change potential windows directory separator
if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) {
$p_path = strtr($p_path, '\\', '/');
}
}
return $p_path;
}
//-------------------------------------------------------------------
/* encryption class from phpsec lib
/**
* Encrypt / decrypt using the Electronic Code Book mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
*/
define('CRYPT_MODE_CTR', -1);
define('CRYPT_MODE_ECB', 1);
/**
* Encrypt / decrypt using the Code Book Chaining mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
*/
define('CRYPT_MODE_CBC', 2);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
*/
define('CRYPT_MODE_CFB', 3);
/**
* Encrypt / decrypt using the Output Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
*/
define('CRYPT_MODE_OFB', 4);
/**
* Encrypt / decrypt using streaming mode.
*/
define('CRYPT_MODE_STREAM', 5);
/**#@-*/
/**#@+
* @access private
* @see self::Crypt_Base()
* @internal These constants are for internal use only
*/
/**
* Base value for the internal implementation $engine switch
*/
define('CRYPT_ENGINE_INTERNAL', 1);
/**
* Base value for the mcrypt implementation $engine switch
*/
define('CRYPT_ENGINE_MCRYPT', 2);
/**
* Base value for the OpenSSL implementation $engine switch
*/
define('CRYPT_ENGINE_OPENSSL', 3);
/**#@-*/
/**
* Base Class for all Crypt_* cipher classes
*
* @package Crypt_Base
* @author Jim Wigginton
* @author Hans-Juergen Petrich
* @access public
*/
class Crypt_Base
{
/**
* The Encryption Mode
*
* @see self::Crypt_Base()
* @var int
* @access private
*/
var $mode;
/**
* The Block Length of the block cipher
*
* @var int
* @access private
*/
var $block_size = 16;
/**
* The Key
*
* @see self::setKey()
* @var string
* @access private
*/
var $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
/**
* The Initialization Vector
*
* @see self::setIV()
* @var string
* @access private
*/
var $iv;
/**
* A "sliding" Initialization Vector
*
* @see self::enableContinuousBuffer()
* @see self::_clearBuffers()
* @var string
* @access private
*/
var $encryptIV;
/**
* A "sliding" Initialization Vector
*
* @see self::enableContinuousBuffer()
* @see self::_clearBuffers()
* @var string
* @access private
*/
var $decryptIV;
/**
* Continuous Buffer status
*
* @see self::enableContinuousBuffer()
* @var bool
* @access private
*/
var $continuousBuffer = false;
/**
* Encryption buffer for CTR, OFB and CFB modes
*
* @see self::encrypt()
* @see self::_clearBuffers()
* @var array
* @access private
*/
var $enbuffer;
/**
* Decryption buffer for CTR, OFB and CFB modes
*
* @see self::decrypt()
* @see self::_clearBuffers()
* @var array
* @access private
*/
var $debuffer;
/**
* mcrypt resource for encryption
*
* The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
* Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
*
* @see self::encrypt()
* @var resource
* @access private
*/
var $enmcrypt;
/**
* mcrypt resource for decryption
*
* The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
* Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
*
* @see self::decrypt()
* @var resource
* @access private
*/
var $demcrypt;
/**
* Does the enmcrypt resource need to be (re)initialized?
*
* @see Crypt_Twofish::setKey()
* @see Crypt_Twofish::setIV()
* @var bool
* @access private
*/
var $enchanged = true;
/**
* Does the demcrypt resource need to be (re)initialized?
*
* @see Crypt_Twofish::setKey()
* @see Crypt_Twofish::setIV()
* @var bool
* @access private
*/
var $dechanged = true;
/**
* mcrypt resource for CFB mode
*
* mcrypt's CFB mode, in (and only in) buffered context,
* is broken, so phpseclib implements the CFB mode by it self,
* even when the mcrypt php extension is available.
*
* In order to do the CFB-mode work (fast) phpseclib
* use a separate ECB-mode mcrypt resource.
*
* @link http://phpseclib.sourceforge.net/cfb-demo.phps
* @see self::encrypt()
* @see self::decrypt()
* @see self::_setupMcrypt()
* @var resource
* @access private
*/
var $ecb;
/**
* Optimizing value while CFB-encrypting
*
* Only relevant if $continuousBuffer enabled
* and $engine == CRYPT_ENGINE_MCRYPT
*
* It's faster to re-init $enmcrypt if
* $buffer bytes > $cfb_init_len than
* using the $ecb resource furthermore.
*
* This value depends of the chosen cipher
* and the time it would be needed for it's
* initialization [by mcrypt_generic_init()]
* which, typically, depends on the complexity
* on its internaly Key-expanding algorithm.
*
* @see self::encrypt()
* @var int
* @access private
*/
var $cfb_init_len = 600;
/**
* Does internal cipher state need to be (re)initialized?
*
* @see self::setKey()
* @see self::setIV()
* @see self::disableContinuousBuffer()
* @var bool
* @access private
*/
var $changed = true;
/**
* Padding status
*
* @see self::enablePadding()
* @var bool
* @access private
*/
var $padding = true;
/**
* Is the mode one that is paddable?
*
* @see self::Crypt_Base()
* @var bool
* @access private
*/
var $paddable = false;
/**
* Holds which crypt engine internaly should be use,
* which will be determined automatically on __construct()
*
* Currently available $engines are:
* - CRYPT_ENGINE_OPENSSL (very fast, php-extension: openssl, extension_loaded('openssl') required)
* - CRYPT_ENGINE_MCRYPT (fast, php-extension: mcrypt, extension_loaded('mcrypt') required)
* - CRYPT_ENGINE_INTERNAL (slower, pure php-engine, no php-extension required)
*
* @see self::_setEngine()
* @see self::encrypt()
* @see self::decrypt()
* @var int
* @access private
*/
var $engine;
/**
* Holds the preferred crypt engine
*
* @see self::_setEngine()
* @see self::setPreferredEngine()
* @var int
* @access private
*/
var $preferredEngine;
/**
* The mcrypt specific name of the cipher
*
* Only used if $engine == CRYPT_ENGINE_MCRYPT
*
* @link http://www.php.net/mcrypt_module_open
* @link http://www.php.net/mcrypt_list_algorithms
* @see self::_setupMcrypt()
* @var string
* @access private
*/
var $cipher_name_mcrypt;
/**
* The openssl specific name of the cipher
*
* Only used if $engine == CRYPT_ENGINE_OPENSSL
*
* @link http://www.php.net/openssl-get-cipher-methods
* @var string
* @access private
*/
var $cipher_name_openssl;
/**
* The openssl specific name of the cipher in ECB mode
*
* If OpenSSL does not support the mode we're trying to use (CTR)
* it can still be emulated with ECB mode.
*
* @link http://www.php.net/openssl-get-cipher-methods
* @var string
* @access private
*/
var $cipher_name_openssl_ecb;
/**
* The default salt used by setPassword()
*
* @see self::setPassword()
* @var string
* @access private
*/
var $password_default_salt = 'phpseclib/salt';
/**
* The namespace used by the cipher for its constants.
*
* ie: AES.php is using CRYPT_AES_MODE_* for its constants
* so $const_namespace is AES
*
* DES.php is using CRYPT_DES_MODE_* for its constants
* so $const_namespace is DES... and so on
*
* All CRYPT_<$const_namespace>_MODE_* are aliases of
* the generic CRYPT_MODE_* constants, so both could be used
* for each cipher.
*
* Example:
* $aes = new Crypt_AES(CRYPT_AES_MODE_CFB); // $aes will operate in cfb mode
* $aes = new Crypt_AES(CRYPT_MODE_CFB); // identical
*
* @see self::Crypt_Base()
* @var string
* @access private
*/
var $const_namespace;
/**
* The name of the performance-optimized callback function
*
* Used by encrypt() / decrypt()
* only if $engine == CRYPT_ENGINE_INTERNAL
*
* @see self::encrypt()
* @see self::decrypt()
* @see self::_setupInlineCrypt()
* @see self::$use_inline_crypt
* @var Callback
* @access private
*/
var $inline_crypt;
/**
* Holds whether performance-optimized $inline_crypt() can/should be used.
*
* @see self::encrypt()
* @see self::decrypt()
* @see self::inline_crypt
* @var mixed
* @access private
*/
var $use_inline_crypt;
/**
* If OpenSSL can be used in ECB but not in CTR we can emulate CTR
*
* @see self::_openssl_ctr_process()
* @var bool
* @access private
*/
var $openssl_emulate_ctr = false;
/**
* Determines what options are passed to openssl_encrypt/decrypt
*
* @see self::isValidEngine()
* @var mixed
* @access private
*/
var $openssl_options;
/**
* Has the key length explicitly been set or should it be derived from the key, itself?
*
* @see self::setKeyLength()
* @var bool
* @access private
*/
var $explicit_key_length = false;
/**
* Don't truncate / null pad key
*
* @see self::_clearBuffers()
* @var bool
* @access private
*/
var $skip_key_adjustment = false;
/**
* Default Constructor.
*
* Determines whether or not the mcrypt extension should be used.
*
* $mode could be:
*
* - CRYPT_MODE_ECB
*
* - CRYPT_MODE_CBC
*
* - CRYPT_MODE_CTR
*
* - CRYPT_MODE_CFB
*
* - CRYPT_MODE_OFB
*
* (or the alias constants of the chosen cipher, for example for AES: CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC ...)
*
* If not explicitly set, CRYPT_MODE_CBC will be used.
*
* @param int $mode
* @access public
*/
function __construct($mode = CRYPT_MODE_CBC)
{
// $mode dependent settings
switch ($mode) {
case CRYPT_MODE_ECB:
$this->paddable = true;
$this->mode = CRYPT_MODE_ECB;
break;
case CRYPT_MODE_CTR:
case CRYPT_MODE_CFB:
case CRYPT_MODE_OFB:
case CRYPT_MODE_STREAM:
$this->mode = $mode;
break;
case CRYPT_MODE_CBC:
default:
$this->paddable = true;
$this->mode = CRYPT_MODE_CBC;
}
$this->_setEngine();
// Determining whether inline crypting can be used by the cipher
if ($this->use_inline_crypt !== false && function_exists('create_function')) {
$this->use_inline_crypt = true;
}
}
/**
* PHP4 compatible Default Constructor.
*
* @see self::__construct()
* @param int $mode
* @access public
*/
function Crypt_Base($mode = CRYPT_MODE_CBC)
{
$this->__construct($mode);
}
/**
* Sets the initialization vector. (optional)
*
* SetIV is not required when CRYPT_MODE_ECB (or ie for AES: CRYPT_AES_MODE_ECB) is being used. If not explicitly set, it'll be assumed
* to be all zero's.
*
* @access public
* @param string $iv
* @internal Can be overwritten by a sub class, but does not have to be
*/
function setIV($iv)
{
if ($this->mode == CRYPT_MODE_ECB) {
return;
}
$this->iv = $iv;
$this->changed = true;
}
/**
* Sets the key length.
*
* Keys with explicitly set lengths need to be treated accordingly
*
* @access public
* @param int $length
*/
function setKeyLength($length)
{
$this->explicit_key_length = true;
$this->changed = true;
$this->_setEngine();
}
/**
* Returns the current key length in bits
*
* @access public
* @return int
*/
function getKeyLength()
{
return $this->key_length << 3;
}
/**
* Returns the current block length in bits
*
* @access public
* @return int
*/
function getBlockLength()
{
return $this->block_size << 3;
}
/**
* Sets the key.
*
* The min/max length(s) of the key depends on the cipher which is used.
* If the key not fits the length(s) of the cipher it will paded with null bytes
* up to the closest valid key length. If the key is more than max length,
* we trim the excess bits.
*
* If the key is not explicitly set, it'll be assumed to be all null bytes.
*
* @access public
* @param string $key
* @internal Could, but not must, extend by the child Crypt_* class
*/
function setKey($key)
{
if (!$this->explicit_key_length) {
$this->setKeyLength(strlen($key) << 3);
$this->explicit_key_length = false;
}
$this->key = $key;
$this->changed = true;
$this->_setEngine();
}
/**
* Sets the password.
*
* Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
* {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2} or pbkdf1:
* $hash, $salt, $count, $dkLen
*
* Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php
*
* @see Crypt/Hash.php
* @param string $password
* @param string $method
* @return bool
* @access public
* @internal Could, but not must, extend by the child Crypt_* class
*/
function setPassword($password, $method = 'pbkdf2')
{
$key = '';
switch ($method) {
default: // 'pbkdf2' or 'pbkdf1'
$func_args = func_get_args();
// Hash function
$hash = isset($func_args[2]) ? $func_args[2] : 'sha1';
// WPA and WPA2 use the SSID as the salt
$salt = isset($func_args[3]) ? $func_args[3] : $this->password_default_salt;
// RFC2898#section-4.2 uses 1,000 iterations by default
// WPA and WPA2 use 4,096.
$count = isset($func_args[4]) ? $func_args[4] : 1000;
// Keylength
if (isset($func_args[5])) {
$dkLen = $func_args[5];
} else {
$dkLen = $method == 'pbkdf1' ? 2 * $this->key_length : $this->key_length;
}
switch (true) {
case $method == 'pbkdf1':
if (!class_exists('Crypt_Hash')) {
include_once 'Crypt/Hash.php';
}
$hashObj = new Crypt_Hash();
$hashObj->setHash($hash);
if ($dkLen > $hashObj->getLength()) {
user_error('Derived key too long');
return false;
}
$t = $password . $salt;
for ($i = 0; $i < $count; ++$i) {
$t = $hashObj->hash($t);
}
$key = substr($t, 0, $dkLen);
$this->setKey(substr($key, 0, $dkLen >> 1));
$this->setIV(substr($key, $dkLen >> 1));
return true;
// Determining if php[>=5.5.0]'s hash_pbkdf2() function avail- and useable
case !function_exists('hash_pbkdf2'):
case !function_exists('hash_algos'):
case !in_array($hash, hash_algos()):
if (!class_exists('Crypt_Hash')) {
include_once 'Crypt/Hash.php';
}
$i = 1;
while (strlen($key) < $dkLen) {
$hmac = new Crypt_Hash();
$hmac->setHash($hash);
$hmac->setKey($password);
$f = $u = $hmac->hash($salt . pack('N', $i++));
for ($j = 2; $j <= $count; ++$j) {
$u = $hmac->hash($u);
$f^= $u;
}
$key.= $f;
}
$key = substr($key, 0, $dkLen);
break;
default:
$key = hash_pbkdf2($hash, $password, $salt, $count, $dkLen, true);
}
}
$this->setKey($key);
return true;
}
/**
* Encrypts a message.
*
* $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other cipher
* implementations may or may not pad in the same manner. Other common approaches to padding and the reasons why it's
* necessary are discussed in the following
* URL:
*
* {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
*
* An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
* strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that
* length.
*
* @see self::decrypt()
* @access public
* @param string $plaintext
* @return string $ciphertext
* @internal Could, but not must, extend by the child Crypt_* class
*/
function encrypt($plaintext)
{
if ($this->paddable) {
$plaintext = $this->_pad($plaintext);
}
if ($this->engine === CRYPT_ENGINE_OPENSSL) {
if ($this->changed) {
$this->_clearBuffers();
$this->changed = false;
}
switch ($this->mode) {
case CRYPT_MODE_STREAM:
return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
case CRYPT_MODE_ECB:
$result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
return !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result;
case CRYPT_MODE_CBC:
$result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->encryptIV);
if (!defined('OPENSSL_RAW_DATA')) {
$result = substr($result, 0, -$this->block_size);
}
if ($this->continuousBuffer) {
$this->encryptIV = substr($result, -$this->block_size);
}
return $result;
case CRYPT_MODE_CTR:
return $this->_openssl_ctr_process($plaintext, $this->encryptIV, $this->enbuffer);
case CRYPT_MODE_CFB:
// cfb loosely routines inspired by openssl's:
// {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
$ciphertext = '';
if ($this->continuousBuffer) {
$iv = &$this->encryptIV;
$pos = &$this->enbuffer['pos'];
} else {
$iv = $this->encryptIV;
$pos = 0;
}
$len = strlen($plaintext);
$i = 0;
if ($pos) {
$orig_pos = $pos;
$max = $this->block_size - $pos;
if ($len >= $max) {
$i = $max;
$len-= $max;
$pos = 0;
} else {
$i = $len;
$pos+= $len;
$len = 0;
}
// ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
$ciphertext = substr($iv, $orig_pos) ^ $plaintext;
$iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
$plaintext = substr($plaintext, $i);
}
$overflow = $len % $this->block_size;
if ($overflow) {
$ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
$iv = $this->_string_pop($ciphertext, $this->block_size);
$size = $len - $overflow;
$block = $iv ^ substr($plaintext, -$overflow);
$iv = substr_replace($iv, $block, 0, $overflow);
$ciphertext.= $block;
$pos = $overflow;
} elseif ($len) {
$ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
$iv = substr($ciphertext, -$this->block_size);
}
return $ciphertext;
case CRYPT_MODE_OFB:
return $this->_openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer);
}
}
if ($this->engine === CRYPT_ENGINE_MCRYPT) {
if ($this->changed) {
$this->_setupMcrypt();
$this->changed = false;
}
if ($this->enchanged) {
@mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
$this->enchanged = false;
}
// re: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
// using mcrypt's default handing of CFB the above would output two different things. using phpseclib's
// rewritten CFB implementation the above outputs the same thing twice.
if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) {
$block_size = $this->block_size;
$iv = &$this->encryptIV;
$pos = &$this->enbuffer['pos'];
$len = strlen($plaintext);
$ciphertext = '';
$i = 0;
if ($pos) {
$orig_pos = $pos;
$max = $block_size - $pos;
if ($len >= $max) {
$i = $max;
$len-= $max;
$pos = 0;
} else {
$i = $len;
$pos+= $len;
$len = 0;
}
$ciphertext = substr($iv, $orig_pos) ^ $plaintext;
$iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
$this->enbuffer['enmcrypt_init'] = true;
}
if ($len >= $block_size) {
if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) {
if ($this->enbuffer['enmcrypt_init'] === true) {
@mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
$this->enbuffer['enmcrypt_init'] = false;
}
$ciphertext.= @mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size));
$iv = substr($ciphertext, -$block_size);
$len%= $block_size;
} else {
while ($len >= $block_size) {
$iv = @mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size);
$ciphertext.= $iv;
$len-= $block_size;
$i+= $block_size;
}
}
}
if ($len) {
$iv = @mcrypt_generic($this->ecb, $iv);
$block = $iv ^ substr($plaintext, -$len);
$iv = substr_replace($iv, $block, 0, $len);
$ciphertext.= $block;
$pos = $len;
}
return $ciphertext;
}
$ciphertext = @mcrypt_generic($this->enmcrypt, $plaintext);
if (!$this->continuousBuffer) {
@mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
}
return $ciphertext;
}
if ($this->changed) {
$this->_setup();
$this->changed = false;
}
if ($this->use_inline_crypt) {
$inline = $this->inline_crypt;
return $inline('encrypt', $this, $plaintext);
}
$buffer = &$this->enbuffer;
$block_size = $this->block_size;
$ciphertext = '';
switch ($this->mode) {
case CRYPT_MODE_ECB:
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
$ciphertext.= $this->_encryptBlock(substr($plaintext, $i, $block_size));
}
break;
case CRYPT_MODE_CBC:
$xor = $this->encryptIV;
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
$block = substr($plaintext, $i, $block_size);
$block = $this->_encryptBlock($block ^ $xor);
$xor = $block;
$ciphertext.= $block;
}
if ($this->continuousBuffer) {
$this->encryptIV = $xor;
}
break;
case CRYPT_MODE_CTR:
$xor = $this->encryptIV;
if (strlen($buffer['ciphertext'])) {
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
$block = substr($plaintext, $i, $block_size);
if (strlen($block) > strlen($buffer['ciphertext'])) {
$buffer['ciphertext'].= $this->_encryptBlock($xor);
}
$this->_increment_str($xor);
$key = $this->_string_shift($buffer['ciphertext'], $block_size);
$ciphertext.= $block ^ $key;
}
} else {
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
$block = substr($plaintext, $i, $block_size);
$key = $this->_encryptBlock($xor);
$this->_increment_str($xor);
$ciphertext.= $block ^ $key;
}
}
if ($this->continuousBuffer) {
$this->encryptIV = $xor;
if ($start = strlen($plaintext) % $block_size) {
$buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
}
}
break;
case CRYPT_MODE_CFB:
// cfb loosely routines inspired by openssl's:
// {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
if ($this->continuousBuffer) {
$iv = &$this->encryptIV;
$pos = &$buffer['pos'];
} else {
$iv = $this->encryptIV;
$pos = 0;
}
$len = strlen($plaintext);
$i = 0;
if ($pos) {
$orig_pos = $pos;
$max = $block_size - $pos;
if ($len >= $max) {
$i = $max;
$len-= $max;
$pos = 0;
} else {
$i = $len;
$pos+= $len;
$len = 0;
}
// ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
$ciphertext = substr($iv, $orig_pos) ^ $plaintext;
$iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
}
while ($len >= $block_size) {
$iv = $this->_encryptBlock($iv) ^ substr($plaintext, $i, $block_size);
$ciphertext.= $iv;
$len-= $block_size;
$i+= $block_size;
}
if ($len) {
$iv = $this->_encryptBlock($iv);
$block = $iv ^ substr($plaintext, $i);
$iv = substr_replace($iv, $block, 0, $len);
$ciphertext.= $block;
$pos = $len;
}
break;
case CRYPT_MODE_OFB:
$xor = $this->encryptIV;
if (strlen($buffer['xor'])) {
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
$block = substr($plaintext, $i, $block_size);
if (strlen($block) > strlen($buffer['xor'])) {
$xor = $this->_encryptBlock($xor);
$buffer['xor'].= $xor;
}
$key = $this->_string_shift($buffer['xor'], $block_size);
$ciphertext.= $block ^ $key;
}
} else {
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
$xor = $this->_encryptBlock($xor);
$ciphertext.= substr($plaintext, $i, $block_size) ^ $xor;
}
$key = $xor;
}
if ($this->continuousBuffer) {
$this->encryptIV = $xor;
if ($start = strlen($plaintext) % $block_size) {
$buffer['xor'] = substr($key, $start) . $buffer['xor'];
}
}
break;
case CRYPT_MODE_STREAM:
$ciphertext = $this->_encryptBlock($plaintext);
break;
}
return $ciphertext;
}
/**
* Decrypts a message.
*
* If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until
* it is.
*
* @see self::encrypt()
* @access public
* @param string $ciphertext
* @return string $plaintext
* @internal Could, but not must, extend by the child Crypt_* class
*/
function decrypt($ciphertext)
{
if ($this->paddable) {
// we pad with chr(0) since that's what mcrypt_generic does. to quote from {@link http://www.php.net/function.mcrypt-generic}:
// "The data is padded with "\0" to make sure the length of the data is n * blocksize."
$ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($this->block_size - strlen($ciphertext) % $this->block_size) % $this->block_size, chr(0));
}
if ($this->engine === CRYPT_ENGINE_OPENSSL) {
if ($this->changed) {
$this->_clearBuffers();
$this->changed = false;
}
switch ($this->mode) {
case CRYPT_MODE_STREAM:
$plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
break;
case CRYPT_MODE_ECB:
if (!defined('OPENSSL_RAW_DATA')) {
$ciphertext.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $this->key, true);
}
$plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
break;
case CRYPT_MODE_CBC:
if (!defined('OPENSSL_RAW_DATA')) {
$padding = str_repeat(chr($this->block_size), $this->block_size) ^ substr($ciphertext, -$this->block_size);
$ciphertext.= substr(openssl_encrypt($padding, $this->cipher_name_openssl_ecb, $this->key, true), 0, $this->block_size);
$offset = 2 * $this->block_size;
} else {
$offset = $this->block_size;
}
$plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->decryptIV);
if ($this->continuousBuffer) {
$this->decryptIV = substr($ciphertext, -$offset, $this->block_size);
}
break;
case CRYPT_MODE_CTR:
$plaintext = $this->_openssl_ctr_process($ciphertext, $this->decryptIV, $this->debuffer);
break;
case CRYPT_MODE_CFB:
// cfb loosely routines inspired by openssl's:
// {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
$plaintext = '';
if ($this->continuousBuffer) {
$iv = &$this->decryptIV;
$pos = &$this->buffer['pos'];
} else {
$iv = $this->decryptIV;
$pos = 0;
}
$len = strlen($ciphertext);
$i = 0;
if ($pos) {
$orig_pos = $pos;
$max = $this->block_size - $pos;
if ($len >= $max) {
$i = $max;
$len-= $max;
$pos = 0;
} else {
$i = $len;
$pos+= $len;
$len = 0;
}
// ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $this->blocksize
$plaintext = substr($iv, $orig_pos) ^ $ciphertext;
$iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
$ciphertext = substr($ciphertext, $i);
}
$overflow = $len % $this->block_size;
if ($overflow) {
$plaintext.= openssl_decrypt(substr($ciphertext, 0, -$overflow), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
if ($len - $overflow) {
$iv = substr($ciphertext, -$overflow - $this->block_size, -$overflow);
}
$iv = openssl_encrypt(str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
$plaintext.= $iv ^ substr($ciphertext, -$overflow);
$iv = substr_replace($iv, substr($ciphertext, -$overflow), 0, $overflow);
$pos = $overflow;
} elseif ($len) {
$plaintext.= openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
$iv = substr($ciphertext, -$this->block_size);
}
break;
case CRYPT_MODE_OFB:
$plaintext = $this->_openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer);
}
return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
}
if ($this->engine === CRYPT_ENGINE_MCRYPT) {
$block_size = $this->block_size;
if ($this->changed) {
$this->_setupMcrypt();
$this->changed = false;
}
if ($this->dechanged) {
@mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
$this->dechanged = false;
}
if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) {
$iv = &$this->decryptIV;
$pos = &$this->debuffer['pos'];
$len = strlen($ciphertext);
$plaintext = '';
$i = 0;
if ($pos) {
$orig_pos = $pos;
$max = $block_size - $pos;
if ($len >= $max) {
$i = $max;
$len-= $max;
$pos = 0;
} else {
$i = $len;
$pos+= $len;
$len = 0;
}
// ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
$plaintext = substr($iv, $orig_pos) ^ $ciphertext;
$iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
}
if ($len >= $block_size) {
$cb = substr($ciphertext, $i, $len - $len % $block_size);
$plaintext.= @mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
$iv = substr($cb, -$block_size);
$len%= $block_size;
}
if ($len) {
$iv = @mcrypt_generic($this->ecb, $iv);
$plaintext.= $iv ^ substr($ciphertext, -$len);
$iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len);
$pos = $len;
}
return $plaintext;
}
$plaintext = @mdecrypt_generic($this->demcrypt, $ciphertext);
if (!$this->continuousBuffer) {
@mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
}
return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
}
if ($this->changed) {
$this->_setup();
$this->changed = false;
}
if ($this->use_inline_crypt) {
$inline = $this->inline_crypt;
return $inline('decrypt', $this, $ciphertext);
}
$block_size = $this->block_size;
$buffer = &$this->debuffer;
$plaintext = '';
switch ($this->mode) {
case CRYPT_MODE_ECB:
for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
$plaintext.= $this->_decryptBlock(substr($ciphertext, $i, $block_size));
}
break;
case CRYPT_MODE_CBC:
$xor = $this->decryptIV;
for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
$block = substr($ciphertext, $i, $block_size);
$plaintext.= $this->_decryptBlock($block) ^ $xor;
$xor = $block;
}
if ($this->continuousBuffer) {
$this->decryptIV = $xor;
}
break;
case CRYPT_MODE_CTR:
$xor = $this->decryptIV;
if (strlen($buffer['ciphertext'])) {
for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
$block = substr($ciphertext, $i, $block_size);
if (strlen($block) > strlen($buffer['ciphertext'])) {
$buffer['ciphertext'].= $this->_encryptBlock($xor);
$this->_increment_str($xor);
}
$key = $this->_string_shift($buffer['ciphertext'], $block_size);
$plaintext.= $block ^ $key;
}
} else {
for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
$block = substr($ciphertext, $i, $block_size);
$key = $this->_encryptBlock($xor);
$this->_increment_str($xor);
$plaintext.= $block ^ $key;
}
}
if ($this->continuousBuffer) {
$this->decryptIV = $xor;
if ($start = strlen($ciphertext) % $block_size) {
$buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
}
}
break;
case CRYPT_MODE_CFB:
if ($this->continuousBuffer) {
$iv = &$this->decryptIV;
$pos = &$buffer['pos'];
} else {
$iv = $this->decryptIV;
$pos = 0;
}
$len = strlen($ciphertext);
$i = 0;
if ($pos) {
$orig_pos = $pos;
$max = $block_size - $pos;
if ($len >= $max) {
$i = $max;
$len-= $max;
$pos = 0;
} else {
$i = $len;
$pos+= $len;
$len = 0;
}
// ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
$plaintext = substr($iv, $orig_pos) ^ $ciphertext;
$iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
}
while ($len >= $block_size) {
$iv = $this->_encryptBlock($iv);
$cb = substr($ciphertext, $i, $block_size);
$plaintext.= $iv ^ $cb;
$iv = $cb;
$len-= $block_size;
$i+= $block_size;
}
if ($len) {
$iv = $this->_encryptBlock($iv);
$plaintext.= $iv ^ substr($ciphertext, $i);
$iv = substr_replace($iv, substr($ciphertext, $i), 0, $len);
$pos = $len;
}
break;
case CRYPT_MODE_OFB:
$xor = $this->decryptIV;
if (strlen($buffer['xor'])) {
for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
$block = substr($ciphertext, $i, $block_size);
if (strlen($block) > strlen($buffer['xor'])) {
$xor = $this->_encryptBlock($xor);
$buffer['xor'].= $xor;
}
$key = $this->_string_shift($buffer['xor'], $block_size);
$plaintext.= $block ^ $key;
}
} else {
for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
$xor = $this->_encryptBlock($xor);
$plaintext.= substr($ciphertext, $i, $block_size) ^ $xor;
}
$key = $xor;
}
if ($this->continuousBuffer) {
$this->decryptIV = $xor;
if ($start = strlen($ciphertext) % $block_size) {
$buffer['xor'] = substr($key, $start) . $buffer['xor'];
}
}
break;
case CRYPT_MODE_STREAM:
$plaintext = $this->_decryptBlock($ciphertext);
break;
}
return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
}
/**
* OpenSSL CTR Processor
*
* PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
* for CTR is the same for both encrypting and decrypting this function is re-used by both Crypt_Base::encrypt()
* and Crypt_Base::decrypt(). Also, OpenSSL doesn't implement CTR for all of it's symmetric ciphers so this
* function will emulate CTR with ECB when necessary.
*
* @see self::encrypt()
* @see self::decrypt()
* @param string $plaintext
* @param string $encryptIV
* @param array $buffer
* @return string
* @access private
*/
function _openssl_ctr_process($plaintext, &$encryptIV, &$buffer)
{
$ciphertext = '';
$block_size = $this->block_size;
$key = $this->key;
if ($this->openssl_emulate_ctr) {
$xor = $encryptIV;
if (strlen($buffer['ciphertext'])) {
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
$block = substr($plaintext, $i, $block_size);
if (strlen($block) > strlen($buffer['ciphertext'])) {
$result = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
$result = !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result;
$buffer['ciphertext'].= $result;
}
$this->_increment_str($xor);
$otp = $this->_string_shift($buffer['ciphertext'], $block_size);
$ciphertext.= $block ^ $otp;
}
} else {
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
$block = substr($plaintext, $i, $block_size);
$otp = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
$otp = !defined('OPENSSL_RAW_DATA') ? substr($otp, 0, -$this->block_size) : $otp;
$this->_increment_str($xor);
$ciphertext.= $block ^ $otp;
}
}
if ($this->continuousBuffer) {
$encryptIV = $xor;
if ($start = strlen($plaintext) % $block_size) {
$buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
}
}
return $ciphertext;
}
if (strlen($buffer['ciphertext'])) {
$ciphertext = $plaintext ^ $this->_string_shift($buffer['ciphertext'], strlen($plaintext));
$plaintext = substr($plaintext, strlen($ciphertext));
if (!strlen($plaintext)) {
return $ciphertext;
}
}
$overflow = strlen($plaintext) % $block_size;
if ($overflow) {
$plaintext2 = $this->_string_pop($plaintext, $overflow); // ie. trim $plaintext to a multiple of $block_size and put rest of $plaintext in $plaintext2
$encrypted = openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
$temp = $this->_string_pop($encrypted, $block_size);
$ciphertext.= $encrypted . ($plaintext2 ^ $temp);
if ($this->continuousBuffer) {
$buffer['ciphertext'] = substr($temp, $overflow);
$encryptIV = $temp;
}
} elseif (!strlen($buffer['ciphertext'])) {
$ciphertext.= openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
$temp = $this->_string_pop($ciphertext, $block_size);
if ($this->continuousBuffer) {
$encryptIV = $temp;
}
}
if ($this->continuousBuffer) {
if (!defined('OPENSSL_RAW_DATA')) {
$encryptIV.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
}
$encryptIV = openssl_decrypt($encryptIV, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
if ($overflow) {
$this->_increment_str($encryptIV);
}
}
return $ciphertext;
}
/**
* OpenSSL OFB Processor
*
* PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
* for OFB is the same for both encrypting and decrypting this function is re-used by both Crypt_Base::encrypt()
* and Crypt_Base::decrypt().
*
* @see self::encrypt()
* @see self::decrypt()
* @param string $plaintext
* @param string $encryptIV
* @param array $buffer
* @return string
* @access private
*/
function _openssl_ofb_process($plaintext, &$encryptIV, &$buffer)
{
if (strlen($buffer['xor'])) {
$ciphertext = $plaintext ^ $buffer['xor'];
$buffer['xor'] = substr($buffer['xor'], strlen($ciphertext));
$plaintext = substr($plaintext, strlen($ciphertext));
} else {
$ciphertext = '';
}
$block_size = $this->block_size;
$len = strlen($plaintext);
$key = $this->key;
$overflow = $len % $block_size;
if (strlen($plaintext)) {
if ($overflow) {
$ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
$xor = $this->_string_pop($ciphertext, $block_size);
if ($this->continuousBuffer) {
$encryptIV = $xor;
}
$ciphertext.= $this->_string_shift($xor, $overflow) ^ substr($plaintext, -$overflow);
if ($this->continuousBuffer) {
$buffer['xor'] = $xor;
}
} else {
$ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
if ($this->continuousBuffer) {
$encryptIV = substr($ciphertext, -$block_size) ^ substr($plaintext, -$block_size);
}
}
}
return $ciphertext;
}
/**
* phpseclib <-> OpenSSL Mode Mapper
*
* May need to be overwritten by classes extending this one in some cases
*
* @return int
* @access private
*/
function _openssl_translate_mode()
{
switch ($this->mode) {
case CRYPT_MODE_ECB:
return 'ecb';
case CRYPT_MODE_CBC:
return 'cbc';
case CRYPT_MODE_CTR:
return 'ctr';
case CRYPT_MODE_CFB:
return 'cfb';
case CRYPT_MODE_OFB:
return 'ofb';
}
}
/**
* Pad "packets".
*
* Block ciphers working by encrypting between their specified [$this->]block_size at a time
* If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to
* pad the input so that it is of the proper length.
*
* Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH,
* where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
* away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
* transmitted separately)
*
* @see self::disablePadding()
* @access public
*/
function enablePadding()
{
$this->padding = true;
}
/**
* Do not pad packets.
*
* @see self::enablePadding()
* @access public
*/
function disablePadding()
{
$this->padding = false;
}
/**
* Treat consecutive "packets" as if they are a continuous buffer.
*
* Say you have a 32-byte plaintext $plaintext. Using the default behavior, the two following code snippets
* will yield different outputs:
*
*
* echo $rijndael->encrypt(substr($plaintext, 0, 16));
* echo $rijndael->encrypt(substr($plaintext, 16, 16));
*
*
* echo $rijndael->encrypt($plaintext);
*
*
* The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
* another, as demonstrated with the following:
*
*
* $rijndael->encrypt(substr($plaintext, 0, 16));
* echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
*
*
* echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
*
*
* With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
* outputs. The reason is due to the fact that the initialization vector's change after every encryption /
* decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
*
* Put another way, when the continuous buffer is enabled, the state of the Crypt_*() object changes after each
* encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
* continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
* however, they are also less intuitive and more likely to cause you problems.
*
* @see self::disableContinuousBuffer()
* @access public
* @internal Could, but not must, extend by the child Crypt_* class
*/
function enableContinuousBuffer()
{
if ($this->mode == CRYPT_MODE_ECB) {
return;
}
$this->continuousBuffer = true;
$this->_setEngine();
}
/**
* Treat consecutive packets as if they are a discontinuous buffer.
*
* The default behavior.
*
* @see self::enableContinuousBuffer()
* @access public
* @internal Could, but not must, extend by the child Crypt_* class
*/
function disableContinuousBuffer()
{
if ($this->mode == CRYPT_MODE_ECB) {
return;
}
if (!$this->continuousBuffer) {
return;
}
$this->continuousBuffer = false;
$this->changed = true;
$this->_setEngine();
}
/**
* Test for engine validity
*
* @see self::Crypt_Base()
* @param int $engine
* @access public
* @return bool
*/
function isValidEngine($engine)
{
switch ($engine) {
case CRYPT_ENGINE_OPENSSL:
if ($this->mode == CRYPT_MODE_STREAM && $this->continuousBuffer) {
return false;
}
$this->openssl_emulate_ctr = false;
$result = $this->cipher_name_openssl &&
extension_loaded('openssl') &&
// PHP 5.3.0 - 5.3.2 did not let you set IV's
version_compare(PHP_VERSION, '5.3.3', '>=');
if (!$result) {
return false;
}
// prior to PHP 5.4.0 OPENSSL_RAW_DATA and OPENSSL_ZERO_PADDING were not defined. instead of expecting an integer
// $options openssl_encrypt expected a boolean $raw_data.
if (!defined('OPENSSL_RAW_DATA')) {
$this->openssl_options = true;
} else {
$this->openssl_options = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING;
}
$methods = openssl_get_cipher_methods();
if (in_array($this->cipher_name_openssl, $methods)) {
return true;
}
// not all of openssl's symmetric cipher's support ctr. for those
// that don't we'll emulate it
switch ($this->mode) {
case CRYPT_MODE_CTR:
if (in_array($this->cipher_name_openssl_ecb, $methods)) {
$this->openssl_emulate_ctr = true;
return true;
}
}
return false;
case CRYPT_ENGINE_MCRYPT:
return $this->cipher_name_mcrypt &&
extension_loaded('mcrypt') &&
in_array($this->cipher_name_mcrypt, @mcrypt_list_algorithms());
case CRYPT_ENGINE_INTERNAL:
return true;
}
return false;
}
/**
* Sets the preferred crypt engine
*
* Currently, $engine could be:
*
* - CRYPT_ENGINE_OPENSSL [very fast]
*
* - CRYPT_ENGINE_MCRYPT [fast]
*
* - CRYPT_ENGINE_INTERNAL [slow]
*
* If the preferred crypt engine is not available the fastest available one will be used
*
* @see self::Crypt_Base()
* @param int $engine
* @access public
*/
function setPreferredEngine($engine)
{
switch ($engine) {
//case CRYPT_ENGINE_OPENSSL:
case CRYPT_ENGINE_MCRYPT:
case CRYPT_ENGINE_INTERNAL:
$this->preferredEngine = $engine;
break;
default:
$this->preferredEngine = CRYPT_ENGINE_OPENSSL;
}
$this->_setEngine();
}
/**
* Returns the engine currently being utilized
*
* @see self::_setEngine()
* @access public
*/
function getEngine()
{
return $this->engine;
}
/**
* Sets the engine as appropriate
*
* @see self::Crypt_Base()
* @access private
*/
function _setEngine()
{
$this->engine = null;
$candidateEngines = array(
$this->preferredEngine,
CRYPT_ENGINE_OPENSSL,
CRYPT_ENGINE_MCRYPT
);
foreach ($candidateEngines as $engine) {
if ($this->isValidEngine($engine)) {
$this->engine = $engine;
break;
}
}
if (!$this->engine) {
$this->engine = CRYPT_ENGINE_INTERNAL;
}
if ($this->engine != CRYPT_ENGINE_MCRYPT && $this->enmcrypt) {
// Closing the current mcrypt resource(s). _mcryptSetup() will, if needed,
// (re)open them with the module named in $this->cipher_name_mcrypt
@mcrypt_module_close($this->enmcrypt);
@mcrypt_module_close($this->demcrypt);
$this->enmcrypt = null;
$this->demcrypt = null;
if ($this->ecb) {
@mcrypt_module_close($this->ecb);
$this->ecb = null;
}
}
$this->changed = true;
}
/**
* Encrypts a block
*
* @access private
* @param string $in
* @return string
* @internal Must be extended by the child Crypt_* class
*/
function _encryptBlock($in)
{
user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR);
}
/**
* Decrypts a block
*
* @access private
* @param string $in
* @return string
* @internal Must be extended by the child Crypt_* class
*/
function _decryptBlock($in)
{
user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR);
}
/**
* Setup the key (expansion)
*
* Only used if $engine == CRYPT_ENGINE_INTERNAL
*
* @see self::_setup()
* @access private
* @internal Must be extended by the child Crypt_* class
*/
function _setupKey()
{
user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR);
}
/**
* Setup the CRYPT_ENGINE_INTERNAL $engine
*
* (re)init, if necessary, the internal cipher $engine and flush all $buffers
* Used (only) if $engine == CRYPT_ENGINE_INTERNAL
*
* _setup() will be called each time if $changed === true
* typically this happens when using one or more of following public methods:
*
* - setKey()
*
* - setIV()
*
* - disableContinuousBuffer()
*
* - First run of encrypt() / decrypt() with no init-settings
*
* @see self::setKey()
* @see self::setIV()
* @see self::disableContinuousBuffer()
* @access private
* @internal _setup() is always called before en/decryption.
* @internal Could, but not must, extend by the child Crypt_* class
*/
function _setup()
{
$this->_clearBuffers();
$this->_setupKey();
if ($this->use_inline_crypt) {
$this->_setupInlineCrypt();
}
}
/**
* Setup the CRYPT_ENGINE_MCRYPT $engine
*
* (re)init, if necessary, the (ext)mcrypt resources and flush all $buffers
* Used (only) if $engine = CRYPT_ENGINE_MCRYPT
*
* _setupMcrypt() will be called each time if $changed === true
* typically this happens when using one or more of following public methods:
*
* - setKey()
*
* - setIV()
*
* - disableContinuousBuffer()
*
* - First run of encrypt() / decrypt()
*
* @see self::setKey()
* @see self::setIV()
* @see self::disableContinuousBuffer()
* @access private
* @internal Could, but not must, extend by the child Crypt_* class
*/
function _setupMcrypt()
{
$this->_clearBuffers();
$this->enchanged = $this->dechanged = true;
if (!isset($this->enmcrypt)) {
static $mcrypt_modes = array(
CRYPT_MODE_CTR => 'ctr',
CRYPT_MODE_ECB => MCRYPT_MODE_ECB,
CRYPT_MODE_CBC => MCRYPT_MODE_CBC,
CRYPT_MODE_CFB => 'ncfb',
CRYPT_MODE_OFB => MCRYPT_MODE_NOFB,
CRYPT_MODE_STREAM => MCRYPT_MODE_STREAM,
);
$this->demcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
$this->enmcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
// we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer()
// to workaround mcrypt's broken ncfb implementation in buffered mode
// see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
if ($this->mode == CRYPT_MODE_CFB) {
$this->ecb = @mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, '');
}
} // else should mcrypt_generic_deinit be called?
if ($this->mode == CRYPT_MODE_CFB) {
@mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size));
}
}
/**
* Pads a string
*
* Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize.
* $this->block_size - (strlen($text) % $this->block_size) bytes are added, each of which is equal to
* chr($this->block_size - (strlen($text) % $this->block_size)
*
* If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
* and padding will, hence forth, be enabled.
*
* @see self::_unpad()
* @param string $text
* @access private
* @return string
*/
function _pad($text)
{
$length = strlen($text);
if (!$this->padding) {
if ($length % $this->block_size == 0) {
return $text;
} else {
user_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})");
$this->padding = true;
}
}
$pad = $this->block_size - ($length % $this->block_size);
return str_pad($text, $length + $pad, chr($pad));
}
/**
* Unpads a string.
*
* If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
* and false will be returned.
*
* @see self::_pad()
* @param string $text
* @access private
* @return string
*/
function _unpad($text)
{
if (!$this->padding) {
return $text;
}
$length = ord($text[strlen($text) - 1]);
if (!$length || $length > $this->block_size) {
return false;
}
return substr($text, 0, -$length);
}
/**
* Clears internal buffers
*
* Clearing/resetting the internal buffers is done everytime
* after disableContinuousBuffer() or on cipher $engine (re)init
* ie after setKey() or setIV()
*
* @access public
* @internal Could, but not must, extend by the child Crypt_* class
*/
function _clearBuffers()
{
$this->enbuffer = $this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
// mcrypt's handling of invalid's $iv:
// $this->encryptIV = $this->decryptIV = strlen($this->iv) == $this->block_size ? $this->iv : str_repeat("\0", $this->block_size);
$this->encryptIV = $this->decryptIV = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, "\0");
if (!$this->skip_key_adjustment) {
$this->key = str_pad(substr($this->key, 0, $this->key_length), $this->key_length, "\0");
}
}
/**
* String Shift
*
* Inspired by array_shift
*
* @param string $string
* @param int $index
* @access private
* @return string
*/
function _string_shift(&$string, $index = 1)
{
$substr = substr($string, 0, $index);
$string = substr($string, $index);
return $substr;
}
/**
* String Pop
*
* Inspired by array_pop
*
* @param string $string
* @param int $index
* @access private
* @return string
*/
function _string_pop(&$string, $index = 1)
{
$substr = substr($string, -$index);
$string = substr($string, 0, -$index);
return $substr;
}
/**
* Increment the current string
*
* @see self::decrypt()
* @see self::encrypt()
* @param string $var
* @access private
*/
function _increment_str(&$var)
{
for ($i = 4; $i <= strlen($var); $i+= 4) {
$temp = substr($var, -$i, 4);
switch ($temp) {
case "\xFF\xFF\xFF\xFF":
$var = substr_replace($var, "\x00\x00\x00\x00", -$i, 4);
break;
case "\x7F\xFF\xFF\xFF":
$var = substr_replace($var, "\x80\x00\x00\x00", -$i, 4);
return;
default:
$temp = unpack('Nnum', $temp);
$var = substr_replace($var, pack('N', $temp['num'] + 1), -$i, 4);
return;
}
}
$remainder = strlen($var) % 4;
if ($remainder == 0) {
return;
}
$temp = unpack('Nnum', str_pad(substr($var, 0, $remainder), 4, "\0", STR_PAD_LEFT));
$temp = substr(pack('N', $temp['num'] + 1), -$remainder);
$var = substr_replace($var, $temp, 0, $remainder);
}
/**
* Setup the performance-optimized function for de/encrypt()
*
* Stores the created (or existing) callback function-name
* in $this->inline_crypt
*
* Internally for phpseclib developers:
*
* _setupInlineCrypt() would be called only if:
*
* - $engine == CRYPT_ENGINE_INTERNAL and
*
* - $use_inline_crypt === true
*
* - each time on _setup(), after(!) _setupKey()
*
*
* This ensures that _setupInlineCrypt() has always a
* full ready2go initializated internal cipher $engine state
* where, for example, the keys allready expanded,
* keys/block_size calculated and such.
*
* It is, each time if called, the responsibility of _setupInlineCrypt():
*
* - to set $this->inline_crypt to a valid and fully working callback function
* as a (faster) replacement for encrypt() / decrypt()
*
* - NOT to create unlimited callback functions (for memory reasons!)
* no matter how often _setupInlineCrypt() would be called. At some
* point of amount they must be generic re-useable.
*
* - the code of _setupInlineCrypt() it self,
* and the generated callback code,
* must be, in following order:
* - 100% safe
* - 100% compatible to encrypt()/decrypt()
* - using only php5+ features/lang-constructs/php-extensions if
* compatibility (down to php4) or fallback is provided
* - readable/maintainable/understandable/commented and... not-cryptic-styled-code :-)
* - >= 10% faster than encrypt()/decrypt() [which is, by the way,
* the reason for the existence of _setupInlineCrypt() :-)]
* - memory-nice
* - short (as good as possible)
*
* Note: - _setupInlineCrypt() is using _createInlineCryptFunction() to create the full callback function code.
* - In case of using inline crypting, _setupInlineCrypt() must extend by the child Crypt_* class.
* - The following variable names are reserved:
* - $_* (all variable names prefixed with an underscore)
* - $self (object reference to it self. Do not use $this, but $self instead)
* - $in (the content of $in has to en/decrypt by the generated code)
* - The callback function should not use the 'return' statement, but en/decrypt'ing the content of $in only
*
*
* @see self::_setup()
* @see self::_createInlineCryptFunction()
* @see self::encrypt()
* @see self::decrypt()
* @access private
* @internal If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt()
*/
function _setupInlineCrypt()
{
// If, for any reason, an extending Crypt_Base() Crypt_* class
// not using inline crypting then it must be ensured that: $this->use_inline_crypt = false
// ie in the class var declaration of $use_inline_crypt in general for the Crypt_* class,
// in the constructor at object instance-time
// or, if it's runtime-specific, at runtime
$this->use_inline_crypt = false;
}
/**
* Creates the performance-optimized function for en/decrypt()
*
* Internally for phpseclib developers:
*
* _createInlineCryptFunction():
*
* - merge the $cipher_code [setup'ed by _setupInlineCrypt()]
* with the current [$this->]mode of operation code
*
* - create the $inline function, which called by encrypt() / decrypt()
* as its replacement to speed up the en/decryption operations.
*
* - return the name of the created $inline callback function
*
* - used to speed up en/decryption
*
*
*
* The main reason why can speed up things [up to 50%] this way are:
*
* - using variables more effective then regular.
* (ie no use of expensive arrays but integers $k_0, $k_1 ...
* or even, for example, the pure $key[] values hardcoded)
*
* - avoiding 1000's of function calls of ie _encryptBlock()
* but inlining the crypt operations.
* in the mode of operation for() loop.
*
* - full loop unroll the (sometimes key-dependent) rounds
* avoiding this way ++$i counters and runtime-if's etc...
*
* The basic code architectur of the generated $inline en/decrypt()
* lambda function, in pseudo php, is:
*
*
* +----------------------------------------------------------------------------------------------+
* | callback $inline = create_function: |
* | lambda_function_0001_crypt_ECB($action, $text) |
* | { |
* | INSERT PHP CODE OF: |
* | $cipher_code['init_crypt']; // general init code. |
* | // ie: $sbox'es declarations used for |
* | // encrypt and decrypt'ing. |
* | |
* | switch ($action) { |
* | case 'encrypt': |
* | INSERT PHP CODE OF: |
* | $cipher_code['init_encrypt']; // encrypt sepcific init code. |
* | ie: specified $key or $box |
* | declarations for encrypt'ing. |
* | |
* | foreach ($ciphertext) { |
* | $in = $block_size of $ciphertext; |
* | |
* | INSERT PHP CODE OF: |
* | $cipher_code['encrypt_block']; // encrypt's (string) $in, which is always: |
* | // strlen($in) == $this->block_size |
* | // here comes the cipher algorithm in action |
* | // for encryption. |
* | // $cipher_code['encrypt_block'] has to |
* | // encrypt the content of the $in variable |
* | |
* | $plaintext .= $in; |
* | } |
* | return $plaintext; |
* | |
* | case 'decrypt': |
* | INSERT PHP CODE OF: |
* | $cipher_code['init_decrypt']; // decrypt sepcific init code |
* | ie: specified $key or $box |
* | declarations for decrypt'ing. |
* | foreach ($plaintext) { |
* | $in = $block_size of $plaintext; |
* | |
* | INSERT PHP CODE OF: |
* | $cipher_code['decrypt_block']; // decrypt's (string) $in, which is always |
* | // strlen($in) == $this->block_size |
* | // here comes the cipher algorithm in action |
* | // for decryption. |
* | // $cipher_code['decrypt_block'] has to |
* | // decrypt the content of the $in variable |
* | $ciphertext .= $in; |
* | } |
* | return $ciphertext; |
* | } |
* | } |
* +----------------------------------------------------------------------------------------------+
*
*
* See also the Crypt_*::_setupInlineCrypt()'s for
* productive inline $cipher_code's how they works.
*
* Structure of:
*
* $cipher_code = array(
* 'init_crypt' => (string) '', // optional
* 'init_encrypt' => (string) '', // optional
* 'init_decrypt' => (string) '', // optional
* 'encrypt_block' => (string) '', // required
* 'decrypt_block' => (string) '' // required
* );
*
*
* @see self::_setupInlineCrypt()
* @see self::encrypt()
* @see self::decrypt()
* @param array $cipher_code
* @access private
* @return string (the name of the created callback function)
*/
function _createInlineCryptFunction($cipher_code)
{
$block_size = $this->block_size;
// optional
$init_crypt = isset($cipher_code['init_crypt']) ? $cipher_code['init_crypt'] : '';
$init_encrypt = isset($cipher_code['init_encrypt']) ? $cipher_code['init_encrypt'] : '';
$init_decrypt = isset($cipher_code['init_decrypt']) ? $cipher_code['init_decrypt'] : '';
// required
$encrypt_block = $cipher_code['encrypt_block'];
$decrypt_block = $cipher_code['decrypt_block'];
// Generating mode of operation inline code,
// merged with the $cipher_code algorithm
// for encrypt- and decryption.
switch ($this->mode) {
case CRYPT_MODE_ECB:
$encrypt = $init_encrypt . '
$_ciphertext = "";
$_plaintext_len = strlen($_text);
for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
$in = substr($_text, $_i, '.$block_size.');
'.$encrypt_block.'
$_ciphertext.= $in;
}
return $_ciphertext;
';
$decrypt = $init_decrypt . '
$_plaintext = "";
$_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
$_ciphertext_len = strlen($_text);
for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
$in = substr($_text, $_i, '.$block_size.');
'.$decrypt_block.'
$_plaintext.= $in;
}
return $self->_unpad($_plaintext);
';
break;
case CRYPT_MODE_CTR:
$encrypt = $init_encrypt . '
$_ciphertext = "";
$_plaintext_len = strlen($_text);
$_xor = $self->encryptIV;
$_buffer = &$self->enbuffer;
if (strlen($_buffer["ciphertext"])) {
for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
$_block = substr($_text, $_i, '.$block_size.');
if (strlen($_block) > strlen($_buffer["ciphertext"])) {
$in = $_xor;
'.$encrypt_block.'
$self->_increment_str($_xor);
$_buffer["ciphertext"].= $in;
}
$_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
$_ciphertext.= $_block ^ $_key;
}
} else {
for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
$_block = substr($_text, $_i, '.$block_size.');
$in = $_xor;
'.$encrypt_block.'
$self->_increment_str($_xor);
$_key = $in;
$_ciphertext.= $_block ^ $_key;
}
}
if ($self->continuousBuffer) {
$self->encryptIV = $_xor;
if ($_start = $_plaintext_len % '.$block_size.') {
$_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
}
}
return $_ciphertext;
';
$decrypt = $init_encrypt . '
$_plaintext = "";
$_ciphertext_len = strlen($_text);
$_xor = $self->decryptIV;
$_buffer = &$self->debuffer;
if (strlen($_buffer["ciphertext"])) {
for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
$_block = substr($_text, $_i, '.$block_size.');
if (strlen($_block) > strlen($_buffer["ciphertext"])) {
$in = $_xor;
'.$encrypt_block.'
$self->_increment_str($_xor);
$_buffer["ciphertext"].= $in;
}
$_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
$_plaintext.= $_block ^ $_key;
}
} else {
for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
$_block = substr($_text, $_i, '.$block_size.');
$in = $_xor;
'.$encrypt_block.'
$self->_increment_str($_xor);
$_key = $in;
$_plaintext.= $_block ^ $_key;
}
}
if ($self->continuousBuffer) {
$self->decryptIV = $_xor;
if ($_start = $_ciphertext_len % '.$block_size.') {
$_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
}
}
return $_plaintext;
';
break;
case CRYPT_MODE_CFB:
$encrypt = $init_encrypt . '
$_ciphertext = "";
$_buffer = &$self->enbuffer;
if ($self->continuousBuffer) {
$_iv = &$self->encryptIV;
$_pos = &$_buffer["pos"];
} else {
$_iv = $self->encryptIV;
$_pos = 0;
}
$_len = strlen($_text);
$_i = 0;
if ($_pos) {
$_orig_pos = $_pos;
$_max = '.$block_size.' - $_pos;
if ($_len >= $_max) {
$_i = $_max;
$_len-= $_max;
$_pos = 0;
} else {
$_i = $_len;
$_pos+= $_len;
$_len = 0;
}
$_ciphertext = substr($_iv, $_orig_pos) ^ $_text;
$_iv = substr_replace($_iv, $_ciphertext, $_orig_pos, $_i);
}
while ($_len >= '.$block_size.') {
$in = $_iv;
'.$encrypt_block.';
$_iv = $in ^ substr($_text, $_i, '.$block_size.');
$_ciphertext.= $_iv;
$_len-= '.$block_size.';
$_i+= '.$block_size.';
}
if ($_len) {
$in = $_iv;
'.$encrypt_block.'
$_iv = $in;
$_block = $_iv ^ substr($_text, $_i);
$_iv = substr_replace($_iv, $_block, 0, $_len);
$_ciphertext.= $_block;
$_pos = $_len;
}
return $_ciphertext;
';
$decrypt = $init_encrypt . '
$_plaintext = "";
$_buffer = &$self->debuffer;
if ($self->continuousBuffer) {
$_iv = &$self->decryptIV;
$_pos = &$_buffer["pos"];
} else {
$_iv = $self->decryptIV;
$_pos = 0;
}
$_len = strlen($_text);
$_i = 0;
if ($_pos) {
$_orig_pos = $_pos;
$_max = '.$block_size.' - $_pos;
if ($_len >= $_max) {
$_i = $_max;
$_len-= $_max;
$_pos = 0;
} else {
$_i = $_len;
$_pos+= $_len;
$_len = 0;
}
$_plaintext = substr($_iv, $_orig_pos) ^ $_text;
$_iv = substr_replace($_iv, substr($_text, 0, $_i), $_orig_pos, $_i);
}
while ($_len >= '.$block_size.') {
$in = $_iv;
'.$encrypt_block.'
$_iv = $in;
$cb = substr($_text, $_i, '.$block_size.');
$_plaintext.= $_iv ^ $cb;
$_iv = $cb;
$_len-= '.$block_size.';
$_i+= '.$block_size.';
}
if ($_len) {
$in = $_iv;
'.$encrypt_block.'
$_iv = $in;
$_plaintext.= $_iv ^ substr($_text, $_i);
$_iv = substr_replace($_iv, substr($_text, $_i), 0, $_len);
$_pos = $_len;
}
return $_plaintext;
';
break;
case CRYPT_MODE_OFB:
$encrypt = $init_encrypt . '
$_ciphertext = "";
$_plaintext_len = strlen($_text);
$_xor = $self->encryptIV;
$_buffer = &$self->enbuffer;
if (strlen($_buffer["xor"])) {
for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
$_block = substr($_text, $_i, '.$block_size.');
if (strlen($_block) > strlen($_buffer["xor"])) {
$in = $_xor;
'.$encrypt_block.'
$_xor = $in;
$_buffer["xor"].= $_xor;
}
$_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
$_ciphertext.= $_block ^ $_key;
}
} else {
for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
$in = $_xor;
'.$encrypt_block.'
$_xor = $in;
$_ciphertext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
}
$_key = $_xor;
}
if ($self->continuousBuffer) {
$self->encryptIV = $_xor;
if ($_start = $_plaintext_len % '.$block_size.') {
$_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
}
}
return $_ciphertext;
';
$decrypt = $init_encrypt . '
$_plaintext = "";
$_ciphertext_len = strlen($_text);
$_xor = $self->decryptIV;
$_buffer = &$self->debuffer;
if (strlen($_buffer["xor"])) {
for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
$_block = substr($_text, $_i, '.$block_size.');
if (strlen($_block) > strlen($_buffer["xor"])) {
$in = $_xor;
'.$encrypt_block.'
$_xor = $in;
$_buffer["xor"].= $_xor;
}
$_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
$_plaintext.= $_block ^ $_key;
}
} else {
for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
$in = $_xor;
'.$encrypt_block.'
$_xor = $in;
$_plaintext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
}
$_key = $_xor;
}
if ($self->continuousBuffer) {
$self->decryptIV = $_xor;
if ($_start = $_ciphertext_len % '.$block_size.') {
$_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
}
}
return $_plaintext;
';
break;
case CRYPT_MODE_STREAM:
$encrypt = $init_encrypt . '
$_ciphertext = "";
'.$encrypt_block.'
return $_ciphertext;
';
$decrypt = $init_decrypt . '
$_plaintext = "";
'.$decrypt_block.'
return $_plaintext;
';
break;
// case CRYPT_MODE_CBC:
default:
$encrypt = $init_encrypt . '
$_ciphertext = "";
$_plaintext_len = strlen($_text);
$in = $self->encryptIV;
for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
$in = substr($_text, $_i, '.$block_size.') ^ $in;
'.$encrypt_block.'
$_ciphertext.= $in;
}
if ($self->continuousBuffer) {
$self->encryptIV = $in;
}
return $_ciphertext;
';
$decrypt = $init_decrypt . '
$_plaintext = "";
$_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
$_ciphertext_len = strlen($_text);
$_iv = $self->decryptIV;
for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
$in = $_block = substr($_text, $_i, '.$block_size.');
'.$decrypt_block.'
$_plaintext.= $in ^ $_iv;
$_iv = $_block;
}
if ($self->continuousBuffer) {
$self->decryptIV = $_iv;
}
return $self->_unpad($_plaintext);
';
break;
}
// Create the $inline function and return its name as string. Ready to run!
if(function_exists('create_function')){
return create_function('$_action, &$self, $_text', $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }');
}
eval('$func = function ($_action, &$self, $_text) { ' . $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' } };');
return $func;
}
/**
* Holds the lambda_functions table (classwide)
*
* Each name of the lambda function, created from
* _setupInlineCrypt() && _createInlineCryptFunction()
* is stored, classwide (!), here for reusing.
*
* The string-based index of $function is a classwide
* unique value representing, at least, the $mode of
* operation (or more... depends of the optimizing level)
* for which $mode the lambda function was created.
*
* @access private
* @return array &$functions
*/
function &_getLambdaFunctions()
{
static $functions = array();
return $functions;
}
/**
* Generates a digest from $bytes
*
* @see self::_setupInlineCrypt()
* @access private
* @param $bytes
* @return string
*/
function _hashInlineCryptFunction($bytes)
{
if (!defined('CRYPT_BASE_WHIRLPOOL_AVAILABLE')) {
define('CRYPT_BASE_WHIRLPOOL_AVAILABLE', (bool)(extension_loaded('hash') && in_array('whirlpool', hash_algos())));
}
$result = '';
$hash = $bytes;
switch (true) {
case CRYPT_BASE_WHIRLPOOL_AVAILABLE:
foreach (str_split($bytes, 64) as $t) {
$hash = hash('whirlpool', $hash, true);
$result .= $t ^ $hash;
}
return $result . hash('whirlpool', $hash, true);
default:
$len = strlen($bytes);
for ($i = 0; $i < $len; $i+=20) {
$t = substr($bytes, $i, 20);
$hash = pack('H*', sha1($hash));
$result .= $t ^ $hash;
}
return $result . pack('H*', sha1($hash));
}
}
}
define('CRYPT_RIJNDAEL_MODE_CTR', CRYPT_MODE_CTR);
/**
* Encrypt / decrypt using the Electronic Code Book mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
*/
define('CRYPT_RIJNDAEL_MODE_ECB', CRYPT_MODE_ECB);
/**
* Encrypt / decrypt using the Code Book Chaining mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
*/
define('CRYPT_RIJNDAEL_MODE_CBC', CRYPT_MODE_CBC);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
*/
define('CRYPT_RIJNDAEL_MODE_CFB', CRYPT_MODE_CFB);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
*/
define('CRYPT_RIJNDAEL_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/
/**
* Pure-PHP implementation of Rijndael.
*
* @package Crypt_Rijndael
* @author Jim Wigginton
* @access public
*/
class Crypt_Rijndael extends Crypt_Base
{
/**
* The namespace used by the cipher for its constants.
*
* @see Crypt_Base::const_namespace
* @var string
* @access private
*/
var $const_namespace = 'RIJNDAEL';
/**
* The mcrypt specific name of the cipher
*
* Mcrypt is useable for 128/192/256-bit $block_size/$key_length. For 160/224 not.
* Crypt_Rijndael determines automatically whether mcrypt is useable
* or not for the current $block_size/$key_length.
* In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly.
*
* @see Crypt_Base::cipher_name_mcrypt
* @see Crypt_Base::engine
* @see self::isValidEngine()
* @var string
* @access private
*/
var $cipher_name_mcrypt = 'rijndael-128';
/**
* The default salt used by setPassword()
*
* @see Crypt_Base::password_default_salt
* @see Crypt_Base::setPassword()
* @var string
* @access private
*/
var $password_default_salt = 'phpseclib';
/**
* The Key Schedule
*
* @see self::_setup()
* @var array
* @access private
*/
var $w;
/**
* The Inverse Key Schedule
*
* @see self::_setup()
* @var array
* @access private
*/
var $dw;
/**
* The Block Length divided by 32
*
* @see self::setBlockLength()
* @var int
* @access private
* @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4. Exists in conjunction with $block_size
* because the encryption / decryption / key schedule creation requires this number and not $block_size. We could
* derive this from $block_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
* of that, we'll just precompute it once.
*/
var $Nb = 4;
/**
* The Key Length (in bytes)
*
* @see self::setKeyLength()
* @var int
* @access private
* @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk
* because the encryption / decryption / key schedule creation requires this number and not $key_length. We could
* derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
* of that, we'll just precompute it once.
*/
var $key_length = 16;
/**
* The Key Length divided by 32
*
* @see self::setKeyLength()
* @var int
* @access private
* @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4
*/
var $Nk = 4;
/**
* The Number of Rounds
*
* @var int
* @access private
* @internal The max value is 14, the min value is 10.
*/
var $Nr;
/**
* Shift offsets
*
* @var array
* @access private
*/
var $c;
/**
* Holds the last used key- and block_size information
*
* @var array
* @access private
*/
var $kl;
/**
* Sets the key.
*
* Keys can be of any length. Rijndael, itself, requires the use of a key that's between 128-bits and 256-bits long and
* whose length is a multiple of 32. If the key is less than 256-bits and the key length isn't set, we round the length
* up to the closest valid key length, padding $key with null bytes. If the key is more than 256-bits, we trim the
* excess bits.
*
* If the key is not explicitly set, it'll be assumed to be all null bytes.
*
* Note: 160/224-bit keys must explicitly set by setKeyLength(), otherwise they will be round/pad up to 192/256 bits.
*
* @see Crypt_Base:setKey()
* @see self::setKeyLength()
* @access public
* @param string $key
*/
function setKey($key)
{
if (!$this->explicit_key_length) {
$length = strlen($key);
switch (true) {
case $length <= 16:
$this->key_size = 16;
break;
case $length <= 20:
$this->key_size = 20;
break;
case $length <= 24:
$this->key_size = 24;
break;
case $length <= 28:
$this->key_size = 28;
break;
default:
$this->key_size = 32;
}
}
parent::setKey($key);
}
/**
* Sets the key length
*
* Valid key lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to
* 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
*
* Note: phpseclib extends Rijndael (and AES) for using 160- and 224-bit keys but they are officially not defined
* and the most (if not all) implementations are not able using 160/224-bit keys but round/pad them up to
* 192/256 bits as, for example, mcrypt will do.
*
* That said, if you want be compatible with other Rijndael and AES implementations,
* you should not setKeyLength(160) or setKeyLength(224).
*
* Additional: In case of 160- and 224-bit keys, phpseclib will/can, for that reason, not use
* the mcrypt php extension, even if available.
* This results then in slower encryption.
*
* @access public
* @param int $length
*/
function setKeyLength($length)
{
switch (true) {
case $length <= 128:
$this->key_length = 16;
break;
case $length <= 160:
$this->key_length = 20;
break;
case $length <= 192:
$this->key_length = 24;
break;
case $length <= 224:
$this->key_length = 28;
break;
default:
$this->key_length = 32;
}
parent::setKeyLength($length);
}
/**
* Sets the block length
*
* Valid block lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to
* 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
*
* @access public
* @param int $length
*/
function setBlockLength($length)
{
$length >>= 5;
if ($length > 8) {
$length = 8;
} elseif ($length < 4) {
$length = 4;
}
$this->Nb = $length;
$this->block_size = $length << 2;
$this->changed = true;
$this->_setEngine();
}
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
*
* @see Crypt_Base::Crypt_Base()
* @param int $engine
* @access public
* @return bool
*/
function isValidEngine($engine)
{
switch ($engine) {
case CRYPT_ENGINE_OPENSSL:
if ($this->block_size != 16) {
return false;
}
$this->cipher_name_openssl_ecb = 'aes-' . ($this->key_length << 3) . '-ecb';
$this->cipher_name_openssl = 'aes-' . ($this->key_length << 3) . '-' . $this->_openssl_translate_mode();
break;
case CRYPT_ENGINE_MCRYPT:
$this->cipher_name_mcrypt = 'rijndael-' . ($this->block_size << 3);
if ($this->key_length % 8) { // is it a 160/224-bit key?
// mcrypt is not usable for them, only for 128/192/256-bit keys
return false;
}
}
return parent::isValidEngine($engine);
}
/**
* Encrypts a block
*
* @access private
* @param string $in
* @return string
*/
function _encryptBlock($in)
{
static $tables;
if (empty($tables)) {
$tables = &$this->_getTables();
}
$t0 = $tables[0];
$t1 = $tables[1];
$t2 = $tables[2];
$t3 = $tables[3];
$sbox = $tables[4];
$state = array();
$words = unpack('N*', $in);
$c = $this->c;
$w = $this->w;
$Nb = $this->Nb;
$Nr = $this->Nr;
// addRoundKey
$wc = $Nb - 1;
foreach ($words as $word) {
$state[] = $word ^ $w[++$wc];
}
// fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components -
// subBytes, shiftRows, mixColumns, and addRoundKey. fips-197.pdf#page=30, "Implementation Suggestions Regarding
// Various Platforms" suggests that performs enhanced implementations are described in Rijndael-ammended.pdf.
// Rijndael-ammended.pdf#page=20, "Implementation aspects / 32-bit processor", discusses such an optimization.
// Unfortunately, the description given there is not quite correct. Per aes.spec.v316.pdf#page=19 [1],
// equation (7.4.7) is supposed to use addition instead of subtraction, so we'll do that here, as well.
// [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf
$temp = array();
for ($round = 1; $round < $Nr; ++$round) {
$i = 0; // $c[0] == 0
$j = $c[1];
$k = $c[2];
$l = $c[3];
while ($i < $Nb) {
$temp[$i] = $t0[$state[$i] >> 24 & 0x000000FF] ^
$t1[$state[$j] >> 16 & 0x000000FF] ^
$t2[$state[$k] >> 8 & 0x000000FF] ^
$t3[$state[$l] & 0x000000FF] ^
$w[++$wc];
++$i;
$j = ($j + 1) % $Nb;
$k = ($k + 1) % $Nb;
$l = ($l + 1) % $Nb;
}
$state = $temp;
}
// subWord
for ($i = 0; $i < $Nb; ++$i) {
$state[$i] = $sbox[$state[$i] & 0x000000FF] |
($sbox[$state[$i] >> 8 & 0x000000FF] << 8) |
($sbox[$state[$i] >> 16 & 0x000000FF] << 16) |
($sbox[$state[$i] >> 24 & 0x000000FF] << 24);
}
// shiftRows + addRoundKey
$i = 0; // $c[0] == 0
$j = $c[1];
$k = $c[2];
$l = $c[3];
while ($i < $Nb) {
$temp[$i] = ($state[$i] & 0xFF000000) ^
($state[$j] & 0x00FF0000) ^
($state[$k] & 0x0000FF00) ^
($state[$l] & 0x000000FF) ^
$w[$i];
++$i;
$j = ($j + 1) % $Nb;
$k = ($k + 1) % $Nb;
$l = ($l + 1) % $Nb;
}
switch ($Nb) {
case 8:
return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);
case 7:
return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);
case 6:
return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);
case 5:
return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);
default:
return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]);
}
}
/**
* Decrypts a block
*
* @access private
* @param string $in
* @return string
*/
function _decryptBlock($in)
{
static $invtables;
if (empty($invtables)) {
$invtables = &$this->_getInvTables();
}
$dt0 = $invtables[0];
$dt1 = $invtables[1];
$dt2 = $invtables[2];
$dt3 = $invtables[3];
$isbox = $invtables[4];
$state = array();
$words = unpack('N*', $in);
$c = $this->c;
$dw = $this->dw;
$Nb = $this->Nb;
$Nr = $this->Nr;
// addRoundKey
$wc = $Nb - 1;
foreach ($words as $word) {
$state[] = $word ^ $dw[++$wc];
}
$temp = array();
for ($round = $Nr - 1; $round > 0; --$round) {
$i = 0; // $c[0] == 0
$j = $Nb - $c[1];
$k = $Nb - $c[2];
$l = $Nb - $c[3];
while ($i < $Nb) {
$temp[$i] = $dt0[$state[$i] >> 24 & 0x000000FF] ^
$dt1[$state[$j] >> 16 & 0x000000FF] ^
$dt2[$state[$k] >> 8 & 0x000000FF] ^
$dt3[$state[$l] & 0x000000FF] ^
$dw[++$wc];
++$i;
$j = ($j + 1) % $Nb;
$k = ($k + 1) % $Nb;
$l = ($l + 1) % $Nb;
}
$state = $temp;
}
// invShiftRows + invSubWord + addRoundKey
$i = 0; // $c[0] == 0
$j = $Nb - $c[1];
$k = $Nb - $c[2];
$l = $Nb - $c[3];
while ($i < $Nb) {
$word = ($state[$i] & 0xFF000000) |
($state[$j] & 0x00FF0000) |
($state[$k] & 0x0000FF00) |
($state[$l] & 0x000000FF);
$temp[$i] = $dw[$i] ^ ($isbox[$word & 0x000000FF] |
($isbox[$word >> 8 & 0x000000FF] << 8) |
($isbox[$word >> 16 & 0x000000FF] << 16) |
($isbox[$word >> 24 & 0x000000FF] << 24));
++$i;
$j = ($j + 1) % $Nb;
$k = ($k + 1) % $Nb;
$l = ($l + 1) % $Nb;
}
switch ($Nb) {
case 8:
return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);
case 7:
return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);
case 6:
return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);
case 5:
return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);
default:
return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]);
}
}
/**
* Setup the key (expansion)
*
* @see Crypt_Base::_setupKey()
* @access private
*/
function _setupKey()
{
// Each number in $rcon is equal to the previous number multiplied by two in Rijndael's finite field.
// See http://en.wikipedia.org/wiki/Finite_field_arithmetic#Multiplicative_inverse
static $rcon = array(0,
0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000,
0x6C000000, 0xD8000000, 0xAB000000, 0x4D000000, 0x9A000000,
0x2F000000, 0x5E000000, 0xBC000000, 0x63000000, 0xC6000000,
0x97000000, 0x35000000, 0x6A000000, 0xD4000000, 0xB3000000,
0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000
);
if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_length === $this->kl['key_length'] && $this->block_size === $this->kl['block_size']) {
// already expanded
return;
}
$this->kl = array('key' => $this->key, 'key_length' => $this->key_length, 'block_size' => $this->block_size);
$this->Nk = $this->key_length >> 2;
// see Rijndael-ammended.pdf#page=44
$this->Nr = max($this->Nk, $this->Nb) + 6;
// shift offsets for Nb = 5, 7 are defined in Rijndael-ammended.pdf#page=44,
// "Table 8: Shift offsets in Shiftrow for the alternative block lengths"
// shift offsets for Nb = 4, 6, 8 are defined in Rijndael-ammended.pdf#page=14,
// "Table 2: Shift offsets for different block lengths"
switch ($this->Nb) {
case 4:
case 5:
case 6:
$this->c = array(0, 1, 2, 3);
break;
case 7:
$this->c = array(0, 1, 2, 4);
break;
case 8:
$this->c = array(0, 1, 3, 4);
}
$w = array_values(unpack('N*words', $this->key));
$length = $this->Nb * ($this->Nr + 1);
for ($i = $this->Nk; $i < $length; $i++) {
$temp = $w[$i - 1];
if ($i % $this->Nk == 0) {
// according to , "the size of an integer is platform-dependent".
// on a 32-bit machine, it's 32-bits, and on a 64-bit machine, it's 64-bits. on a 32-bit machine,
// 0xFFFFFFFF << 8 == 0xFFFFFF00, but on a 64-bit machine, it equals 0xFFFFFFFF00. as such, doing 'and'
// with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is.
$temp = (($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF); // rotWord
$temp = $this->_subWord($temp) ^ $rcon[$i / $this->Nk];
} elseif ($this->Nk > 6 && $i % $this->Nk == 4) {
$temp = $this->_subWord($temp);
}
$w[$i] = $w[$i - $this->Nk] ^ $temp;
}
// convert the key schedule from a vector of $Nb * ($Nr + 1) length to a matrix with $Nr + 1 rows and $Nb columns
// and generate the inverse key schedule. more specifically,
// according to (section 5.3.3),
// "The key expansion for the Inverse Cipher is defined as follows:
// 1. Apply the Key Expansion.
// 2. Apply InvMixColumn to all Round Keys except the first and the last one."
// also, see fips-197.pdf#page=27, "5.3.5 Equivalent Inverse Cipher"
list($dt0, $dt1, $dt2, $dt3) = $this->_getInvTables();
$temp = $this->w = $this->dw = array();
for ($i = $row = $col = 0; $i < $length; $i++, $col++) {
if ($col == $this->Nb) {
if ($row == 0) {
$this->dw[0] = $this->w[0];
} else {
// subWord + invMixColumn + invSubWord = invMixColumn
$j = 0;
while ($j < $this->Nb) {
$dw = $this->_subWord($this->w[$row][$j]);
$temp[$j] = $dt0[$dw >> 24 & 0x000000FF] ^
$dt1[$dw >> 16 & 0x000000FF] ^
$dt2[$dw >> 8 & 0x000000FF] ^
$dt3[$dw & 0x000000FF];
$j++;
}
$this->dw[$row] = $temp;
}
$col = 0;
$row++;
}
$this->w[$row][$col] = $w[$i];
}
$this->dw[$row] = $this->w[$row];
// Converting to 1-dim key arrays (both ascending)
$this->dw = array_reverse($this->dw);
$w = array_pop($this->w);
$dw = array_pop($this->dw);
foreach ($this->w as $r => $wr) {
foreach ($wr as $c => $wc) {
$w[] = $wc;
$dw[] = $this->dw[$r][$c];
}
}
$this->w = $w;
$this->dw = $dw;
}
/**
* Performs S-Box substitutions
*
* @access private
* @param int $word
*/
function _subWord($word)
{
static $sbox;
if (empty($sbox)) {
list(, , , , $sbox) = $this->_getTables();
}
return $sbox[$word & 0x000000FF] |
($sbox[$word >> 8 & 0x000000FF] << 8) |
($sbox[$word >> 16 & 0x000000FF] << 16) |
($sbox[$word >> 24 & 0x000000FF] << 24);
}
/**
* Provides the mixColumns and sboxes tables
*
* @see Crypt_Rijndael:_encryptBlock()
* @see Crypt_Rijndael:_setupInlineCrypt()
* @see Crypt_Rijndael:_subWord()
* @access private
* @return array &$tables
*/
function &_getTables()
{
static $tables;
if (empty($tables)) {
// according to (section 5.2.1),
// precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so
// those are the names we'll use.
$t3 = array_map('intval', array(
// with array_map('intval', ...) we ensure we have only int's and not
// some slower floats converted by php automatically on high values
0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491,
0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC,
0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB,
0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B,
0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83,
0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A,
0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F,
0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA,
0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B,
0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713,
0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6,
0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85,
0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411,
0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B,
0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1,
0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF,
0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E,
0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6,
0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B,
0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD,
0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8,
0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2,
0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049,
0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810,
0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197,
0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F,
0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C,
0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927,
0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733,
0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5,
0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0,
0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C
));
foreach ($t3 as $t3i) {
$t0[] = (($t3i << 24) & 0xFF000000) | (($t3i >> 8) & 0x00FFFFFF);
$t1[] = (($t3i << 16) & 0xFFFF0000) | (($t3i >> 16) & 0x0000FFFF);
$t2[] = (($t3i << 8) & 0xFFFFFF00) | (($t3i >> 24) & 0x000000FF);
}
$tables = array(
// The Precomputed mixColumns tables t0 - t3
$t0,
$t1,
$t2,
$t3,
// The SubByte S-Box
array(
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
)
);
}
return $tables;
}
/**
* Provides the inverse mixColumns and inverse sboxes tables
*
* @see Crypt_Rijndael:_decryptBlock()
* @see Crypt_Rijndael:_setupInlineCrypt()
* @see Crypt_Rijndael:_setupKey()
* @access private
* @return array &$tables
*/
function &_getInvTables()
{
static $tables;
if (empty($tables)) {
$dt3 = array_map('intval', array(
0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B,
0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5,
0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B,
0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358, 0xE0692949, 0xC9C8448E,
0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D,
0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9,
0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272, 0x1F8F57E3, 0x55AB2A66,
0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED,
0xCF1C2B8A, 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4,
0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD,
0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60,
0x98FB2419, 0xBDE997D6, 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79,
0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C,
0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24,
0x0A67B10C, 0x57E70F93, 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C,
0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814,
0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B,
0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084,
0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC, 0x8652EC0D, 0xC1E3D077,
0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22,
0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F,
0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, 0xC3AFF582,
0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB,
0x267809CD, 0x5918F46E, 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF,
0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035,
0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17,
0x4DD68D76, 0xEFB04D43, 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46,
0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D,
0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A,
0xD2DF599C, 0xF2733F55, 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678,
0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC, 0x3C498B28, 0x0D9541FF,
0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0
));
foreach ($dt3 as $dt3i) {
$dt0[] = (($dt3i << 24) & 0xFF000000) | (($dt3i >> 8) & 0x00FFFFFF);
$dt1[] = (($dt3i << 16) & 0xFFFF0000) | (($dt3i >> 16) & 0x0000FFFF);
$dt2[] = (($dt3i << 8) & 0xFFFFFF00) | (($dt3i >> 24) & 0x000000FF);
};
$tables = array(
// The Precomputed inverse mixColumns tables dt0 - dt3
$dt0,
$dt1,
$dt2,
$dt3,
// The inverse SubByte S-Box
array(
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
)
);
}
return $tables;
}
/**
* Setup the performance-optimized function for de/encrypt()
*
* @see Crypt_Base::_setupInlineCrypt()
* @access private
*/
function _setupInlineCrypt()
{
// Note: _setupInlineCrypt() will be called only if $this->changed === true
// So here we are'nt under the same heavy timing-stress as we are in _de/encryptBlock() or de/encrypt().
// However...the here generated function- $code, stored as php callback in $this->inline_crypt, must work as fast as even possible.
$lambda_functions =& Crypt_Rijndael::_getLambdaFunctions();
// We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
// (Currently, for Crypt_Rijndael/AES, one generated $lambda_function cost on php5.5@32bit ~80kb unfreeable mem and ~130kb on php5.5@64bit)
// After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
$gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
// Generation of a uniqe hash for our generated code
$code_hash = "Crypt_Rijndael, {$this->mode}, {$this->Nr}, {$this->Nb}";
if ($gen_hi_opt_code) {
$code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
}
if (!isset($lambda_functions[$code_hash])) {
switch (true) {
case $gen_hi_opt_code:
// The hi-optimized $lambda_functions will use the key-words hardcoded for better performance.
$w = $this->w;
$dw = $this->dw;
$init_encrypt = '';
$init_decrypt = '';
break;
default:
for ($i = 0, $cw = count($this->w); $i < $cw; ++$i) {
$w[] = '$w[' . $i . ']';
$dw[] = '$dw[' . $i . ']';
}
$init_encrypt = '$w = $self->w;';
$init_decrypt = '$dw = $self->dw;';
}
$Nr = $this->Nr;
$Nb = $this->Nb;
$c = $this->c;
// Generating encrypt code:
$init_encrypt.= '
static $tables;
if (empty($tables)) {
$tables = &$self->_getTables();
}
$t0 = $tables[0];
$t1 = $tables[1];
$t2 = $tables[2];
$t3 = $tables[3];
$sbox = $tables[4];
';
$s = 'e';
$e = 's';
$wc = $Nb - 1;
// Preround: addRoundKey
$encrypt_block = '$in = unpack("N*", $in);'."\n";
for ($i = 0; $i < $Nb; ++$i) {
$encrypt_block .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$w[++$wc].";\n";
}
// Mainrounds: shiftRows + subWord + mixColumns + addRoundKey
for ($round = 1; $round < $Nr; ++$round) {
list($s, $e) = array($e, $s);
for ($i = 0; $i < $Nb; ++$i) {
$encrypt_block.=
'$'.$e.$i.' =
$t0[($'.$s.$i .' >> 24) & 0xff] ^
$t1[($'.$s.(($i + $c[1]) % $Nb).' >> 16) & 0xff] ^
$t2[($'.$s.(($i + $c[2]) % $Nb).' >> 8) & 0xff] ^
$t3[ $'.$s.(($i + $c[3]) % $Nb).' & 0xff] ^
'.$w[++$wc].";\n";
}
}
// Finalround: subWord + shiftRows + addRoundKey
for ($i = 0; $i < $Nb; ++$i) {
$encrypt_block.=
'$'.$e.$i.' =
$sbox[ $'.$e.$i.' & 0xff] |
($sbox[($'.$e.$i.' >> 8) & 0xff] << 8) |
($sbox[($'.$e.$i.' >> 16) & 0xff] << 16) |
($sbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n";
}
$encrypt_block .= '$in = pack("N*"'."\n";
for ($i = 0; $i < $Nb; ++$i) {
$encrypt_block.= ',
($'.$e.$i .' & '.((int)0xFF000000).') ^
($'.$e.(($i + $c[1]) % $Nb).' & 0x00FF0000 ) ^
($'.$e.(($i + $c[2]) % $Nb).' & 0x0000FF00 ) ^
($'.$e.(($i + $c[3]) % $Nb).' & 0x000000FF ) ^
'.$w[$i]."\n";
}
$encrypt_block .= ');';
// Generating decrypt code:
$init_decrypt.= '
static $invtables;
if (empty($invtables)) {
$invtables = &$self->_getInvTables();
}
$dt0 = $invtables[0];
$dt1 = $invtables[1];
$dt2 = $invtables[2];
$dt3 = $invtables[3];
$isbox = $invtables[4];
';
$s = 'e';
$e = 's';
$wc = $Nb - 1;
// Preround: addRoundKey
$decrypt_block = '$in = unpack("N*", $in);'."\n";
for ($i = 0; $i < $Nb; ++$i) {
$decrypt_block .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$dw[++$wc].';'."\n";
}
// Mainrounds: shiftRows + subWord + mixColumns + addRoundKey
for ($round = 1; $round < $Nr; ++$round) {
list($s, $e) = array($e, $s);
for ($i = 0; $i < $Nb; ++$i) {
$decrypt_block.=
'$'.$e.$i.' =
$dt0[($'.$s.$i .' >> 24) & 0xff] ^
$dt1[($'.$s.(($Nb + $i - $c[1]) % $Nb).' >> 16) & 0xff] ^
$dt2[($'.$s.(($Nb + $i - $c[2]) % $Nb).' >> 8) & 0xff] ^
$dt3[ $'.$s.(($Nb + $i - $c[3]) % $Nb).' & 0xff] ^
'.$dw[++$wc].";\n";
}
}
// Finalround: subWord + shiftRows + addRoundKey
for ($i = 0; $i < $Nb; ++$i) {
$decrypt_block.=
'$'.$e.$i.' =
$isbox[ $'.$e.$i.' & 0xff] |
($isbox[($'.$e.$i.' >> 8) & 0xff] << 8) |
($isbox[($'.$e.$i.' >> 16) & 0xff] << 16) |
($isbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n";
}
$decrypt_block .= '$in = pack("N*"'."\n";
for ($i = 0; $i < $Nb; ++$i) {
$decrypt_block.= ',
($'.$e.$i. ' & '.((int)0xFF000000).') ^
($'.$e.(($Nb + $i - $c[1]) % $Nb).' & 0x00FF0000 ) ^
($'.$e.(($Nb + $i - $c[2]) % $Nb).' & 0x0000FF00 ) ^
($'.$e.(($Nb + $i - $c[3]) % $Nb).' & 0x000000FF ) ^
'.$dw[$i]."\n";
}
$decrypt_block .= ');';
$lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
array(
'init_crypt' => '',
'init_encrypt' => $init_encrypt,
'init_decrypt' => $init_decrypt,
'encrypt_block' => $encrypt_block,
'decrypt_block' => $decrypt_block
)
);
}
$this->inline_crypt = $lambda_functions[$code_hash];
}
}