Skip to content

Commit

Permalink
Redirect after Titan request, generate directories (#5)
Browse files Browse the repository at this point in the history
* Add titan redirects, fix writing to subdirectories

* Remove unneeded string conversion

* Make *most* of requested changes. Not settings yet.

* Add separate [titan] section to config

* More requested changes

* i am dum
  • Loading branch information
stellarskylark authored May 26, 2022
1 parent f468e93 commit 0d67c81
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 22 deletions.
13 changes: 10 additions & 3 deletions geminim.ini
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,25 @@ rootDir = "pub/"
# Defaults to "/home/$#/" on POSIX systems and "C:\Users\$#" on Windows
homeDir = "/home/$#/pub"

[titan]

# Password that the client must provide in order to get write access
# to files on the server. Defaults to "titanpassword" --
# FOR OBVIOUS REASONS YOU SHOULD DEFINITELY CHANGE IT
titanPass = "titanpassword"
password = "titanpassword"

# Whether the password is required. Defaults to "true".
# It is recommended that it stays that way.
titanPassRequired = "true"
passwordRequired = "true"

# Maximum size that the server will accept for Titan uploads, in bytes.
# Defaults to 10485760 (10 MiB)
titanUploadLimit = "10485760"
uploadLimit = "10485760"

# If "true", redirect to the uploaded content after a Titan request completes.
# If "false", serve a simple "upload successful" message.
# Defaults to "true".
redirect = "true"

# Define a vhost's redirect zones
# The server will respond with a redirect for every
Expand Down
32 changes: 19 additions & 13 deletions src/config.nim
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,13 @@ type
vhosts*: Table[string, VHost]
homeDir*: string
dirHeader*: string
titanPass*: string
titanPassRequired*: bool
titanUploadLimit*: int
titanSettings*: TitanSettings

TitanSettings* = object
password*: string
passwordRequired*: bool
uploadLimit*: int
redirect*: bool

const defaultHome =
when defined(posix): "/home/$#/"
Expand Down Expand Up @@ -117,9 +121,12 @@ proc readSettings*(path: string): Settings =
keyFile: "mykey.pem",
homeDir: defaultHome,
dirHeader: "header.gemini",
titanPass: "titanpassword",
titanPassRequired: true,
titanUploadLimit: 10485760)
titanSettings: TitanSettings(
password: "titanpassword",
passwordRequired: true,
uploadLimit: 10485760,
redirect: true)
)

var f = newFilestream(path, fmRead)
if f != nil:
Expand All @@ -146,13 +153,12 @@ proc readSettings*(path: string): Settings =
of "keyfile": result.keyfile = e.value
of "homedir": result.homeDir = e.value
of "dirheader": result.dirHeader = e.value
of "titanpass": result.titanPass = e.value
of "titanpassrequired":
if e.value == "false":
result.titanPassRequired = false
else:
result.titanPassRequired = true
of "titanuploadlimit": result.titanUploadLimit = e.value.parseInt
elif section == "titan":
case e.key.toLowerAscii
of "password": result.titanSettings.password = e.value
of "passwordrequired": result.titanSettings.passwordRequired = e.value.parseBool
of "uploadlimit": result.titanSettings.uploadLimit = e.value.parseInt
of "redirect": result.titanSettings.redirect = e.value.parseBool
else:
let zoneType =
case keyval[1]
Expand Down
31 changes: 25 additions & 6 deletions src/geminim.nim
Original file line number Diff line number Diff line change
Expand Up @@ -128,16 +128,31 @@ proc processTitanRequest(server: Server, req: Request): Future[Response] {.async
if size == 0:
return response(StatusMalformedRequest, "No file size specified")

if size > server.settings.titanUploadLimit:
let titanSettings = server.settings.titanSettings

if size > titanSettings.uploadLimit:
return response(StatusError,
"File size exceeds limit of " & $server.settings.titanUploadLimit & " bytes.")
"File size exceeds limit of " &
$titanSettings.uploadLimit & " bytes.")

if token != server.settings.titanPass and server.settings.titanPassRequired:
if token != titanSettings.password and titanSettings.passwordRequired:
return response(StatusNotAuthorised, "Token not recognized")

var filePath = req.res.filePath
if dirExists(filePath):
filePath = filePath / "index.gmi" # assume we want to write index.gmi
let (parent, _ ) = filePath.splitPath

try:
createDir(parent) # will simply succeed if it already exists
except OSError:
return response(StatusError,
"Error writing to: " & $req.res.resPath)
except IOError:
return response(StatusError,
"Could not create path: " & $req.res.resPath &
". Usually this means one of the \"directories\" in the path is actually a file.")

if dirExists(filePath): # We're writing index.gmi in an existing directory
filePath = filePath / "index.gmi"

let buffer = await req.client.recv(size)
try:
Expand All @@ -149,7 +164,11 @@ proc processTitanRequest(server: Server, req: Request): Future[Response] {.async
echo getCurrentExceptionMsg()
return response(StatusError, "")

result = response(StatusSuccess, "text/gemini\r\nSuccessfully wrote file")
result =
if titanSettings.redirect:
response(StatusRedirect, req.params[0].replace("titan://", "gemini://"))
else:
response(StatusSuccess, "text/gemini\r\nSuccessfully wrote file")


proc serveFile(server: Server, path: string): Future[Response] {.async.} =
Expand Down

0 comments on commit 0d67c81

Please sign in to comment.