Example #1
0
 /**
  * This method is called before any HTTP method and validates there is enough free space to store the file
  *
  * @param string $uri
  * @param null $data
  * @throws \Sabre\DAV\Exception\InsufficientStorage
  * @return bool
  */
 public function checkQuota($uri, $data = null)
 {
     $length = $this->getLength();
     if ($length) {
         if (substr($uri, 0, 1) !== '/') {
             $uri = '/' . $uri;
         }
         list($parentUri, $newName) = \Sabre\HTTP\URLUtil::splitPath($uri);
         if (is_null($parentUri)) {
             $parentUri = '';
         }
         $req = $this->server->httpRequest;
         if ($req->getHeader('OC-Chunked')) {
             $info = \OC_FileChunking::decodeName($newName);
             $chunkHandler = new \OC_FileChunking($info);
             // subtract the already uploaded size to see whether
             // there is still enough space for the remaining chunks
             $length -= $chunkHandler->getCurrentSize();
         }
         $freeSpace = $this->getFreeSpace($parentUri);
         if ($freeSpace !== \OCP\Files\FileInfo::SPACE_UNKNOWN && $length > $freeSpace) {
             if (isset($chunkHandler)) {
                 $chunkHandler->cleanup();
             }
             throw new \Sabre\DAV\Exception\InsufficientStorage();
         }
     }
     return true;
 }
 /**
  * Our PROPFIND handler
  *
  * Here we set a contenttype, if the node didn't already have one.
  *
  * @param PropFind $propFind
  * @param INode $node
  * @return void
  */
 function propFind(PropFind $propFind, INode $node)
 {
     $propFind->handle('{DAV:}getcontenttype', function () use($propFind) {
         list(, $fileName) = URLUtil::splitPath($propFind->getPath());
         return $this->getContentType($fileName);
     });
 }
Example #3
0
 private function convertPrincipal($principal, $toV2)
 {
     list(, $name) = URLUtil::splitPath($principal);
     if ($toV2) {
         return "principals/users/{$name}";
     }
     return "principals/{$name}";
 }
Example #4
0
 /**
  * Renames the node
  *
  * @param string $name The new name
  * @return void
  */
 function setName($name)
 {
     list($parentPath, ) = URLUtil::splitPath($this->path);
     list(, $newName) = URLUtil::splitPath($name);
     $newPath = $parentPath . '/' . $newName;
     rename($this->path, $newPath);
     $this->path = $newPath;
 }
Example #5
0
 /**
  * Renames the node
  *
  * @param string $name The new name
  * @return void
  */
 public function setName($name)
 {
     list($parentPath, ) = URLUtil::splitPath($this->path);
     list(, $newName) = URLUtil::splitPath($name);
     $newPath = $parentPath . '/' . $newName;
     Utils::renameObject($this->nodeId, $name);
     // rename($this->path,$newPath);
     $this->path = $newPath;
 }
Example #6
0
 public function getName()
 {
     if ($this->isLink) {
         return $this->sharedNode->getName();
     } else {
         list(, $name) = \Sabre\HTTP\URLUtil::splitPath($this->linkPath);
         return $name;
     }
 }
Example #7
0
 /**
  * Returns the addressbook home for a given principal
  *
  * @param string $principal
  * @return string
  */
 protected function getAddressbookHomeForPrincipal($principal)
 {
     if (strrpos($principal, 'principals/users', -strlen($principal)) !== FALSE) {
         list(, $principalId) = URLUtil::splitPath($principal);
         return self::ADDRESSBOOK_ROOT . '/users/' . $principalId;
     }
     if (strrpos($principal, 'principals/system', -strlen($principal)) !== FALSE) {
         list(, $principalId) = URLUtil::splitPath($principal);
         return self::ADDRESSBOOK_ROOT . '/system/' . $principalId;
     }
     throw new \LogicException('This is not supposed to happen');
 }
 function getCalendarsForUser($principalUri)
 {
     /** @var Termin $termin */
     $termin = Termin::model()->findByPk($this->termin_id);
     if (!$termin) {
         return [];
     }
     list(, $name) = \Sabre\HTTP\URLUtil::splitPath($principalUri);
     if ($name !== 'guest') {
         return [];
     }
     return [['id' => $this->termin_id, 'uri' => $this->termin_id, 'principaluri' => $principalUri, '{DAV:}displayname' => $termin->gremium->getName(), '{' . \Sabre\CalDAV\Plugin::NS_CALENDARSERVER . '}getctag' => rand(0, 100000000), '{http://sabredav.org/ns}sync-token' => '0', '{' . \Sabre\CalDAV\Plugin::NS_CALDAV . '}supported-calendar-component-set' => new \Sabre\CalDAV\Property\SupportedCalendarComponentSet(["VEVENT", "VJOURNAL", "VTODO"]), '{' . \Sabre\CalDAV\Plugin::NS_CALDAV . '}schedule-calendar-transp' => new \Sabre\CalDAV\Property\ScheduleCalendarTransp('opaque'), '{http://sabredav.org/ns}read-only' => '1']];
 }
Example #9
0
 /**
  * Renames the node
  * @param string $name The new name
  * @throws \Sabre\DAV\Exception\BadRequest
  * @throws \Sabre\DAV\Exception\Forbidden
  */
 public function setName($name)
 {
     // rename is only allowed if the update privilege is granted
     if (!$this->info->isUpdateable()) {
         throw new \Sabre\DAV\Exception\Forbidden();
     }
     list($parentPath, ) = \Sabre\HTTP\URLUtil::splitPath($this->path);
     list(, $newName) = \Sabre\HTTP\URLUtil::splitPath($name);
     // verify path of the target
     $this->verifyPath();
     $newPath = $parentPath . '/' . $newName;
     $this->fileView->rename($this->path, $newPath);
     $this->path = $newPath;
     $this->refreshInfo();
 }
Example #10
0
 /**
  * This method returns a node for a principal.
  *
  * The passed array contains principal information, and is guaranteed to
  * at least contain a uri item. Other properties may or may not be
  * supplied by the authentication backend.
  *
  * @param array $principal
  * @return \Sabre\DAV\INode
  */
 function getChildForPrincipal(array $principal)
 {
     $node = parent::getChildForPrincipal($principal);
     /*
      * Création du carnet d'adresse par défaut s'il n'existe pas
      */
     if (!$node || count($node->getChildren()) == 0) {
         //No addressBook. Create default one
         $principalUri = $principal["uri"];
         list(, $principalId) = \Sabre\HTTP\URLUtil::splitPath($principalUri);
         $name = "contacts";
         $properties = ['{DAV:}displayname' => $name, '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}addressbook-description' => "Contacts de " . $principalId];
         $this->carddavBackend->createAddressBook($principalUri, $name, $properties);
         $node = parent::getChildForPrincipal($principal);
     }
     return $node;
 }
Example #11
0
 /**
  * This method returns a node for a principal.
  *
  * The passed array contains principal information, and is guaranteed to
  * at least contain a uri item. Other properties may or may not be
  * supplied by the authentication backend.
  *
  * @param array $principal
  * @return \Sabre\DAV\INode
  */
 function getChildForPrincipal(array $principal)
 {
     $node = parent::getChildForPrincipal($principal);
     /*
      * Création du calendrier par défaut s'il n'existe pas
      */
     if (!$node || count($node->getChildren()) == 0) {
         //No calendar. Create default one
         $principalUri = $principal["uri"];
         list(, $principalId) = \Sabre\HTTP\URLUtil::splitPath($principalUri);
         $name = $principalId;
         $properties = ['{DAV:}displayname' => $name, '{' . \Sabre\CalDAV\Plugin::NS_CALDAV . '}calendar' => $name];
         $this->caldavBackend->createCalendar($principalUri, $name, $properties);
         $node = parent::getChildForPrincipal($principal);
     }
     return $node;
 }
Example #12
0
 /**
  * Returns a list of principals based on a prefix.
  *
  * This prefix will often contain something like 'principals'. You are only
  * expected to return principals that are in this base path.
  *
  * You are expected to return at least a 'uri' for every user, you can
  * return any additional properties if you wish so. Common properties are:
  *   {DAV:}displayname
  *   {http://sabredav.org/ns}email-address - This is a custom SabreDAV
  *	 field that's actualy injected in a number of other properties. If
  *	 you have an email address, use this property.
  *
  * @param string $prefixPath
  * @return array
  */
 function getPrincipalsByPrefix($prefixPath)
 {
     $principals = [];
     foreach ($this->allprincipals as $row) {
         // Checking if the principal is in the prefix
         list($rowPrefix) = URLUtil::splitPath($row['uri']);
         if ($rowPrefix !== $prefixPath) {
             continue;
         }
         $principal = ['uri' => $row['uri']];
         foreach ($this->fieldMap as $key => $value) {
             if ($row[$value['dbField']]) {
                 $principal[$key] = $row[$value['dbField']];
             }
         }
         $principals[] = $principal;
     }
     return $principals;
 }
Example #13
0
 /**
  * Returns the list of address books for a specific user.
  *
  * Every addressbook should have the following properties:
  *   id - an arbitrary unique id
  *   uri - the 'basename' part of the url
  *   principaluri - Same as the passed parameter
  *
  * Any additional clark-notation property may be passed besides this. Some
  * common ones are :
  *   {DAV:}displayname
  *   {urn:ietf:params:xml:ns:carddav}addressbook-description
  *   {http://calendarserver.org/ns/}getctag
  *
  * @param string $principalUri
  * @return array
  */
 function getAddressBooksForUser($principalUri)
 {
     $query = $this->db->getQueryBuilder();
     $query->select(['id', 'uri', 'displayname', 'principaluri', 'description', 'synctoken'])->from('addressbooks')->where($query->expr()->eq('principaluri', $query->createParameter('principaluri')))->setParameter('principaluri', $principalUri);
     $addressBooks = [];
     $result = $query->execute();
     while ($row = $result->fetch()) {
         $addressBooks[] = ['id' => $row['id'], 'uri' => $row['uri'], 'principaluri' => $row['principaluri'], '{DAV:}displayname' => $row['displayname'], '{' . Plugin::NS_CARDDAV . '}addressbook-description' => $row['description'], '{http://calendarserver.org/ns/}getctag' => $row['synctoken'], '{http://sabredav.org/ns}sync-token' => $row['synctoken'] ? $row['synctoken'] : '0'];
     }
     $result->closeCursor();
     // query for shared calendars
     $principals = $this->principalBackend->getGroupMembership($principalUri);
     $principals[] = $principalUri;
     $query = $this->db->getQueryBuilder();
     $result = $query->select(['a.id', 'a.uri', 'a.displayname', 'a.principaluri', 'a.description', 'a.synctoken', 's.access'])->from('dav_shares', 's')->join('s', 'addressbooks', 'a', $query->expr()->eq('s.resourceid', 'a.id'))->where($query->expr()->in('s.principaluri', $query->createParameter('principaluri')))->andWhere($query->expr()->eq('s.type', $query->createParameter('type')))->setParameter('type', 'addressbook')->setParameter('principaluri', $principals, IQueryBuilder::PARAM_STR_ARRAY)->execute();
     while ($row = $result->fetch()) {
         list(, $name) = URLUtil::splitPath($row['principaluri']);
         $uri = $row['uri'] . '_shared_by_' . $name;
         $displayName = $row['displayname'] . "({$name})";
         $addressBooks[] = ['id' => $row['id'], 'uri' => $uri, 'principaluri' => $principalUri, '{DAV:}displayname' => $displayName, '{' . Plugin::NS_CARDDAV . '}addressbook-description' => $row['description'], '{http://calendarserver.org/ns/}getctag' => $row['synctoken'], '{http://sabredav.org/ns}sync-token' => $row['synctoken'] ? $row['synctoken'] : '0', '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}owner-principal' => $row['principaluri'], '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}read-only' => $row['access'] === self::ACCESS_READ];
     }
     $result->closeCursor();
     return $addressBooks;
 }
Example #14
0
 /**
  * This method tells the tree system to pre-fetch and cache a list of
  * children of a single parent.
  *
  * There are a bunch of operations in the WebDAV stack that request many
  * children (based on uris), and sometimes fetching many at once can
  * optimize this.
  *
  * This method returns an array with the found nodes. It's keys are the
  * original paths. The result may be out of order.
  *
  * @param array $paths List of nodes that must be fetched.
  * @return array
  */
 function getMultipleNodes($paths)
 {
     // Finding common parents
     $parents = [];
     foreach ($paths as $path) {
         list($parent, $node) = URLUtil::splitPath($path);
         if (!isset($parents[$parent])) {
             $parents[$parent] = [$node];
         } else {
             $parents[$parent][] = $node;
         }
     }
     $result = [];
     foreach ($parents as $parent => $children) {
         $parentNode = $this->getNodeForPath($parent);
         if ($parentNode instanceof IMultiGet) {
             foreach ($parentNode->getMultipleChildren($children) as $childNode) {
                 $fullPath = $parent . '/' . $childNode->getName();
                 $result[$fullPath] = $childNode;
                 $this->cache[$fullPath] = $childNode;
             }
         } else {
             foreach ($children as $child) {
                 $fullPath = $parent . '/' . $child;
                 $result[$fullPath] = $this->getNodeForPath($fullPath);
             }
         }
     }
     return $result;
 }
Example #15
0
 /**
  * Copies a file or directory.
  *
  * This method must work recursively and delete the destination
  * if it exists
  *
  * @param string $source
  * @param string $destination
  * @throws \Sabre\DAV\Exception\ServiceUnavailable
  * @return void
  */
 public function copy($source, $destination)
 {
     if (!$this->fileView) {
         throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup');
     }
     // this will trigger existence check
     $this->getNodeForPath($source);
     list($destinationDir, $destinationName) = \Sabre\HTTP\URLUtil::splitPath($destination);
     try {
         $this->fileView->verifyPath($destinationDir, $destinationName);
     } catch (\OCP\Files\InvalidPathException $ex) {
         throw new InvalidPath($ex->getMessage());
     }
     try {
         $this->fileView->copy($source, $destination);
     } catch (StorageNotAvailableException $e) {
         throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
     } catch (ForbiddenException $ex) {
         throw new Forbidden($ex->getMessage(), $ex->getRetry());
     } catch (LockedException $e) {
         throw new FileLocked($e->getMessage(), $e->getCode(), $e);
     }
     list($destinationDir, ) = \Sabre\HTTP\URLUtil::splitPath($destination);
     $this->markDirty($destinationDir);
 }
Example #16
0
 /**
  * @param string $filePath
  * @param \Sabre\DAV\INode $node
  * @throws \Sabre\DAV\Exception\BadRequest
  */
 public function sendFileIdHeader($filePath, \Sabre\DAV\INode $node = null)
 {
     // chunked upload handling
     if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
         list($path, $name) = \Sabre\HTTP\URLUtil::splitPath($filePath);
         $info = \OC_FileChunking::decodeName($name);
         if (!empty($info)) {
             $filePath = $path . '/' . $info['name'];
         }
     }
     // we get the node for the given $filePath here because in case of afterCreateFile $node is the parent folder
     if (!$this->server->tree->nodeExists($filePath)) {
         return;
     }
     $node = $this->server->tree->getNodeForPath($filePath);
     if ($node instanceof \OC\Connector\Sabre\Node) {
         $fileId = $node->getFileId();
         if (!is_null($fileId)) {
             $this->server->httpResponse->setHeader('OC-FileId', $fileId);
         }
     }
 }
Example #17
0
 /**
  * Returns the addressbook home for a given principal
  *
  * @param string $principal
  * @return string
  */
 protected function getAddressbookHomeForPrincipal($principal)
 {
     list(, $principalId) = \Sabre\HTTP\URLUtil::splitPath($principal);
     return self::ADDRESSBOOK_ROOT . '/' . $principalId;
 }
Example #18
0
    /**
     * Use this method to create a new collection
     *
     * @param string $uri The new uri
     * @param MkCol $mkCol
     * @return array|null
     */
    function createCollection($uri, MkCol $mkCol) {

        list($parentUri, $newName) = URLUtil::splitPath($uri);

        // Making sure the parent exists
        try {
            $parent = $this->tree->getNodeForPath($parentUri);

        } catch (Exception\NotFound $e) {
            throw new Exception\Conflict('Parent node does not exist');

        }

        // Making sure the parent is a collection
        if (!$parent instanceof ICollection) {
            throw new Exception\Conflict('Parent node is not a collection');
        }

        // Making sure the child does not already exist
        try {
            $parent->getChild($newName);

            // If we got here.. it means there's already a node on that url, and we need to throw a 405
            throw new Exception\MethodNotAllowed('The resource you tried to create already exists');

        } catch (Exception\NotFound $e) {
            // NotFound is the expected behavior.
        }


        if (!$this->emit('beforeBind', [$uri])) return;

        if ($parent instanceof IExtendedCollection) {

            /**
             * If the parent is an instance of IExtendedCollection, it means that
             * we can pass the MkCol object directly as it may be able to store
             * properties immediately.
             */
            $parent->createExtendedCollection($newName, $mkCol);

        } else {

            /**
             * If the parent is a standard ICollection, it means only
             * 'standard' collections can be created, so we should fail any
             * MKCOL operation that carries extra resourcetypes.
             */
            if (count($mkCol->getResourceType()) > 1) {
                throw new Exception\InvalidResourceType('The {DAV:}resourcetype you specified is not supported here.');
            }

            $parent->createDirectory($newName);

        }

        // If there are any properties that have not been handled/stored,
        // we ask the 'propPatch' event to handle them. This will allow for
        // example the propertyStorage system to store properties upon MKCOL.
        if ($mkCol->getRemainingMutations()) {
            $this->emit('propPatch', [$uri, $mkCol]);
        }
        $success = $mkCol->commit();

        if (!$success) {
            $result = $mkCol->getResult();
            // generateMkCol needs the href key to exist.
            $result['href'] = $uri;
            return $result;
        }

        $this->tree->markDirty($parentUri);
        $this->emit('afterBind', [$uri]);

    }
Example #19
0
 /**
  * Returns this principals name.
  *
  * @return string
  */
 function getName()
 {
     $uri = $this->principalProperties['uri'];
     list(, $name) = URLUtil::splitPath($uri);
     return $name;
 }
Example #20
0
 /**
  * Use this method to create a new collection
  *
  * The {DAV:}resourcetype is specified using the resourceType array.
  * At the very least it must contain {DAV:}collection.
  *
  * The properties array can contain a list of additional properties.
  *
  * @param string $uri The new uri
  * @param array $resourceType The resourceType(s)
  * @param array $properties A list of properties
  * @return array|null
  */
 function createCollection($uri, array $resourceType, array $properties)
 {
     list($parentUri, $newName) = URLUtil::splitPath($uri);
     // Making sure {DAV:}collection was specified as resourceType
     if (!in_array('{DAV:}collection', $resourceType)) {
         throw new Exception\InvalidResourceType('The resourceType for this collection must at least include {DAV:}collection');
     }
     // Making sure the parent exists
     try {
         $parent = $this->tree->getNodeForPath($parentUri);
     } catch (Exception\NotFound $e) {
         throw new Exception\Conflict('Parent node does not exist');
     }
     // Making sure the parent is a collection
     if (!$parent instanceof ICollection) {
         throw new Exception\Conflict('Parent node is not a collection');
     }
     // Making sure the child does not already exist
     try {
         $parent->getChild($newName);
         // If we got here.. it means there's already a node on that url, and we need to throw a 405
         throw new Exception\MethodNotAllowed('The resource you tried to create already exists');
     } catch (Exception\NotFound $e) {
         // This is correct
     }
     if (!$this->emit('beforeBind', [$uri])) {
         return;
     }
     // There are 2 modes of operation. The standard collection
     // creates the directory, and then updates properties
     // the extended collection can create it directly.
     if ($parent instanceof IExtendedCollection) {
         $parent->createExtendedCollection($newName, $resourceType, $properties);
     } else {
         // No special resourcetypes are supported
         if (count($resourceType) > 1) {
             throw new Exception\InvalidResourceType('The {DAV:}resourcetype you specified is not supported here.');
         }
         $parent->createDirectory($newName);
         $rollBack = false;
         $exception = null;
         $errorResult = null;
         if (count($properties) > 0) {
             try {
                 $errorResult = $this->updateProperties($uri, $properties);
                 if (!isset($errorResult[200])) {
                     $rollBack = true;
                 }
             } catch (Exception $e) {
                 $rollBack = true;
                 $exception = $e;
             }
         }
         if ($rollBack) {
             if (!$this->emit('beforeUnbind', [$uri])) {
                 return;
             }
             $this->tree->delete($uri);
             // Re-throwing exception
             if ($exception) {
                 throw $exception;
             }
             // Re-arranging the result so it makes sense for
             // generateMultiStatus.
             $newResult = ['href' => $uri];
             foreach ($errorResult as $property => $code) {
                 if (!isset($newResult[$code])) {
                     $newResult[$code] = [$property => null];
                 } else {
                     $newResult[$code][$property] = null;
                 }
             }
             return $newResult;
         }
     }
     $this->tree->markDirty($parentUri);
     $this->emit('afterBind', [$uri]);
 }
Example #21
0
 private function convertPrincipal($principalUri, $toV2)
 {
     if ($this->principalBackend->getPrincipalPrefix() === 'principals') {
         list(, $name) = URLUtil::splitPath($principalUri);
         if ($toV2 === true) {
             return "principals/users/{$name}";
         }
         return "principals/{$name}";
     }
     return $principalUri;
 }
Example #22
0
 /**
  * serialize
  *
  * @param DAV\Server $server
  * @param \DOMElement $dom
  * @return void
  */
 function serialize(DAV\Server $server, \DOMElement $dom)
 {
     $document = $dom->ownerDocument;
     $properties = $this->responseProperties;
     $xresponse = $document->createElement('d:response');
     $dom->appendChild($xresponse);
     $uri = URLUtil::encodePath($this->href);
     if ($uri === '/') {
         $uri = '';
     }
     // Adding the baseurl to the beginning of the url
     $uri = $server->getBaseUri() . $uri;
     $xresponse->appendChild($document->createElement('d:href', $uri));
     if ($this->httpStatus) {
         $statusString = "HTTP/1.1 " . $this->httpStatus . " " . HTTP\Response::$statusCodes[$this->httpStatus];
         $xresponse->appendChild($document->createElement('d:status', $statusString));
     }
     // The properties variable is an array containing properties, grouped by
     // HTTP status
     foreach ($properties as $httpStatus => $propertyGroup) {
         // The 'href' is also in this array, and it's special cased.
         // We will ignore it
         if ($httpStatus == 'href') {
             continue;
         }
         // If there are no properties in this group, we can also just carry on
         if (!count($propertyGroup)) {
             continue;
         }
         $xpropstat = $document->createElement('d:propstat');
         $xresponse->appendChild($xpropstat);
         $xprop = $document->createElement('d:prop');
         $xpropstat->appendChild($xprop);
         $nsList = $server->xmlNamespaces;
         foreach ($propertyGroup as $propertyName => $propertyValue) {
             $propName = null;
             preg_match('/^{([^}]*)}(.*)$/', $propertyName, $propName);
             // special case for empty namespaces
             if ($propName[1] == '') {
                 $currentProperty = $document->createElement($propName[2]);
                 $xprop->appendChild($currentProperty);
                 $currentProperty->setAttribute('xmlns', '');
             } else {
                 if (!isset($nsList[$propName[1]])) {
                     $nsList[$propName[1]] = 'x' . count($nsList);
                 }
                 // If the namespace was defined in the top-level xml namespaces, it means
                 // there was already a namespace declaration, and we don't have to worry about it.
                 if (isset($server->xmlNamespaces[$propName[1]])) {
                     $currentProperty = $document->createElement($nsList[$propName[1]] . ':' . $propName[2]);
                 } else {
                     $currentProperty = $document->createElementNS($propName[1], $nsList[$propName[1]] . ':' . $propName[2]);
                 }
                 $xprop->appendChild($currentProperty);
             }
             if (is_scalar($propertyValue)) {
                 if ($propertyValue !== '') {
                     // we want a self-closing xml element for empty strings.
                     $text = $document->createTextNode($propertyValue);
                     $currentProperty->appendChild($text);
                 }
             } elseif ($propertyValue instanceof DAV\PropertyInterface) {
                 $propertyValue->serialize($server, $currentProperty);
             } elseif (!is_null($propertyValue)) {
                 throw new DAV\Exception('Unknown property value type: ' . gettype($propertyValue) . ' for property: ' . $propertyName);
             }
         }
         $xpropstat->appendChild($document->createElement('d:status', 'HTTP/1.1 ' . $httpStatus . ' ' . HTTP\Response::$statusCodes[$httpStatus]));
     }
 }
Example #23
0
 /**
  * Returns the list of groups a principal is a member of
  *
  * @param string $principal
  * @return array
  * @throws Exception
  */
 public function getGroupMembership($principal)
 {
     list($prefix, $name) = URLUtil::splitPath($principal);
     if ($prefix === 'principals/users') {
         $user = $this->userManager->get($name);
         if (!$user) {
             throw new Exception('Principal not found');
         }
         $groups = $this->groupManager->getUserGroups($user);
         $groups = array_map(function ($group) {
             /** @var IGroup $group */
             return 'principals/groups/' . $group->getGID();
         }, $groups);
         $groups[] = 'principals/users/' . $name . '/calendar-proxy-read';
         $groups[] = 'principals/users/' . $name . '/calendar-proxy-write';
         return $groups;
     }
     return [];
 }
Example #24
0
 /**
  * @brief Creates the directory listing for the given path.
  *
  * @param string $path which should be displayed
  */
 public function generateDirectoryIndex($path)
 {
     // (owner_id = channel_id) is visitor owner of this directory?
     $is_owner = local_channel() && $this->auth->owner_id == local_channel() ? true : false;
     if ($this->auth->getTimezone()) {
         date_default_timezone_set($this->auth->getTimezone());
     }
     require_once 'include/conversation.php';
     require_once 'include/text.php';
     if ($this->auth->owner_nick) {
         $html = profile_tabs(get_app(), $is_owner ? true : false, $this->auth->owner_nick);
     }
     $files = $this->server->getPropertiesForPath($path, array('{DAV:}displayname', '{DAV:}resourcetype', '{DAV:}getcontenttype', '{DAV:}getcontentlength', '{DAV:}getlastmodified'), 1);
     $parent = $this->server->tree->getNodeForPath($path);
     $parentpath = array();
     // only show parent if not leaving /cloud/; TODO how to improve this?
     if ($path && $path != "cloud") {
         list($parentUri) = \Sabre\HTTP\URLUtil::splitPath($path);
         $fullPath = \Sabre\HTTP\URLUtil::encodePath($this->server->getBaseUri() . $parentUri);
         $parentpath['icon'] = $this->enableAssets ? '<a href="' . $fullPath . '"><img src="' . $this->getAssetUrl('icons/parent' . $this->iconExtension) . '" width="24" alt="' . t('parent') . '"></a>' : '';
         $parentpath['path'] = $fullPath;
     }
     $f = array();
     foreach ($files as $file) {
         $ft = array();
         $type = null;
         // This is the current directory, we can skip it
         if (rtrim($file['href'], '/') == $path) {
             continue;
         }
         list(, $name) = \Sabre\HTTP\URLUtil::splitPath($file['href']);
         if (isset($file[200]['{DAV:}resourcetype'])) {
             $type = $file[200]['{DAV:}resourcetype']->getValue();
             // resourcetype can have multiple values
             if (!is_array($type)) {
                 $type = array($type);
             }
             foreach ($type as $k => $v) {
                 // Some name mapping is preferred
                 switch ($v) {
                     case '{DAV:}collection':
                         $type[$k] = t('Collection');
                         break;
                     case '{DAV:}principal':
                         $type[$k] = t('Principal');
                         break;
                     case '{urn:ietf:params:xml:ns:carddav}addressbook':
                         $type[$k] = t('Addressbook');
                         break;
                     case '{urn:ietf:params:xml:ns:caldav}calendar':
                         $type[$k] = t('Calendar');
                         break;
                     case '{urn:ietf:params:xml:ns:caldav}schedule-inbox':
                         $type[$k] = t('Schedule Inbox');
                         break;
                     case '{urn:ietf:params:xml:ns:caldav}schedule-outbox':
                         $type[$k] = t('Schedule Outbox');
                         break;
                     case '{http://calendarserver.org/ns/}calendar-proxy-read':
                         $type[$k] = 'Proxy-Read';
                         break;
                     case '{http://calendarserver.org/ns/}calendar-proxy-write':
                         $type[$k] = 'Proxy-Write';
                         break;
                 }
             }
             $type = implode(', ', $type);
         }
         // If no resourcetype was found, we attempt to use
         // the contenttype property
         if (!$type && isset($file[200]['{DAV:}getcontenttype'])) {
             $type = $file[200]['{DAV:}getcontenttype'];
         }
         if (!$type) {
             $type = t('Unknown');
         }
         $size = isset($file[200]['{DAV:}getcontentlength']) ? (int) $file[200]['{DAV:}getcontentlength'] : '';
         $lastmodified = isset($file[200]['{DAV:}getlastmodified']) ? $file[200]['{DAV:}getlastmodified']->getTime()->format('Y-m-d H:i:s') : '';
         $fullPath = \Sabre\HTTP\URLUtil::encodePath('/' . trim($this->server->getBaseUri() . ($path ? $path . '/' : '') . $name, '/'));
         $displayName = isset($file[200]['{DAV:}displayname']) ? $file[200]['{DAV:}displayname'] : $name;
         $displayName = $this->escapeHTML($displayName);
         $type = $this->escapeHTML($type);
         $icon = '';
         if ($this->enableAssets) {
             $node = $this->server->tree->getNodeForPath(($path ? $path . '/' : '') . $name);
             foreach (array_reverse($this->iconMap) as $class => $iconName) {
                 if ($node instanceof $class) {
                     $icon = '<a href="' . $fullPath . '"><img src="' . $this->getAssetUrl($iconName . $this->iconExtension) . '" alt="" width="24"></a>';
                     break;
                 }
             }
         }
         $parentHash = '';
         $owner = $this->auth->owner_id;
         $splitPath = explode('/', $fullPath);
         if (count($splitPath) > 3) {
             for ($i = 3; $i < count($splitPath); $i++) {
                 $attachName = urldecode($splitPath[$i]);
                 $attachHash = $this->findAttachHash($owner, $parentHash, $attachName);
                 $parentHash = $attachHash;
             }
         }
         $attachIcon = "";
         // "<a href=\"attach/".$attachHash."\" title=\"".$displayName."\"><i class=\"fa fa-arrow-circle-o-down\"></i></a>";
         // put the array for this file together
         $ft['attachId'] = $this->findAttachIdByHash($attachHash);
         $ft['fileStorageUrl'] = substr($fullPath, 0, strpos($fullPath, "cloud/")) . "filestorage/" . $this->auth->getCurrentUser();
         $ft['icon'] = $icon;
         $ft['attachIcon'] = $size ? $attachIcon : '';
         // @todo Should this be an item value, not a global one?
         $ft['is_owner'] = $is_owner;
         $ft['fullPath'] = $fullPath;
         $ft['displayName'] = $displayName;
         $ft['type'] = $type;
         $ft['size'] = $size;
         $ft['sizeFormatted'] = userReadableSize($size);
         $ft['lastmodified'] = $lastmodified ? datetime_convert('UTC', date_default_timezone_get(), $lastmodified) : '';
         $ft['iconFromType'] = getIconFromType($type);
         $f[] = $ft;
     }
     $output = '';
     if ($this->enablePost) {
         $this->server->emit('onHTMLActionsPanel', array($parent, &$output));
     }
     $html .= replace_macros(get_markup_template('cloud.tpl'), array('$header' => t('Files') . ": " . $this->escapeHTML($path) . "/", '$total' => t('Total'), '$actionspanel' => $output, '$shared' => t('Shared'), '$create' => t('Create'), '$upload' => t('Upload'), '$is_owner' => $is_owner, '$parentpath' => $parentpath, '$entries' => $f, '$name' => t('Name'), '$type' => t('Type'), '$size' => t('Size'), '$lastmod' => t('Last Modified'), '$parent' => t('parent'), '$edit' => t('Edit'), '$delete' => t('Delete'), '$nick' => $this->auth->getCurrentUser()));
     $a = get_app();
     \App::$page['content'] = $html;
     load_pdl($a);
     $theme_info_file = "view/theme/" . current_theme() . "/php/theme.php";
     if (file_exists($theme_info_file)) {
         require_once $theme_info_file;
         if (function_exists(str_replace('-', '_', current_theme()) . '_init')) {
             $func = str_replace('-', '_', current_theme()) . '_init';
             $func($a);
         }
     }
     construct_page($a);
 }
Example #25
0
	/**
	 * Get raw PathInfo from request (not urldecoded)
	 * @throws \Exception
	 * @return string Path info
	 */
	public function getRawPathInfo() {
		$requestUri = isset($this->server['REQUEST_URI']) ? $this->server['REQUEST_URI'] : '';
		// remove too many leading slashes - can be caused by reverse proxy configuration
		if (strpos($requestUri, '/') === 0) {
			$requestUri = '/' . ltrim($requestUri, '/');
		}

		$requestUri = preg_replace('%/{2,}%', '/', $requestUri);

		// Remove the query string from REQUEST_URI
		if ($pos = strpos($requestUri, '?')) {
			$requestUri = substr($requestUri, 0, $pos);
		}

		$scriptName = $this->server['SCRIPT_NAME'];
		$pathInfo = $requestUri;

		// strip off the script name's dir and file name
		// FIXME: Sabre does not really belong here
		list($path, $name) = \Sabre\HTTP\URLUtil::splitPath($scriptName);
		if (!empty($path)) {
			if($path === $pathInfo || strpos($pathInfo, $path.'/') === 0) {
				$pathInfo = substr($pathInfo, strlen($path));
			} else {
				throw new \Exception("The requested uri($requestUri) cannot be processed by the script '$scriptName')");
			}
		}
		if (strpos($pathInfo, '/'.$name) === 0) {
			$pathInfo = substr($pathInfo, strlen($name) + 1);
		}
		if (strpos($pathInfo, $name) === 0) {
			$pathInfo = substr($pathInfo, strlen($name));
		}
		if($pathInfo === false || $pathInfo === '/'){
			return '';
		} else {
			return $pathInfo;
		}
	}
Example #26
0
 /**
  * Triggered before a node is deleted
  *
  * This allows us to check permissions for any operation that will delete
  * an existing node.
  *
  * @param string $uri
  * @return void
  */
 function beforeUnbind($uri)
 {
     list($parentUri) = URLUtil::splitPath($uri);
     $this->checkPrivileges($parentUri, '{DAV:}unbind', self::R_RECURSIVEPARENTS);
 }
Example #27
0
 /**
  * Returns the name of this object
  *
  * @return string
  */
 function getName()
 {
     list(, $name) = URLUtil::splitPath($this->principalInfo['uri']);
     return $name;
 }
Example #28
0
 /**
  * Returns the list of groups a principal is a member of
  *
  * @param string $principal
  * @param bool $needGroups
  * @return array
  * @throws Exception
  */
 public function getGroupMembership($principal, $needGroups = false)
 {
     list($prefix, $name) = URLUtil::splitPath($principal);
     if ($prefix === $this->principalPrefix) {
         $user = $this->userManager->get($name);
         if (!$user) {
             throw new Exception('Principal not found');
         }
         if ($this->hasGroups || $needGroups) {
             $groups = $this->groupManager->getUserGroups($user);
             $groups = array_map(function ($group) {
                 /** @var IGroup $group */
                 return 'principals/groups/' . $group->getGID();
             }, $groups);
             return $groups;
         }
     }
     return [];
 }
Example #29
0
	/**
	 * @param resource $data
	 * @return null|string
	 * @throws Exception
	 * @throws BadRequest
	 * @throws NotImplemented
	 * @throws ServiceUnavailable
	 */
	private function createFileChunked($data) {
		list($path, $name) = \Sabre\HTTP\URLUtil::splitPath($this->path);

		$info = \OC_FileChunking::decodeName($name);
		if (empty($info)) {
			throw new NotImplemented('Invalid chunk name');
		}
		$chunk_handler = new \OC_FileChunking($info);
		$bytesWritten = $chunk_handler->store($info['index'], $data);

		//detect aborted upload
		if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
			if (isset($_SERVER['CONTENT_LENGTH'])) {
				$expected = $_SERVER['CONTENT_LENGTH'];
				if ($bytesWritten != $expected) {
					$chunk_handler->remove($info['index']);
					throw new BadRequest(
						'expected filesize ' . $expected . ' got ' . $bytesWritten);
				}
			}
		}

		if ($chunk_handler->isComplete()) {
			list($storage,) = $this->fileView->resolvePath($path);
			$needsPartFile = $this->needsPartFile($storage);
			$partFile = null;

			$targetPath = $path . '/' . $info['name'];
			/** @var \OC\Files\Storage\Storage $targetStorage */
			list($targetStorage, $targetInternalPath) = $this->fileView->resolvePath($targetPath);

			$exists = $this->fileView->file_exists($targetPath);

			try {
				$this->emitPreHooks($exists, $targetPath);

				$this->changeLock(ILockingProvider::LOCK_EXCLUSIVE);

				if ($needsPartFile) {
					// we first assembly the target file as a part file
					$partFile = $this->getPartFileBasePath($path . '/' . $info['name']) . '.ocTransferId' . $info['transferid'] . '.part';
					/** @var \OC\Files\Storage\Storage $targetStorage */
					list($partStorage, $partInternalPath) = $this->fileView->resolvePath($partFile);


					$chunk_handler->file_assemble($partStorage, $partInternalPath, $this->fileView->getAbsolutePath($targetPath));

					// here is the final atomic rename
					$renameOkay = $targetStorage->moveFromStorage($partStorage, $partInternalPath, $targetInternalPath);

					$fileExists = $this->fileView->file_exists($targetPath);
					if ($renameOkay === false || $fileExists === false) {
						\OCP\Util::writeLog('webdav', '\OC\Files\Filesystem::rename() failed', \OCP\Util::ERROR);
						// only delete if an error occurred and the target file was already created
						if ($fileExists) {
							// set to null to avoid double-deletion when handling exception
							// stray part file
							$partFile = null;
							$targetStorage->unlink($targetInternalPath);
						}
						$this->changeLock(ILockingProvider::LOCK_SHARED);
						throw new Exception('Could not rename part file assembled from chunks');
					}
				} else {
					// assemble directly into the final file
					$chunk_handler->file_assemble($targetStorage, $targetInternalPath, $this->fileView->getAbsolutePath($targetPath));
				}

				// allow sync clients to send the mtime along in a header
				$request = \OC::$server->getRequest();
				if (isset($request->server['HTTP_X_OC_MTIME'])) {
					if ($targetStorage->touch($targetInternalPath, $request->server['HTTP_X_OC_MTIME'])) {
						header('X-OC-MTime: accepted');
					}
				}

				// since we skipped the view we need to scan and emit the hooks ourselves
				$this->fileView->getUpdater()->update($targetPath);

				$this->changeLock(ILockingProvider::LOCK_SHARED);

				$this->emitPostHooks($exists, $targetPath);

				$info = $this->fileView->getFileInfo($targetPath);
				return $info->getEtag();
			} catch (\Exception $e) {
				if ($partFile !== null) {
					$targetStorage->unlink($targetInternalPath);
				}
				$this->convertToSabreException($e);
			}
		}

		return null;
	}
 /**
  * This method will check if the url matches the temporary file pattern
  * if it does, it will return an path based on $this->dataDir for the
  * temporary file storage.
  *
  * @param string $path
  * @return bool|string
  */
 protected function isTempFile($path)
 {
     // We're only interested in the basename.
     list(, $tempPath) = URLUtil::splitPath($path);
     foreach ($this->temporaryFilePatterns as $tempFile) {
         if (preg_match($tempFile, $tempPath)) {
             return $this->getDataDir() . '/sabredav_' . md5($path) . '.tempfile';
         }
     }
     return false;
 }