Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 6 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
language: php

php:
- '7.4'
- '8.1'

env:
global:
Expand All @@ -19,7 +19,7 @@ before_script:
- git clone https://github.com/nextcloud/server.git
- mv server/ nextcloud
- cd nextcloud
- git checkout origin/stable19 -b stable19
- git checkout origin/stable25 -b stable25
- mkdir custom_apps
- cp -pi ${TRAVIS_BUILD_DIR}/travis/apps.config.php config
- cd 3rdparty
Expand All @@ -28,6 +28,10 @@ before_script:
- php occ maintenance:install --database ${NEXTCLOUD_DB} --database-name ${NEXTCLOUD_DB_NAME} --database-user ${NEXTCLOUD_DB_USER} --database-pass ${NEXTCLOUD_DB_PASSWD} --admin-user ${NEXTCLOUD_ADMIN_NAME} --admin-pass ${NEXTCLOUD_ADMIN_PASSWD}
- mkdir custom_apps/${NEXTCLOUD_APP}
- cp -r ${TRAVIS_BUILD_DIR}/{appinfo,lib,tests} custom_apps/${NEXTCLOUD_APP}
- cp ${TRAVIS_BUILD_DIR}/composer.json custom_apps/${NEXTCLOUD_APP}
- cd custom_apps/${NEXTCLOUD_APP}
- composer install
- cd ../../
- php occ app:enable ${NEXTCLOUD_APP}

script:
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ query "hash" tag,sets MD5/SHA256/SHA512.

# Usage

- cd apps/checksum_api
- Composer update
- Composer dump-autoload


## Method

GET
Expand Down
50 changes: 0 additions & 50 deletions appinfo/database.xml

This file was deleted.

2 changes: 1 addition & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
<category>tools</category>
<bugs>https://github.com/RCOSDP/nextcloud-checksum_api/issues</bugs>
<dependencies>
<nextcloud min-version="15" max-version="19" />
<nextcloud min-version="25" max-version="26" />
</dependencies>
</info>
16 changes: 16 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"autoload-dev": {
"psr-4": {
"OCA\\ChecksumAPI\\": "lib/"
}
},
"config": {
"optimize-autoloader": true
},
"require-dev": {
"phpunit/phpunit": "^9"
},
"require": {
"amphp/parallel": "^1.4"
}
}
85 changes: 64 additions & 21 deletions lib/Controller/ChecksumAPIController.php
Original file line number Diff line number Diff line change
@@ -1,38 +1,47 @@
<?php



declare(strict_types=1);

namespace OCA\ChecksumAPI\Controller;

use OC\Files\Filesystem;
require __DIR__ . '../../../vendor/autoload.php';

use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCSController;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\IDBConnection;
use OCP\ILogger;
use OCP\IRequest;
use OCP\IUserSession;

use OCA\ChecksumAPI\Db\Hash;
use OCA\ChecksumAPI\Db\HashMapper;

use Amp\Parallel\Worker\DefaultPool;
use Amp;
use OCA\ChecksumAPI\Jobs\HashableTask;
use Psr\Log\LoggerInterface;

class ChecksumAPIController extends OCSController {

private $rootFolder;
private $userSession;
private $mapper;
private $appManager;
private $logger;
private $minFileSizeToExcuteParallel = 20971520;
private $hashTypes = ['md5', 'sha256', 'sha512'];
private $versionAppId = 'files_versions';

public function __construct($appName,
IRequest $request,
IRootFolder $rootFolder,
IUserSession $userSession,
HashMapper $mapper,
ILogger $logger) {
public function __construct(
$appName,
IRequest $request,
IRootFolder $rootFolder,
IUserSession $userSession,
HashMapper $mapper,
LoggerInterface $logger
) {
parent::__construct($appName, $request);
$this->rootFolder = $rootFolder;
$this->userSession = $userSession;
Expand All @@ -41,7 +50,7 @@ public function __construct($appName,
}

private function isValidHash(string $hash) {
foreach($this->hashTypes as $hashType) {
foreach ($this->hashTypes as $hashType) {
if ($hashType === $hash) {
return true;
}
Expand All @@ -62,7 +71,7 @@ private function getMatchedVersion(string $path, string $revision) {
return null;
}

private function saveRecord(int $fileid, int $revision, string $hashType, string $hash) {
function saveRecord(int $fileid, int $revision, string $hashType, string $hash) {
$entity = new Hash();
$entity->setFileid($fileid);
$entity->setRevision($revision);
Expand Down Expand Up @@ -94,7 +103,7 @@ public function checksum($hash, $path, $revision) {
}

$hashTypes = explode(',', $hash);
foreach($hashTypes as $hashType) {
foreach ($hashTypes as $hashType) {
if (!$this->isValidHash($hashType)) {
$this->logger->error('query parameter hash is invalid.');
return new DataResponse(
Expand Down Expand Up @@ -139,16 +148,14 @@ public function checksum($hash, $path, $revision) {
if ($revision === strval($latestRevision)) {
$this->logger->info('latest version matches');
} else {
// check if version function is enabled
if (!\OCP\App::isEnabled($this->versionAppId)) {
if (!\OC::$server->getAppManager()->isEnabledForUser($this->versionAppId)) {
$this->logger->error('version function is not enabled');
return new DataResponse(
'version function is not enabled',
Http::STATUS_NOT_IMPLEMENTED
);
}
$this->logger->info($this->versionAppId . ' is enabled');

$version = $this->getMatchedVersion($path, $revision);
if (is_null($version)) {
$this->logger->error('specified revision is not found');
Expand All @@ -163,6 +170,7 @@ public function checksum($hash, $path, $revision) {
}

$entities = [];
$tasks = [];
foreach ($hashTypes as $hashType) {
$entity = $this->mapper->find($fileid, $targetRevision, $hashType);
if (is_null($entity)) {
Expand All @@ -175,13 +183,48 @@ public function checksum($hash, $path, $revision) {
$view = new \OC\Files\View('/');
$info = $view->getLocalFile($targetFile);
}
$hash = hash_file($hashType, $info);
$this->logger->debug('hash: ' . $hash);
$entity = $this->saveRecord($fileid, $targetRevision, $hashType, $hash);
// check file size 20MB
if (fileSize($info) <= $this->minFileSizeToExcuteParallel || count($hashTypes) === 1) {
$hash = hash_file($hashType, $info);
$this->logger->debug('hash: ' . $hash);
$entity = $this->saveRecord($fileid, $targetRevision, $hashType, $hash);
array_push($entities, $entity);
} else {
array_push(
$tasks,
new HashableTask(
'hashCalculator',
[
"hashType" => $hashType,
"fileid" => $fileid,
"revision" => $targetRevision,
"info" => $info
],
),
);
}
} else {
array_push($entities, $entity);
}
array_push($entities, $entity);
}

if (!empty($tasks)) {
Amp\Loop::run(function () use (&$entities, $tasks) {
$pool = new DefaultPool;
$coroutines = [];
foreach ($tasks as $task) {
$coroutines[] = Amp\call(function () use ($pool, $task) {
$entity = yield $pool->enqueue($task);
$this->mapper->insert($entity);
return $entity;
});
}
$completedTask = yield Amp\Promise\all($coroutines);
foreach ($completedTask as $task) {
array_push($entities, $task);
}
return yield $pool->shutdown();
});
}
$res = [];
$hashes = [];
foreach ($entities as $entity) {
Expand Down
2 changes: 2 additions & 0 deletions lib/Db/Hash.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace OCA\ChecksumAPI\Db;

require __DIR__ . '../../../../../lib/composer/autoload.php';

use OCP\AppFramework\Db\Entity;

class Hash extends Entity {
Expand Down
2 changes: 2 additions & 0 deletions lib/Db/HashMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace OCA\ChecksumAPI\Db;

require __DIR__ . '../../../vendor/autoload.php';

use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\QBMapper;
use OCP\DB\QueryBuilder\IQueryBuilder;
Expand Down
43 changes: 43 additions & 0 deletions lib/Jobs/HashableTask.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace OCA\ChecksumAPI\Jobs;

require __DIR__ . '../../../../../lib/composer/autoload.php';

use Amp\Parallel\Worker\Environment;
use Amp\Parallel\Worker\Task;
use OCA\ChecksumAPI\Db\Hash;

class HashableTask implements Task {
/**
* @var callable
*/
private $function;

private $args;

public function __construct($function, $args) {
$this->function = $function;
$this->args = $args;
}

/**
* {@inheritdoc}
*/
public function run(Environment $environment) {
$function = $this->function;
return $this->$function($this->args);
}

public function hashCalculator($params) {
$hash = hash_file($params["hashType"], $params["info"]);
$entity = new Hash();
$entity->setFileid($params["fileid"]);
$entity->setRevision($params["revision"]);
$entity->setType($params["hashType"]);
$entity->setHash($hash);
return $entity;
}
}
2 changes: 1 addition & 1 deletion lib/Migration/Version00001Date20201016095257.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt
]);
$table->addColumn('hash', 'string', [
'notnull' => true,
'length' => 64,
'length' => 128,
'default' => '',
]);
$table->setPrimaryKey(['id']);
Expand Down
Loading