Listen to \OC\Filesystem's read signal via Util::connectHook

Hey there, again :wink:

I try to listen to file reads by connecting via the method described in the post title, inspired by how Joas Schilling did it in his files_downloadactivity app:

Application.php

public function __construct(array $urlParams = array()) {
    parent::__construct('hyperlog', $urlParams);

    $container = $this->getContainer();
    $this->registerHooks();
}

private function registerHooks() {
    $this->getContainer()->query('SessionHooks')->register();
    $this->getContainer()->query('FileHooks')->register();
    // read-hook (for logging downloads)
    Util::connectHook('OC_Filesystem', 'read', $this, 'listenReadFile');
}

public function listenReadFile($params) {
    /** @var Listener $hooks */
    $hooks = $this->getContainer()->query(Listener::class);
    $hooks->readFile($params['path']);
}

Listener.php

<?php
namespace OCA\HyperLog\Activity;


use OCA\HyperLog\Service\LogService;
use OCP\Files\IRootFolder;
use OCP\IRequest;
use OCP\IUser;

class Listener {
    protected $rootFolder;
    protected $request;
    protected $user;
    protected $logService;

    public function __construct(IRootFolder $rootFolder, IRequest $request, IUser $user, LogService $logService) {
        $this->rootFolder = $rootFolder;
        $this->request = $request;
        $this->user = $user;
        $this->logService = $logService;

        $this->logService->log('Listener instantiated');
    }

    public function readFile($path) {
        $this->logService->log(sprintf('File %s read', $path));
    }
}

Nothing is being logged and Listener doesn't seem to get instantiated. Am I missing something? I thought instantiation would happen automatically.

Any help appreciated.

Best regards,
Constantin

Hi again, It is a nextcloud app and as far as I know, ownCloud has not any hook or event for reading a file. Maybe you can open an issue about this or better create a pull request for that purpose in Github.

By the way, did u try the storage wrapper idea?

Hey there,

yes, I did try the storage wrapper idea but it turned out to be not so easy as i thought first. So far it works only for thumbnails displayed in the web UI. Maybe it has something to do with the following error message that appears in my owncloud.log:

Storage wrapper 'LogWrapper' was not registered via the 'OC_Filesystem - preSetup' hook which could cause potential problems.

Having taken a quick look into owncloud/core I thought OC_Filesystem would emit that signal so I could hook in there:

Storage wrapper should work theoratically, whatever :slight_smile: Seems like you are right about read signals. I found before and after read event in here https://github.com/owncloud/core/blob/2a6722494dcecf175597d524093ceeeef10d47ae/lib/private/Files/View.php#L586 . You can listen this event to achieve your purpose. Your listener should something like that https://github.com/owncloud/security/blob/master/lib/Hooks.php#L82. You will listen "file.beforeread" and "file.afterread" events, these events are supplying path as an argument.

Hey karakayasemi,

your StorageWrapper idea works indeed! :blush:
I mistakenly constrained the file access events to be logged to 'r' mode… turned out downloaded files are opened in 'rb' mode. So that's it, I guess.

Thank you very much for that!

Glad to hear that :slight_smile: