public function callback(\OCP\Files\Node $node) { $nodepath = $node->getPath(); $username = explode('/', $nodepath)[1]; try { $user = $this->usermanager->get($username); } catch (\Exception $e) { \OCP\Util::writeLog('ftpquota', 'get user failed: ' . $e->getMessage(), \OCP\Util::ERROR); return; } try { $homedir = $user->getHome(); } catch (\Exception $e) { \OCP\Util::writeLog('ftpquota', 'get user home failed: ' . $e->getMessage(), \OCP\Util::ERROR); return; } exec("/usr/local/sbin/pure-quotacheck -d " . escapeshellarg($homedir . '/files'), $output, $return_value); if ($return_value !== 0) { \OCP\Util::writeLog('ftpquota', 'pure-quotacheck returned ' . $return_value . ' ' . implode("\n", $output), \OCP\Util::ERROR); } }
/** * Get shares for a given path * * @param \OCP\Files\Node $path * @return IShare[] */ public function getSharesByPath(Node $path) { $qb = $this->dbConnection->getQueryBuilder(); $cursor = $qb->select('*')->from('share')->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))->execute(); $shares = []; while ($data = $cursor->fetch()) { $shares[] = $this->createShare($data); } $cursor->closeCursor(); return $shares; }
/** * Determines if the node is a share which is hosted externally * * * @param Node $node * * @return bool */ private function isExternalShare($node) { $sid = explode(':', $node->getStorage()->getId()); return $sid[0] === 'shared' && $sid[2][0] !== '/'; }
/** * Returns the path which goes from the file, up to the user folder, based on a node: * parent_folder/current_folder/my_file * * This is used for the preview system, which needs a full path * * getPath() on the file produces a path like: * '/userId/files/my_folder/my_sub_folder/my_file' * * So we substract the path to the folder, giving us a relative path * 'my_folder/my_sub_folder/my_file' * * @param Node $file * * @return string */ public function getPathFromUserFolder($file) { $path = $file->getPath(); return $this->getRelativePath($path); }
/** * Makes extra sure that we can actually do something with the file * * @param Node $node * * @throws NotFoundServiceException */ private function validateNode($node) { if (!$node->getMimetype() || !$node->isReadable()) { throw new NotFoundServiceException("Can't access the file"); } }
/** * Returns what we known about the owner of a node * * @param Node $node * * @return null|array<string,int|string> */ private function getOwnerData($node) { $owner = $node->getOwner(); $ownerData = []; if ($owner) { $ownerData = ['uid' => $owner->getUID(), 'displayname' => $owner->getDisplayName()]; } return $ownerData; }
/** * Get called by 'post_write' hook (file creation, file update) * @param \OCP\Files\Node $file the file */ public function update($file, $userId) { // debug logging $this->logger->log('update - ' . $file->getPath(), 'debug'); if (!$file instanceof \OCP\Files\File) { return; } $mimetype = $file->getMimeType(); // debug logging $this->logger->log('update - mimetype ' . $mimetype, 'debug'); $this->emit('\\OCA\\Music\\Utility\\Scanner', 'update', array($file->getPath())); if (substr($mimetype, 0, 5) === 'image') { $coverFileId = $file->getId(); $parentFolderId = $file->getParent()->getId(); $this->albumBusinessLayer->updateCover($coverFileId, $parentFolderId); return; } if (substr($mimetype, 0, 5) !== 'audio' && substr($mimetype, 0, 15) !== 'application/ogg') { return; } if (ini_get('allow_url_fopen')) { // TODO find a way to get this for a sharee $isSharee = $userId && $this->userId !== $userId; $musicPath = $this->configManager->getUserValue($this->userId, $this->appName, 'path'); if ($musicPath !== null || $musicPath !== '/' || $musicPath !== '') { // TODO verify $musicPath = $this->userFolder->get($musicPath)->getPath(); // skip files that aren't inside the user specified path (and also for sharees - TODO remove this) if (!$isSharee && substr($file->getPath(), 0, strlen($musicPath)) !== $musicPath) { $this->logger->log('skipped - outside of specified path', 'debug'); return; } } $fileInfo = $this->extractor->extract('oc://' . $file->getPath()); $hasComments = array_key_exists('comments', $fileInfo); if (!$hasComments) { // TODO: fix this dirty fallback // fallback to local file path removed $this->logger->log('fallback metadata extraction - removed code', 'debug'); // $fileInfo = $this->extractor->extract($this->api->getLocalFilePath($path)); // $hasComments = array_key_exists('comments', $fileInfo); } // artist $artist = null; if ($hasComments && array_key_exists('artist', $fileInfo['comments'])) { $artist = $fileInfo['comments']['artist'][0]; if (count($fileInfo['comments']['artist']) > 1) { $this->logger->log('multiple artists found (use shortest): ' . implode(', ', $fileInfo['comments']['artist']), 'debug'); // determine shortest, because the longer names are just concatenations of all artists for ($i = 0; $i < count($fileInfo['comments']['artist']); $i++) { if (strlen($fileInfo['comments']['artist'][$i]) < strlen($artist)) { $artist = $fileInfo['comments']['artist'][$i]; } } } } if ($artist === '') { // assume artist is not set $artist = null; } $alternativeTrackNumber = null; // title $title = null; if ($hasComments && array_key_exists('title', $fileInfo['comments'])) { $title = $fileInfo['comments']['title'][0]; } if ($title === null || $title === '') { // fallback to file name $title = $file->getName(); if (preg_match('/^(\\d+)\\W*[.-]\\W*(.*)/', $title, $matches) === 1) { $alternativeTrackNumber = $matches[1]; if (preg_match('/(.*)(\\.(mp3|ogg))$/', $matches[2], $titleMatches) === 1) { $title = $titleMatches[1]; } else { $title = $matches[2]; } } } // album $album = null; if ($hasComments && array_key_exists('album', $fileInfo['comments'])) { $album = $fileInfo['comments']['album'][0]; } if ($album === '' || $album === null) { // album name not set in fileinfo, use parent folder name as album name if ($this->userFolder->getId() === $file->getParent()->getId()) { // if the file is in user home, still set album name to unknown $album = null; } else { $album = $file->getParent()->getName(); } } // track number $trackNumber = null; if ($hasComments && array_key_exists('track_number', $fileInfo['comments'])) { $trackNumber = $fileInfo['comments']['track_number'][0]; } if ($trackNumber === null && $alternativeTrackNumber !== null) { $trackNumber = $alternativeTrackNumber; } // convert track number '1/10' to '1' $tmp = explode('/', $trackNumber); $trackNumber = $tmp[0]; // check for numeric values - cast them to int and verify it's a natural number above 0 if (is_numeric($trackNumber) && (int) $trackNumber > 0) { $trackNumber = (int) $trackNumber; } else { $trackNumber = null; } $year = null; if ($hasComments && array_key_exists('year', $fileInfo['comments'])) { $year = $fileInfo['comments']['year'][0]; if (!ctype_digit($year)) { $year = null; } } $fileId = $file->getId(); $length = null; if (array_key_exists('playtime_seconds', $fileInfo)) { $length = ceil($fileInfo['playtime_seconds']); } $bitrate = null; if (array_key_exists('audio', $fileInfo) && array_key_exists('bitrate', $fileInfo['audio'])) { $bitrate = $fileInfo['audio']['bitrate']; } // debug logging $this->logger->log('extracted metadata - ' . sprintf('artist: %s, album: %s, title: %s, track#: %s, year: %s, mimetype: %s, length: %s, bitrate: %s, fileId: %i, this->userId: %s, userId: %s', $artist, $album, $title, $trackNumber, $year, $mimetype, $length, $bitrate, $fileId, $this->userId, $userId), 'debug'); if (!$userId) { $userId = $this->userId; } // add artist and get artist entity $artist = $this->artistBusinessLayer->addArtistIfNotExist($artist, $userId); $artistId = $artist->getId(); // add album and get album entity $album = $this->albumBusinessLayer->addAlbumIfNotExist($album, $year, $artistId, $userId); $albumId = $album->getId(); // add track and get track entity $track = $this->trackBusinessLayer->addTrackIfNotExist($title, $trackNumber, $artistId, $albumId, $fileId, $mimetype, $userId, $length, $bitrate); // debug logging $this->logger->log('imported entities - ' . sprintf('artist: %d, album: %d, track: %d', $artistId, $albumId, $track->getId()), 'debug'); } }
/** * Returns the path which goes from the file, up to the root folder of the Gallery: * current_folder/my_file * * That root folder changes when folders are shared publicly * * @param File|Folder|Node $node * * @return string */ public function getPathFromVirtualRoot($node) { $path = $node->getPath(); $nodeType = $node->getType(); // Needed because fromRootToFolder always ends with a slash if ($nodeType === 'dir') { $path .= '/'; } $path = str_replace($this->fromRootToFolder, '', $path); $path = rtrim($path, '/'); return $path; }