/**
  * new add data set to database
  *
  * @param array $data
  */
 public function add($data)
 {
     $source = $data['id'];
     $timestamp = time();
     $this->connection->beginTransaction();
     $query = $this->connection->getQueryBuilder();
     $query->insert($this->table)->values(['source' => $query->createNamedParameter($source), 'timestamp' => $query->createNamedParameter($timestamp), 'category' => $query->createParameter('category'), 'key' => $query->createParameter('key'), 'value' => $query->createParameter('value')]);
     $this->removeOldStatistics($source);
     foreach ($data['items'] as $item) {
         $query->setParameter('category', $item[0])->setParameter('key', $item[1])->setParameter('value', $item[2]);
         $query->execute();
     }
     $this->connection->commit();
 }
Beispiel #2
0
 /**
  * @param string $dir
  * @throws \OC\ForbiddenException
  */
 public function scan($dir = '')
 {
     if (!Filesystem::isValidPath($dir)) {
         throw new \InvalidArgumentException('Invalid path to scan');
     }
     $mounts = $this->getMounts($dir);
     foreach ($mounts as $mount) {
         if (is_null($mount->getStorage())) {
             continue;
         }
         $storage = $mount->getStorage();
         // if the home storage isn't writable then the scanner is run as the wrong user
         if ($storage->instanceOfStorage('\\OC\\Files\\Storage\\Home') and (!$storage->isCreatable('') or !$storage->isCreatable('files'))) {
             throw new ForbiddenException();
         }
         $relativePath = $mount->getInternalPath($dir);
         $scanner = $storage->getScanner();
         $scanner->setUseTransactions(false);
         $this->attachListener($mount);
         $isDbLocking = \OC::$server->getLockingProvider() instanceof DBLockingProvider;
         if (!$isDbLocking) {
             $this->db->beginTransaction();
         }
         try {
             $scanner->scan($relativePath, \OC\Files\Cache\Scanner::SCAN_RECURSIVE, \OC\Files\Cache\Scanner::REUSE_ETAG | \OC\Files\Cache\Scanner::REUSE_SIZE);
         } catch (StorageNotAvailableException $e) {
             $this->logger->error('Storage ' . $storage->getId() . ' not available');
             $this->logger->logException($e);
             $this->emit('\\OC\\Files\\Utils\\Scanner', 'StorageNotAvailable', [$e]);
         }
         if (!$isDbLocking) {
             $this->db->commit();
         }
     }
 }
 /**
  * Update properties
  *
  * @param Node $node node for which to update properties
  * @param array $properties array of properties to update
  *
  * @return bool
  */
 private function updateProperties($node, $properties)
 {
     $path = $node->getPath();
     $deleteStatement = 'DELETE FROM `*PREFIX*properties`' . ' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?';
     $insertStatement = 'INSERT INTO `*PREFIX*properties`' . ' (`userid`,`propertypath`,`propertyname`,`propertyvalue`) VALUES(?,?,?,?)';
     $updateStatement = 'UPDATE `*PREFIX*properties` SET `propertyvalue` = ?' . ' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?';
     // TODO: use "insert or update" strategy ?
     $existing = $this->getProperties($node, array());
     $this->connection->beginTransaction();
     foreach ($properties as $propertyName => $propertyValue) {
         // If it was null, we need to delete the property
         if (is_null($propertyValue)) {
             if (array_key_exists($propertyName, $existing)) {
                 $this->connection->executeUpdate($deleteStatement, array($this->user, $path, $propertyName));
             }
         } else {
             if (!array_key_exists($propertyName, $existing)) {
                 $this->connection->executeUpdate($insertStatement, array($this->user, $path, $propertyName, $propertyValue));
             } else {
                 $this->connection->executeUpdate($updateStatement, array($propertyValue, $this->user, $path, $propertyName));
             }
         }
     }
     $this->connection->commit();
     unset($this->cache[$path]);
     return true;
 }
Beispiel #4
0
 /**
  * Move a file or folder in the cache
  *
  * @param \OC\Files\Cache\Cache $sourceCache
  * @param string $sourcePath
  * @param string $targetPath
  * @throws \OC\DatabaseException
  */
 public function moveFromCache(Cache $sourceCache, $sourcePath, $targetPath)
 {
     // normalize source and target
     $sourcePath = $this->normalize($sourcePath);
     $targetPath = $this->normalize($targetPath);
     $sourceData = $sourceCache->get($sourcePath);
     $sourceId = $sourceData['fileid'];
     $newParentId = $this->getParentId($targetPath);
     list($sourceStorageId, $sourcePath) = $sourceCache->getMoveInfo($sourcePath);
     list($targetStorageId, $targetPath) = $this->getMoveInfo($targetPath);
     // sql for final update
     $moveSql = 'UPDATE `*PREFIX*filecache` SET `storage` =  ?, `path` = ?, `path_hash` = ?, `name` = ?, `parent` =? WHERE `fileid` = ?';
     if ($sourceData['mimetype'] === 'httpd/unix-directory') {
         //find all child entries
         $sql = 'SELECT `path`, `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path` LIKE ?';
         $result = $this->connection->executeQuery($sql, [$sourceStorageId, $this->connection->escapeLikeParameter($sourcePath) . '/%']);
         $childEntries = $result->fetchAll();
         $sourceLength = strlen($sourcePath);
         $this->connection->beginTransaction();
         $query = $this->connection->prepare('UPDATE `*PREFIX*filecache` SET `storage` = ?, `path` = ?, `path_hash` = ? WHERE `fileid` = ?');
         foreach ($childEntries as $child) {
             $newTargetPath = $targetPath . substr($child['path'], $sourceLength);
             $query->execute([$targetStorageId, $newTargetPath, md5($newTargetPath), $child['fileid']]);
         }
         $this->connection->executeQuery($moveSql, [$targetStorageId, $targetPath, md5($targetPath), basename($targetPath), $newParentId, $sourceId]);
         $this->connection->commit();
     } else {
         $this->connection->executeQuery($moveSql, [$targetStorageId, $targetPath, md5($targetPath), basename($targetPath), $newParentId, $sourceId]);
     }
 }
Beispiel #5
0
 /**
  * Commit the active propagation batch
  */
 public function commitBatch()
 {
     if (!$this->inBatch) {
         throw new \BadMethodCallException('Not in batch');
     }
     $this->inBatch = false;
     $this->connection->beginTransaction();
     $query = $this->connection->getQueryBuilder();
     $storageId = (int) $this->storage->getStorageCache()->getNumericId();
     $query->update('filecache')->set('mtime', $query->createFunction('GREATEST(`mtime`, ' . $query->createParameter('time') . ')'))->set('etag', $query->expr()->literal(uniqid()))->where($query->expr()->eq('storage', $query->expr()->literal($storageId, IQueryBuilder::PARAM_INT)))->andWhere($query->expr()->eq('path_hash', $query->createParameter('hash')));
     $sizeQuery = $this->connection->getQueryBuilder();
     $sizeQuery->update('filecache')->set('size', $sizeQuery->createFunction('`size` + ' . $sizeQuery->createParameter('size')))->where($query->expr()->eq('storage', $query->expr()->literal($storageId, IQueryBuilder::PARAM_INT)))->andWhere($query->expr()->eq('path_hash', $query->createParameter('hash')))->andWhere($sizeQuery->expr()->gt('size', $sizeQuery->expr()->literal(-1, IQueryBuilder::PARAM_INT)));
     foreach ($this->batch as $item) {
         $query->setParameter('time', $item['time'], IQueryBuilder::PARAM_INT);
         $query->setParameter('hash', $item['hash']);
         $query->execute();
         if ($item['size']) {
             $sizeQuery->setParameter('size', $item['size'], IQueryBuilder::PARAM_INT);
             $sizeQuery->setParameter('hash', $item['hash']);
             $sizeQuery->execute();
         }
     }
     $this->batch = [];
     $this->connection->commit();
 }
Beispiel #6
0
 /**
  * @param string $dir
  * @throws \OC\ForbiddenException
  */
 public function scan($dir = '')
 {
     if (!Filesystem::isValidPath($dir)) {
         throw new \InvalidArgumentException('Invalid path to scan');
     }
     $mounts = $this->getMounts($dir);
     foreach ($mounts as $mount) {
         if (is_null($mount->getStorage())) {
             continue;
         }
         $storage = $mount->getStorage();
         // if the home storage isn't writable then the scanner is run as the wrong user
         if ($storage->instanceOfStorage('\\OC\\Files\\Storage\\Home') and (!$storage->isCreatable('') or !$storage->isCreatable('files'))) {
             throw new ForbiddenException();
         }
         $relativePath = $mount->getInternalPath($dir);
         $scanner = $storage->getScanner();
         $scanner->setUseTransactions(false);
         $this->attachListener($mount);
         $this->db->beginTransaction();
         $scanner->scan($relativePath, \OC\Files\Cache\Scanner::SCAN_RECURSIVE, \OC\Files\Cache\Scanner::REUSE_ETAG | \OC\Files\Cache\Scanner::REUSE_SIZE);
         $this->db->commit();
     }
     $this->propagator->propagateChanges(time());
 }
Beispiel #7
0
 /**
  * @param string $dir
  * @throws \OC\ForbiddenException
  */
 public function scan($dir = '')
 {
     if (!Filesystem::isValidPath($dir)) {
         throw new \InvalidArgumentException('Invalid path to scan');
     }
     $mounts = $this->getMounts($dir);
     foreach ($mounts as $mount) {
         if (is_null($mount->getStorage())) {
             continue;
         }
         $storage = $mount->getStorage();
         // if the home storage isn't writable then the scanner is run as the wrong user
         if ($storage->instanceOfStorage('\\OC\\Files\\Storage\\Home') and (!$storage->isCreatable('') or !$storage->isCreatable('files'))) {
             if ($storage->file_exists('') or $storage->getCache()->inCache('')) {
                 throw new ForbiddenException();
             } else {
                 // if the root exists in neither the cache nor the storage the user isn't setup yet
                 break;
             }
         }
         $relativePath = $mount->getInternalPath($dir);
         $scanner = $storage->getScanner();
         $scanner->setUseTransactions(false);
         $this->attachListener($mount);
         $isDbLocking = \OC::$server->getLockingProvider() instanceof DBLockingProvider;
         $scanner->listen('\\OC\\Files\\Cache\\Scanner', 'removeFromCache', function ($path) use($storage) {
             $this->triggerPropagator($storage, $path);
         });
         $scanner->listen('\\OC\\Files\\Cache\\Scanner', 'updateCache', function ($path) use($storage) {
             $this->triggerPropagator($storage, $path);
         });
         $scanner->listen('\\OC\\Files\\Cache\\Scanner', 'addToCache', function ($path) use($storage) {
             $this->triggerPropagator($storage, $path);
         });
         if (!$isDbLocking) {
             $this->db->beginTransaction();
         }
         try {
             $storage->getPropagator()->beginBatch();
             $scanner->scan($relativePath, \OC\Files\Cache\Scanner::SCAN_RECURSIVE, \OC\Files\Cache\Scanner::REUSE_ETAG | \OC\Files\Cache\Scanner::REUSE_SIZE);
             $cache = $storage->getCache();
             if ($cache instanceof Cache) {
                 // only re-calculate for the root folder we scanned, anything below that is taken care of by the scanner
                 $cache->correctFolderSize($relativePath);
             }
             $storage->getPropagator()->commitBatch();
         } catch (StorageNotAvailableException $e) {
             $this->logger->error('Storage ' . $storage->getId() . ' not available');
             $this->logger->logException($e);
             $this->emit('\\OC\\Files\\Utils\\Scanner', 'StorageNotAvailable', [$e]);
         }
         if (!$isDbLocking) {
             $this->db->commit();
         }
     }
 }
Beispiel #8
0
 /**
  * update database with the new owners
  *
  * @param array $owners
  * @throws \Exception
  */
 private function updateOwners($owners)
 {
     $this->connection->beginTransaction();
     try {
         foreach ($owners as $id => $owner) {
             $query = $this->connection->getQueryBuilder();
             $query->update($this->table)->set('parent', $query->createNamedParameter(null))->set('uid_owner', $query->createNamedParameter($owner['owner']))->set('uid_initiator', $query->createNamedParameter($owner['initiator']))->where($query->expr()->eq('id', $query->createNamedParameter($id)))->execute();
         }
         $this->connection->commit();
     } catch (\Exception $e) {
         $this->connection->rollBack();
         throw $e;
     }
 }
Beispiel #9
0
 private function migrate(LegacyStoragesService $legacyService, StoragesService $storageService)
 {
     $existingStorage = $legacyService->getAllStorages();
     $this->connection->beginTransaction();
     try {
         foreach ($existingStorage as $storage) {
             $storageService->addStorage($storage);
         }
         $this->connection->commit();
     } catch (\Exception $e) {
         $this->logger->logException($e);
         $this->connection->rollBack();
     }
 }
Beispiel #10
0
 /**
  * @param string $path
  * @param int $type self::LOCK_SHARED or self::LOCK_EXCLUSIVE
  * @throws \OCP\Lock\LockedException
  */
 public function acquireLock($path, $type)
 {
     if ($this->connection->inTransaction()) {
         $this->logger->warning("Trying to acquire a lock for '{$path}' while inside a transition");
     }
     $this->connection->beginTransaction();
     $this->initLockField($path);
     if ($type === self::LOCK_SHARED) {
         $result = $this->connection->executeUpdate('UPDATE `*PREFIX*file_locks` SET `lock` = `lock` + 1 WHERE `key` = ? AND `lock` >= 0', [$path]);
     } else {
         $result = $this->connection->executeUpdate('UPDATE `*PREFIX*file_locks` SET `lock` = -1 WHERE `key` = ? AND `lock` = 0', [$path]);
     }
     $this->connection->commit();
     if ($result !== 1) {
         throw new LockedException($path);
     }
     $this->markAcquire($path, $type);
 }
 private function migrate(LegacyStoragesService $legacyService, StoragesService $storageService)
 {
     $existingStorage = $legacyService->getAllStorages();
     $this->connection->beginTransaction();
     try {
         foreach ($existingStorage as $storage) {
             $mountOptions = $storage->getMountOptions();
             if (!empty($mountOptions) && !isset($mountOptions['enable_sharing'])) {
                 // existing mounts must have sharing enabled by default to avoid surprises
                 $mountOptions['enable_sharing'] = true;
                 $storage->setMountOptions($mountOptions);
             }
             $storageService->addStorage($storage);
         }
         $this->connection->commit();
     } catch (\Exception $e) {
         $this->logger->logException($e);
         $this->connection->rollBack();
     }
 }
 /**
  * {@inheritdoc}
  */
 public function setTagGroups(ISystemTag $tag, $groupIds)
 {
     // delete relationships first
     $this->connection->beginTransaction();
     try {
         $query = $this->connection->getQueryBuilder();
         $query->delete(self::TAG_GROUP_TABLE)->where($query->expr()->eq('systemtagid', $query->createNamedParameter($tag->getId())))->execute();
         // add each group id
         $query = $this->connection->getQueryBuilder();
         $query->insert(self::TAG_GROUP_TABLE)->values(['systemtagid' => $query->createNamedParameter($tag->getId()), 'gid' => $query->createParameter('gid')]);
         foreach ($groupIds as $groupId) {
             $query->setParameter('gid', $groupId);
             $query->execute();
         }
         $this->connection->commit();
     } catch (\Exception $e) {
         $this->connection->rollback();
         throw $e;
     }
 }
Beispiel #13
0
 /**
  * Share a path
  *
  * @param \OCP\Share\IShare $share
  * @return \OCP\Share\IShare The share object
  * @throws ShareNotFound
  * @throws \Exception
  */
 public function create(\OCP\Share\IShare $share)
 {
     $qb = $this->dbConn->getQueryBuilder();
     $qb->insert('share');
     $qb->setValue('share_type', $qb->createNamedParameter($share->getShareType()));
     if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
         //Set the UID of the user we share with
         $qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()));
     } else {
         if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
             //Set the GID of the group we share with
             $qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()));
         } else {
             if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
                 //Set the token of the share
                 $qb->setValue('token', $qb->createNamedParameter($share->getToken()));
                 //If a password is set store it
                 if ($share->getPassword() !== null) {
                     $qb->setValue('share_with', $qb->createNamedParameter($share->getPassword()));
                 }
                 //If an expiration date is set store it
                 if ($share->getExpirationDate() !== null) {
                     $qb->setValue('expiration', $qb->createNamedParameter($share->getExpirationDate(), 'datetime'));
                 }
                 if (method_exists($share, 'getParent')) {
                     $qb->setValue('parent', $qb->createNamedParameter($share->getParent()));
                 }
             } else {
                 throw new \Exception('invalid share type!');
             }
         }
     }
     // Set what is shares
     $qb->setValue('item_type', $qb->createParameter('itemType'));
     if ($share->getNode() instanceof \OCP\Files\File) {
         $qb->setParameter('itemType', 'file');
     } else {
         $qb->setParameter('itemType', 'folder');
     }
     // Set the file id
     $qb->setValue('item_source', $qb->createNamedParameter($share->getNode()->getId()));
     $qb->setValue('file_source', $qb->createNamedParameter($share->getNode()->getId()));
     // set the permissions
     $qb->setValue('permissions', $qb->createNamedParameter($share->getPermissions()));
     // Set who created this share
     $qb->setValue('uid_initiator', $qb->createNamedParameter($share->getSharedBy()));
     // Set who is the owner of this file/folder (and this the owner of the share)
     $qb->setValue('uid_owner', $qb->createNamedParameter($share->getShareOwner()));
     // Set the file target
     $qb->setValue('file_target', $qb->createNamedParameter($share->getTarget()));
     // Set the time this share was created
     $qb->setValue('stime', $qb->createNamedParameter(time()));
     // insert the data and fetch the id of the share
     $this->dbConn->beginTransaction();
     $qb->execute();
     $id = $this->dbConn->lastInsertId('*PREFIX*share');
     $this->dbConn->commit();
     // Now fetch the inserted share and create a complete share object
     $qb = $this->dbConn->getQueryBuilder();
     $qb->select('*')->from('share')->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
     $cursor = $qb->execute();
     $data = $cursor->fetch();
     $cursor->closeCursor();
     if ($data === false) {
         throw new ShareNotFound();
     }
     $share = $this->createShare($data);
     return $share;
 }
 /**
  * Converts legacy home storage ids in the format
  * "local::/data/dir/path/userid/" to the new format "home::userid"
  */
 public function run(IOutput $out)
 {
     // only run once
     if ($this->config->getAppValue('core', 'repairlegacystoragesdone') === 'yes') {
         return;
     }
     $dataDir = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/');
     $dataDir = rtrim($dataDir, '/') . '/';
     $dataDirId = 'local::' . $dataDir;
     $count = 0;
     $hasWarnings = false;
     $this->connection->beginTransaction();
     // note: not doing a direct UPDATE with the REPLACE function
     // because regexp search/extract is needed and it is not guaranteed
     // to work on all database types
     $sql = 'SELECT `id`, `numeric_id` FROM `*PREFIX*storages`' . ' WHERE `id` LIKE ?' . ' ORDER BY `id`';
     $result = $this->connection->executeQuery($sql, array($dataDirId . '%'));
     while ($row = $result->fetch()) {
         $currentId = $row['id'];
         // one entry is the datadir itself
         if ($currentId === $dataDirId) {
             continue;
         }
         try {
             if ($this->fixLegacyStorage($currentId, (int) $row['numeric_id'])) {
                 $count++;
             }
         } catch (RepairException $e) {
             $hasWarnings = true;
             $out->warning('Could not repair legacy storage ' . $currentId . ' automatically.');
         }
     }
     // check for md5 ids, not in the format "prefix::"
     $sql = 'SELECT COUNT(*) AS "c" FROM `*PREFIX*storages`' . ' WHERE `id` NOT LIKE \'%::%\'';
     $result = $this->connection->executeQuery($sql);
     $row = $result->fetch();
     // find at least one to make sure it's worth
     // querying the user list
     if ((int) $row['c'] > 0) {
         $userManager = \OC::$server->getUserManager();
         // use chunks to avoid caching too many users in memory
         $limit = 30;
         $offset = 0;
         do {
             // query the next page of users
             $results = $userManager->search('', $limit, $offset);
             $storageIds = array();
             foreach ($results as $uid => $userObject) {
                 $storageId = $dataDirId . $uid . '/';
                 if (strlen($storageId) <= 64) {
                     // skip short storage ids as they were handled in the previous section
                     continue;
                 }
                 $storageIds[$uid] = $storageId;
             }
             if (count($storageIds) > 0) {
                 // update the storages of these users
                 foreach ($storageIds as $uid => $storageId) {
                     $numericId = Storage::getNumericStorageId($storageId);
                     try {
                         if (!is_null($numericId) && $this->fixLegacyStorage($storageId, (int) $numericId)) {
                             $count++;
                         }
                     } catch (RepairException $e) {
                         $hasWarnings = true;
                         $out->warning('Could not repair legacy storage ' . $storageId . ' automatically.');
                     }
                 }
             }
             $offset += $limit;
         } while (count($results) >= $limit);
     }
     $out->info('Updated ' . $count . ' legacy home storage ids');
     $this->connection->commit();
     if ($hasWarnings) {
         $out->warning('Some legacy storages could not be repaired. Please manually fix them then re-run ./occ maintenance:repair');
     } else {
         // if all were done, no need to redo the repair during next upgrade
         $this->config->setAppValue('core', 'repairlegacystoragesdone', 'yes');
     }
 }
Beispiel #15
0
 /**
  * Commit the database changes done during a transaction that is in progress
  */
 public function commit()
 {
     $this->connection->commit();
 }