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]; } }