Learning pieces
The goal of this section is to group issues that I faced during code development and its correspondent solutions.
Linux system admin
About systemd
systemd is the linux equivalent to mac's launchd. It is a service manager
that offers interesting tool for system administrators, namely, process initialization.
Here are excellent articles about systemd:
1. Linode - What is systemd
2. Freedesktop - systemd
Set up ssh on Ubuntu
More information here
# Install the openssh-server
sudo apt update
sudo apt install openssh-server
# After installation, the service is started automatically. Check it with
sudo systemctl status ssh
# Tell the firewall to allow ssh connections (using the ubuntu firewall manager tool `ufw`)
sudo ufw allow ssh
Listen to open tcp ports
More information here
This will print all listening sockets (-l) along with the port number (-n), with TCP ports (-t) and UDP ports (-u) also listed in the output.
Include a exception rule in the ubuntu firewall
Other linux distributions
iptables -A INPUT -p tcp --dport 4958 -j ACCEPT
sudo service iptables restart
sudo systemctl restart iptables
Check the status of an open port
MAC system admin
Starting up services on startup for MAC
HTML
Text area starting at random position
I was puzzled by this problem. I thought that was related with some
css properties such as align:center. The reason was extra spaces in
the declaration of the textarea input in the html.
To solve this problem, instead of
write asCSS
Updating CSS variables programmatically
I would like to update the color pallete of my icons programmatically.
In order to do that, I need to change the css variables that I have
defined. I can do that by accessing the style attribute of
document.documentElement.
let root = document.documentElement;
function set_pallete_brazil() {
root.style.setProperty('--pallete-1', '#00520c');
root.style.setProperty('--pallete-2', '#f5c800');
root.style.setProperty('--pallete-3', '#ddecdd');
root.style.setProperty('--pallete-4', '#1e5fba');
root.style.setProperty('--pallete-5', 'white');
}
Mask + Clipping
I am using the Mask+Clipping technique to programmatically change the color pallete of icons.
The technique consists in creating a <div> element and set a background
on it (the dynamic color pallete is added here). With the --webkit-mask
property, I set the image file containing the mask. The latter is typically
a png file with transparent background and the mask colored in black.
In my case, I also need to cut part of a second masked object to create the effect of the object inside the lens.
<div class="button-image-common lens"></div>
<div class="button-image-common zoomed-interrogation-mark circle-clip"></div>
.lens{
background-color: var(--pallete-4);
-webkit-mask-image: url("/games/assets/icons/masks/mask-lens.png");
-webkit-mask-repeat: no-repeat;
-webkit-mask-size: contain;
z-index:2;
top: calc(25%);
left: calc(-15%);
}
.circle-clip{
--b-clip-circle-radius: calc( 0.27*var(--b-width) );
--b-clip-circle-center-x: var(--b-clip-circle-radius);
--b-clip-circle-center-y: var(--b-clip-circle-radius);
clip-path: circle( var(--b-clip-circle-radius) at var(--b-clip-circle-center-y) var(--b-clip-circle-center-x));
}
.zoomed-interrogation-mark{
background-color: var(--pallete-4);
-webkit-mask-image: url("/games/assets/icons/masks/mask-interrogation.png");
-webkit-mask-repeat: no-repeat;
-webkit-mask-size: contain;
-webkit-mask-position: calc(0.2*var(--b-width)) 0px;
z-index:2;
top: calc(31%);
left: calc(20%);
height: 50%;
}
The mask property: https://developer.mozilla.org/en-US/docs/Web/CSS/mask
Web Standards
Specifying IPV6 address in browser
iPut in between brackets. For example, http://[ipv6].
Setting up a domain
- Register a domain: I've registered
barriguinhas.frin google domains. - Register a dynamic DNS in Google Domains.
In the menu, click on DNS.
Next, look for Show advanced parameters.
Click in the Dynamic DNS tab and register a DNS rule. For example, I've created a rule that mapsword-detective.barriguinhas.frto the IP address of my home router. - Update the mapped IP Address. You can do via a https request like the following:
https://username:password@domains.google.com/nic/update?hostname=subdomain.yourdomain.com&myip=1.2.3.4
The username and passwords are generated in the google domains webpage. Nonetheless, the best is to set up ddclient that automatically updates that for you.
Certificate authority and HTTPS
Create a self-signed certificate authority
Generate the private key for my server
Create a certificate signing request (csr)
Create a configuration file
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
Sign my certificate (via my .csr) with my certificate authority
openssl x509 -req -CA rootCA.crt -CAkey rootCA.key -in word-detective.csr \
-out word-detective.crt -days 365 -CAcreateserial -extfile word-detective.ext
Add the certificate authority in firefox
Setup the https server
const options = {
key: fs.readFileSync('certificates/word-detective.key'),
cert: fs.readFileSync('certificates/word-detective.crt')
};
let httpsServer = https.createServer(options,app);
httpsServer.listen(4958);
More info in:https://www.baeldung.com/openssl-self-signed-cert
And also in:https://nodejs.org/en/knowledge/HTTP/servers/how-to-create-a-HTTPS-server/
Programmatically uploading files
The easiest way is to use the FormData object which is available
in most browsers. An instance of FormData passed as the body of
a fetch call will behave exactly as if you are sending a form
with encoding set to multipart/form-data.
let text = `#text#`;
const formData = new FormData();
formData.append('text_file', new Blob([text]));
return fetch('/api/puzzle-from-file', {
method: 'POST',
mode: 'cors',
cache: 'no-cache',
credentials: 'same-origin',
redirect: 'follow',
referrerPolicy: 'no-referrer',
body: formData
})
In this case, the fetch will automatically fill up the content-type field.
Including the boundary token.
Read more about the FormData object: https://developer.mozilla.org/en-US/docs/Web/API/FormData
More about CORS: https://javascript.info/fetch-crossorigin
Content-type and fetch method
When sending a file, we should use the multipart/form-data content type.
However, there is an extra field that need to be set, which is the boundary
field. It is in fact a delimiter, as it is the & in get requests. The
boundary tells you when an input field starts and when it ends.
If you do not manually set the Content-Typein the fetch method, then
it automatically fills up for you. But if you write something like
https://stackoverflow.com/questions/3508338/what-is-the-boundary-in-multipart-form-data
POST /foo HTTP/1.1
Content-Length: 68137
Content-Type: multipart/form-data; boundary=---------------------------974767299852498929531610575
-----------------------------974767299852498929531610575
Content-Disposition: form-data; name="description"
some text
-----------------------------974767299852498929531610575
Content-Disposition: form-data; name="myFile"; filename="foo.txt"
Content-Type: text/plain
(content of the uploaded file foo.txt)
-----------------------------974767299852498929531610575--
The MIME type: application/octet-stream is kind of a joker type. It is the basic
type for binary files.
More about Content-Type header here. Mime types: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types
Form enctypes
| enctype | description |
|---|---|
| application/x-www-form-urlencoded | Default. All characters are encoded before sent (spaces are converted to "+" symbols, and special characters are converted to ASCII HEX values) |
| multipart/form-data | This value is necessary if the user will upload a file through the form |
| text/plain | Sends data without any encoding at all. Not recommended |
C++
Object slicing
Let A and B two classes such that B inherits from A. Object slicing happens in the following situation
A a;
B b;
a = b;
That is, when you try to assign the derived object o the base one. It is a natural thing to happen, since the base class may not have all the specialized members of B.
Apparently, there is no compiler flag that emits a warning when this happens. You can avoid that by making the assignment operator a virtual method.
Reading binary data from stdin
From: How to construct a c fstream from a posix file descriptor
AFAIK, there is no way to do this in standard C++. Depending on your platform, your implementation of the standard library may offer (as a nonstandard extension) a fstream constructor taking a file descriptor as input. (This is the case for libstdc++, IIRC) or a FILE*.
#include <ext/stdio_filebuf.h>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
ofstream ofs("test.txt");
ofs << "Writing to a basic_ofstream object..." << endl;
ofs.close();
int posix_handle = fileno(::fopen("test.txt", "r"));
__gnu_cxx::stdio_filebuf<char> filebuf(posix_handle, std::ios::in); // 1
istream is(&filebuf); // 2
return 0;
}
Reading binary data from cin
I was not able to achieve this. It seems that cin is configured to interpret the input data as something non-binary, and by not doing that, it may interpret a sequence of bits as being the newline character or some other character that stops the reading. Nonetheless, I was not able to change cin to read in binary though.
Reading from cin after a pipe
In order to do this type of reading, I cannot use some functions provided by the api of istream. Namely, seekg and tellg. There is no definition of file position in a pipe stream.
More info in: https://stackoverflow.com/questions/53981505/cin-tellg-returns-1-when-receiving-input-from-a-pipe
Javascript
Promises error handling
Promises are great dealing with exceptions. Inside the executor function
and also inside every handler (then method), we have an implicity try...catch
block. Any exception that is thrown there will be catched by the next catch
method in the promise chain.
let assets_promise = fetch(messages_json_location)
.then((response) => response.json())
.then((response_json) => {
assets.messages = response_json;
})
.then(() => getPuzzle())
.then((puzzle_json) => {
cm.set(JSON.stringify(puzzle_json));
assets.puzzle = puzzle_json;
})
.then(() => new Promise(function (resolve) {
resolve(assets);
}))
.catch( (error) => config.fatal_error_handler(error) );
}
catch block is executed and I handled
all of them in a single function config.fatal_error_handler.
Error handling
I am basically extending the builtin javascript object Error to create
my custom errors; and I use instanceof to check the error type.
class MyError extends Error {
constructor(message) {
super(message);
this.name = this.constructor.name;
}
}
class NoPuzzleGenerated extends MyError {};
if (error instanceof NoPuzzleGenerated) {
document.location.href = `/error/no-puzzle-generated?errorMessage=${error.message}`;
} else {
document.location.href = "/error/500";
}
Page redirection
I was getting the following error with production code:
The error was caused everytime the recently_visited cookie was expired, and
a redirection was made to the puzzle selector page. It happens that, even
after the redirection instruction
the remaining of the code continue to execute. The, when it tried to fetch the assets, it raised the error, because the address of the assets is given via a relative path, and the page address has changed.
To solve the issue, I redefined the redirect_to_today_puzzle function. Instead,
I named it should_redirect_to_today_puzzle and conditioned the fetch portion
of the code to execute only when redirection was not done.