Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Package Manager] Re-Download missing packages #14018

Open
wants to merge 31 commits into
base: 3.x
Choose a base branch
from
Open
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
3fc5038
Filter user input used in phpthumb
opengeek Jul 11, 2018
606dc0f
Prevent directory traversal and limit files deleted when clearing mod…
opengeek Jul 12, 2018
4ab3571
MODX Revolution 2.6.5-pl
opengeek Jul 12, 2018
eef48c8
Fix zips from build to ensure they do not include 777/666 attributes
opengeek Jul 13, 2018
f291a83
[Package Manager] Re-Download missing packages
exside Jul 28, 2018
51f4052
Make monster oneliner multiline
exside Jul 29, 2018
bd29d3f
Split up oneliner into variables...
exside Jul 29, 2018
43a626c
Harmonize comment style + empty dir fix
exside Jul 29, 2018
6a2f944
Separate code into getMetadata() method
exside Jul 29, 2018
69c081b
Fix issue with update mode
exside Jul 29, 2018
290cee5
Optimization & Dealing with various edge cases
exside Jul 30, 2018
4195e57
Change getMetadata() to return directly
exside Aug 3, 2018
d0fd631
Otherwise a xx4 or xx5 would be detected too.
Ibochkarev Feb 17, 2019
f459f06
Merge pull request #1 from Ibochkarev/patch-2
exside Feb 20, 2019
ade661c
[Package Manager] Re-Download missing packages
exside Jul 28, 2018
160b7d6
Make monster oneliner multiline
exside Jul 29, 2018
5bbb2b1
Split up oneliner into variables...
exside Jul 29, 2018
8257b2d
Harmonize comment style + empty dir fix
exside Jul 29, 2018
35eeb5f
Separate code into getMetadata() method
exside Jul 29, 2018
a2647cc
Fix issue with update mode
exside Jul 29, 2018
317c829
Optimization & Dealing with various edge cases
exside Jul 30, 2018
1a00781
Change getMetadata() to return directly
exside Aug 3, 2018
bb8318b
Otherwise a xx4 or xx5 would be detected too.
Ibochkarev Feb 17, 2019
6353263
solve merge conflicts after rebase
exside May 22, 2019
017304e
revert unwanted file changes...
exside May 22, 2019
f4b6b9d
it's my editor trying to be smart...
exside May 22, 2019
7dfa009
Revert "revert unwanted file changes..."
exside May 22, 2019
4662482
Merge remote-tracking branch 'origin/patch-1' into patch-1
exside May 22, 2019
509acd3
re-add double whitespace at the end (yeah, still the editor)...
exside May 22, 2019
2136019
whitespace again
exside May 22, 2019
4fb2db2
Update core/model/modx/transport/modtransportpackage.class.php
Jako Sep 19, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 103 additions & 29 deletions core/model/modx/transport/modtransportpackage.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,9 @@ public function getTransport($state = -1) {
$packageDir = $workspace->get('path') . 'packages/';
$sourceFile = $this->get('source');
if ($sourceFile) {
$transferred= file_exists($packageDir . $sourceFile);
$transferred = file_exists($packageDir . $sourceFile);
if (!$transferred) { /* if no transport zip, attempt to get it */
if (!$transferred= $this->transferPackage($sourceFile, $packageDir)) {
if (!$transferred = $this->transferPackage($sourceFile, $packageDir)) {
$this->xpdo->log(xPDO::LOG_LEVEL_ERROR,$this->xpdo->lexicon('package_err_transfer',array(
'sourceFile' => $sourceFile,
'packageDir' => $packageDir,
Expand All @@ -216,9 +216,10 @@ public function getTransport($state = -1) {
}
if ($transferred) {
if ($state < 0) {
/* if directory is missing but zip exists, and DB state value is incorrect, fix here */
/* if directory is missing or empty but zip exists, and DB state value is incorrect, fix here */
$targetDir = basename($sourceFile, '.transport.zip');
$state = is_dir($packageDir.$targetDir) ? $this->get('state') : xPDOTransport::STATE_PACKED;
$packageTargetDirIsNotEmpty = (count(glob($packageDir . $targetDir . '/*')) !== 0)
$state = (is_dir($packageDir . $targetDir) && $packageTargetDirIsNotEmpty) ? $this->get('state') : xPDOTransport::STATE_PACKED;
}
/* retrieve the package */
$this->package = xPDOTransport :: retrieve($this->xpdo, $packageDir . $sourceFile, $packageDir, $state);
Expand All @@ -240,6 +241,40 @@ public function getTransport($state = -1) {
return $this->package;
}

/**
* Get metadata for a package in a more usable format
*
* @access public
* @param array $metadata optional input array to be processed, defaults to package metadata
* @param string $keyfield the inner array element pointing to the value for key substitution
* @return array an array of metadata accessible by $keyfield
*/
public function getMetadata($metadata = array(), $keyfield = 'name') {
if (empty($metadata)) {
$metadata = $this->get('metadata');
}

if (!is_array($metadata[0])) {
return $metadata;
}

return array_reduce($metadata, function ($result, $item) use ($keyfield) {
$key = $item[$keyfield];
unset($item[$keyfield]);

/* recurisvely handle nested arrays, attributes and children */
foreach ($item as $k => $v) {
if (is_array($v) && !empty($v)) {
$item[$k] = $this->getMetadata($v);
}
}

$result[$key] = $item;

return $result;
}, array());
}

/**
* Removes and uninstalls the package.
*
Expand Down Expand Up @@ -361,13 +396,35 @@ public function uninstall(array $options = array()) {
* @return boolean True if successful.
*/
public function transferPackage($sourceFile, $targetDir) {
$transferred= false;
$content= '';
$transferred = false;
$content = '';
if (is_dir($targetDir) && is_writable($targetDir)) {
if (!is_array($this->xpdo->version)) { $this->xpdo->getVersionData(); }
$productVersion = $this->xpdo->version['code_name'].'-'.$this->xpdo->version['full_version'];

$source= $this->get('service_url') . $sourceFile.(strpos($sourceFile,'?') !== false ? '&' : '?').'revolution_version='.$productVersion;
$productVersion = join('-', array(
$this->xpdo->version['code_name'],
$this->xpdo->version['full_version']
));

/* make sure the package is downloaded, if not attempt re-download */
if (strpos($sourceFile, '//') === false && !file_exists($targetDir . $sourceFile)) {
/* get the package metadata */
$metadata = $this->getMetadata();

if (!empty($metadata) && ($metadata['location'] || $metadata['file'])) {
/* assign remote download URL */
if ($metadata['location']) {
if (is_array($metadata['location'])) {
$source = $metadata['location']['text'];
} else {
$source = $metadata['location'];
}
} else {
$source = $metadata['file']['children']['location']['text'];
}
}
} else {
$source = $this->get('service_url') . $sourceFile.(strpos($sourceFile,'?') !== false ? '&' : '?').'revolution_version='.$productVersion;
}

/* see if user has allow_url_fopen on and is not behind a proxy */
$proxyHost = $this->xpdo->getOption('proxy_host',null,'');
Expand Down Expand Up @@ -421,6 +478,11 @@ public function transferPackage($sourceFile, $targetDir) {
}
}
$content = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);

if ($status >= 400) {
$content = '';
}
curl_close($ch);
}

Expand All @@ -436,7 +498,7 @@ public function transferPackage($sourceFile, $targetDir) {
$transferred= $cacheManager->writeFile($target, $content);
}
} else {
$this->xpdo->log(xPDO::LOG_LEVEL_ERROR,'MODX could not download the file. You must enable allow_url_fopen, cURL or fsockopen to use remote transport packaging.');
$this->xpdo->log(xPDO::LOG_LEVEL_ERROR, 'MODX could not download the file. ' . (isset($status) ? 'Server responded with status code ' . $status . '.' : 'You must enable allow_url_fopen, cURL or fsockopen to use remote transport packaging.'));
JoshuaLuckers marked this conversation as resolved.
Show resolved Hide resolved
}
} else {
$this->xpdo->log(xPDO::LOG_LEVEL_ERROR,$this->xpdo->lexicon('package_err_target_write',array(
Expand Down Expand Up @@ -666,33 +728,45 @@ protected function _getByFsockopen($url) {
$purl = parse_url($url);
$host = $purl['host'];
$path = !empty($purl['path']) ? $purl['path'] : '/';
if (!empty($purl['query'])) { $path .= '?'.$purl['query']; }
if (!empty($purl['query'])) {
$path .= '?' . $purl['query'];
}
$port = !empty($purl['port']) ? $purl['port'] : '80';

$timeout = 10;
$response = '';
$fp = @fsockopen($host,$port,$errno,$errstr,$timeout);

if( !$fp ) {
$this->xpdo->log(xPDO::LOG_LEVEL_ERROR,'Could not retrieve from '.$url);
$this->xpdo->log(xPDO::LOG_LEVEL_ERROR, 'Could not retrieve from ' . $url);
} else {
fwrite($fp, "GET $path ".$_SERVER['SERVER_PROTOCOL']."\r\n" .
"Host: $host\r\n" .
"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3\r\n" .
"Accept: */*\r\n" .
"Accept-Language: en-us,en;q=0.5\r\n" .
"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" .
"Keep-Alive: 300\r\n" .
"Connection: keep-alive\r\n" .
"Referer: http://$host\r\n\r\n");

while ($line = fread($fp, 4096)) {
$response .= $line;
}
fclose($fp);

$pos = strpos($response, "\r\n\r\n");
$response = substr($response, $pos + 4);
$out = implode("\r\n", array(
"GET $path " . $_SERVER['SERVER_PROTOCOL'],
"Host: $host",
"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3",
"Accept: */*",
"Accept-Language: en-us,en;q=0.5",
"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7",
"Keep-Alive: 300",
"Connection: keep-alive",
"Referer: " . MODX_URL_SCHEME . $host,
"\r\n"
));
fwrite($fp, $out);

$status = explode(' ', fgets($fp, 13))[1];

if (strpos($status, '4') === 0 || strpos($status, '5') === 0) {
$response = '';
} else {
while ($line = fread($fp, 4096)) {
$response .= $line;
}
$pos = strpos($response, "\r\n\r\n");
$response = substr($response, $pos + 4);
}

fclose($fp);
}
return $response;
}
Expand Down