Deblan blog

Tag #Javascript


Projet : du P2P dans une page web

J'ai beaucoup de convictions pour Internet. je considère la centralisation sur "Internet" comme uné énormité est un mauvais retour dans le lointain passé du 3515. Globalement, ce n'est pas mes machines à la maison et ma grande gueule qui va changer le monde. Comment faire avancer un peu plus le Schmilblick alors ?!

Depuis le début de la semaine je suis sur un projet qui vise à décentraliser le contenu d'un site internet. Dit comme ça, on s'imagine le mec qui va poser ces fichiers sur 50 serveurs HTTP différents et qui sera content de lui...bah vous n'avez presque pas tout à fait tort ! Ce que j'aimerais faire est simple à comprendre : à la place d'héberger un contenu potentiellement lourd sur mon serveur, je vais le proposer en torrent. Seulement, je ne veux pas un bête lien que l'utilisateur va ouvrir manuellement avec son client P2P favori. L'objectif est de coller une couche javascript dans la page qui va contacter le fameux client P2P et une fois le téléchargement terminé, affichera le contenu dans la page.

Voila un contenu HTML type avant :

<video data-dimension="destroy" src="torrent://tracker.du.torrent.com/fichier.ogv.torrent"></video>

...et après :

<video data-dimension="destroy" src="file:///chemin/vers/fichier.ogv"></video>

J'ai imaginé plusieurs méthodes et pour commencer (et prouver que ça peut fonctionner), je vais utiliser un daemon coté client (en plus du navigateur). Les websockets html5 auront la charge de communiquer avec celui-ci.

Diagramme de séquence projet torrent

Je souhaite avoir un rendu fonctionnel et pouvoir utiliser des torrents dans une page (même si ce n'est pas pratique et rapide). Si une solution similaire est suivie et améliorer avec des gens 100 fois plus skillés que moi, alors monsieur Toutlemonde pourrait faire son Youtube dans sa grotte...euh garage...non : maison !


[Retour] Contrer des robots stupides sans captcha

C'est un post rapide qui va permettre de faire un retour sur la solution pour contrer les robots sans utiliser de captcha.

Pour rappel, le concept est simple : on place dans l'action du formulaire un mot clé qui invalide sa soumission. Ce mot clé est supprimé quand l'utilisateur déplace sa souris dans la page qui contient ce formulaire. Cette méthode admet que l'utilisateur a activé le Javascript sur son navigateur.

Après quelques mois d'utilisation, que peut-on en conclure ? Cette méthode fonctionne du feu de dieu ! Je suis passé à coté de plus de 50 milles commentaires indésirables. La crainte que j'avais se portait sur les supports mobiles : finalement, aucune inquiétude, ça fonctionne très bien sur les smartphones et les tablettes.

J'ai implanté cette solution sur un blog Wordpress et ça fonctionne très bien également...À croire que les développeurs de robots sont des manches.

Évidement, tout développement spécifique de robot va contrer cette sécurité, mais c'est assez rare finalement.

Sécurité informatique


Afficher une webcam sur son site (version Linux)

Il y a déjà un article pour afficher sa webcam sur une page web mais en plus d'être un peu à la rue, il ne fonctionne pas sur Linux.

Nous allons voir comment intégrer une webcam sur son site web sous Linux.

Il nous faut :

  • Un serveur web
  • Un accès SSH
  • Une webcam
  • Un ou deux logiciels en local

Note : je travail sur Debian, il faut donc transposer mes commandes pour votre distribution.

Étape 1 : les logiciels en local
# aptitude update
# aptitude install openssh-client vgrabbj rsync imagemagick screen
  • openssh-client : notre client SSH
  • vgrabbj : il permettra de capturer les images de la webcam
  • rsync : il sera notre outil d'upload d'image et va s'appuyer sur SSH
  • imagemagick : pour faire un traitement sur l'image (ajouter du texte)
  • screen : pour lancer le script sans monopoliser un terminal
Étape 2 : préparation des répertoires de travail

On va créer un répertoire qui accueillera le script et la capture :

# le répertoire du script
$ if [ -d "$HOME/bin" ] || mkdir "$HOME/bin"
# le répertoire de la capture
$ if [ -d "$HOME/.webcam" ] || mkdir "$HOME/.webcam"

Création du fichier :

$ cd "$HOME/bin"
$ touch webcam
$ chmod +x webcam
Étape 3 : Et on édite le script

Je propose de faire ça en simple shell, donc pas de bash mais un bon vieux sh (ou dash sur Debian).

#!/bin/sh

On prépare des variables de configuration :

# Le login et le serveur
SSH_SERVER="simon@exemple.com"
# Des options à passer au client SSH
# -p indique le port de connexion
# -i permet de paramétrer une clé SSH
SSH_OPTIONS=" -p 22 -i $HOME/.ssh/id_dsa" 

# Chemin vers l'image que va générer la webcam
IMG_LOCAL="$HOME/.webcam/webcam.jpg"

# Le chemin de l'image sur le serveur distant
IMG_REMOTE="/services/web/www/exemple.com/public_html/ressources/webcam.jpg"

# Qualité de l'image générée (de 1 à 100 et plus c'est grand, plus c'est zoli)
IMG_QUALITY=75

# Les dimensions de l'image
# sqcif= 128x96,     qsif = 160x120,
# qcif = 176x144,    sif  = 320x240,
# cif  = 352x288,    vga  = 640x480,
# svga = 800x600,    xga  = 1024x768,
# sxga = 1280x1024,  uxga = 1600x1200
IMG_SIZE=sif

# Je vais afficher du texte sur l'image donc je paramètre sa couleur et sa position
IMG_TEXT_COLOR=black
IMG_TEXT_X=8
IMG_TEXT_Y=16

# Le périphérique webcam à utiliser
VIDEO_INPUT=/dev/video0

# Le temps entre deux captures (en secondes)
WAIT=5

# la fonction text va retourner le texte à afficher sur la webcam
text() {
	# ça donnera : login @ mm/jj/aa hh:mm:ss
	echo "$USER @ $(date +'%D %r')"
}

On ajoute une sécurité : ne pas avoir deux scripts qui tente un accès à la webcam en même temps :

LOCK="$HOME/.webcam/.lock"

while [ -f "$LOCK" ]; do
	sleep 1
done

touch "$LOCK"

On termine par les commandes de capture, d'écriture du texte et d'upload :

# On capture l'image
vgrabbj -i "$IMG_SIZE" -f "$IMG_LOCAL" -d "$VIDEO_INPUT" -q "$IMG_QUALITY" -a 3 -n

# On ajoute le texte
mogrify -fill "$IMG_TEXT_COLOR" -pointsize 11 -annotate +"$IMG_TEXT_X"+"$IMG_TEXT_Y" "$(text)" "$IMG_LOCAL"

# On upload 
rsync -avz -e "ssh $SSH_OPTIONS" "$IMG_LOCAL" "$SSH_SERVER":"$IMG_REMOTE"
# Note : certains seront peut-être plus à l'aise avec scp, c'est comme vous voulez

On termine par boucler tout ça :

# on délock l'accès à la webcam
rm -f "$LOCK"

# On fait attendre un peu le script
sleep $WAIT

# On l'exécute lui-même 
"$0"&

# Et on arrête l'exécution courante
exit 0

Le script complet (sans commentaire) :

#!/bin/sh

SSH_SERVER="simon@exemple.com"
SSH_OPTIONS=" -p 22 -i $HOME/.ssh/id_dsa" 

IMG_LOCAL="$HOME/.webcam/webcam.jpg"

IMG_REMOTE="/services/web/www/exemple.com/public_html/ressources/webcam.jpg"

IMG_QUALITY=75
IMG_SIZE=sif
IMG_TEXT_COLOR=black
IMG_TEXT_X=8
IMG_TEXT_Y=16

VIDEO_INPUT=/dev/video0

WAIT=5

text() {
	echo "$USER @ $(date +'%D %r')"
}

LOCK="$HOME/.webcam/.lock"
 
while [ -f "$LOCK" ]; do
	sleep 1
done

touch "$LOCK"

vgrabbj -i "$IMG_SIZE" -f "$IMG_LOCAL" -d "$VIDEO_INPUT" -q "$IMG_QUALITY" -a 3 -n
mogrify -fill "$IMG_TEXT_COLOR" -pointsize 11 -annotate +"$IMG_TEXT_X"+"$IMG_TEXT_Y" "$(text)" "$IMG_LOCAL"
rsync -avz -e "ssh $SSH_OPTIONS" "$IMG_LOCAL" "$SSH_SERVER":"$IMG_REMOTE"

rm -f "$LOCK"

sleep $WAIT
"$0"&
exit 0
Étape 4 : la page html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Ma webcam</title>
<script>
// Deux helpers pour attacher un évenement à un object et un selecteur rapide d'élement par id
var addEvent = function(object, eventName, myFunction) {
	if(object.addEventListener) {
		object.addEventListener(eventName, myFunction, false);
	} else if(object.attachEvent) {
		object.attachEvent('on'+eventName, myFunction);
	}
}
var $ = function(id) {
	return document.getElementById(id);
}

// On ne veut pas de clignottement donc entre chaque
// chargement d'image, on attend que celui-ci soit 
// terminé pour mettre à jour l'image dans la page
var image_reload = function(id, time) {
	var img = $(id);
	if(img) {
		var _img = new Image();
		var src = (img.getAttribute('src')).split('?')[0]+'?'+Math.random();
		_img.src = src;
		addEvent(_img, 'load', function() {
			img.setAttribute('src', src);
		});
		window.setTimeout(function() {
			image_reload(id, time);
		}, time);
	}
}

addEvent(window, 'load', function() {
	// id de l'image de la webcam et temps de rafraissement
	image_reload('webcam', 2000); 
});
</script>
<body>

<p><img data-dimension="destroy" id="webcam" src="/ressources/webcam.jpg" alt="" title=""/></p>

</body>
Étape 5 : lancer le script
$ screen
$ ./bin/webcam

C'est terminé :)


Contrer des robots stupides sans captcha

Ceux qui côtoyaientt mon ancien blog devaient rentrer un captcha pour poster un commentaire.

Le problème c'est que personnellement, ça me gonfle de me cogner une image presque illisible à lire pour un simple message. Seulement il y a toujours et encore nos amis les robots pour casser l'ambiance.

Comment bloquer ces robots sans captcha ?

Pour vous j'ai une astuce simple qui depuis 2 jours a permis de bloquer un peu plus de 300 robots (tout les robots qui ont essayé de poster d'ailleurs).

Cette technique ne fonctionne que pour les robots complétements cons et qui ne sont pas développés spécifiquement !

Étape 1 : créer une page dédiée à la gestion des robots

Vous devez (pouvez) créer une page qui va réceptionner les robots détectés et qui leur laissera un joli message de bienvenue. De mon coté, j'ai aussi décidé d'enregistrer les informations réceptionnées ($_POST, $_GET, $_COOKIE, $_SERVER).

J'ai décidé de rendre accessible cette page avec l'url "/bot"

Étape 2 : préparer les formulaires à sécuriser

Comme je l'ai écrit, c'est simple et pour ce faire, il suffit d'ajouter l'url de la page pour les robots dans l'action du formulaire.

Par exemple, voila ce que vous trouverez dans le code source de ce blog :

<form method="post" id="comment_form" action="/bot?/post/429/Contrer-des-robots-stupides-sans-captcha#comment_form" enctype="multipart/form-data">

Il vaut évidement remarquer le "/bot?" ajouté à la vraie action du formulaire.

Étape 3 : owned le bot

Comme les robots sont cons et qu'ils sont souvent démunis d'un tas d'outils, il suffit d'utiliser l'un d'eux : javascript.

Pour se faire, on va définir que si la personne bouge la souris sur la page, alors elle n'est pas un bot. Par conséquent, il suffit de supprimer "/bot?" de l'action du formulaire :

<script type="text/javascript">
$(document).ready(function() {
	$(document).mousemove(function() {
		var action = $('#comment_form').attr('action').replace(/^\/bot\?/, '');
		$('#comment_form').attr('action', action);
	});
});
</script>

Edit : Une optimisation du code a été proposée par GromNaN et je la préconise. La voici :

<script type="text/javascript">
$(document).ready(function() {
	$(document).one('mousemove', function() {
		var $form = $('#comment_form');
		var action = $form.attr('action').replace(/^\/bot\?/, '');
		$form.attr('action', action);
	});
});
</script>

Rien de plus simple et ça semble très bien fonctionner.

Seul petit bémol : ça implique que les internautes ont le javascript activé.