Ejemplo n.º 1
0
 /// <summary>
 ///     Handles a request.</summary>
 /// <param name="request">
 ///     Request to handle.</param>
 /// <param name="setUsername">
 ///     Action to call when login is successful. Typically used to set the username in a session.</param>
 /// <param name="loggedInUser">
 ///     Username of the user currently logged in (typically read from a session).</param>
 public HttpResponse Handle(HttpRequest request, string loggedInUser, Action<string> setUsername)
 {
     return new UrlResolver(
         new UrlMapping(path: "/login", handler: req => loginHandler(req, setUsername)),
         new UrlMapping(path: "/changepassword", handler: req => changePasswordHandler(req, loggedInUser)),
         new UrlMapping(path: "/createuser", handler: req => createUserHandler(req, loggedInUser)),
         new UrlMapping(path: "/logout", handler: req => logoutHandler(req, setUsername))
     ).Handle(request);
 }
Ejemplo n.º 2
0
        /// <summary>Returns an <see cref="HttpResponse"/> that handles the specified request, either by delivering a file from the local file system,
        /// or by listing the contents of a directory in the local file system. The file or directory served is determined from the configured
        /// <see cref="BaseDirectory"/> and the <see cref="HttpRequest.Url"/> of the specified <paramref name="request"/>.</summary>
        /// <param name="request">HTTP request from the client.</param>
        /// <returns>An <see cref="HttpResponse"/> encapsulating the file transfer or directory listing.</returns>
        public HttpResponse Handle(HttpRequest request)
        {
            if (request.Url.Path == "/$/directory-listing/xsl")
                return HttpResponse.Create(new MemoryStream(DirectoryListingXsl), "application/xml; charset=utf-8");

            if (request.Url.Path.StartsWith("/$/directory-listing/icons/" /* watch out for the hardcoded length below */))
                return HttpResponse.Create(new MemoryStream(GetDirectoryListingIcon(request.Url.Path.Substring(27))), "image/png");

            if (request.Url.Path.StartsWith("/$/"))
                throw new HttpNotFoundException();

            var dirStyle = (Options ?? DefaultOptions).DirectoryListingStyle;
            string p = BaseDirectory.EndsWith(Path.DirectorySeparatorChar.ToString()) ? BaseDirectory.Remove(BaseDirectory.Length - 1) : BaseDirectory;
            string[] urlPieces = request.Url.Path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
            string soFar = "";
            string soFarUrl = "";
            for (int i = 0; i < urlPieces.Length; i++)
            {
                string piece = urlPieces[i].UrlUnescape();
                if (piece == "..")
                    throw new HttpException(HttpStatusCode._403_Forbidden);

                var candidateFiles = new List<string> { piece };
                if (piece.EndsWith(".htm"))
                    candidateFiles.Add(piece + "l");
                else if (piece.EndsWith(".html"))
                    candidateFiles.Add(piece.Substring(0, piece.Length - 1));
                else if (piece.EndsWith(".jpg"))
                    candidateFiles.Add(piece.Substring(0, piece.Length - 1) + "eg");
                else if (piece.EndsWith(".jpeg"))
                    candidateFiles.Add(piece.Substring(0, piece.Length - 2) + "g");

                foreach (var suitablePiece in candidateFiles)
                {
                    string nextSoFar = soFar + Path.DirectorySeparatorChar + suitablePiece;
                    string curPath = p + nextSoFar;

                    if (!File.Exists(curPath) && !Directory.Exists(curPath) && curPath.Contains('*') && dirStyle != DirectoryListingStyle.Forbidden)
                        curPath = new DirectoryInfo(p + soFar).GetFileSystemInfos(suitablePiece).Select(fs => fs.FullName).FirstOrDefault() ?? curPath;

                    if (File.Exists(curPath))
                    {
                        soFarUrl += "/" + new DirectoryInfo(p + soFar).GetFiles(suitablePiece)[0].Name.UrlEscape();

                        if (request.Url.Path != soFarUrl)
                            return HttpResponse.Redirect(request.Url.WithPath(soFarUrl));

                        var opts = Options ?? DefaultOptions;
                        return HttpResponse.File(curPath, opts.GetMimeType(curPath), opts.MaxAge, request.Headers.IfModifiedSince);
                    }
                    else if (Directory.Exists(curPath))
                    {
                        soFarUrl += "/" + new DirectoryInfo(p + soFar).GetDirectories(suitablePiece)[0].Name.UrlEscape();
                        soFar = nextSoFar;
                        goto foundOne;
                    }
                }

                // The specified piece is neither a file nor a directory.
                throw new HttpNotFoundException(request.Url.WithPathOnly(soFarUrl + "/" + piece).ToHref());

                foundOne:;
            }

            // If this point is reached, it’s a directory
            if (request.Url.Path != soFarUrl + "/")
                return HttpResponse.Redirect(request.Url.WithPath(soFarUrl + "/"));

            switch (dirStyle)
            {
                case DirectoryListingStyle.Forbidden:
                    throw new HttpException(HttpStatusCode._401_Unauthorized);
                case DirectoryListingStyle.XmlPlusXsl:
                    var auth = (Options ?? DefaultOptions).DirectoryListingAuth;
                    if (auth != null)
                    {
                        var response = auth(request);
                        if (response != null)
                            return response;
                    }
                    if (!Directory.Exists(p + soFar))
                        throw new FileNotFoundException("Directory does not exist.", p + soFar);
                    return HttpResponse.Create(generateDirectoryXml(p + soFar, request.Url, soFarUrl + "/"), "application/xml; charset=utf-8");
                default:
                    throw new InvalidOperationException("Invalid directory listing style: " + (int) dirStyle);
            }
        }
Ejemplo n.º 3
0
        private HttpResponse createUserHandler(HttpRequest req, string loggedInUserName)
        {
            if (req.Method != HttpMethod.Post)
                return createUserForm(req.Url["returnto"], false, false, null, null, null, req.Url.WithoutQuery("returnto"));

            var username = req.Post["username"].Value;
            var newpassword = req.Post["newpassword1"].Value;
            var newpassword2 = req.Post["newpassword2"].Value;
            var returnTo = req.Post["returnto"].Value;

            if (username == null || newpassword == null || newpassword2 == null)
                // if returnTo is null, this removes the query parameter
                return HttpResponse.Redirect(req.Url.WithQuery("returnto", returnTo));

            string passwordHash;
            bool canCreateUsers;
            if (!getUser(ref loggedInUserName, out passwordHash, out canCreateUsers) || !canCreateUsers)
                throw new HttpException(HttpStatusCode._401_Unauthorized);

            if (newpassword2 != newpassword)
                // Passwords don’t match.
                return createUserForm(returnTo, false, true, username, newpassword, newpassword2, req.Url.WithoutQuery("returnto"));

            if (!createUser(username, createHash(newpassword), false))
                // The user already exists.
                return createUserForm(returnTo, true, false, username, newpassword, newpassword2, req.Url.WithoutQuery("returnto"));

            // Success.
            return HttpResponse.Redirect(returnTo ?? _defaultReturnTo(req.Url));
        }
Ejemplo n.º 4
0
        private HttpResponse changePasswordHandler(HttpRequest req, string loggedInUser)
        {
            if (loggedInUser == null)
                return HttpResponse.Redirect(req.Url.WithPathParent().WithPathOnly("/login").WithQuery("returnto", req.Url.ToHref()));

            if (req.Method != HttpMethod.Post)
                return changePasswordForm(loggedInUser, req.Url["returnto"], false, false, null, null, null, req.Url.WithoutQuery("returnto"));

            var oldpassword = req.Post["password"].Value;
            var newpassword = req.Post["newpassword1"].Value;
            var newpassword2 = req.Post["newpassword2"].Value;
            var returnTo = req.Post["returnto"].Value;

            if (loggedInUser == null || oldpassword == null || newpassword == null || newpassword2 == null)
                return HttpResponse.Redirect(returnTo == null ? req.Url : req.Url.WithQuery("returnto", returnTo));

            if (newpassword2 != newpassword)
                return changePasswordForm(loggedInUser, returnTo, false, true, oldpassword, newpassword, newpassword2, req.Url.WithoutQuery("returnto"));

            if (!changePassword(loggedInUser, createHash(newpassword), h => verifyHash(oldpassword, h)))
                return changePasswordForm(loggedInUser, req.Url["returnto"], true, false, oldpassword, newpassword, newpassword2, req.Url.WithoutQuery("returnto"));

            return HttpResponse.Redirect(returnTo ?? _defaultReturnTo(req.Url));
        }
Ejemplo n.º 5
0
        private HttpResponse loginHandler(HttpRequest req, Action<string> setUsername)
        {
            if (req.Method != HttpMethod.Post)
                return loginForm(req.Url["returnto"], false, null, null, req.Url.WithoutQuery("returnto"));

            var username = req.Post["username"].Value;
            var password = req.Post["password"].Value;
            var returnTo = req.Post["returnto"].Value;

            if (username == null || password == null)
                return HttpResponse.Redirect(req.Url.WithQuery("returnto", returnTo));

            string passwordHash;
            bool canCreateUsers;
            if (getUser(ref username, out passwordHash, out canCreateUsers) && verifyHash(password, passwordHash))
            {
                // Login successful!
                setUsername(username);
                return HttpResponse.Redirect(returnTo ?? _defaultReturnTo(req.Url));
            }

            // Login failed.
            return loginForm(returnTo, true, username, password, req.Url);
        }
Ejemplo n.º 6
0
 private HttpResponse logoutHandler(HttpRequest req, Action<string> setUsername)
 {
     setUsername(null);
     return HttpResponse.Redirect(req.Url.WithParent("login"));
 }
Ejemplo n.º 7
0
        /// <summary>
        ///     Retrieves the session ID from the session cookie (specified by the cookie name) from the given <see
        ///     cref="HttpRequest"/> and calls the <paramref name="handler"/> function. A session cookie is added to the HTTP
        ///     response returned by the handler only if either <see cref="DeleteSession"/> or <see cref="NewSession"/> have been
        ///     called (possibly by the handler). Before the possibly augmented HTTP response is returned, the status of
        ///     DeleteSession and NewSession is reset.</summary>
        /// <param name="req">
        ///     The current HTTP request.</param>
        /// <param name="handler">
        ///     The inner request handler to execute.</param>
        /// <returns>
        ///     An HTTP response, possibly augmented with a session cookie.</returns>
        public HttpResponse Handle(HttpRequest req, Func<HttpResponse> handler)
        {
            if (req == null)
                throw new ArgumentNullException("req");
            if (handler == null)
                throw new ArgumentNullException("handler");

            if (req.Headers != null && req.Headers.Cookie != null && req.Headers.Cookie.ContainsKey(CookieName))
            {
                var cookie = req.Headers.Cookie[CookieName];
                SessionID = cookie.Value;
                CookiePath = cookie.Path;
                CookieExpires = cookie.Expires;
            }
            else
            {
                SessionID = null;
            }

            var response = handler();

            if (response != null && ((_deleteSession && SessionID != null) || _newSession))
            {
                if (response.Headers.SetCookie == null)
                    response.Headers.SetCookie = new List<Cookie>();

                response.Headers.SetCookie.Add(new Cookie
                {
                    Name = CookieName,
                    Value = _deleteSession ? "-" : _newSessionID,
                    Path = _deleteSession ? CookiePath : _newCookiePath,
                    Expires = _deleteSession ? new DateTime(1970, 1, 1) : _newCookieExpires,
                    HttpOnly = true,
                });
            }

            _deleteSession = false;
            _newSession = false;
            return response;
        }