Skip to content

Commit 1813eba

Browse files
authored
cloud_py_api 0.1.5 (#80)
* cloud_py_api 0.1.5 * psalm fixes
1 parent 08a4c5c commit 1813eba

File tree

5 files changed

+233
-4
lines changed

5 files changed

+233
-4
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [0.1.5 - 2023-02-25]
6+
7+
### Changed
8+
9+
- Changed binary package format from one file to folder to speedup startup
10+
511
## [0.1.4 - 2023-01-23]
612

713
### Removed

appinfo/info.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ You can support us in several ways:
3434
[![Liberapay](https://liberapay.com/assets/widgets/donate.svg)](https://liberapay.com/cloud_py_api/donate)
3535
]]>
3636
</description>
37-
<version>0.1.4</version>
37+
<version>0.1.5</version>
3838
<licence>agpl</licence>
3939
<author mail="andrey18106x@gmail.com" homepage="https://github.com/andrey18106">Andrey Borysenko</author>
4040
<author mail="bigcat88@icloud.com" homepage="https://github.com/bigcat88">Alexander Piskun</author>

lib/Service/UtilsService.php

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,229 @@ public function compareBinaryHash(string $url, string $binaryPath) {
342342
return true;
343343
}
344344

345+
/**
346+
* Perform cURL to download python binary (in directory format)
347+
*
348+
* @param string $url
349+
* @param array $binariesFolder appdata binaries folder
350+
* @param string $appId target Application::APP_ID
351+
* @param string $filename archive and extracted folder name
352+
* @param bool $update flag to determine whether to update already downloaded binary or not
353+
*
354+
* @return array
355+
*/
356+
public function downloadPythonBinaryDir(
357+
string $url,
358+
array $binariesFolder,
359+
string $appId,
360+
string $filename = 'main',
361+
bool $update = false
362+
): array {
363+
if (isset($binariesFolder['success']) && $binariesFolder['success']) {
364+
$dir = $binariesFolder['path'] . '/';
365+
} else {
366+
return $binariesFolder; // Return getAppDataFolder result
367+
}
368+
$file_name = $filename . '.tar.gz';
369+
$save_file_loc = $dir . $file_name;
370+
$shouldDownloadBinary = $this->compareBinaryDirectoryHashes($url, $binariesFolder, $appId);
371+
372+
if (!file_exists($dir . $filename) || ($update && $shouldDownloadBinary)) {
373+
$cURL = curl_init($url);
374+
$fp = fopen($save_file_loc, 'wb');
375+
if ($fp) {
376+
curl_setopt_array($cURL, [
377+
CURLOPT_RETURNTRANSFER => true,
378+
CURLOPT_FILE => $fp,
379+
CURLOPT_FOLLOWLOCATION => true,
380+
]);
381+
curl_exec($cURL);
382+
curl_close($cURL);
383+
fclose($fp);
384+
$unpacked = $this->unTarGz($binariesFolder, $filename . '.tar.gz');
385+
unlink($save_file_loc);
386+
return [
387+
'downloaded' => true,
388+
'unpacked' => $unpacked
389+
];
390+
}
391+
}
392+
393+
return [
394+
'downloaded' => true,
395+
'unpacked' => true,
396+
];
397+
}
398+
399+
/**
400+
* Extract tar.gz file
401+
*
402+
* @param array $binariesFolder appdata binaries folder
403+
* @param string $src_filename source tar.gz file name
404+
*
405+
* @return array
406+
*/
407+
public function unTarGz(array $binariesFolder, string $src_filename): array {
408+
if (isset($binariesFolder['success']) && $binariesFolder['success']) {
409+
$dir = $binariesFolder['path'] . '/';
410+
$src_file = $dir . $src_filename;
411+
$phar = new \PharData($src_file);
412+
$extracted = $phar->extractTo($dir, null, true);
413+
$filename = $phar->getFilename();
414+
return [
415+
'extracted' => $extracted,
416+
'filename' => $filename
417+
];
418+
}
419+
return [
420+
'extracted' => false,
421+
];
422+
}
423+
424+
/**
425+
* Perform cURL to get binary folder hashes sha256 sum
426+
*
427+
* @param string $url url to the binary hashsums file
428+
*
429+
* @return array
430+
*/
431+
public function downloadBinaryDirHashes(string $url): array {
432+
$cURL = curl_init($url);
433+
curl_setopt_array($cURL, [
434+
CURLOPT_RETURNTRANSFER => true,
435+
CURLOPT_FOLLOWLOCATION => true,
436+
]);
437+
$binaryHash = curl_exec($cURL);
438+
curl_close($cURL);
439+
return [
440+
'success' => $binaryHash != false,
441+
'binaryHash' => json_decode($binaryHash, true),
442+
];
443+
}
444+
445+
/**
446+
* Compare binary folder hashes from release.
447+
* If hash not exists return `true` (download anyway)
448+
*
449+
* @param string $url
450+
* @param array $binariesFolder
451+
*
452+
* @return bool
453+
*/
454+
public function compareBinaryDirectoryHashes(
455+
string $url, array $binariesFolder, string $appId
456+
): bool {
457+
$currentBinaryHashes = $this->getCurrentBinaryDirHashes($binariesFolder, $appId);
458+
$newBinaryHashes = $this->downloadBinaryDirHashes(str_replace('.tar.gz', '.json', $url));
459+
if ($newBinaryHashes['success'] && $currentBinaryHashes['success']) {
460+
// Skip hash check of archive file
461+
$archiveFilename = $appId . '_' . $this->getBinaryName() . '.tar.gz';
462+
if (isset($newBinaryHashes['binaryHashes'][$archiveFilename])) {
463+
unset($newBinaryHashes['binaryHashes'][$archiveFilename]);
464+
}
465+
foreach ($newBinaryHashes['binaryHashes'] as $filename => $hash) {
466+
$fileExists = !isset($currentBinaryHashes[$filename]);
467+
$currentHash = $currentBinaryHashes['binaryHashes'][$filename];
468+
$hashEqual = $currentHash == $hash;
469+
if (!$fileExists || !$hashEqual) {
470+
return true;
471+
}
472+
}
473+
return false;
474+
}
475+
return true;
476+
}
477+
478+
/**
479+
* Get current binary folder files hashes
480+
*
481+
* @param array $binariesFolder
482+
*
483+
* @return array
484+
*/
485+
public function getCurrentBinaryDirHashes(array $binariesFolder, string $appId): array {
486+
$currentBinaryHashes = [];
487+
$archiveFilename = $appId . '_' . $this->getBinaryName() . '.tar.gz';
488+
if (file_exists($binariesFolder['path'] . '/' . $archiveFilename)) {
489+
$currentBinaryHashes[$archiveFilename] = hash_file(
490+
'sha256',
491+
$binariesFolder['path'] . '/' . $archiveFilename
492+
);
493+
}
494+
$extractedBinaryFolder = $binariesFolder['path'] . '/' . $appId . '_'. $this->getBinaryName();
495+
$files = scandir($extractedBinaryFolder);
496+
if ($files !== false) {
497+
foreach ($files as $file) {
498+
if ($file != '.' && $file != '..') {
499+
// Get sha256 hash of each file
500+
// If file is directory, get sha256 hash of each file in directory
501+
if (is_dir($extractedBinaryFolder . '/' . $file)) {
502+
$dirFiles = scandir($extractedBinaryFolder . '/' . $file);
503+
$currentBinaryHashes = $this->getFolderHashes(
504+
$dirFiles,
505+
$file,
506+
$extractedBinaryFolder . '/' . $file,
507+
$currentBinaryHashes,
508+
$appId
509+
);
510+
} else {
511+
$binaryFolderFilePath = $appId . '_' . $this->getBinaryName() . '/' . $file;
512+
$currentBinaryHashes[$binaryFolderFilePath] = hash_file(
513+
'sha256',
514+
$extractedBinaryFolder . '/' . $file
515+
);
516+
}
517+
}
518+
}
519+
}
520+
return [
521+
'success' => count($currentBinaryHashes) > 0,
522+
'binaryHashes' => $currentBinaryHashes
523+
];
524+
}
525+
526+
/**
527+
* Get sha256 hashes of each file in binary folder
528+
* Recursive function call if file is directory
529+
*
530+
* @param array $files
531+
* @param string $folder
532+
* @param string $extractedBinaryFolder
533+
* @param array $currentBinaryHashes
534+
* @param string $appId
535+
*
536+
* @return array
537+
*/
538+
private function getFolderHashes(
539+
array $files,
540+
string $folder,
541+
string $extractedBinaryFolder,
542+
array $currentBinaryHashes,
543+
string $appId
544+
): array {
545+
foreach ($files as $file) {
546+
if ($file != '.' && $file != '..') {
547+
// Get sha256 hash of each file
548+
// If file is directory, get sha256 hash of each file in directory
549+
if (is_dir($extractedBinaryFolder . '/' . $file)) {
550+
$dirFiles = scandir($extractedBinaryFolder . '/' . $file);
551+
$currentBinaryHashes = $this->getFolderHashes(
552+
$dirFiles,
553+
$folder. '/' . $file, $extractedBinaryFolder . '/' . $file,
554+
$currentBinaryHashes, $appId
555+
);
556+
} else {
557+
$binaryFolderFilePath = $appId . '_'
558+
. $this->getBinaryName() . '/' . $folder . '/' . $file;
559+
$currentBinaryHashes[$binaryFolderFilePath] = hash_file(
560+
'sha256', $extractedBinaryFolder . '/' . $file
561+
);
562+
}
563+
}
564+
}
565+
return $currentBinaryHashes;
566+
}
567+
345568
/**
346569
* Perform cURL to get binary's sha256 sum
347570
*

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "cloud_py_api",
33
"description": "Nextcloud Python API (Framework)",
4-
"version": "0.1.4",
4+
"version": "0.1.5",
55
"keywords": [
66
"nextcloud",
77
"python",

0 commit comments

Comments
 (0)