/** * Through a POST request you can create new sponsors * * @param array $headers The HTTP headers * @throws DAV_Status * @see DAV_Resource::method_POST() */ public function method_POST(&$headers) { $displayname = $_POST['displayname']; $description = $_POST['description']; $sponsor_name = $_POST['sponsor_name']; // Only administrators can add a sponsor if (!DAV::$ACLPROVIDER->wheel()) { throw DAV::forbidden('Only administrators are allowed to create sponsors'); } // Sponsor name must be one of the following characters a-zA-Z0-9_-., starting with an alphanumeric character and must be between 1 and 255 characters long if (empty($displayname) || !preg_match('/^[a-zA-Z0-9]{1}[a-zA-Z0-9_\\-\\.]{0,254}$/D', $sponsor_name)) { throw new DAV_Status(DAV::HTTP_BAD_REQUEST, 'Sponsor name has the wrong format. The name can be a maximum of 255 characters long and should start with an alphanumeric character, followed by alphanumeric characters or one of the following: _-.'); } // Check if the group name doesn't exist $collection = BeeHub::getNoSQL()->sponsors; $result = $collection->findOne(array('name' => $sponsor_name), array('name' => true)); if (!is_null($result)) { // Duplicate key: bad request! throw new DAV_Status(DAV::HTTP_CONFLICT, "Sponsor name already exists, please choose a different sponsor name!"); } // Store in the database $collection->insert(array('name' => $sponsor_name)); // Fetch the sponsor and store extra properties $sponsor = DAV::$REGISTRY->resource(BeeHub::SPONSORS_PATH . $sponsor_name); $sponsor->user_set(DAV::PROP_DISPLAYNAME, $displayname); if (!empty($description)) { $sponsor->user_set(BeeHub::PROP_DESCRIPTION, $description); } $sponsor->storeProperties(); // Add the current user as admin of the sponsor $sponsor->change_memberships(basename($this->user_prop_current_user_principal()), BeeHub_Sponsor::ADMIN_ACCEPT); $sponsor->change_memberships(basename($this->user_prop_current_user_principal()), BeeHub_Sponsor::SET_ADMIN); // Sponsor created, redirect to the sponsor page DAV::redirect(DAV::HTTP_SEE_OTHER, BeeHub::SPONSORS_PATH . $sponsor->name); }
public function testForbidden() { $status = DAV::forbidden('Test message'); $this->assertInstanceOf('DAV_Status', $status, 'DAV::forbidden() should return a DAV_Status object'); $this->assertSame(403, $status->getCode(), 'DAV::forbidden() should return a DAV_Status object with code 403'); $this->assertSame('Test message', $status->getMessage(), 'DAV::forbidden() should return a DAV_Status object with code 403'); }
public function method_POST(&$headers) { $displayname = $_POST['displayname']; $description = $_POST['description']; $group_name = $_POST['group_name']; $user_sponsor = BeeHub::getAuth()->current_user()->user_prop(BeeHub::PROP_SPONSOR); // If you don't have a (default) sponsor, you're not allowed to add a group if (empty($user_sponsor)) { throw DAV::forbidden("Only users with a sponsor are allowed to create groups"); } // Group name must be one of the following characters a-zA-Z0-9_-., starting with an alphanumeric character and must be between 1 and 255 characters long and can't be one of the forbidden names if (empty($displayname) || in_array(strtolower($group_name), BeeHub::$FORBIDDEN_GROUP_NAMES) || !preg_match('/^[a-zA-Z0-9]{1}[a-zA-Z0-9_\\-\\.]{0,254}$/D', $group_name)) { throw new DAV_Status(DAV::HTTP_BAD_REQUEST, 'Group name has the wrong format. The name can be a maximum of 255 characters long and should start with an alphanumeric character, followed by alphanumeric characters or one of the following: _-.'); } // Check if the group name doesn't exist $collection = BeeHub::getNoSQL()->groups; $result = $collection->findOne(array('name' => $group_name), array('name' => true)); if (!is_null($result)) { // Duplicate key: bad request! throw new DAV_Status(DAV::HTTP_CONFLICT, "Group name already exists, please choose a different group name!"); } $groupdir = DAV::unslashify(BeeHub::$CONFIG['environment']['datadir']) . DIRECTORY_SEPARATOR . $group_name; // Check for existing groupdir if (file_exists($groupdir)) { throw new DAV_Status(DAV::HTTP_INTERNAL_SERVER_ERROR); } // Store in the database $collection->insert(array('name' => $group_name)); // Fetch the group and store extra properties $group = DAV::$REGISTRY->resource(BeeHub::GROUPS_PATH . $group_name); $group->user_set(DAV::PROP_DISPLAYNAME, $displayname); if (!empty($description)) { $group->user_set(BeeHub::PROP_DESCRIPTION, $description); } $group->storeProperties(); // Add the current user as admin of the group $group->change_memberships(basename($this->user_prop_current_user_principal()), BeeHub_Group::USER_ACCEPT); $group->change_memberships(basename($this->user_prop_current_user_principal()), BeeHub_Group::ADMIN_ACCEPT); $group->change_memberships(basename($this->user_prop_current_user_principal()), BeeHub_Group::SET_ADMIN); // And create a group directory if (!mkdir($groupdir)) { throw new DAV_Status(DAV::HTTP_INTERNAL_SERVER_ERROR); } // And create the directory in the database $document = array('path' => $group_name, 'depth' => 1, 'collection' => true); $filesCollection = BeeHub::getNoSQL()->files; $filesCollection->save($document); $groupdir_resource = DAV::$REGISTRY->resource('/' . $group_name); $groupdir_resource->user_set(BeeHub::PROP_SPONSOR, $user_sponsor); $groupdir_resource->user_set(DAV::PROP_ACL, '[["' . BeeHub::GROUPS_PATH . $group->name . '",false,["DAV: read", "DAV: write"],false]]'); $groupdir_resource->storeProperties(); // Group created, redirect to the group page DAV::redirect(DAV::HTTP_SEE_OTHER, BeeHub::GROUPS_PATH . $group->name); }
private function internal_create_member($name, $collection = false) { $this->assert(DAVACL::PRIV_WRITE_CONTENT); $path = $this->path . $name; $localPath = BeeHub::localPath($path); $cups = $this->current_user_principals(); // Determine the sponsor $user = BeeHub::getAuth()->current_user(); if (!is_null($user)) { $user_sponsors = $user->user_prop_sponsor_membership(); } if (is_null($user) || count($user_sponsors) == 0) { // If the user doesn't have any sponsors, he/she can't create files and directories throw DAV::forbidden("You need to be logged in and have at least one sponsor to upload files"); } $sponsor = $this->user_prop(BeeHub::PROP_SPONSOR); // The default is the directory sponsor if (!in_array($sponsor, $user_sponsors)) { //But a user can only create files sponsored by his own sponsors $sponsor = $user->user_prop(BeeHub::PROP_SPONSOR); } // Create the subdirectory or file if (file_exists($localPath)) { throw DAV::forbidden(); } $result = $collection ? @mkdir($localPath) : touch($localPath); if (!$result) { throw new DAV_Status(DAV::HTTP_INTERNAL_SERVER_ERROR); } // And create the object in the database $unslashifiedPath = \DAV::unslashify($path); if (substr($unslashifiedPath, 0, 1) === '/') { $unslashifiedPath = substr($unslashifiedPath, 1); } $document = array('path' => $unslashifiedPath, 'depth' => substr_count($unslashifiedPath, '/') + 1); if ($collection) { $document['collection'] = true; } $filesCollection = BeeHub::getNoSQL()->files; $filesCollection->save($document); // And set the attributes $new_resource = DAV::$REGISTRY->resource($path); if (!$collection) { $new_resource->user_set(DAV::PROP_GETETAG, BeeHub::ETag()); } $new_resource->user_set(DAV::PROP_OWNER, $this->user_prop_current_user_principal()); $new_resource->user_set(BeeHub::PROP_SPONSOR, $sponsor); $new_resource->storeProperties(); return $new_resource; }
/** * 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:acl-principal-prop-set REPORT request * * @param DAV_Resource $resource The resource to perform the request on * @return void */ private function handle_acl_principal_prop_set($resource) { $ppr = $resource->property_priv_read(array(DAV::PROP_ACL)); if (!$ppr[DAV::PROP_ACL]) { throw DAV::forbidden(); } $principals = array(); foreach ($resource->user_prop_acl() as $ace) { if ('/' === $ace->principal[0]) { $principals[$ace->principal] = true; } elseif (isset(DAVACL::$PRINCIPALS[$ace->principal])) { continue; } else { $href = $resource->prop($ace->principal); if ($href instanceof DAV_Element_href) { $principals[$href->URIs[0]] = true; } } } $multistatus = DAV_Multistatus::inst(); foreach (array_keys($principals) as $href) { if ($href && ($principal = DAV::$REGISTRY->resource($href))) { $response = new DAV_Element_response($href); foreach ($this->entity as $property) { try { $response->setProperty($property, $principal->prop($property)); } catch (DAV_Status $e) { $response->setStatus($property, $e); } } $multistatus->addResponse($response); } } }
/** * 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(); }
public function method_POST(&$headers) { $this->init_props(); // For all POST requests, you need to send a POST field 'password' with the current password if (!isset($_POST['password']) || !$this->check_password($_POST['password'])) { throw DAV::forbidden(); } if (isset($_POST['verification_code'])) { // Now verify the e-mail address if (!$this->verify_email_address($_POST['verification_code'])) { throw DAV::forbidden(); } DAV::redirect(DAV::HTTP_SEE_OTHER, $this->path); return; } elseif (isset($_POST['new_password'])) { $this->set_password($_POST['new_password']); DAV::redirect(DAV::HTTP_SEE_OTHER, $this->path); return; } throw new DAV_Status(DAV::HTTP_BAD_REQUEST); }
public function method_POST(&$headers) { $auth = BeeHub::getAuth(); if (!$auth->is_authenticated()) { throw DAV::forbidden(); } $admin_functions = array('add_members', 'add_admins', 'delete_admins', 'delete_members'); if (!$this->is_admin()) { foreach ($admin_functions as $function) { if (isset($_POST[$function])) { throw DAV::forbidden(); } } } // Allow users to request or remove membership $current_user = $auth->current_user(); if (isset($_POST['leave'])) { $this->change_memberships($current_user, self::DELETE_MEMBER); } if (isset($_POST['join'])) { $message = null; if (!$this->is_member()) { // This user is not invited for this group, so sent the administrators an e-mail with this request $message = 'Dear sponsor administrator, ' . $current_user->prop(DAV::PROP_DISPLAYNAME) . ' (' . $current_user->prop(BeeHub::PROP_EMAIL) . ') wants to join the sponsor \'' . $this->prop(DAV::PROP_DISPLAYNAME) . '\'. One of the sponsor administrators needs to either accept or reject this membership request. Please see your notifications in BeeHub to do this: ' . BeeHub::urlbase(true) . '/system/?show_notifications=1 Best regards, BeeHub'; $recipients = array(); foreach ($this->users as $user => $attributes) { if ($attributes['is_admin']) { $user = BeeHub::user($user); $recipients[$user->prop(BeeHub::PROP_EMAIL)] = $user->prop(DAV::PROP_DISPLAYNAME); } } } $this->change_memberships(array($current_user->name), self::USER_ACCEPT); if (!is_null($message)) { BeeHub::email($recipients, 'BeeHub notification: membership request for sponsor ' . $this->prop(DAV::PROP_DISPLAYNAME), $message); } } // Run administrator actions: add members, admins and requests foreach ($admin_functions as $key) { if (isset($_POST[$key])) { if (!is_array($_POST[$key])) { throw new DAV_Status(DAV::HTTP_BAD_REQUEST); } $members = array_map(array('BeeHub_Sponsor', 'get_user_name'), $_POST[$key]); switch ($key) { case 'add_members': foreach ($members as $member) { $user = BeeHub::user($member); if (!$this->is_member($user)) { // The user was not a member of this sponsor yet, so notify him/her $message = 'Dear ' . $user->prop(DAV::PROP_DISPLAYNAME) . ', You are now sponsored by \'' . $this->prop(DAV::PROP_DISPLAYNAME) . '\'. Best regards, BeeHub'; BeeHub::email(array($user->prop(BeeHub::PROP_EMAIL) => $user->prop(DAV::PROP_DISPLAYNAME)), 'BeeHub notification: new sponsor ' . $this->prop(DAV::PROP_DISPLAYNAME), $message); } } $this->change_memberships($members, self::ADMIN_ACCEPT); break; case 'add_admins': $this->change_memberships($members, self::SET_ADMIN); break; case 'delete_admins': $this->check_admin_remove($members); $this->change_memberships($members, self::UNSET_ADMIN); break; case 'delete_members': $this->change_memberships($members, self::DELETE_MEMBER); foreach ($members as $member) { $user = BeeHub::user($member); $message = 'Dear ' . $user->prop(DAV::PROP_DISPLAYNAME) . ', Sponsor administrator ' . $current_user->prop(DAV::PROP_DISPLAYNAME) . ' removed you from the sponsor \'' . $this->prop(DAV::PROP_DISPLAYNAME) . '\'. If you believe you should be a member of this sponsor, please contact one of the sponsor administrators. Best regards, BeeHub'; BeeHub::email(array($user->prop(BeeHub::PROP_EMAIL) => $user->prop(DAV::PROP_DISPLAYNAME)), 'BeeHub notification: removed from sponsor ' . $this->prop(DAV::PROP_DISPLAYNAME), $message); } break; default: //Should/could never happen throw new DAV_Status(DAV::HTTP_INTERNAL_SERVER_ERROR); break; } } } }
/** * @see DAVACL_Resource::user_set_owner() */ protected function user_set_owner($owner) { // The owner should exist and be visible if (!($owner = DAV::$REGISTRY->resource($owner)) || !$owner->isVisible() || !$owner instanceof BeeHub_User) { throw new DAV_Status(DAV::HTTP_BAD_REQUEST, DAV::COND_RECOGNIZED_PRINCIPAL); } // You should be authenticated if (!($cup = $this->user_prop_current_user_principal()) || !($cup = DAV::$REGISTRY->resource($cup))) { throw DAV::forbidden(); } // Get the sponsor of this resource if ($sponsor = $this->user_prop_sponsor()) { $sponsor = DAV::$REGISTRY->resource($sponsor); } else { // There is no sponsor set for this file. How can that be? throw new DAV_Status(DAV::HTTP_INTERNAL_SERVER_ERROR, 'There is no sponsor set for this file!'); } // If you are owner, and the new owner is sponsored by the resource sponsor if ($this->user_prop_owner() === $cup->path && in_array($owner->path, $sponsor->user_prop_group_member_set())) { return $this->user_set(DAV::PROP_OWNER, $owner->path); } // If you are not the owner, you can become owner if you have write // privileges on both the resource itself as its parent collection if ($this->user_prop_owner() !== $cup->path && $owner->path === $cup->path && $this->collection() instanceof BeeHub_Directory) { $this->assert(BeeHub::PRIV_READ_CONTENT); $this->assert(DAVACL::PRIV_READ_ACL); $this->assert(DAVACL::PRIV_WRITE_CONTENT); $this->collection()->assert(DAVACL::PRIV_WRITE_CONTENT); // If the user is not sponsored by the resource sponsor, we have to change // the resource sponsor if (!in_array($this->user_prop_sponsor(), BeeHub::getAuth()->current_user()->user_prop_sponsor_membership())) { // If the user is sponsored by the collection sponsor, then let's take // that sponsor if (!in_array($this->collection()->user_prop_sponsor(), BeeHub::getAuth()->current_user()->user_prop_sponsor_membership())) { // Else take the default sponsor of the user if (!$cup->user_prop_sponsor()) { throw DAV::forbidden(); } else { $this->user_set(BeeHub::PROP_SPONSOR, $cup->user_prop_sponsor()); } } else { $this->user_set(BeeHub::PROP_SPONSOR, $this->collection()->user_prop_sponsor()); } } return $this->user_set(DAV::PROP_OWNER, $owner->path); } // If the owner still isn't changed, you are not allowed to do so throw DAV::forbidden(); }
/** * Assert whether the current user has certain privileges for this resource * * @param array $privileges * @throws DAV_Status FORBIDDEN */ public function assert($privileges) { if (!is_array($privileges)) { $privileges = array((string) $privileges); } $flags = array(); foreach ($privileges as $p) { $supportedPrivileges = DAV::$ACLPROVIDER->user_prop_supported_privilege_set(); $privilege = null; foreach ($supportedPrivileges as $supportedPrivilege) { $privilege = $supportedPrivilege->findSubPrivilege($p); if (!is_null($privilege)) { break; } } if (is_null($privilege)) { throw new DAV_Status(DAV::HTTP_INTERNAL_SERVER_ERROR, 'Privilege not found: ' . $p); } if ($privilege->isAggregatePrivilege()) { throw new DAV_Status(DAV::HTTP_INTERNAL_SERVER_ERROR, 'You cannot (and should not) assert aggregate privileges: ' . $p); } $flags[$p] = 0; } sort($privileges); $privstring = implode(',', $privileges); if (array_key_exists($privstring, $this->assertCache)) { if ($this->assertCache[$privstring]) { throw $this->assertCache[$privstring]; } else { return true; } } $eacl = $this->effective_acl(); foreach ($eacl as $ace) { list($deny, $privs) = $ace; foreach ($privs as $p) { if (isset($flags[$p]) && false !== $flags[$p]) { $flags[$p] = !$deny; } } foreach ($flags as $f) { if (true !== $f) { continue 2; } } $this->assertCache[$privstring] = null; return true; } $need_privileges = ''; foreach (array_keys($flags) as $priv) { if (!$flags[$priv]) { $need_privileges .= '<' . DAV::expand($priv) . '/>'; } } $this->assertCache[$privstring] = DAV::forbidden(array(DAV::COND_NEED_PRIVILEGES => $need_privileges)); throw $this->assertCache[$privstring]; }
public function method_COPY($path) { $this->assert(BeeHub::PRIV_READ_CONTENT); $this->assert(DAVACL::PRIV_READ_ACL); $destinationResource = DAV::$REGISTRY->resource($path); $parent = DAV::$REGISTRY->resource(dirname($path)); if (!$parent) { throw new DAV_Status(DAV::HTTP_CONFLICT, 'Unable to COPY to unexisting collection'); } if (!$parent instanceof BeeHub_Directory) { throw new DAV_Status(DAV::HTTP_FORBIDDEN); } if ($destinationResource instanceof DAVACL_Resource) { $destinationResource->assert(DAVACL::PRIV_WRITE_CONTENT); $destinationResource->assert(DAVACL::PRIV_WRITE_ACL); $parent->method_DELETE(basename($path)); } else { $parent->assert(DAVACL::PRIV_WRITE_CONTENT); } // Determine the sponsor $user = BeeHub::getAuth()->current_user(); $user_sponsors = $user->user_prop_sponsor_membership(); if (count($user_sponsors) === 0) { // If the user doesn't have any sponsors, he/she can't create files and directories throw DAV::forbidden(); } $localPath = BeeHub::localPath($path); exec('cp ' . BeeHub::escapeshellarg($this->localPath) . ' ' . BeeHub::escapeshellarg($localPath)); // And copy the attributes $new_resource = new BeeHub_File($path); foreach ($this->stored_props as $prop => $value) { if (!in_array($prop, array(DAV::PROP_OWNER, BeeHub::PROP_SPONSOR, DAV::PROP_ACL, DAV::PROP_GETETAG, DAV::PROP_LOCKDISCOVERY))) { $new_resource->user_set($prop, $value); } } $sponsor = $parent->user_prop_sponsor(); // The default is the directory sponsor if (!in_array($sponsor, $user_sponsors)) { //But a user can only create files sponsored by his own sponsors $sponsor = $user->user_prop(BeeHub::PROP_SPONSOR); } // And set the new properties $new_resource->user_set(DAV::PROP_OWNER, $this->user_prop_current_user_principal()); $new_resource->user_set(BeeHub::PROP_SPONSOR, $sponsor); $new_resource->user_set(DAV::PROP_GETETAG, BeeHub::ETag()); $new_resource->storeProperties(); }
$simpleSaml->login(); } if ($_SERVER['REQUEST_METHOD'] === 'GET') { require_once 'views' . DIRECTORY_SEPARATOR . 'saml_connect.php'; exit; } if ($_SERVER['REQUEST_METHOD'] !== 'POST') { throw new DAV_Status(DAV::HTTP_METHOD_NOT_ALLOWED); } // Get some authentication info $user = $auth->current_user(); $surfId = $simpleSaml->getAuthData("saml:sp:NameID"); $surfId = $surfId['Value']; // You need to supply the users current password (as stored in the local database) if (!$user->check_password($_POST['password'])) { throw DAV::forbidden(); } // Unlink potential other local account linked to this SURFconext ID $collection = BeeHub::getNoSQL()->users; $collection->update(array('surfconext_id' => $surfId), array('$unset' => array('surfconext_id' => '', 'surfconext_description' => ''))); // And connect it to the current user $user->user_set(BeeHub::PROP_SURFCONEXT, $surfId); $attributes = $simpleSaml->getAttributes(); $surfconext_description = @$attributes['urn:mace:terena.org:attribute-def:schacHomeOrganization'][0]; if (empty($surfconext_description)) { $surfconext_description = 'Unknown account'; } $user->user_set(BeeHub::PROP_SURFCONEXT_DESCRIPTION, $surfconext_description); $user->storeProperties(); // Redirect to the user's profile page DAV::redirect(DAV::HTTP_SEE_OTHER, $user->path);
/** * Called by {@link method_PROPFIND()} * @param string $path * @param DAV_Resource $resource * @param array $props */ private function handle3($resource, $props) { $propprivs = $resource->property_priv_read($props); $response = new DAV_Element_response($resource->path); foreach ($props as $prop) { if (array_key_exists($prop, $propprivs) && !$propprivs[$prop]) { $response->setStatus($prop, DAV::forbidden()); } else { try { $value = $resource->prop($prop); if (!is_null($value)) { $response->setProperty($prop, $value); } else { $response->setStatus($prop, DAV_Status::$NOT_FOUND); } } catch (DAV_Status $e) { $response->setStatus($prop, $e); } } } DAV_Multistatus::inst()->addResponse($response); }