GitHub Signatures in Gitea
A small lifehack for the Gitea owners. As you may know, GitHub signs commits done with its web interface with its GPG key. These commits may end up on your Gitea server. It looks rather unconvincing:
Commit listCommit page
Luckily it is fixable by a simple lifehack:
Commit listCommit page
https://sandfox.me/misc/gitea-github.html
Commit listCommit page
Luckily it is fixable by a simple lifehack:
- Register user ‘github’
- Login with it and optionally set up a profile
- Add the web flow GPG key: https://github.com/web-flow.gpg
- Add
noreply@github.com
to the account emails - Mind the security and disable sign-in for this account
Commit listCommit page
https://sandfox.me/misc/gitea-github.html
RPM5 lost all distros
With OpenMandriva Lx 4 now in beta it seems that RPM5 lost all its main users.CAOS, Ark and Unity are discontinued, Wind River and OpenMandriva switched to RPMv4
Interestingly, it’s also the end of urpmi with both Mageia and OpenMandriva switching to dnf.
It seems rpm world entered a semi-unified state with dnf and zypper, both libsolv based and partly interoperable
https://sandfox.me/linux/rpm5.html
Interestingly, it’s also the end of urpmi with both Mageia and OpenMandriva switching to dnf.
It seems rpm world entered a semi-unified state with dnf and zypper, both libsolv based and partly interoperable
https://sandfox.me/linux/rpm5.html
Dark Theme for the Blog
Just finalized the dark theme for the blog. The idea is simple, use
@media (prefers-color-scheme: dark) {
a {
color: #4be
}
}
The browser then will respect the OS dark mode or have its own night mode and show your website in dark:
Light mode Dark mode
That’s simple and cool!
One of the problems currently is testing. It is possible but rarely comfortable. None of the browsers has mode setting in their dev tools.
https://sandfox.me/misc/dark-theme.html
prefers-color-scheme
media query and wrap dark style elements with it:@media (prefers-color-scheme: dark) {
a {
color: #4be
}
}
The browser then will respect the OS dark mode or have its own night mode and show your website in dark:
Light mode Dark mode
That’s simple and cool!
One of the problems currently is testing. It is possible but rarely comfortable. None of the browsers has mode setting in their dev tools.
- Firefox only reads theme status from the operating system. There are some switcher extensions but they don’t work properly.
- Chrome can be run with
--force-dark-mode
CLI param. - Opera here is the best. Choosing light/dark themes in browser will also change the
prefers-color-scheme
rendering in the fly.
https://sandfox.me/misc/dark-theme.html
On Common Misuse of the File Formats
A small rant about text file format holy wars. I believe that most of the file formats that participate in these holy wars are rather good and the most of the frustration comes from their misuse.
JSON is an awesome human-inspectable serialization language. It’s good for network intercommunication and maybe for data exporting. It’s strict and standartized and readable at least in its “pretty” form. However, it’s a terrible configuration language due to its extremely strict syntax and lack of comments.
I want to return to the comparison of TOML and YAML in another post, so let’s go directly to the bad parts. Just try to serialize a random dictionary with TOML and look at the result. It will be a mess. Also many new features introduced in TOML 0.5, like dotted keys, make sense only when the config is written by a human.TOML is not too popular yet to have any known bad applications so let’s get to YAML.YAML is extremely insecure to be used as a data exchange format for untrusted data. It also wastes a lot of space for indentation spaces. Ironically, Rails collected both misuses for YAML by using it both as a parsable language for the POST body (in past) and a default serialization language for complex fields in the database. Also, YAML’s short json-like syntax is also made solely for a human decision making.
Of course all these applications are not isolated and often there are options depending on the point of view, like RSS/Atom and JSON Feed both making sense depending on whether you see it as an alternative representation of a website as a document or a stream in a serialized form or some sort of REST response.
Well, there are no solutions, only trade-offs. Choose your languages wisely.
https://sandfox.me/misc/file-formats-misuse.html
- XML is a DOCUMENT language
- JSON is a SERIALIZATION language
- TOML and YAML are CONFIGURATION languages. TOML vs YAML holy war is out of scope of this post
<stream:stream>
in the beginning that’s never closed. Terrible. It also has no place in RPC-like protocols.SOAP for example is another terrible application for XML.JSON is an awesome human-inspectable serialization language. It’s good for network intercommunication and maybe for data exporting. It’s strict and standartized and readable at least in its “pretty” form. However, it’s a terrible configuration language due to its extremely strict syntax and lack of comments.
composer.json
and package.json
are terrible applications for JSON, but, interestingly, composer.lock
and package-lock.json
are not.Pipenv can be an example of the correct usage. It uses TOML for the config and JSON for the lock file.I want to return to the comparison of TOML and YAML in another post, so let’s go directly to the bad parts. Just try to serialize a random dictionary with TOML and look at the result. It will be a mess. Also many new features introduced in TOML 0.5, like dotted keys, make sense only when the config is written by a human.TOML is not too popular yet to have any known bad applications so let’s get to YAML.YAML is extremely insecure to be used as a data exchange format for untrusted data. It also wastes a lot of space for indentation spaces. Ironically, Rails collected both misuses for YAML by using it both as a parsable language for the POST body (in past) and a default serialization language for complex fields in the database. Also, YAML’s short json-like syntax is also made solely for a human decision making.
Of course all these applications are not isolated and often there are options depending on the point of view, like RSS/Atom and JSON Feed both making sense depending on whether you see it as an alternative representation of a website as a document or a stream in a serialized form or some sort of REST response.
Well, there are no solutions, only trade-offs. Choose your languages wisely.
https://sandfox.me/misc/file-formats-misuse.html
Fix AsciiDoc Display in Gitea
After installing my own Gitea I looked for the support for the markups I use.Gitea has support for external markup renderers and the official doc lists configs for both reStructuredText and AsciiDoc:
[markup.asciidoc]
ENABLED = true
FILE_EXTENSIONS = .adoc,.asciidoc
RENDER_COMMAND = "asciidoctor --out-file=- -"
; Input is not a standard input but a file
IS_INPUT_FILE = false
[markup.restructuredtext]
ENABLED = true
FILE_EXTENSIONS = .rst
RENDER_COMMAND = rst2html.py
IS_INPUT_FILE = false
RST works perfectly but AsciiDoc has two visible problems:
Glitch on the topUseless timestamp on the bottom
Unfortunately it seems that the Asciidoctor CLI cannot produce html code that will be correctly rendered by Gitea so we need to use the Ruby interface.
require 'asciidoctor'
# Load the document in the embeddable mode
document = Asciidoctor.load STDIN.read
# Embeddable doesn't display the main header so render it manually
puts "<h1>#{document.doctitle}</h1>"
# Render HTML
puts document.convert
Now replace the asciidoctor call with our new script:
[markup.asciidoc]
ENABLED = true
FILE_EXTENSIONS = .adoc,.asciidoc
RENDER_COMMAND = "ruby /path/to/gitea-asciidoc.rb"
; Input is not a standard input but a file
IS_INPUT_FILE = false
and enjoy a non glitchy AsciiDoc render.
https://sandfox.me/ruby/gitea-asciidoc.html
[markup.asciidoc]
ENABLED = true
FILE_EXTENSIONS = .adoc,.asciidoc
RENDER_COMMAND = "asciidoctor --out-file=- -"
; Input is not a standard input but a file
IS_INPUT_FILE = false
[markup.restructuredtext]
ENABLED = true
FILE_EXTENSIONS = .rst
RENDER_COMMAND = rst2html.py
IS_INPUT_FILE = false
RST works perfectly but AsciiDoc has two visible problems:
Glitch on the topUseless timestamp on the bottom
Unfortunately it seems that the Asciidoctor CLI cannot produce html code that will be correctly rendered by Gitea so we need to use the Ruby interface.
require 'asciidoctor'
# Load the document in the embeddable mode
document = Asciidoctor.load STDIN.read
# Embeddable doesn't display the main header so render it manually
puts "<h1>#{document.doctitle}</h1>"
# Render HTML
puts document.convert
Now replace the asciidoctor call with our new script:
[markup.asciidoc]
ENABLED = true
FILE_EXTENSIONS = .adoc,.asciidoc
RENDER_COMMAND = "ruby /path/to/gitea-asciidoc.rb"
; Input is not a standard input but a file
IS_INPUT_FILE = false
and enjoy a non glitchy AsciiDoc render.
https://sandfox.me/ruby/gitea-asciidoc.html
PHP 7.4: Splat Inconsistency
PHP 7.4 has this great new feature: splat operator now works in array expressions.
<?php
var_export([1,2,3, ...[4,5,6]]); // [1,2,3,4,5,6]
including when it is in the middle
<?php
var_export([1,2,3, ...[4,5,6], 7,8,9]); // [1,2,3,4,5,6,7,8,9]
Let’s have some variadic function
<?php
function sum(...$values)
{
return array_sum($values);
}
but
<?php
// PHP 5.6 - 7.4
echo sum(1,2,3, ...[4,5,6], 7,8,9); // PHP Fatal error: Cannot use positional argument after argument unpacking
of course there is a well-known workaround
<?php
echo sum(1,2,3, ...[4,5,6], ...[7,8,9]); // 45
and now also this
<?php
// PHP 7.4+
echo sum(...[1,2,3, ...[4,5,6], 7,8,9]); // 45
but why wasn’t the original behavior fixed as well?
https://sandfox.me/php/splat-inconsistency.html
<?php
var_export([1,2,3, ...[4,5,6]]); // [1,2,3,4,5,6]
including when it is in the middle
<?php
var_export([1,2,3, ...[4,5,6], 7,8,9]); // [1,2,3,4,5,6,7,8,9]
Let’s have some variadic function
<?php
function sum(...$values)
{
return array_sum($values);
}
but
<?php
// PHP 5.6 - 7.4
echo sum(1,2,3, ...[4,5,6], 7,8,9); // PHP Fatal error: Cannot use positional argument after argument unpacking
of course there is a well-known workaround
<?php
echo sum(1,2,3, ...[4,5,6], ...[7,8,9]); // 45
and now also this
<?php
// PHP 7.4+
echo sum(...[1,2,3, ...[4,5,6], 7,8,9]); // 45
but why wasn’t the original behavior fixed as well?
https://sandfox.me/php/splat-inconsistency.html
Encryptor
Created a simple cli file encryptor using libsodium
The app can create a password-protected file encoded with XSalsa20 and Argon2id
See my dev portal: https://sandfox.dev/php/encryptor.html
https://sandfox.me/php/php-encryptor.html
The app can create a password-protected file encoded with XSalsa20 and Argon2id
See my dev portal: https://sandfox.dev/php/encryptor.html
https://sandfox.me/php/php-encryptor.html
Composer Yaml
My new library to allow composer to read config from YAML file. There is some demand in comments for composer config but the developers are not interestedand most 3rd party attempts to solve it are limited to yaml2json converters.
I tried a slightly different approach. There is a command in the composer itself that changes the way the config is read:
What I tried to do: I put yaml2json converter in place of
You can find the project on my new dev website: https://sandfox.dev/php/composer-yaml.html
https://sandfox.me/php/composer-yaml.html
I tried a slightly different approach. There is a command in the composer itself that changes the way the config is read:
composer global
. During its execution it changes current working directory, resets composer state, and forces the composer to read config from another directory.What I tried to do: I put yaml2json converter in place of
global
‘s directory changing code, and it seems it worked. Of course, some things got broken like any command that tries to change composer.json will no longer have any effect, however many people don’t use them and it may be an acceptable tradeoff for using yml-based config.You can find the project on my new dev website: https://sandfox.dev/php/composer-yaml.html
https://sandfox.me/php/composer-yaml.html
Bitbucket to Remove Mercurial Support
So Mercurial lost its biggest hosting platform. Sad to see it because I always thought that it has much more usable CLIand much better branching system for corporate development than git.
https://sandfox.me/misc/bitbucket-mercurial.html
After much consideration, we’ve decided to remove Mercurial support from Bitbucket Cloud and its API. Mercurial features and repositories will be officially removed from Bitbucket and its API on June 1, 2020.https://bitbucket.org/blog/sunsetting-mercurial-support-in-bitbucket
https://sandfox.me/misc/bitbucket-mercurial.html
PHP access private methods and fields
These two simple functions can come in handy as helpers for something like PsySH.PHP >= 7.0 is required.
Note
Don’t use them in actual production code! That would be awful
Call private method of an object:
<?php
function call_private_method($object, string $method, ...$args)
{
return (function ($method, ...$args) {
return call_user_func_array([$this, $method], $args);
})->call($object, $method, ...$args);
}
Get private field of an object:
<?php
function get_private_field($object, string $field)
{
return (function ($field) {
return $this->$field;
})->call($object, $field);
}
Example:
<?php
class A
{
private $secret = 'SECRET234';
private function doStuff($whatever)
{
return $whatever . '!';
}
}
$a = new A;
get_private_field($a, 'secret'); // SECRET234
call_private_method($a, 'doStuff', 'whatever'); // whatever!
UPD: “Why not make a library out of it”, I thought. So it’s now a library: github.com
https://sandfox.me/2016/11/16/php-private-access.html
Note
Don’t use them in actual production code! That would be awful
Call private method of an object:
<?php
function call_private_method($object, string $method, ...$args)
{
return (function ($method, ...$args) {
return call_user_func_array([$this, $method], $args);
})->call($object, $method, ...$args);
}
Get private field of an object:
<?php
function get_private_field($object, string $field)
{
return (function ($field) {
return $this->$field;
})->call($object, $field);
}
Example:
<?php
class A
{
private $secret = 'SECRET234';
private function doStuff($whatever)
{
return $whatever . '!';
}
}
$a = new A;
get_private_field($a, 'secret'); // SECRET234
call_private_method($a, 'doStuff', 'whatever'); // whatever!
UPD: “Why not make a library out of it”, I thought. So it’s now a library: github.com
https://sandfox.me/2016/11/16/php-private-access.html
Embracing CommonMark as the One True Markdown
As you may know, CommonMark is a project aiming to create unified and unambiguous Markdown syntax specification. So, I’m in. I want to spread the word and even use it in my own blog.
The trouble number one is that Jekyll uses kramdown by default. So we find a gem and the gem is jekyll-commonmark. Oh hell, we lost syntax highlighting 🙁
The trouble number two is that CommonMark standard lacks support for server side syntax highlighting. That’s bad, I don’t want any JavaScript on my static pages. Let’s try to wrap it somehow and enable syntax highligting.
The strong side of Ruby CommonMark implementation, CommonMarker is its ability to parse a document to the abstract syntax tree, so let’s use it to extract our blocks and highlight them with Rouge for example.
# get our abstract syntax tree
ast = CommonMarker.render_doc('some markdown here')
# search code blocks
ast.walk do |node|
if node.type == :code_block
next if node.fence_info == '' # skip if we don't know how to highlight
source = node.string_content # get node content that's our source code
# now try to use highlighter
# I prefer Rouge which is also a default choice in Jekyll
# `node.fence_info` will hold the language we want to highlight
# for example,
# ```ruby
# # code here
# ```
# will have node.fence_info == 'ruby'
lexer = Rouge::Lexer.find_fancy(node.fence_info)
formatter = Rouge::Formatters::HTML.new # get most common formatter
# format our html
html = '<div class="highlighter-rouge">' +
formatter.format(lexer.lex(source)) +
'</div>'
# and render it
new_node = CommonMarker::Node.new(:html)
new_node.string_content = html
# insert our new parsed content and remove original code block
node.insert_before(new_node)
node.delete
end
end
# done! we have a document with highlighted source blocks
puts ast.to_html
To avoid this headache in the future I released this scenario as a gem:commonmarker-rouge. And now by just forking jekyll-commonmark and changing
https://sandfox.me/2016/04/06/embracing-commonmark.html
The trouble number one is that Jekyll uses kramdown by default. So we find a gem and the gem is jekyll-commonmark. Oh hell, we lost syntax highlighting 🙁
The trouble number two is that CommonMark standard lacks support for server side syntax highlighting. That’s bad, I don’t want any JavaScript on my static pages. Let’s try to wrap it somehow and enable syntax highligting.
The strong side of Ruby CommonMark implementation, CommonMarker is its ability to parse a document to the abstract syntax tree, so let’s use it to extract our blocks and highlight them with Rouge for example.
# get our abstract syntax tree
ast = CommonMarker.render_doc('some markdown here')
# search code blocks
ast.walk do |node|
if node.type == :code_block
next if node.fence_info == '' # skip if we don't know how to highlight
source = node.string_content # get node content that's our source code
# now try to use highlighter
# I prefer Rouge which is also a default choice in Jekyll
# `node.fence_info` will hold the language we want to highlight
# for example,
# ```ruby
# # code here
# ```
# will have node.fence_info == 'ruby'
lexer = Rouge::Lexer.find_fancy(node.fence_info)
formatter = Rouge::Formatters::HTML.new # get most common formatter
# format our html
html = '<div class="highlighter-rouge">' +
formatter.format(lexer.lex(source)) +
'</div>'
# and render it
new_node = CommonMarker::Node.new(:html)
new_node.string_content = html
# insert our new parsed content and remove original code block
node.insert_before(new_node)
node.delete
end
end
# done! we have a document with highlighted source blocks
puts ast.to_html
To avoid this headache in the future I released this scenario as a gem:commonmarker-rouge. And now by just forking jekyll-commonmark and changing
CommonMarker
to CommonMarker::Rouge
I have a blog parsed as CommonMark with syntax highlighting intact.https://sandfox.me/2016/04/06/embracing-commonmark.html
What Is Dead May Never Die
Let’s have some fun with theDrowned God andUnix signals.
This is a simple program that catches
#include <stdio.h> // for printf() && perror()
#include <stdlib.h> // for exit()
#include <signal.h> // for all the signal fun
#include <unistd.h> // for sleep()
/**
* catch signals
*/
void catch(int sig)
{
static int counter = 0;
// prevent exit by SIGINT and SIGTERM 3 times and then exit program
if (sig == SIGINT || sig == SIGTERM) {
if (counter < 3) {
printf("What is dead may never die\n");
counter += 1;
} else {
printf("Okay... 🙁\n");
exit(0);
}
}
}
int main(int ac, char ** av)
{
// set catcher for the interrupt signal
if (signal(SIGINT, catch) == SIG_ERR) {
perror("Can't catch SIGINT\n");
}
// set catcher for the kill signal
if (signal(SIGTERM, catch) == SIG_ERR) {
perror("Can't catch SIGTERM\n");
}
printf("We do not sow\n");
// keep running in background, we exit by other means
while(1) {
sleep(1);
}
}
Compile it and run, then try to kill all Greyjoy 😀
[sandfox@paloalto fun]$ clang -o greyjoy greyjoy.c
[sandfox@paloalto fun]$ ./greyjoy &
[1] 31366
We do not sow
[sandfox@paloalto fun]$ killall greyjoy
What is dead may never die
[sandfox@paloalto fun]$ killall greyjoy
What is dead may never die
[sandfox@paloalto fun]$ killall greyjoy
What is dead may never die
[sandfox@paloalto fun]$ killall greyjoy
Okay... 🙁
[1]+ Done ./greyjoy
[sandfox@paloalto fun]$
It seems they are somehow protected 😀
A good example of signals handling can be found here:www.thegeekstuff.com
https://sandfox.me/2016/03/21/greyjoy.html
This is a simple program that catches
SIGINT
and SIGTERM
#include <stdio.h> // for printf() && perror()
#include <stdlib.h> // for exit()
#include <signal.h> // for all the signal fun
#include <unistd.h> // for sleep()
/**
* catch signals
*/
void catch(int sig)
{
static int counter = 0;
// prevent exit by SIGINT and SIGTERM 3 times and then exit program
if (sig == SIGINT || sig == SIGTERM) {
if (counter < 3) {
printf("What is dead may never die\n");
counter += 1;
} else {
printf("Okay... 🙁\n");
exit(0);
}
}
}
int main(int ac, char ** av)
{
// set catcher for the interrupt signal
if (signal(SIGINT, catch) == SIG_ERR) {
perror("Can't catch SIGINT\n");
}
// set catcher for the kill signal
if (signal(SIGTERM, catch) == SIG_ERR) {
perror("Can't catch SIGTERM\n");
}
printf("We do not sow\n");
// keep running in background, we exit by other means
while(1) {
sleep(1);
}
}
Compile it and run, then try to kill all Greyjoy 😀
[sandfox@paloalto fun]$ clang -o greyjoy greyjoy.c
[sandfox@paloalto fun]$ ./greyjoy &
[1] 31366
We do not sow
[sandfox@paloalto fun]$ killall greyjoy
What is dead may never die
[sandfox@paloalto fun]$ killall greyjoy
What is dead may never die
[sandfox@paloalto fun]$ killall greyjoy
What is dead may never die
[sandfox@paloalto fun]$ killall greyjoy
Okay... 🙁
[1]+ Done ./greyjoy
[sandfox@paloalto fun]$
It seems they are somehow protected 😀
A good example of signals handling can be found here:www.thegeekstuff.com
https://sandfox.me/2016/03/21/greyjoy.html
This entry was edited (5 years ago)