current status:
- got expiration and format selections to work
- fixed modals (password, QR-code, etc.)
- replaced glyphicons with Bootstrap icons (needs CSP relaxation to work)
- tested the different settings and combinations
- got editor tabs to change active status
to be done:
- add "Dark Mode" to translation strings
- figure out how to change prettify theme when dark mode gets selected
- check tab alignment in HTML source
current status:
- renders without PHP errors & passes unit tests
- displays pastes
- responsive navbar
- right-to-left support
- auto dark mode with toggle
to be done:
- add "Dark Mode" to translation strings
- get expiration and format selections to work
- fix modals (password, QR-code, etc.)
- replace glyphicons with Bootstrap Icons (no longer included)
- test all the different settings and combinations
- check tab alignment in HTML source
Because the response from the API is PHP output, the usual `Content-Length` header is absent.
This [custom header technique](https://stackoverflow.com/questions/15097712/how-can-i-use-deflated-gzipped-content-with-an-xhr-onprogress-function/32799706#32799706) allows the client to know the total length of the data being received, in order to display a progress indicator.
Here's a code example with `XMLHttpRequest`:
```
xhr.addEventListener("progress", (e) => {
if (e.lengthComputable) {
onDownloadProgress({
loaded: e.loaded,
total: e.total,
});
} else {
const uncompressedContentLength = xhr.getResponseHeader(
"X-Uncompressed-Content-Length",
);
if (uncompressedContentLength) {
onDownloadProgress({
loaded: e.loaded,
total: Number(uncompressedContentLength),
});
}
}
});
```
Notes:
- `Fetch` can be used as well (only reason I use `XMLHttpRequest` is because `fetch` doesn't allow to track the progress of uploaded data (when creating a paste); whereas `XMLHttpRequest` does).
- `e.loaded` can be different between browsers; Firefox reports the length of the compressed data, Chrome reports the length of uncompressed data (see https://github.com/whatwg/xhr/issues/388). A workaround for this is to manually set our progress indicator to 100% when the request finishes.
using filter_vars instead of filter_input, because our unit tests depend on manipulating global arrays, which are not used by filter_input - we would have to mock the function in the unit testing, it therefore is cleaner to use the same code paths in testing as in production
some inputs in I18n and TrafficLimiter remain unfiltered, since we already validate them by other means (IP lib and/or preg_match)
our minimum PHP version is 7.3, so we can drop the two < 5.6 fallback checks
Scrutinizer pointed out that the dieerr() function isn't available in this
class. Code does work when invoked by migrate script, but this way it would
also work in other contexts.