server.c kept an array of all of its active clients, calling realloc(3)
everytime its size had to be modified. However, reallocating this array
had the undesired consequence of moving other active clients to other
memory locations.
Potentially, this would result in dangling pointers from other
components that also kept pointers to struct server_client instances
e.g.: handler.c.
For this reason, the array-based approach has been completely dropped,
in favour of a doubly-linked list.
This new feature adds a HTML form on each directory listing that allows
to search files recursively, starting from the current user directory.
Wildcard patterns are also allowed.
Otherwise, this would generate strings such as "directory//resource" if
dirpath contained a trailing slash, which could be problematic for users
relying on ctfw.
While commit 1ffba8f5 fixed a wrong display of the mkdir, upload and
logout forms, it did not take login forms into consideration, which must
displayed as grid.
Under some circumstances, clients could cause SIGPIPE to slcl. Since
this signal was not handled by server.c (i.e., via sigaction(3)), slcl
would crash without any error messages printed to stderr.
In such situation, SIGPIPE should not be usually considered a fatal
error, so it is preferrable to close the connection and keep working.
Given the following contrived example request:
/example%FB%DC&arg%DE1=examplevalue%AA
slcl must decode each token separately, so that percent-encoded
characters '&', '=' or '?' do not get accidently intepreted.
Due to the lack of double quotes, passwords with whitespaces were not
passed correctly to printf(1), thus making users not able to log into
their account.
OTOH, for some reason usernames containing whitespaces made jq(1)
complain, so it has been decided not to support them.
Otherwise, write_body_mem and write_body_mem would silently fail,
causing undefined behaviour.
Notes:
The return value for write_ctx_free is currently assigned to that of
fclose(3), which can be either 0 on success or EOF on failure.
However, it makes sense for write_body_mem and write_body_mem to simply
check against non-zero.
Also, it would not be sensible to return EOF to caller functions, which
expect either 0 (success), -1 (fatal error) or 1 (input error).
Considering http.h defined HTTP/1.1-only responses such as "303 See
Other", as well as incoming HTTP/1.1-only features (e.g.: byte serving),
it did not make much sense to keep a somewhat broken compatibility
against HTTP/1.0.
Unfortunately, this breaks support with some existing clients such
as lynx(1), even if HTTP/1.0 was already deprecated many years ago.
However, even lynx(1) can be configured to support HTTP/1.1.
select(2) has a number of well-known issues (e.g.: FD_SETSIZE limiting
the maximum amount of file descriptors to watch) that are mostly solved
by poll(2) and thus can be used as a drop-in replacement.
When using HTTP "Content-Disposition: attachment;", users are forced to
download files in order to use them, whereas others might prefer to open
them in the browser.
Therefore, now that URL parameters are supported by http.h, previews can
be forced by adding "preview=1" or "preview=true" (case-insensitive) as
a URL parameters. Any other parameters are ignored by slcl.
For users, a "Preview" link has been added next to the "Share" button
for each file.
Now, http_payload includes a list of human-readable parameters that can
be read (but not modified) by users. Given the following example link:
/test?key1=value1&key2=value2
This will generate two parameters, with the following values:
{
.args =
{
[0] = {.key = "key1", .value = "value1"},
[1] = {.key = "key2", .value = "value2"}
},
.n_args = 2
}
As expected, if any URL parameters are given, struct http_payload member
"resource" is accordingly trimmed so as not to include any parameters.
Therefore, considering the example above:
{.args = {...}, .resource = "/test"}
Limitations:
- Since the definition of struct http_arg is both shared by http.h
(as a read-only pointer within struct http_payload) and http.c
(as a read/write pointer within struct ctx), its members (namely key
and value) must remain as read/write pointers, even if they must not
be modified by users of http.h.
So far, slcl would just close the connection with a client when the
Content-Length of an incoming request exceeded the user quota, without
any meaningful information given back to the user.
Now, slcl responds with a HTML file with meaningful information about
the error.
Limitations:
- While this commits has been successfully tested on ungoogled-chromium,
LibreWolf (and I assume Firefox and any other derivates too) does not
seem to receive the response from the server.
- However, this issue only occurred during local testing, but not
on remote instances.
- When a non-empty username and an empty password was given, slcl would
crash due to a double free(3). This happened because append_form would
grow the form list before sanitizing the input and, since the output
pointer was not updated to the caller function, the latter would attempt
to free a now-old pointer.
- Additionally, some compilers such as clang complained about the
potential use of an uninitialized variable when calling forms_free.
- Also, it was a good opportunity to refactor get_forms and its caller
functions, as get_forms was not differentiate fatal errors from user
input errors.
As otherwise reported by clang 14.0.0:
main.c:679:14: warning: variable 'cur' is used uninitialized whenever '&&' condition is false [-Wsometimes-uninitialized]
else if (available && quota_current(a, username, &cur))
This was a minor issue after all, as pq was not used unless available
were set.
So far, usergen printed a JSON object over standard output that had to
be manually copied into db.json. Now, this step is done automatically,
thanks to jq(1). OTOH, user directory is now also created by usergen.
So far, slcl used the default browser behaviour (i.e.,
Content-Disposition: inline), which means files were typically shown on
the web browser itself. However, this caused two issues:
- Users would have to right-click -> "Save Link As..." to download a
file, which might be inconvenient for some users.
- The original file name would not be retrieved for publicly shared
files.
Now, file download is always requested to the browser, and the original
file path is retrieved via readlink(2).
So far, slcl failed with poorly described error messages when any of the
essential directories were missing. Now, these are created automatically
so that the initial setup is easier.