Some work yo.
This commit is contained in:
parent
01d3b4306e
commit
801d3776a6
3
Makefile
3
Makefile
|
@ -40,9 +40,6 @@ endif
|
|||
html:
|
||||
$(PELICAN) $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS)
|
||||
|
||||
rsync:
|
||||
rsync --delete -vah ../ mdk.fr:/var/www/
|
||||
|
||||
help:
|
||||
@echo 'Makefile for a pelican Web site '
|
||||
@echo ' '
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
Title: Compose Key vs Dead Key
|
||||
Date: 2017-07-12
|
||||
|
||||
L'AFNOR à lancé autour de juin 2017 un appel à commentaires à propos
|
||||
de [la normalisation du clavier
|
||||
français](http://www.afnor.org/presse_juin2017/clavier-francais-afnor-ouvre-projet-de-norme-aux-commentaires/),
|
||||
réunissant 3725 retours.
|
||||
|
||||
Parmis ces retours certains mentionnent la compose key :
|
||||
|
||||
> […] il est possible de composer une quantitée de symboles bien plus
|
||||
grande qu'avec une dead key
|
||||
|
||||
> […] et éventuellement une touche de composition pour permettre
|
||||
d'obtenir des caractères exotiques ou non-latins (ex: compose + oc
|
||||
= © / compose + or = ® / compose + tm = ™
|
||||
|
||||
> Un clavier permettant de composer simplement les emojis les plus
|
||||
courants semble donc répondre à un réel besoin.
|
||||
|
||||
> Une alternative que je trouve intéressante serait de proposer une
|
||||
touche "Composer" (en référence à la touche utilisée sur les
|
||||
anciens claviers Sun) qui permettrait de composer des ligatures.
|
||||
|
||||
> Il s’agit d’une touche morte qui permet de composer «visuellement»
|
||||
les caractères non présents sur le clavier. Par exemple :
|
||||
[COMPOSE]+[O]+[/] = Ø
|
||||
|
||||
> La touche morte traditonnellement appelée « composition » (ou
|
||||
« compose », aussi en français par anglicisme) devrait être appelée
|
||||
« touche morte neutre », surtout depuis que selon Unicode, des
|
||||
lettres sont composées à partir de caractères indépendants et de
|
||||
diacritiques combinants. On a des caractères précomposés qui
|
||||
peuvent être décomposés. Dans cet espace conceptuel, une touche
|
||||
morte de composition semble ne plus avoir de place.
|
||||
|
||||
|
||||
Lors de la première réunion de dépuillement des commentaires, l'AFNOR
|
||||
a rejeté l'idée de la compose key, la trouvant je cite "trop
|
||||
compliquée".
|
||||
|
||||
|
||||
# Les dead keys
|
||||
|
||||
Les [dead keys](https://en.wikipedia.org/wiki/Dead_key) sont des
|
||||
touches permettant d'attacher un signe à la frappe suivante,
|
||||
typiquement un caractère.
|
||||
|
||||
Il faut donc une touche morte par diacritique.
|
||||
|
||||
Ainsi, si la touche `[']` est une touche morte, suivie d'un `[e]`, elle
|
||||
donne `é`.
|
||||
|
||||
|
||||
# La compose key
|
||||
|
||||
La [compose key](https://en.wikipedia.org/wiki/Compose_key) est comme
|
||||
un commentaire le mentionne une "touche morte neutre", elle permet
|
||||
comme son nom l'indique de "composer" les touches suivantes, c'est à
|
||||
dire de les "assembler".
|
||||
|
||||
Il n'y a donc qu'une seule touche "compose" sur un clavier.
|
||||
|
||||
Ainsi, `[COMPOSE] [e] [']` donne `é`.
|
||||
|
||||
|
||||
# Compatibilité
|
||||
|
||||
Il n'existe aucune incompatibilité à proposer des dead keys et une
|
||||
compose keys sur une même disposition physique: les touches mortes
|
||||
étant des diacritiques et la compose key une autre touche.
|
||||
|
||||
|
||||
# Avantages et inconvénients
|
||||
|
||||
## Avantage de la dead-key
|
||||
|
||||
Les touches mortes permettent accès rapide aux saisies courantes: `[']
|
||||
[e]` suffit pour obtenir un `é`, alors qu'il faut taper `[compose] [']
|
||||
[e]` avec une compose key.
|
||||
|
||||
|
||||
## Inconvénient de la dead-key
|
||||
|
||||
Il est plus lent d'obtenir une diacritique seule, comme l'apostrophe,
|
||||
pour lequel il faut taper `['] [ ]`, ce qui n'est pas
|
||||
intuitif. L'intuition ammene aussi certaines personnes à taper
|
||||
`[']['][backspace]` pour obtenir une apostrophe.
|
||||
|
||||
|
||||
Cet inconvénient n'a pas le même impact pour toutes les dead keys, ni
|
||||
dans tous les environnements, typiquement les guillemets, souvent
|
||||
utilisé par paires, peut profiter de la séquence `["] ["]` générant
|
||||
deux guillets, l'utilisateur peut ainsi se décaler entre les deux
|
||||
guillemets pour y saisir son texte.
|
||||
|
||||
|
||||
## Avantage de la compose key
|
||||
|
||||
La compose key permet de composer des caractères au delà des
|
||||
diacritiques, sans alterer le comportement des touches diacritiques,
|
||||
et ce de manière intuitive puisque c'est souvent une simple
|
||||
superposition visuelle de caractères. Aussi la pluspart des compositions
|
||||
peuvent se composer dans les deux sens : `[compose] [e] [']` et
|
||||
`[compose] ['] [e]` sont identiques.
|
||||
|
||||
Voici quelques exemples typiques tirés d'un fichier de configuration
|
||||
de la
|
||||
[libX11](https://github.com/mirror/libX11/blob/master/nls/en_US.UTF-8/Compose.pre)
|
||||
:
|
||||
|
||||
- `[compose] [o] [c]` donne `©`
|
||||
- `[compose] [o] [r]` donne `®`
|
||||
- `[compose] [+] [-]` donne `±`
|
||||
- `[compose] [?] [?]` donne `¿`
|
||||
- `[compose] [ ] [ ]` donne un espace insécable
|
||||
- `[compose] [s] [s]` donne `ß`
|
||||
- `[compose] [S] [S]` donne `ẞ`
|
||||
- `[compose] [o] [e]` donne `œ`
|
||||
- `[compose] [O] [E]` donne `Œ`
|
||||
- `[compose] [o] [o]` donne `°`
|
||||
- `[compose] [<] [<]` donne `«`
|
||||
- `[compose] [>] [>]` donne `»`
|
||||
- `[compose] [%] [o]` donne `‰`
|
||||
- `[compose] [=] [e]` donne `€`
|
||||
- `[compose] [c] [|]` donne `¢`
|
||||
- `[compose] [L] [-]` donne `£`
|
||||
- `[compose] [y] [=]` donne `¥`
|
||||
- `[compose] [.] [.]` donne `…`
|
||||
- `[compose] [N] [o]` donne `№`
|
||||
- `[compose] [<] [3]` donne `♥`
|
||||
- `[compose] [:] [)]` donne `☺`
|
||||
- `[compose] [:] [(]` donne `☹`
|
||||
- `[compose] [p] [o] [o]` donne `💩` (U+1F4A9 "PILE OF POO")
|
||||
|
||||
Ce fichier contient 4042 compositions au total, dont une partie non
|
||||
négligable n'est évidemment pas atteignable avec une dead-key, comme
|
||||
ẞ, qui nécessiterai que le `[s]` soit une touche morte.
|
||||
|
||||
Parmis ces exemples, certains sont intéressants à utiliser au
|
||||
quotidien dans certains métiers, comme №, √, →, ✓, ✗, ±, …, ≠, ≤, ≥,
|
Binary file not shown.
After Width: | Height: | Size: 719 KiB |
Binary file not shown.
After Width: | Height: | Size: 155 KiB |
|
@ -13,12 +13,18 @@ Senior software architect at [meltygroup](https://www.meltygroup.com).
|
|||
[docs.python.org/fr/](https://docs.python.org/fr/),
|
||||
[git repository](https://github.com/python/python-docs-fr),
|
||||
[progression](https://mdk.fr/blog/python-documentation-translation.html)).
|
||||
- [Code en Seine](https://codeenseine.fr/): An bi-monthly free Python workshop at the CRI Paris.
|
||||
- [Hackinscience](https://hackinscience.org/): A yearly Python intensive week at the CRI Paris.
|
||||
- [logtop](http://julienpalard.github.io/logtop/) a realtime log line analzer, Debian packaged.
|
||||
- Many others on [my github account](https://github.com/julienpalard).
|
||||
- [pipe](https://pypi.python.org/pypi/pipe/) A Python module enablig a sh like infix syntax (using pipes).
|
||||
- [vt100-emulator](https://github.com/JulienPalard/vt100-emulator) A headless terminal emulator in C89.
|
||||
- [turtl-backup](https://github.com/JulienPalard/turtl-backup) A tool to backup a turtl / framanotes account.
|
||||
- Many others on [my github account](https://github.com/JulienPalard).
|
||||
|
||||
- Join me on IRC, I'm `mdk` on [freenode](https://webchat.freenode.net)
|
||||
- [My CV](https://mdk.fr/Julien-Palard.pdf)
|
||||
- [My ssh key](https://mdk.fr/id_ed25519.pub)
|
||||
- [My gpg key](https://mdk.fr/gpg.pub)
|
||||
- I'm `mdk` on [freenode](https://webchat.freenode.net)
|
||||
|
||||
> "Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning." - Rick Cook - The Wizardry Compiled (1989) -
|
||||
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
status: hidden
|
||||
title: Cybersécurité — Code Review
|
||||
slug: di3oK1oochatha-codereview
|
||||
robots: noindex
|
||||
|
||||
# Code Review
|
||||
|
||||
Le nom du projet est: `codereview`, en minuscule (c'est important pour
|
||||
le [rendu](https://mdk.fr/pages/obiree2uaza2sh-rendu.html)).
|
||||
|
||||
Contexte : Vous faites de la relecture de code pour un projet open
|
||||
source que vous utilisez depuis fort fort longtemps (mais après les
|
||||
cours de sécu, vous vous êtes décidés à aller relire ça) donc tout ce
|
||||
que vous écrivez est public, sera lu par des inconnus, et le core dev
|
||||
qui fait ça sur son temps libre et pour le plaisir, et ne parle pas
|
||||
forcément français. Ah et c'est sur github donc vous rédigez en
|
||||
Markdown. Vous pouvez rendre une faille par fichier markdown (comme
|
||||
si vous ouvriez une issue par faille, une issue = un fichier).
|
||||
|
||||
Le code est fourni, vous devez donc le relire, lister les failles que
|
||||
vous voyez, pour chaque faille l'expliquer suffisamment clairement
|
||||
pour prouver qu'elle est exploitable, voir fournir un expemple
|
||||
d'exploitation, et vous devez proposer une correction. N'oubliez pas
|
||||
que vous vous adressez à un développeur, qui n'a pas forcément votre
|
||||
niveau, mais qui est peut être meilleur dans d'autres domaines.
|
||||
|
||||
|
||||
<?php
|
||||
|
||||
$db = new PDO('sqlite:'.dirname(__FILE__).'/db.sqlite');
|
||||
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
||||
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$db->query(
|
||||
"CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
login TEXT UNIQUE,
|
||||
password TEXT,
|
||||
is_admin INTEGER
|
||||
)");
|
||||
$db->query(
|
||||
"CREATE TABLE IF NOT EXISTS sessions (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
created DATETIME,
|
||||
user_id INTEGER
|
||||
)");
|
||||
$db->query(
|
||||
"CREATE TABLE IF NOT EXISTS articles (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
title TEXT,
|
||||
body TEXT
|
||||
)");
|
||||
|
||||
$db->query('INSERT OR IGNORE INTO users (login, password, is_admin) VALUES ("admin", "admin123", 1)');
|
||||
|
||||
|
||||
if (!empty($_COOKIE['session_id'])) {
|
||||
$session_id = $_COOKIE['session_id'];
|
||||
}
|
||||
else {
|
||||
if (!empty($_SERVER['HTTP_AUTHORIZATION'])) {
|
||||
list($login, $password) = explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], strlen("Basic "))));
|
||||
$user = $db->query(sprintf('SELECT id, is_admin FROM users WHERE login = "%s" AND password = "%s"', $login, $password))->fetch();
|
||||
}
|
||||
$db->query(sprintf("INSERT INTO sessions (created, user_id) VALUES ('%s', '%s')",
|
||||
date("Y-m-d H:i:s"),
|
||||
$user['id']));
|
||||
$session_id = $db->lastInsertId();
|
||||
}
|
||||
|
||||
$session = $db->query(sprintf(
|
||||
"SELECT * from sessions LEFT JOIN users ON users.id = sessions.user_id WHERE sessions.id = %s",
|
||||
$session_id))->fetch();
|
||||
|
||||
if ($_GET['page'] == 'users')
|
||||
{
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'PUT' ||
|
||||
$_SERVER['REQUEST_METHOD'] == 'POST' ||
|
||||
$_SERVER['REQUEST_METHOD'] == 'GET')
|
||||
{
|
||||
if (!$session['is_admin'])
|
||||
{
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
header('WWW-Authenticate: Basic realm="Admin Zone');
|
||||
die();
|
||||
}
|
||||
}
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'PUT')
|
||||
{
|
||||
$db->query(sprintf('UPDATE users SET password = "%s" WHERE id = "%s"',
|
||||
$_GET['new_password'], $_GET['user_id']));
|
||||
}
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST')
|
||||
{
|
||||
$db->query(sprintf('INSERT INTO users (login, password, is_admin) VALUES ("%s", "%s", 0)',
|
||||
$_GET['login'], $_GET['password']));
|
||||
}
|
||||
// Que ce soit un GET, PUT, ou POST on affiche la liste:
|
||||
// TODO: tpl, en attendant, var_dump ça suffit, c'est une page d'admin.
|
||||
var_dump($db->query('SELECT * FROM users')->fetchAll());
|
||||
}
|
||||
|
||||
|
||||
if ($_GET['page'] == 'sessions') {
|
||||
if (!$session['is_admin'])
|
||||
{
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
header('WWW-Authenticate: Basic realm="Admin Zone"');
|
||||
die();
|
||||
}
|
||||
var_dump($db->query('SELECT * FROM sessions')->fetchall());
|
||||
}
|
||||
|
||||
if ($_GET['page'] == 'redirect') {
|
||||
/**
|
||||
* Do not allow open redirects, only signed redirects. Open redirects
|
||||
* allow easy phishing (presenting pretty URLs with legit domain,
|
||||
* redirecting to phising site.
|
||||
*/
|
||||
$target = $_GET['target'];
|
||||
$given_checksum = $_GET['checksum'];
|
||||
if (sha1($target) != $given_checksum)
|
||||
{
|
||||
header('HTTP/1.0 400 Bad request');
|
||||
die();
|
||||
}
|
||||
header("Location: " . $_GET['target'], TRUE, 301);
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
if ($_GET['page'] == 'static') {
|
||||
/**
|
||||
* Allow static assets to be included. Only from ./static/. We're using
|
||||
* PHP even for static assets so we can later minify CSS and JS on the fly
|
||||
* \o/
|
||||
*/
|
||||
include "./static/" . $_GET['asset'];
|
||||
}
|
||||
|
||||
|
||||
if ($_GET['page'] == 'upload') {
|
||||
if (!isset($_FILES['file'])) {
|
||||
echo '<form method="post" enctype="multipart/form-data">
|
||||
<input type="file" name="file">
|
||||
<input type="submit" value="upload">
|
||||
</form>';
|
||||
die();
|
||||
}
|
||||
$uploaddir = './uploads';
|
||||
@mkdir("./uploads", 0700);
|
||||
$uploadfile = $uploaddir . '/' . basename($_FILES['file']['name']);
|
||||
assert('!in_array("' . $_FILES["file"]["type"] . '", ["image/jpeg", "image/png"])');
|
||||
if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)) {
|
||||
echo "Uploaded successfully: <a href='$uploadfile'>$uploadfile</a>\n";
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($_GET['page'] == 'new_article') {
|
||||
/**
|
||||
* We hired a remote dev to do the client. Note for later: Don't fscking
|
||||
* do that ever again. He did everything in Python (Like PHP was not the
|
||||
* obvious choice? (spoiler: he won't get paid)) And he insisted on
|
||||
* transmiting everything as base64 encoded "pickled" values, telling
|
||||
* that's better than json and easier than protobuf, srly? Fsck this.
|
||||
* Plus I hate Python documentation, there's never A SINGLE FSCKING
|
||||
* EXAMPLE in this FSCKING DOC. Hopefully I found an example on
|
||||
* stackoverflow, thanks Google for ranking SO before python, but sorry
|
||||
* for the code. TODO: Rewrite the client in PHP.
|
||||
*
|
||||
* Test data:
|
||||
* gAN9cQAoWAQAAABib2R5cQFYFgAAAERvbG9yLCBtdWNoIG11Y2ggZG9sb3JxAlgFAAAAdGl0bGVxA1gLAAAATG9yZW0gSXBzdW1xBHUu
|
||||
*/
|
||||
|
||||
$base64_encode_picke = $_GET['article'];
|
||||
exec(sprintf('python3 -c "import json; import pickle; import base64; print(json.dumps(pickle.loads(base64.b64decode(%s))))"',
|
||||
"'" + $base64_encode_picke + "'"), $output);
|
||||
$json = json_decode($output[0], TRUE);
|
||||
$db->query(sprintf('INSERT INTO articles (title, body) VALUES ("%s", "%s")',
|
||||
$json['title'], $json['body']));
|
||||
}
|
||||
|
||||
if ($_GET['page'] == 'articles') {
|
||||
// TODO: Template.
|
||||
var_dump($db->query('SELECT * FROM articles')->fetchall());
|
||||
}
|
||||
|
||||
|
||||
setcookie('session_id', $session_id);
|
Loading…
Reference in New Issue