/** * Handles the UNLOCK request * * @param DAV_Resource $resource * @return void * @throws DAV_Status */ protected function handle($resource) { if (!DAV::$LOCKPROVIDER) { throw new DAV_Status(DAV::HTTP_FORBIDDEN); } $lock = DAV::$LOCKPROVIDER->getlock(DAV::getPath()); if (!$lock || $this->locktoken !== $lock->locktoken) { throw new DAV_Status(DAV::HTTP_CONFLICT, DAV::COND_LOCK_TOKEN_MATCHES_REQUEST_URI); } DAV::$LOCKPROVIDER->unlock($lock->lockroot); DAV::header(array('status' => DAV::HTTP_NO_CONTENT)); }
/** * Checks and handles MKCOL request * @param DAV_Resource $resource * @return void * @throws DAV_Status */ protected function handle($resource) { if ($resource) { if ($resource->isVisible()) { throw new DAV_Status(DAV::HTTP_METHOD_NOT_ALLOWED); } throw DAV::forbidden(); } $resource = DAV::$REGISTRY->resource(dirname(DAV::getPath())); if (!$resource or !$resource->isVisible()) { throw new DAV_Status(DAV::HTTP_CONFLICT, 'Unable to MKCOL in unknown resource'); } if (!$resource instanceof DAV_Collection) { throw new DAV_Status(DAV::HTTP_METHOD_NOT_ALLOWED); } if (0 < (int) @$_SERVER['CONTENT_LENGTH']) { throw new DAV_Status(DAV::HTTP_UNSUPPORTED_MEDIA_TYPE); } $resource->assertLock(); $resource->method_MKCOL(basename(DAV::getPath())); DAV::redirect(DAV::HTTP_CREATED, DAV::getPath()); }
/** * Handles a DAV:expand-property REPORT request * * @param DAV_Resource $resource The resource to perform the request on * @return void */ private function handle_expand_property($resource) { $response = $this->handle_expand_property_recursively(DAV::getPath(), $this->entity); DAV_Multistatus::inst()->addResponse($response)->close(); }
/** * Handle the PROPPATCH request * * @param DAV_Resource $resource * @return void * @throws DAV_Status */ protected function handle($resource) { $resource->assertLock(); if (empty($this->props)) { throw new DAV_Status(DAV::HTTP_BAD_REQUEST, 'No properties found in request body.'); } $priv_write = $resource->property_priv_write(array_keys($this->props)); $errors = array(); foreach ($this->props as $name => $value) { try { if (@DAV::$PROTECTED_PROPERTIES[$name]) { throw new DAV_Status(DAV::HTTP_FORBIDDEN, DAV::COND_CANNOT_MODIFY_PROTECTED_PROPERTY); } if (!@$priv_write[$name]) { throw DAV::forbidden(); } $resource->method_PROPPATCH($name, $value); } catch (DAV_Status $e) { $errors[$name] = $e; } } $response = new DAV_Element_response(DAV::getPath()); if (empty($errors)) { try { $resource->storeProperties(); } catch (DAV_Status $e) { foreach (array_keys($this->props) as $propname) { $errors[$propname] = $e; } } } if (empty($errors)) { foreach (array_keys($this->props) as $propname) { $response->setStatus($propname, DAV_Status::$OK); } } else { $failed_dependency = new DAV_Status(DAV::HTTP_FAILED_DEPENDENCY); foreach (array_keys($this->props) as $propname) { if (!isset($errors[$propname])) { $errors[$propname] = $failed_dependency; } } foreach ($errors as $propname => $status) { $response->setStatus($propname, $status); } } DAV_Multistatus::inst()->addResponse($response); DAV_Multistatus::inst()->close(); }
<li><a href="<?php echo BeeHub::urlbase(true) . DAV::getPath() . '?login=passwd'; ?> ">With username/password</a></li> <?php if (@BeeHub_Auth::inst()->simpleSaml()->isAuthenticated()) { ?> <li><a href="<?php echo DAV::getPath() . '?logout=yes'; ?> ">Log out from SURFconext</a></li> <?php } else { ?> <li><a href="<?php echo BeeHub::urlbase(true) . DAV::getPath() . '?login=conext'; ?> ">With SURFconext</a></li> <?php } ?> <li><a href="<?php echo BeeHub::urlbase(true) . '/system/password_reset.php'; ?> ">I forgot my password</a></li> </ul> </li> <?php } ?> <li class="beehub-spacer-surfsara-logo visible-desktop"></li>
public function testGetPath() { $this->assertSame(DAV::parseURI($_SERVER['REQUEST_URI'], true), DAV::getPath(), 'DAV::getPath() should return the correct path'); }
/** * Check the HTTP If-Match header * * @return void */ private function check_if_match_header() { if (isset($_SERVER['HTTP_IF_MATCH'])) { $header = $_SERVER['HTTP_IF_MATCH']; $none = false; } elseif (isset($_SERVER['HTTP_IF_NONE_MATCH'])) { $header = $_SERVER['HTTP_IF_NONE_MATCH']; $none = true; } else { return; } $resource = DAV::$REGISTRY->resource(DAV::getPath()); // The simplest case: just an asterisk '*'. if (preg_match('@^\\s*\\*\\s*$@', $header)) { if ((!$resource || !$resource->isVisible()) && !$none) { throw new DAV_Status(DAV::HTTP_PRECONDITION_FAILED, 'If-Match'); } if ($resource && $resource->isVisible() && $none) { throw new DAV_Status(DAV::HTTP_PRECONDITION_FAILED, 'If-None-Match'); } return; } // A list of entity-tags $header .= ','; preg_match_all('@((?:W/)?"(?:[^"\\\\]|\\\\.)*")\\s*,@', $header, $matches); $etags = $matches[1]; if (!count($etags)) { throw new DAV_Status(DAV::HTTP_BAD_REQUEST, 'Couldn\'t parse If-(None-)Match header.'); } if ((!$resource || !$resource->isVisible()) && !$none) { throw new DAV_Status(DAV::HTTP_PRECONDITION_FAILED, 'If-Match'); } // $resource exists: $resource_etag = $resource->user_prop_getetag(); if ($none) { foreach ($etags as $etag) { if (self::equalETags($resource_etag, $etag)) { throw new DAV_Status(DAV::HTTP_PRECONDITION_FAILED, 'If-None-Match'); } } } else { foreach ($etags as $etag) { if (self::equalETags($resource_etag, $etag)) { return; } } throw new DAV_Status(DAV::HTTP_PRECONDITION_FAILED, 'If-Match'); } }
/** * Refreshes an already existing lock * * @param DAV_Resource $resource * @return void * @throws DAV_Statuss */ private function handleRefreshLock($resource) { $if_header = $this->if_header; if (!isset($if_header[DAV::getPath()]) || !$if_header[DAV::getPath()]['lock']) { throw new DAV_Status(DAV::HTTP_BAD_REQUEST, array(DAV::COND_LOCK_TOKEN_SUBMITTED => new DAV_Element_href(DAV::getPath()))); } // I think this can never evaluate to true, because DAV_Request already checks // whether the 'If' header matches the lock token of the resource. So if the // resource doesn't have a lock, this is already detected before this method // is called! (However, I don't dare to delete this yet and it doesn't hurt to // keep it) if (!($lock = DAV::$LOCKPROVIDER->getlock(DAV::getPath()))) { throw new DAV_Status(DAV::HTTP_PRECONDITION_FAILED, array(DAV::COND_LOCK_TOKEN_MATCHES_REQUEST_URI)); } DAV::$LOCKPROVIDER->refresh($lock->lockroot, $lock->locktoken, $this->timeout); if (!($lockdiscovery = $resource->prop_lockdiscovery())) { throw new DAV_Status(DAV::HTTP_INTERNAL_SERVER_ERROR); } // Generate output: DAV::header('application/xml; charset="utf-8"'); echo DAV::xml_header() . '<D:prop xmlns:D="DAV:"><D:lockdiscovery>' . $lockdiscovery . '</D:lockdiscovery></D:prop>'; }
/** * Determines whether you need to authenticate based on the method and URL of the request * @return boolean True if authentication is required, false otherwise */ public static function is_authentication_required() { $path = DAV::unslashify(DAV::getPath()); /** * You don't need to authenticate when: * - GET (or HEAD) or POST on the users collection (required to create a new user) * - GET (or HEAD) on the system collection (required to read the 'homepage') * In other cases you do need to authenticate */ $noRequireAuth = $path === DAV::unslashify(BeeHub::USERS_PATH) && in_array($_SERVER['REQUEST_METHOD'], array('GET', 'POST', 'HEAD')) || $path === DAV::unslashify(BeeHub::SYSTEM_PATH) && in_array($_SERVER['REQUEST_METHOD'], array('GET', 'HEAD')); return !$noRequireAuth; }
/** * Handles the PUT request * * This method checks whether the PUT request is valid and, if so, writes the * request body to the resource. * * @param DAV_Resource $resource */ protected function handle($resource) { # This variable also flags if a new resource was created. $parent = null; if (!$resource) { if (!is_null($this->range_start)) { throw new DAV_Status(DAV::HTTP_NOT_FOUND); } $parent = DAV::$REGISTRY->resource(dirname(DAV::getPath())); if (!$parent || !$parent instanceof DAV_Collection) { throw new DAV_Status(DAV::HTTP_CONFLICT, 'Unable to PUT file in non-existing collection.'); } $parent->assertLock(); $parent->create_member(basename(DAV::getPath())); $resource = DAV::$REGISTRY->resource(DAV::getPath()); } elseif ($resource instanceof DAV_Collection) { throw new DAV_Status(DAV::HTTP_METHOD_NOT_ALLOWED, 'Method PUT not supported on collections.'); } else { $resource->assertLock(); } if (is_null($this->range_start)) { try { if (isset($_SERVER['CONTENT_TYPE']) && 'application/octet-stream' !== $_SERVER['CONTENT_TYPE']) { $resource->set_getcontenttype($_SERVER['CONTENT_TYPE']); } else { $resource->set_getcontenttype(null); } } catch (DAV_Status $e) { } if (isset($_SERVER['HTTP_CONTENT_LANGUAGE'])) { try { $resource->set_getcontentlanguage($_SERVER['HTTP_CONTENT_LANGUAGE']); } catch (DAV_Status $e) { } } $resource->storeProperties(); $input = fopen('php://input', 'r'); try { $resource->method_PUT($input); fclose($input); } catch (DAV_Status $e) { fclose($input); if ($parent) { $parent->method_DELETE(basename(DAV::getPath())); } throw $e; } } else { $cl = $resource->user_prop_getcontentlength(); if (!is_null($cl) && ($this->range_start > $cl or !is_null($this->range_total) && $this->range_total !== $cl)) { throw new DAV_Status(DAV::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE); } $input = fopen('php://input', 'r'); try { $resource->method_PUT_range($input, $this->range_start, $this->range_end, $this->range_total); fclose($input); } catch (DAV_Status $e) { fclose($input); throw $e; } } if ($etag = $resource->prop_getetag()) { header('ETag: ' . htmlspecialchars_decode($etag)); } if ($parent) { DAV::redirect(DAV::HTTP_CREATED, DAV::getPath()); } else { DAV::header(array('status' => DAV::HTTP_NO_CONTENT)); } }
public function method_PUT($stream) { // Assert the privileges of the current user if (DAV::getPath() === $this->path) { $this->assert(DAVACL::PRIV_WRITE_CONTENT); } // Try to open the (local) file for writing if (!($resource = fopen($this->localPath, 'w'))) { throw new DAV_Status(DAV::HTTP_INTERNAL_SERVER_ERROR); } // Try to write to the file. try { $size = 0; // Do we know how big this file will be? if (($cl = (int) @$_SERVER['CONTENT_LENGTH']) || ($cl = (int) @$_SERVER['HTTP_X_EXPECTED_ENTITY_LENGTH'])) { # The client has indicated the length of the request entity body: set_time_limit(120); $time = time(); // Loop until we reach the end of the request body (or when we have read the indicated length) while ($cl && !feof($stream)) { // Make sure the script doesn't timeout if (time() - $time > 60) { set_time_limit(120); $time = time(); } // Determine the size of the chunk we will read $chunk_size = $cl; if ($chunk_size > DAV::$CHUNK_SIZE) { $chunk_size = DAV::$CHUNK_SIZE; } // Read a chunk from the request body and write it to the (local) file $buffer = fread($stream, $chunk_size); $chunk_size = strlen($buffer); if ($chunk_size !== fwrite($resource, $buffer)) { throw new DAV_Status(DAV::HTTP_INSUFFICIENT_STORAGE); } $size += $chunk_size; // $cl contains the number of bytes to read: the HTTP 'Content-Length' // header minus the number of bytes we have already read $cl -= $chunk_size; } // If $cl is still bigger than 0, that means we've met the end of the body // before reading the number of bytes indicated by the HTTP header if ($cl) { throw new DAV_Status(DAV::HTTP_BAD_REQUEST, 'Request entity too small'); } } else { # The client didn't give us any clue about the request body entity size. # Let's make the best of it... set_time_limit(120); $time = time(); // We break out of this loop, from within it while (true) { // Make sure the script doesn't timeout if (time() - $time > 60) { set_time_limit(120); $time = time(); } // Read a chunk from the request body ... $buffer = fread($stream, DAV::$CHUNK_SIZE); if ($buffer === false || $buffer === '') { // If the buffer is empty, we apparantly reached the end of the file break; } // ... and write it to the (local) file $bufferSize = strlen($buffer); if ($bufferSize !== fwrite($resource, $buffer)) { throw new DAV_Status(DAV::HTTP_INSUFFICIENT_STORAGE); } $size += $bufferSize; } } } catch (DAV_Status $e) { // If at some point this fails, we will close the file properly before // rethrowing the (DAV_Status) exception. fclose($resource); unlink($this->localPath); throw $e; } // The file is successfully saved, close it and store some metadata fclose($resource); $contenttype = $this->user_prop_getcontenttype(); if (!$contenttype) { // If we can't determine or set the content type, just ignore this problem try { $this->set_getcontenttype(BeeHub::determineContentType($this->path)); } catch (DAV_Status $e) { } } $this->user_set(DAV::PROP_GETCONTENTLENGTH, $size); $this->user_set(DAV::PROP_GETETAG, BeeHub::ETag()); $this->storeProperties(); // Reread the file system data $this->stat = stat($this->localPath); }
/** * Checks and handles the PROPFIND request * * @param DAV_Resource $resource * @return void * @throws DAV_Status */ protected function handle($resource) { /* * RFC4918 §9.1: * A client MUST submit a Depth header with a value of "0", "1", or * "infinity" with a PROPFIND request. Servers MUST support "0" and "1" * depth requests on WebDAV-compliant resources and SHOULD support * "infinity" requests. In practice, support for infinite-depth * requests MAY be disabled, due to the performance and security * concerns associated with this behavior. Servers SHOULD treat a * request without a Depth header as if a "Depth: infinity" header was * included. * * RFC4918 §9.1.1: * 403 Forbidden - A server MAY reject PROPFIND requests on collections * with depth header of "Infinity", in which case it SHOULD use this * error with the precondition code 'propfind-finite-depth' inside the * error body. */ if ($resource instanceof DAV_Collection and DAV::DEPTH_INF === $this->depth()) { //$d = debug_backtrace(); throw new DAV_Status(DAV::HTTP_FORBIDDEN, DAV::COND_PROPFIND_FINITE_DEPTH); } $this->handle2($resource); if ($resource instanceof DAV_Collection && DAV::DEPTH_1 === $this->depth()) { foreach ($resource as $path) { $subpath = DAV::getPath() . $path; $subresource = DAV::$REGISTRY->resource($subpath); if ($subresource->isVisible()) { $this->handle2($subresource); } } } DAV_Multistatus::inst()->close(); }
/** * Determines whether the copy request is valid and if so, copies the resources * * @param DAV_Resource $resource * @return void * @throws DAV_Status */ protected function handle($resource) { $destination = $this->destination(); if ($resource instanceof DAV_Collection) { $destination = DAV::slashify($destination); } else { // The next line is here to make the litmus test succeed. The author of // litmus had eir own doubts wether this is actually desirable behaviour, // but chose to require this behaviour anyway: $destination = DAV::unslashify($destination); } // Can't move the root collection: if ($this instanceof DAV_Request_MOVE && '/' === DAV::getPath()) { throw new DAV_Status(DAV::HTTP_FORBIDDEN); } // Assert proper Depth: header value: if (DAV::DEPTH_1 === $this->depth() or $this instanceof DAV_Request_MOVE && DAV::DEPTH_INF !== $this->depth()) { throw new DAV_Status(DAV::HTTP_BAD_REQUEST, 'Illegal value for Depth: header.'); } // Check: Can't move a collection to one of its members. if ($this instanceof DAV_Request_MOVE && '/' === substr(DAV::getPath(), -1) && 0 === strpos($destination, DAV::getPath())) { throw new DAV_Status(DAV::HTTP_FORBIDDEN, "Can't move a collection to itself or one of its members."); } $resourceCollection = $resource->collection(); if ($this instanceof DAV_Request_MOVE) { $resourceCollection->assertLock(); $resource->assertLock(); $resource->assertMemberLocks(); } if ('/' !== $destination[0]) { // Copy to an external URI? $isCreated = $resource->method_COPY_external($destination, $this->overwrite()); if ($this instanceof DAV_Request_MOVE && !DAV_Multistatus::active()) { DAV_Request_DELETE::delete($resource); } if (DAV_Multistatus::active()) { DAV_Multistatus::inst()->close(); } elseif ($isCreated) { DAV::redirect(DAV::HTTP_CREATED, $destination); } else { DAV::header(array('status' => DAV::HTTP_NO_CONTENT)); } return; } // Check: Won't move a resource to one of its parents. if (0 === strpos(DAV::slashify(DAV::getPath()), DAV::slashify($destination))) { throw new DAV_Status(DAV::HTTP_NOT_IMPLEMENTED, "Won't move or copy a resource to one of its parents."); } $destinationResource = DAV::$REGISTRY->resource($destination); $destinationCollection = DAV::$REGISTRY->resource(dirname($destination)); if (!$destinationCollection) { throw new DAV_Status(DAV::HTTP_CONFLICT, 'Unable to COPY to unexisting destination collection'); } if ($destinationResource) { if (!$this->overwrite()) { throw new DAV_Status(DAV::HTTP_PRECONDITION_FAILED); } else { $destinationResource->assertLock(); } } else { $destinationCollection->assertLock(); } if ($this instanceof DAV_Request_MOVE) { if (DAV::$LOCKPROVIDER) { foreach (DAV::$LOCKPROVIDER->memberLocks(DAV::getPath()) as $lock) { DAV::$LOCKPROVIDER->unlock($lock->lockroot); } if ($lock = DAV::$LOCKPROVIDER->getlock(DAV::getPath())) { DAV::$LOCKPROVIDER->unlock($lock->lockroot); } } $resourceCollection->method_MOVE(basename($resource->path), $destination); } else { $this->copy_recursively($resource, $destination); } #<<<<<<<< #// This version always returns a 207 Multistatus wrapper: #if (!DAV_Multistatus::active()) # if ( $destinationResource ) # DAV_Multistatus::inst()->addStatus( # $resource->path, # new DAV_Status( DAV::HTTP_NO_CONTENT ) # ); # else # DAV_Multistatus::inst()->addStatus( # $resource->path, # new DAV_Status( # DAV::HTTP_CREATED, DAV::path2uri($destination) # ) # ); #DAV_Multistatus::inst()->close(); #======== if (DAV_Multistatus::active()) { DAV_Multistatus::inst()->close(); } elseif ($destinationResource) { DAV::header(array('status' => DAV::HTTP_NO_CONTENT)); } else { DAV::redirect(DAV::HTTP_CREATED, $destination); } #>>>>>>>> }
* * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * @package BeeHub */ // Bootstrap the application require_once '../src/beehub_bootstrap.php'; $config = BeeHub::config(); if (@$config['install']['run_install'] === 'true') { require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . 'scripts' . DIRECTORY_SEPARATOR . 'webserver_install.php'; exit; } // If a GET request on the root doesn't have this server as a referer, redirect to the homepage: if (!isset($_GET['nosystem']) && DAV::getPath() === '/' && $_SERVER['REQUEST_METHOD'] === 'GET' && (!isset($_SERVER['HTTP_REFERER']) || $_SERVER['SERVER_NAME'] !== parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST))) { DAV::redirect(DAV::HTTP_SEE_OTHER, BeeHub::SYSTEM_PATH); return; } // After bootstrapping, start authentication if (APPLICATION_ENV === BeeHub::ENVIRONMENT_TEST || !empty($_SERVER['HTTPS'])) { BeeHub_Auth::inst()->handle_authentication(BeeHub_Auth::is_authentication_required()); } // And finally handle the request $request = DAV_Request::inst(); if ($request) { $request->handleRequest(); } // End of file