This mod is designed to help write more secure formspec handling code. It achieves this by throwing out the concept of "formspec names" entirely and giving each formspec shown to the player a unique, random ID. The player can only then submit form data using this unique ID, and, the handling code can invalidate the ID during processing automatically.
This reduces the risk that an attacker can forge formspec data and send uninvited packets to the server. The server will discard any form data that appears to come from a client that is attempting to use old or incorrect fsc-created forms and will note this event in the minetest log.
Because of the simplicity of the approach, mods will no longer need to focus on basic formspec handling code and can instead spent their time verifying the proper permissions and input data correctness.
This mod also provides a much more simple way to maintain a formspec "context" and pass it along to subsequent formspecs. This makes writing formspec code simpler as the context does not need to be maintained outside the formspec handling or creation code, and no memory leakage needs to be worried about.
A player can also only ever obtain one context, and attempting to use an invalid or outdated context will result in all current valid formspec contexts being revoked. Combined together, all these features make formspecs a lot safer to work with.
Usage
The basic workflow of `fsc` contains of a single function call. Outside of this function call, there are no other API functions or data.
Code: Select all
function fsc.show(name, formspec, context, callback)
-- `name`: a playername,
-- `formspec`: a valid formspec string,
-- `context`: any data, may be `nil`
-- `callback`: function(player, fields, context).
The callback function will only be called if basic sanity checks on the data pass requirements. You can implement it simply as follows:
Code: Select all
local function callback(player, fields, context)
-- `player`: player object,
-- `fields`: table containing formspec data returned by the player client,
-- `context`: any data, will never be `nil`. If no context was passed
-- to `fsc.show()`, it will contain `{}`
return true
end
keep the form open.
If you return `true`, or if you return `nil` and `fields.quit` is set, then the fsc code will invalidate the ID and close the formspec. You should return `true` unless you want to keep the form open to the player.
Making a simple callback handler that shows a new form is therefore relatively straightforward. The below example passes the current context data through to the new form. The old form will close, and the new form will appear to the player with the new content.
Code: Select all
local function callback(player, fields, context)
local name = player:get_player_name()
if fields.rename then
fsc.show(name,
"field[new_name;What is the new name?;" .. minetest.formspec_escape(context.old_name) .. "]",
context,
callback)
return
else
-- do something else
return true
end
end
Code: Select all
fsc.show(name, formspec, {}, function() end)
Node formspecs are not handled. Due to the nature of node/inventory formspecs, it is inherently impossible to perform the same checks on node/inventory formspecs as `fsc` can do for (normal) formspecs.
License: FormSpec Context ('fsc') mod for minetest, licensed under the `ISC` license:
Dependencies: none
Github: https://github.com/sofar/fsc
Archive (master): https://github.com/sofar/fsc/archive/master.zip