/** * Performs the staggered download of file. * * @param array $params A parameters array, as sent by the user interface * * @return array A return status array */ public function importFromURL($params) { $this->params = $params; // Fetch data $url = $this->getParam('url'); $localFilename = $this->getParam('localFilename'); $frag = $this->getParam('frag', -1); $totalSize = $this->getParam('totalSize', -1); $doneSize = $this->getParam('doneSize', -1); $maxExecTime = $this->getParam('maxExecTime', 5); $runTimeBias = $this->getParam('runTimeBias', 75); $length = $this->getParam('length', 1048576); if (empty($localFilename)) { $localFilename = basename($url); if (strpos($localFilename, '?') !== false) { $paramsPos = strpos($localFilename, '?'); $localFilename = substr($localFilename, 0, $paramsPos - 1); $platformBaseDirectories = $this->container->platform->getPlatformBaseDirs(); $tmpDir = $platformBaseDirectories['tmp']; $tmpDir = rtrim($tmpDir, '/\\'); $localFilename = $tmpDir . '/' . $localFilename; } } // Init retArray $retArray = array("status" => true, "error" => '', "frag" => $frag, "totalSize" => $totalSize, "doneSize" => $doneSize, "percent" => 0, "localfile" => $localFilename); try { $timer = new Timer($maxExecTime, $runTimeBias); $start = $timer->getRunningTime(); // Mark the start of this download $break = false; // Don't break the step do { // Do we have to initialize the file? if ($frag == -1) { // Currently downloaded size $doneSize = 0; if (@file_exists($localFilename)) { @unlink($localFilename); } // Delete and touch the output file $fp = @fopen($localFilename, 'wb'); if ($fp !== false) { @fclose($fp); } // Init $frag = 0; $retArray['totalSize'] = $this->adapter->getFileSize($url); if ($retArray['totalSize'] <= 0) { $retArray['totalSize'] = 0; } $totalSize = $retArray['totalSize']; } // Calculate from and length $from = $frag * $length; $to = $length + $from - 1; // Try to download the first frag $required_time = 1.0; $error = ''; try { $result = $this->adapter->downloadAndReturn($url, $from, $to, $this->adapterOptions); } catch (DownloadError $e) { $result = false; $error = $e->getMessage(); } if ($result === false) { // Failed download if ($frag == 0) { // Failure to download first frag = failure to download. Period. $retArray['status'] = false; $retArray['error'] = $error; return $retArray; } else { // Since this is a staggered download, consider this normal and finish $frag = -1; $totalSize = $doneSize; $break = true; } } // Add the currently downloaded frag to the total size of downloaded files if ($result !== false) { $fileSize = strlen($result); $doneSize += $fileSize; // Append the file $fp = @fopen($localFilename, 'ab'); if ($fp === false) { // Can't open the file for writing $retArray['status'] = false; $retArray['error'] = JText::sprintf('LIB_FOF_DOWNLOAD_ERR_COULDNOTWRITELOCALFILE', $localFilename); return $retArray; } fwrite($fp, $result); fclose($fp); $frag++; if ($fileSize < $length || $fileSize > $length || $totalSize == $doneSize && $totalSize > 0) { // A partial download or a download larger than the frag size means we are done $frag = -1; //debugMsg("-- Import complete (partial download of last frag)"); $totalSize = $doneSize; $break = true; } } // Advance the frag pointer and mark the end $end = $timer->getRunningTime(); // Do we predict that we have enough time? $required_time = max(1.1 * ($end - $start), $required_time); if ($required_time > 10 - $end + $start) { $break = true; } $start = $end; } while ($timer->getTimeLeft() > 0 && !$break); if ($frag == -1) { $percent = 100; } elseif ($doneSize <= 0) { $percent = 0; } else { if ($totalSize > 0) { $percent = 100 * ($doneSize / $totalSize); } else { $percent = 0; } } // Update $retArray $retArray = array("status" => true, "error" => '', "frag" => $frag, "totalSize" => $totalSize, "doneSize" => $doneSize, "percent" => $percent); } catch (DownloadError $e) { $retArray['status'] = false; $retArray['error'] = $e->getMessage(); } return $retArray; }
/** * Performs a slow, thorough check of all files and folders (including MD5/SHA1 sum checks) * * @param int $idx The index from where to start * * @return array Progress report */ public function slowCheck($idx = 0) { $ret = array('done' => false, 'files' => array(), 'folders' => array(), 'idx' => $idx); $totalFiles = count($this->fileList); $totalFolders = count($this->dirList); $fileKeys = array_keys($this->fileList); $timer = new Timer(3.0, 75.0); while ($timer->getTimeLeft() && ($idx < $totalFiles || $idx < $totalFolders)) { if ($idx < $totalFolders) { $directory = JPATH_ROOT . '/' . $this->dirList[$idx]; if (!@is_dir($directory)) { $ret['folders'][] = $directory; } } if ($idx < $totalFiles) { $fileKey = $fileKeys[$idx]; $filePath = JPATH_ROOT . '/' . $fileKey; $fileData = $this->fileList[$fileKey]; if (!@file_exists($filePath)) { $ret['files'][] = $fileKey . ' (missing)'; } elseif (@filesize($filePath) != $fileData[0]) { $ret['files'][] = $fileKey . ' (size ' . @filesize($filePath) . ' ≠ ' . $fileData[0] . ')'; } else { if (function_exists('sha1_file')) { $fileSha1 = @sha1_file($filePath); if ($fileSha1 != $fileData[2]) { $ret['files'][] = $fileKey . ' (SHA1 ' . $fileSha1 . ' ≠ ' . $fileData[2] . ')'; } } elseif (function_exists('md5_file')) { $fileMd5 = @md5_file($filePath); if ($fileMd5 != $fileData[1]) { $ret['files'][] = $fileKey . ' (MD5 ' . $fileMd5 . ' ≠ ' . $fileData[1] . ')'; } } } } $idx++; } if ($idx >= $totalFiles && $idx >= $totalFolders) { $ret['done'] = true; } $ret['idx'] = $idx; return $ret; }
/** * @covers FOF30\Timer\Timer::getTimeLeft */ public function testGetTimeLeft() { FakeTimer::$microtime = 123456; $timer = new Timer(8, 33); FakeTimer::$microtime = 123456.64; $timeLeft = $timer->getTimeLeft(); $this->assertEquals(2.0, $timeLeft, 'Time left must depend on current microtime', 1.0E-10); FakeTimer::$microtime = 123458.64; $timeLeft = $timer->getTimeLeft(); $this->assertEquals(0, $timeLeft, 'Time left must depend on current microtime (2)', 1.0E-10); FakeTimer::$microtime = 123459.64; $timeLeft = $timer->getTimeLeft(); $this->assertEquals(-1.0, $timeLeft, 'Time left can be negative when we have run out of time', 1.0E-10); }