Skip to content

Commit ef6a3bf

Browse files
authored
Fix database query to also return files not stored on local backends (fixes #72) (#269)
1 parent 66f1028 commit ef6a3bf

1 file changed

Lines changed: 67 additions & 50 deletions

File tree

lib/Db/DbFileMapper.php

Lines changed: 67 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,38 @@
11
<?php
22

3-
// SPDX-FileCopyrightText: 2025 Lennart Dohmann <lennart.dohmann@gdata.de>
3+
// SPDX-FileCopyrightText: 2025 G DATA CyberDefense AG
4+
// SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
5+
// SPDX-FileCopyrightText: 2012-2016 ownCloud, Inc.
46
//
57
// SPDX-License-Identifier: AGPL-3.0-or-later
68

9+
// Parts of this file are copied from the nextcloud files_antivirus app
10+
// https://github.com/nextcloud/files_antivirus
11+
// /blob/00b25bfe35af45627d871e905c8eb94554df4b9d/lib/BackgroundJob/BackgroundScanner.php
12+
713
namespace OCA\GDataVaas\Db;
814

915
use OCP\AppFramework\Db\QBMapper;
1016
use OCP\DB\Exception;
1117
use OCP\DB\QueryBuilder\IQueryBuilder;
18+
use OCP\Files\FileInfo;
19+
use OCP\Files\IMimeTypeLoader;
20+
use OCP\IConfig;
1221
use OCP\IDBConnection;
1322

1423
class DbFileMapper extends QBMapper {
1524
private string $stringType;
25+
private IMimeTypeLoader $mimeTypeLoader;
26+
private IConfig $config;
1627

1728
/**
1829
* @throws Exception
1930
*/
20-
public function __construct(IDBConnection $db) {
31+
public function __construct(IDBConnection $db, IMimeTypeLoader $mimeTypeLoader, IConfig $config) {
2132
parent::__construct($db, 'filecache');
2233
$this->stringType = $this->getStringTypeDeclarationSQL();
34+
$this->mimeTypeLoader = $mimeTypeLoader;
35+
$this->config = $config;
2336
}
2437

2538
/**
@@ -48,34 +61,33 @@ private function getStringTypeDeclarationSQL(): string {
4861
* @throws Exception if the database platform is not supported
4962
*/
5063
public function getFileIdsWithoutTags(array $excludedTagIds, int $limit, int $offset = 0): array {
51-
$qb = $this->db->getQueryBuilder();
52-
$qb->automaticTablePrefix(true);
64+
$dirMimeTypeId = $this->mimeTypeLoader->getId(FileInfo::MIMETYPE_FOLDER);
65+
$instanceId = $this->config->getSystemValue('instanceid', '');
5366

54-
$qb->select('f.fileid')
55-
->from($this->getTableName(), 'f')
67+
$query = $this->db->getQueryBuilder();
68+
$query->select('fc.fileid')
69+
->from('filecache', 'fc')
70+
->leftJoin('fc', 'storages', 's', $query->expr()->eq('fc.storage', 's.numeric_id'))
5671
->leftJoin(
57-
'f', 'systemtag_object_mapping', 'o', $qb->expr()->eq(
58-
'o.objectid', $qb->createFunction(sprintf('CAST(f.fileid AS %s)', $this->stringType))))
59-
->leftJoin('f', 'mimetypes', 'm', $qb->expr()->eq('f.mimetype', 'm.id'))
60-
->where($qb->expr()->notIn(
61-
'o.systemtagid', $qb->createNamedParameter($excludedTagIds, IQueryBuilder::PARAM_INT_ARRAY)))
62-
->orWhere($qb->expr()->isNull('o.systemtagid'))
63-
->andWhere($qb->expr()->notLike('m.mimetype', $qb->createNamedParameter('%unix-directory%')))
64-
->andWhere($qb->expr()->orX(
65-
$qb->expr()->eq('o.objecttype', $qb->createNamedParameter('files')),
66-
$qb->expr()->isNull('o.objecttype')
67-
))
68-
->andWhere($qb->expr()->orX(
69-
$qb->expr()->like('f.path', $qb->createNamedParameter('files/%')),
70-
$qb->expr()->like('f.path', $qb->createNamedParameter('__groupfolders/%'))
72+
'fc', 'systemtag_object_mapping', 'o', $query->expr()->eq(
73+
'o.objectid', $query->createFunction(sprintf('CAST(fc.fileid AS %s)', $this->stringType))))
74+
->where($query->expr()->notIn(
75+
'o.systemtagid', $query->createNamedParameter($excludedTagIds, IQueryBuilder::PARAM_INT_ARRAY)))
76+
->orWhere($query->expr()->isNull('o.systemtagid'))
77+
->andWhere($query->expr()->neq('fc.mimetype', $query->createNamedParameter($dirMimeTypeId)))
78+
->andWhere($query->expr()->orX(
79+
$query->expr()->like('fc.path', $query->createNamedParameter('files/%')),
80+
$query->expr()->notLike('s.id', $query->createNamedParameter('home::%'))
7181
))
72-
->andWhere($qb->expr()->notLike('f.path', $qb->createNamedParameter('__groupfolders/versions/%')))
73-
->orderBy('f.fileid', 'DESC')
82+
->andWhere($query->expr()->notLike('fc.path', $query->createNamedParameter("appdata_$instanceId/%")))
83+
->andWhere($query->expr()->notLike('fc.path', $query->createNamedParameter("\_\_groupfolders/versions/%")))
84+
->andWhere($query->expr()->notLike('fc.path', $query->createNamedParameter("\_\_groupfolders/trash/%")))
85+
->orderBy('fc.fileid', 'DESC')
7486
->setFirstResult($offset)
7587
->setMaxResults($limit);
7688

7789
$fileIds = [];
78-
$result = $qb->executeQuery();
90+
$result = $query->executeQuery();
7991
while ($row = $result->fetch()) {
8092
$fileIds[] = $row['fileid'];
8193
}
@@ -91,30 +103,33 @@ public function getFileIdsWithoutTags(array $excludedTagIds, int $limit, int $of
91103
* @throws Exception if the database platform is not supported
92104
*/
93105
public function getFileIdsWithTags(array $includedTagIds, int $limit, int $offset = 0): array {
94-
$qb = $this->db->getQueryBuilder();
95-
$qb->automaticTablePrefix(true);
106+
$dirMimeTypeId = $this->mimeTypeLoader->getId(FileInfo::MIMETYPE_FOLDER);
107+
$instanceId = $this->config->getSystemValue('instanceid', '');
96108

97-
$qb->select('f.fileid')
98-
->from($this->getTableName(), 'f')
109+
$query = $this->db->getQueryBuilder();
110+
$query->select('fc.fileid')
111+
->from('filecache', 'fc')
112+
->leftJoin('fc', 'storages', 's', $query->expr()->eq('fc.storage', 's.numeric_id'))
99113
->leftJoin(
100-
'f', 'systemtag_object_mapping', 'o', $qb->expr()->eq(
101-
'o.objectid', $qb->createFunction(sprintf('CAST(f.fileid AS %s)', $this->stringType))))
102-
->leftJoin('f', 'mimetypes', 'm', $qb->expr()->eq('f.mimetype', 'm.id'))
103-
->where($qb->expr()->in(
104-
'o.systemtagid', $qb->createNamedParameter($includedTagIds, IQueryBuilder::PARAM_INT_ARRAY)))
105-
->andWhere($qb->expr()->notLike('m.mimetype', $qb->createNamedParameter('%unix-directory%')))
106-
->andWhere($qb->expr()->eq('o.objecttype', $qb->createNamedParameter('files')))
107-
->andWhere($qb->expr()->orX(
108-
$qb->expr()->like('f.path', $qb->createNamedParameter('files/%')),
109-
$qb->expr()->like('f.path', $qb->createNamedParameter('__groupfolders/%'))
114+
'fc', 'systemtag_object_mapping', 'o', $query->expr()->eq(
115+
'o.objectid', $query->createFunction(sprintf('CAST(fc.fileid AS %s)', $this->stringType))))
116+
->where($query->expr()->in(
117+
'o.systemtagid', $query->createNamedParameter($includedTagIds, IQueryBuilder::PARAM_INT_ARRAY)))
118+
->orWhere($query->expr()->isNull('o.systemtagid'))
119+
->andWhere($query->expr()->neq('fc.mimetype', $query->createNamedParameter($dirMimeTypeId)))
120+
->andWhere($query->expr()->orX(
121+
$query->expr()->like('fc.path', $query->createNamedParameter('files/%')),
122+
$query->expr()->notLike('s.id', $query->createNamedParameter('home::%'))
110123
))
111-
->andWhere($qb->expr()->notLike('f.path', $qb->createNamedParameter('__groupfolders/versions/%')))
112-
->orderBy('f.fileid', 'DESC')
124+
->andWhere($query->expr()->notLike('fc.path', $query->createNamedParameter("appdata_$instanceId/%")))
125+
->andWhere($query->expr()->notLike('fc.path', $query->createNamedParameter("\_\_groupfolders/versions/%")))
126+
->andWhere($query->expr()->notLike('fc.path', $query->createNamedParameter("\_\_groupfolders/trash/%")))
127+
->orderBy('fc.fileid', 'DESC')
113128
->setFirstResult($offset)
114129
->setMaxResults($limit);
115130

116131
$fileIds = [];
117-
$result = $qb->executeQuery();
132+
$result = $query->executeQuery();
118133
while ($row = $result->fetch()) {
119134
$fileIds[] = $row['fileid'];
120135
}
@@ -129,20 +144,22 @@ public function getFileIdsWithTags(array $includedTagIds, int $limit, int $offse
129144
public function getFilesCount(): int {
130145
$fileCount = 0;
131146

147+
$dirMimeTypeId = $this->mimeTypeLoader->getId(FileInfo::MIMETYPE_FOLDER);
148+
$instanceId = $this->config->getSystemValue('instanceid', '');
149+
132150
$fileQuery = $this->db->getQueryBuilder();
133151
$fileQuery->select($fileQuery->func()->count())
134-
->from('filecache', 'f')
135-
->leftJoin('f', 'mimetypes', 'm', $fileQuery->expr()->eq('f.mimetype', 'm.id'))
136-
->where($fileQuery->expr()->eq('storage', $fileQuery->createParameter('storageId')))
137-
->andWhere($fileQuery->expr()->notLike(
138-
'm.mimetype', $fileQuery->createNamedParameter('%unix-directory%'))
139-
)
152+
->from('filecache', 'fc')
153+
->leftJoin('fc', 'storages', 's', $fileQuery->expr()->eq('fc.storage', 's.numeric_id'))
154+
->where($fileQuery->expr()->eq('fc.storage', $fileQuery->createParameter('storageId')))
155+
->andWhere($fileQuery->expr()->neq('fc.mimetype', $fileQuery->createNamedParameter($dirMimeTypeId)))
140156
->andWhere($fileQuery->expr()->orX(
141-
$fileQuery->expr()->like('f.path', $fileQuery->createNamedParameter('files/%')),
142-
$fileQuery->expr()->like('f.path', $fileQuery->createNamedParameter('__groupfolders/%'))
157+
$fileQuery->expr()->like('fc.path', $fileQuery->createNamedParameter('files/%')),
158+
$fileQuery->expr()->notLike('s.id', $fileQuery->createNamedParameter('home::%'))
143159
))
144-
->andWhere($fileQuery->expr()->notLike('f.path', $fileQuery->createNamedParameter('__groupfolders/versions/%')));
145-
160+
->andWhere($fileQuery->expr()->notLike('fc.path', $fileQuery->createNamedParameter("appdata_$instanceId/%")))
161+
->andWhere($fileQuery->expr()->notLike('fc.path', $fileQuery->createNamedParameter("\_\_groupfolders/versions/%")))
162+
->andWhere($fileQuery->expr()->notLike('fc.path', $fileQuery->createNamedParameter("\_\_groupfolders/trash/%")));
146163

147164
$storageQuery = $this->db->getQueryBuilder();
148165
$storageQuery->selectAlias('numeric_id', 'id')

0 commit comments

Comments
 (0)