Permalink
Browse files

Rework public links to use Middleware model. Adds support for /public…

…/LINK/dl/FILENAME, including BasicAuth if share is pass-protected.
  • Loading branch information...
1 parent 81c8fe5 commit 9dafdf61d448c35da670445f2f6d1f5a8a104347 @cdujeu cdujeu committed Sep 2, 2016
@@ -466,6 +466,6 @@
</registry_contributions>
<class_definition filename="plugins/action.share/src/ShareCenter.php" classname="Pydio\Share\ShareCenter"/>
<dependencies>
- <activePlugin pluginName="access.AJXP_STREAM_PROVIDER|access.ajxp_user|access.ajxp_conf|access.ajxp_admin"/>
+ <!--<activePlugin pluginName="access.AJXP_STREAM_PROVIDER|access.ajxp_user|access.ajxp_conf|access.ajxp_admin"/>-->
</dependencies>
</ajxp_plugin>
@@ -0,0 +1,157 @@
+<?php
+/*
+ * Copyright 2007-2016 Abstrium <contact (at) pydio.com>
+ * This file is part of Pydio.
+ *
+ * Pydio is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Pydio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Pydio. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The latest code can be found at <https://pydio.com/>.
+ */
+namespace Pydio\Share\Http;
+
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Pydio\Core\Http\Server;
+use Pydio\Core\Model\Context;
+use Pydio\Core\Model\ContextInterface;
+use Pydio\Core\Services\AuthService;
+use Pydio\Core\Services\UsersService;
+
+defined('AJXP_EXEC') or die('Access not allowed');
+
+/**
+ * Class MinisiteAuthMiddleware
+ * @package Pydio\Share\Http
+ */
+class MinisiteAuthMiddleware
+{
+ /**
+ * Parse request parameters
+ * @param ServerRequestInterface $requestInterface
+ * @param ResponseInterface $responseInterface
+ * @return ResponseInterface
+ */
+ public static function handleRequest(ServerRequestInterface $requestInterface, ResponseInterface $responseInterface, callable $next = null){
+
+ $rest = $requestInterface->getAttribute("rest");
+ $hash = $requestInterface->getAttribute("hash");
+ $shareData = $requestInterface->getAttribute("data");
+
+ if($rest){
+ AuthService::$useSession = false;
+ }else{
+ session_name("AjaXplorer_Shared".str_replace(".","_",$hash));
+ session_start();
+ AuthService::disconnect();
+ }
+
+ if (!empty($shareData["PRELOG_USER"])) {
+
+ $loggedUser = AuthService::logUser($shareData["PRELOG_USER"], "", true);
+ $requestInterface = $requestInterface->withAttribute("ctx", Context::contextWithObjects($loggedUser, null));
+
+ } else if(isSet($shareData["PRESET_LOGIN"])) {
+
+ if($rest){
+ $responseInterface = self::basicHttp($shareData["PRESET_LOGIN"], $requestInterface, $responseInterface);
+ if($responseInterface->getStatusCode() === 401){
+ return $responseInterface;
+ }
+ }else{
+ $_SESSION["PENDING_REPOSITORY_ID"] = $shareData["REPOSITORY"];
+ $_SESSION["PENDING_FOLDER"] = "/";
+ }
+
+ }
+
+ /** @var ContextInterface $ctx */
+ $ctx = $requestInterface->getAttribute("ctx");
+
+ if (isSet($_GET["lang"])) {
+ if ($ctx->hasUser()) {
+ $ctx->getUser()->setPref("lang", $_GET["lang"]);
+ } else {
+ setcookie("AJXP_lang", $_GET["lang"]);
+ }
+ }
+
+ if(!$rest){
+ $_SESSION["CURRENT_MINISITE"] = $hash;
+ }
+ if(!empty($ctx) && $ctx->hasUser() && isSet($shareData["REPOSITORY"])){
+ $repoObject = UsersService::getRepositoryWithPermission($ctx->getUser(), $shareData["REPOSITORY"]);
+ $ctx->setRepositoryObject($repoObject);
+ $requestInterface = $requestInterface->withAttribute("ctx", $ctx);
+ }
+
+ return Server::callNextMiddleWare($requestInterface, $responseInterface, $next);
+
+ }
+
+ /**
+ * Perform Basic HTTP Auth
+ * @param string $presetLogin
+ * @param ServerRequestInterface $requestInterface
+ * @param ResponseInterface $responseInterface
+ * @return ResponseInterface|static
+ * @throws \Pydio\Core\Exception\LoginException
+ */
+ public static function basicHttp($presetLogin, ServerRequestInterface &$requestInterface, ResponseInterface $responseInterface){
+
+ $serverData = $requestInterface->getServerParams();
+ $localHttpLogin = $serverData["PHP_AUTH_USER"];
+ $localHttpPassw = $serverData['PHP_AUTH_PW'];
+
+ // mod_php
+ if (isset($serverData['PHP_AUTH_USER'])) {
+ $localHttpLogin = $serverData['PHP_AUTH_USER'];
+ $localHttpPassw = $serverData['PHP_AUTH_PW'];
+
+ // most other servers
+ } elseif (isset($serverData['HTTP_AUTHORIZATION'])) {
+ if (strpos(strtolower($serverData['HTTP_AUTHORIZATION']), 'basic') === 0) {
+ list($localHttpLogin, $localHttpPassw) = explode(':', base64_decode(substr($serverData['HTTP_AUTHORIZATION'], 6)));
+ }
+ // Sometimes prepend a REDIRECT
+ } elseif (isset($serverData['REDIRECT_HTTP_AUTHORIZATION'])) {
+
+ if (strpos(strtolower($serverData['REDIRECT_HTTP_AUTHORIZATION']), 'basic') === 0) {
+ list($localHttpLogin, $localHttpPassw) = explode(':', base64_decode(substr($serverData['REDIRECT_HTTP_AUTHORIZATION'], 6)));
+ }
+
+ }
+
+ // Check that localHttpLogin == Hash ?
+
+ if (empty($localHttpPassw)) {
+ return $responseInterface->withHeader("WWW-Authenticate", "Basic realm=\"Please provide password\"")->withStatus(401);
+ }
+
+ try {
+
+ $loggedUser = AuthService::logUser($presetLogin, $localHttpPassw, false, false, "-1");
+ $requestInterface = $requestInterface->withAttribute("ctx", Context::contextWithObjects($loggedUser, null));
+ return $responseInterface;
+
+ } catch (\Pydio\Core\Exception\LoginException $l) {
+ if ($l->getLoginError() !== -4) {
+ return $responseInterface->withHeader("WWW-Authenticate", "Basic realm=\"Please provide a valid password\"")->withStatus(401);
+ }else{
+ throw $l;
+ }
+ }
+
+ }
+
+}
@@ -0,0 +1,90 @@
+<?php
+/*
+ * Copyright 2007-2016 Abstrium <contact (at) pydio.com>
+ * This file is part of Pydio.
+ *
+ * Pydio is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Pydio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Pydio. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The latest code can be found at <https://pydio.com/>.
+ */
+namespace Pydio\Share\Http;
+
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Pydio\Core\Exception\PydioException;
+use Pydio\Core\Http\Middleware\SapiMiddleware;
+use Pydio\Core\Http\Server;
+use Pydio\Core\Model\Context;
+use Pydio\Core\PluginFramework\PluginsService;
+use Pydio\Core\Services\AuthService;
+use Pydio\Core\Services\LocaleService;
+use Pydio\Share\Model\ShareLink;
+use Pydio\Share\ShareCenter;
+
+defined('AJXP_EXEC') or die('Access not allowed');
+
+/**
+ * Class MinisiteRootMiddleware
+ * @package Pydio\Share\Http
+ */
+class MinisiteRootMiddleware extends SapiMiddleware
+{
+
+ private $hash;
+
+ /**
+ * MinisiteRootMiddleware constructor.
+ * @param $hash
+ */
+ public function __construct($hash){
+ $this->hash = $hash;
+ }
+
+ /**
+ * @param ServerRequestInterface $request
+ * @param ResponseInterface $response
+ * @param callable|null $next
+ * @return ResponseInterface|null
+ * @throws PydioException
+ */
+ public function handleRequest(ServerRequestInterface $request, ResponseInterface $response, callable $next = null){
+
+ PluginsService::getInstance()->initActivePlugins();
+ $shareCenter = ShareCenter::getShareCenter(Context::emptyContext());
+ $data = $shareCenter->getShareStore()->loadShare($this->hash);
+ $mess = LocaleService::getMessages();
+ if($data === false){
+ AuthService::disconnect();
+ throw new PydioException($mess["share_center.166"]);
+ }
+ if(ShareLink::isShareExpired($data)){
+ AuthService::disconnect();
+ throw new PydioException($mess["share_center.165"]);
+ }
+ if(!empty($data) && is_array($data)){
+ if($data["SHARE_TYPE"] !== "minisite"){
+ ShareCenter::loadPubliclet($data);
+ return;
+ }
+ $request = $request->withAttribute("hash", $this->hash);
+ $request = $request->withAttribute("data", $data);
+ }else{
+ throw new PydioException($mess["share_center.166"]);
+ }
+ $response = Server::callNextMiddleWare($request, $response, $next);
+ $this->emitResponse($request, $response);
+ return null;
+
+ }
+}
@@ -0,0 +1,115 @@
+<?php
+/*
+ * Copyright 2007-2016 Abstrium <contact (at) pydio.com>
+ * This file is part of Pydio.
+ *
+ * Pydio is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Pydio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Pydio. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The latest code can be found at <https://pydio.com/>.
+ */
+namespace Pydio\Share\Http;
+
+use Psr\Http\Message\ServerRequestInterface;
+use Pydio\Core\Http\Middleware\SapiMiddleware;
+use Pydio\Core\Http\Server;
+use Pydio\Core\Model\Context;
+use Pydio\Core\Services\ConfService;
+use Pydio\Share\View\MinisiteRenderer;
+use Zend\Diactoros\Response;
+
+defined('AJXP_EXEC') or die('Access not allowed');
+
+/**
+ * Class ShareServer
+ * @package Pydio\Share\Http
+ */
+class MinisiteServer extends Server
+{
+
+ /**
+ * @var string
+ */
+ private $crtLinkHash;
+
+ /**
+ * @var bool
+ */
+ private $rest = false;
+
+ /**
+ * MinisiteServer constructor.
+ * @param $base
+ * @param $linkHash
+ * @param bool $rest
+ */
+ public function __construct($base, $linkHash, $rest = false)
+ {
+ $this->crtLinkHash = $linkHash;
+ $this->rest = $rest;
+ parent::__construct($base);
+ if($rest){
+ ConfService::currentContextIsRestAPI($base);
+ }
+ }
+
+ protected function stackMiddleWares()
+ {
+ $this->middleWares->push(array("Pydio\\Share\\View\\MinisiteRenderer", "handleRequest"));
+ $this->middleWares->push(array("Pydio\\Share\\Http\\MinisiteAuthMiddleware", "handleRequest"));
+ $topMiddleware = new MinisiteRootMiddleware($this->crtLinkHash);
+ $this->topMiddleware = $topMiddleware;
+ $this->middleWares->push(array($this->topMiddleware, "handleRequest"));
+ }
+
+ /**
+ * @param bool $rest
+ * @return ServerRequestInterface
+ */
+ protected function initServerRequest($rest = false){
+
+ $request = parent::initServerRequest();
+ $body = $request->getParsedBody();
+ if(is_array($_GET) && count($_GET)){
+ $body = array_merge($body, $_GET);
+ $request = $request->withParsedBody($body);
+ }
+ if($this->rest){
+ $request = $request->withAttribute("rest", true);
+ }
+ return $request;
+
+ }
+
+ /**
+ * @param $code
+ * @param $message
+ * @param $fichier
+ * @param $ligne
+ * @param $context
+ */
+ public function catchError($code, $message, $fichier, $ligne, $context)
+ {
+ $req = $this->getRequest();
+ $resp = new Response();
+
+ $setUrl = ConfService::getGlobalConf("SERVER_URL");
+ $data = array();
+ if (!empty($setUrl)) {
+ $data["AJXP_APPLICATION_BASE"] = $setUrl;
+ }
+ MinisiteRenderer::writeHtml($resp, Context::emptyContext(), $data, "", $message);
+ $this->topMiddleware->emitResponse($req, $resp);
+ }
+
+}
Oops, something went wrong.

0 comments on commit 9dafdf6

Please sign in to comment.