diff --git a/README.md b/README.md index d574fc5..9b549a5 100644 --- a/README.md +++ b/README.md @@ -37,9 +37,9 @@ The default config is as follows: ```amethystconf host * { directory:./html - apimode:0 + pesmode:0 block-ua:match("Discordbot") - index:index2.html + index:index.html } globals { @@ -51,15 +51,14 @@ globals { cert:./cert.pem max-length:8192 } -} ``` It uses a key-value syntax, and uses a `:` as its seperator. A few key directives: `host`, followed by a hostname signifies a host that will be available. Similar to nginx's `server_name` directive. `globals` signifies all values that are of global importance, like the key and certificate file. `directory` signifies the directory to look in for files on that specific host. `index`, while not in the default config, signifies what path should be returned if the client only asks for `/` (or any subpaths without files). -`apimode` signifies if the API mode must be enabled, allowing the server to run custom Python code to manipulate the request or file further. -`block-ua` signifies if a specific (or loosely matched) User-Agent must be blocked from accessing the site. +`pesmode` signifies if the PES mode must be enabled, allowing the server to run custom Python code to manipulate the request or file further. +`block-ua` signifies if a specific (or loosely matched) User-Agent must be blocked from accessing the site. `proxy` signifies if a the server needs to get the response from a different (remote) server but still needs to be available at this host. `max-length` signifies the maximum length a request may have. AmethystConf has only 4 datatypes: `String`, `Boolean`, `Function` and `None`. A quick rundown: @@ -67,3 +66,32 @@ AmethystConf has only 4 datatypes: `String`, `Boolean`, `Function` and `None`. A `Boolean` is the datatype used to enable/disable features. A `Boolean` can have one of two possible values: `1` or `0`. `Function` is the datatype used in `match()`, it signifies that the parser has to do some work on this string before it can use it. `None` is the datatype assigned to any key without a value. +## PES (Python Extension Script) +The PES (Python Extension Script) is one of Amethysts main selling points. It's a new type of a dynamic page. A PES file is pretty much a +Python script with some conventions. Currently it is in very alpha form. It will be heavily improved upon to make sure even people with no +Python knowledge can work with it. Here's how it works: +If PES mode is enabled, the request is sent to the `pes.py` script, more specifically, the `on_request(req)` function of the `PES()` class. +From there, the decoded request is given to you to play with. All of Amethysts request and file processing tools are available, and soon +a function will be added to hand the request back to Amethyst, if it is deemed not suitable for PES mode. +Once you're done manipulating the request, all you have to do is call `return self.build_response(http_status_code, resp_body, mimetype)` and Amethyst will handle the rest. +A few examples of what can be achieved with PES mode without writing any other language than Python, HTML and CSS: +* Showing a random image from the `/pics` folder upon requesting `/randompic` from the server +* Dynamically updating the time on a website +* Create a complex calculator +* Upload files to the server +* Lock down webpages with a login prompt. +* And much, much more. + +While it might not be able to create truly dynamic pages (since PES runs server-side, not client-side), it is dynamically static, basically, it's a dynamic page until it's rendered +in browser, where it's static, as PES cannot change anything there. +**WARNING!** +PES is an advanced feature! You can absolutely compromise the security of your webserver by having a misconfigured PES file. While Amethyst still has a few protection measures built-in +that activate before any request reaches the PES, but some are bypassed unless manually invoked in the PES. Because of that, here's a general user advisory: +* Use `self.fh.read_file(file_path, host=None)` instead of `open(file_path)` because of file inclusion or directory traversal concerns. +* Use `self.fh.write_file(file_path, host=None)` instead of `open(file_path)` because of file inclusion or directory traversal concerns. +* **NEVER** allow the PES to run shell code! +* **NEVER** allow the PES to run **ANYTHING** uploaded via the internet! +* Try running as much of the code locally, getting data from the internet can not only take long, it can also pose a security risk. + +The PES will **NOT** warn you if you have security issues, it's a very hands-off approach. The PES will happily run `sudo rm -rf / --no-preserve-root` if given the command and +setup for shell execution and not tell you until everything is gone. Prevent those scenarios by limiting what PES does as much as possible!