WebHook Google Code – recevoir un mail à chaque commit

Dans Google code il y a la possibilité d’utiliser un gestionnaire de version tel que subversion (svn) ou mercurial (hg). C’est bien pratique, mais malheureusement, de base, rien n’est prévu pour prévenir (excepté par flux RSS) les gens de ces mises à jour. Cependant, Google code permet d’utiliser un webhook en post commit.

Qu’est-ce qu’un webhook?

Un webhook c’est un « crochet web », c’est-à-dire une URL a appelée après (avant ou pendant) une action X. Dans notre cas, après chaque commit une URL est appelée.

Utilisation

Voici un exemple de code que j’utilise pour plusieurs de mes projets :

<?php
// project name
$projects = array('mon-super-projet');
 
// google code webhook key
$keys = array(
	'b-box'	=> 'Top-Secret_key_fourni_par_google-dans-l-adminsitration'
);
 
//user agent from google code
$useragent = 'Google Code Project Hosting (+http://code.google.com/p/support/wiki/PostCommitWebHooks)';
 
//email of all owner (eg. project chief)
$owners = array('vous@example.com');
 
//email of all team members except owners
$users = array('toi@example.com');
 
//sender of email
$sender = 'WebHook mailer<webmaster@exemple.com>';
 
//----------------------------------------------------------------------
$project = (isset($_GET['p']))?$_GET['p']:'';
$revision = (isset($_GET['r']))?intval($_GET['r']):-99;
$data = file_get_contents('php://input');
$digest = (isset($_SERVER['HTTP_GOOGLE_CODE_PROJECT_HOSTING_HOOK_HMAC']))?$_SERVER['HTTP_GOOGLE_CODE_PROJECT_HOSTING_HOOK_HMAC']:'';
 
//----------------------------------------------------------------------
/**
 * Send a mail
 * @param string $from email of the sender : sample@example.com or "name"<sample@example.com>;
 * @param array $to [a] => list of email [cc], [bcc] (hidden), ...
 * @param string $subject
 * @param string $body
 * @return bool true if success
 */
function mailer($from, array $to, $subject, $body)
{
	if (empty($to))
	{
		return false;
	}
 
	$headers = 'From: ' . $from . "\n";
 
	$a = '';
 
	if (isset($to['a']) &amp;&amp; !empty($to['a']))
	{
		$a = implode(',', $to['a']);
	}
 
	if (isset($to['bcc']) &amp;&amp; !empty($to['bcc']))
	{
		$headers .= 'Bcc: ' . implode(',', $to['bcc']) . "\n";
	}
 
	if (isset($to['cc']) &amp;&amp; !empty($to['cc']))
	{
		$headers .= 'Cc: ' . implode(',', $to['cc']) . "\n";
	}
 
	$headers .= 'MIME-Version: 1.0' . "\n";
	$headers .= 'Content-Type: text/plain; charset="UTF-8"' . "\n";
	$headers .= 'Content-Transfer-Encoding: 8bit' . "\n";
	$headers .= 'X-Mailer: PHP/' . phpversion();
 
	return mail($a, '[webhook]' . $subject, $body, $headers);
}
 
function failed($test_id, $msg)
{
	global $sender, $owners;
 
	$msg .= "\n--\nWebHook mail from the Google code project";
 
	mailer($sender, array('bcc' => $owners), 'failed test #' . $test_id, $msg);
 
	die('KO');
}
 
function get_ip()
{ 
	return (isset($_SERVER['HTTP_X_FORWARDED_FOR']))?$_SERVER['HTTP_X_FORWARDED_FOR']:(isset($_SERVER['HTTP_CLIENT_IP']))?$_SERVER['HTTP_CLIENT_IP']:$_SERVER['REMOTE_ADDR'];
}
 
//----------------------------------------------------------------------
if ($useragent != $_SERVER['HTTP_USER_AGENT'])
{
	// failed 1
	failed(1, 'User agent is bad : ' . htmlspecialchars($_SERVER['HTTP_USER_AGENT']) . "\n\nFrom : " . get_ip());
}
elseif (empty($project) || !in_array($project, $projects))
{
	// failed 2
	failed(2, 'No project set : ' . htmlspecialchars($project) . "\n\nFrom : " . get_ip());
}
else
{
	$hmac = hash_hmac('md5', $data, $keys[ $project ]);
	$data = json_decode($data, true);
 
	if (empty($digest) || $digest != $hmac)
	{
		// failed 3
		failed(3, 'Bad digest : ' . $digest . ' vs ' . $hmac . "\n\nFrom : " . get_ip());
	}
	elseif (intval($data['revision_count']) != count($data['revisions']))
	{
		// failed 4
		failed(4, 'Bad count : ' . count($data['revisions']) . ' vs ' . intval($data['revision_count']) . "\n\nFrom : " . get_ip());
	}
	else
	{
		$mail_body = '';
		foreach($data['revisions'] as $_revision)
		{
			$mail_body .= 'Revision : ' . "\t" . htmlentities($_revision['revision']) . ' from ' . htmlentities($_revision['author']) . ' at ' . date('Y-m-d H:i', intval($_revision['timestamp'])) . "\n";
			$mail_body .= 'Added : ' . "\t" . implode("\n\t\t", htmlentities($_revision['added'])) . "\n";
			$mail_body .= 'Modified : ' . "\t" . implode("\n\t\t\t", htmlentities($_revision['modified'])) . "\n";
			$mail_body .= 'Removed : ' . "\t" . implode("\n\t\t\t", htmlentities($_revision['removed'])) . "\n\n";
//			$mail_body .= 'URL : ' . "\t\t" . htmlentities($_revision['url']) . "\n\n";
			$mail_body .= 'Message : ' . "\t" . htmlentities($_revision['message']) . "\n\n\n";
//			$_revision['path_count'];
		}
		$mail_body .= "\n--\nWebHook mail from the Google code project : " . $project . "\nhttp://code.google.com/p/" . $project . "/\n";
 
		mailer($sender, array('bcc' => $owners + $users), '[' . $project . ']New revision #' . $revision, $mail_body);
	}
}
 
exit('OK');
 
# EOF

Plus d’info : PostCommitWebHooks

Wampserver : quick switch xdebug menu

Pour une fois, un article sous Ms Windows. Stage oblige, je passe du temps sous celui-ci (XP 🙁 ). Afin d’optimiser son travail, il y a parfois des petites choses bien pratiques, telles que ce que je vais vous présenter.

XDebug est un outil merveilleux, parfois capricieux, certes, mais très utile. Il permet, notamment1 :

  • Affichage de tracé d’erreur
  • Meilleures lectures des exceptions
  • Débogage pas-à-pas
  • Profiling d’application

Bref, des choses essentielles en développement. Et, contrairement à ce que certains IDE2 font, il permet surtout de le faire sur un serveur « réel », donc avec une utilisation « réel ».

Le but de ce billet n’est pas de présenter XDebug, d’autres le font mieux que moi 3, mais bien de vous présenter un petit script vous permettant d’activer et désactiver XDebug sur wampserver.

Installation

  1. Téléchargez le fichier 4 et décompressez-le.
  2. Suivez les instructions d’installation décrite dans le fichier installe. Il y a seulement 1 fichier à modifier + 1 fichier par version de PHP installée.
  3. Relancer wampserver et tester!

Si vous avez des questions, n’hésitez pas.

Plus d’informations

  1. On parle de serveur web avec PHP …
  2. Par exemple, Zend Studio permet un débogage pas à pas mais en interne donc réduit …
  3. cf. plus d’informations
  4. XDebug quick switch menu for wampserver

Activation, désactivation du wifi sur un D-Link DSL-2640B via PHP

Un script PHP en ligne de commande pour activer // désactiver le wifi sur un modem D-Link DSL-2640B. Cela permet d’illustrer un peu l’intérêt de faire du scripting …

Je ne ferais pas de commentaires, mais n’hésitez pas à poser des questions …

#!/usr/bin/php
<?php
 
//Variable definition
//
//router
$login = 'admin';
$password = 'admin';
$ip = '192.168.1.1';
 
//
//wifi
$wifi = array(
	// /!\ don't touch this /!\
	'wlSsidIdx'	=> 0,
	'wlEnbl'	=> 1,
	'wlCountry'	=> 'GB',
	'wlBasicRate'	=> '',
 
	//ssid name
	'wlSsid'	=> 'monSuperRéseauxWifi',
	//0 = visible, 1 = hide
	'wlHide'	=> 0,
	//number of chanel or 0 for auto selection
	'wlChannel'	=> 1,
	//Transmission Speed
	'wlRate'	=> 0,
	//wifi mode 0=802.11b only, 1=Mixed 802.11g and 802.11b, 4=802.11g only
	'wlgMode'	=> 4,
 
	'wlWpaGTKRekey'	=> 750,
	'wlWpa'			=> 'aes',
	'wlAuthMode'	=> 'psk2',
	//authentification mode : 0 = none, 1 = wep, 2 = auto (wpa or wpa2), 3 = wpa2 only, 4 = wpa only
	'wlAuth'	=> 0,
	'wlWpaPsk'	=> 'masuperclefdelamortquitue',
	'wlWep'		=> 'disabled',
	'wlPreauth'	=> 0
);
 
/////////////////////
 
class cli
{
	const LINE_BREAK = "\r\n";
	const LINE_NO_BREAK = '';
	const LINE_RETURN = "\r";
	const LINE_NOTHING = ' ';
 
	protected $_TEMP = 250000;//1/4 of seconds
	protected $_MULTIPLICATOR = 4; //1/4 -> 4
 
	protected $_LENGTH = 60;
 
	protected function _write_empty_space($lng)
	{
		while($lng < $this->_LENGTH)
		{
			echo ' ';
			$lng++;
		}
	}
 
	protected function _echo($message, $break)
	{
		echo $message, $break;
		if ($break == self::LINE_NO_BREAK)
		{
			$this->_write_empty_space(strlen($message));
		}
	}
 
	protected function _sleep($second)
	{
		$second = $second * $this->_MULTIPLICATOR;
		$i = 0;
		$j = 0;
		while ($i < $second)
		{
			usleep($this->_TEMP);
 
			if ($i % 4)
			{
				$this->_echo('.', self::LINE_NOTHING);
				$i++;
			}
			else
			{
				if($j % 2)
				{
					$this->_echo('', self::LINE_RETURN);
					$this->_write_empty_space(0);
					$this->_echo('', self::LINE_RETURN);
				}
				else
				{
					$this->_echo('Please wait', self::LINE_NOTHING);
					$i++;
				}
				$j++;
			}
		}
		$this->_echo('', self::LINE_RETURN);
	}
}
 
class wifi extends cli
{
	protected $_ch;
	protected $_baseUrl;
 
	public function __construct($wifi, $ip, $login, $password, $activation)
	{
		$this->_baseUrl = 'http://' . $ip . '/';
 
		$this->_ch = curl_init();
		curl_setopt($this->_ch, CURLOPT_HEADER, false);
		curl_setopt($this->_ch, CURLOPT_RETURNTRANSFER, true);
 
		$this->_auth($login, $password);
 
		$activation = intval($activation);
 
		if ($activation == 1)
		{
			$this->_activation($wifi);
		}
		else
		{
			$this->_disactivation($wifi);
		}
	}
 
	public function __destruct()
	{
		curl_close($this->_ch);
	}
 
	protected function _activation($wifi)
	{
		$this->_echo('Activation ...', self::LINE_NO_BREAK);
 
		$wifi['wlBasicRate'] = ($wifi['wlgMode'] == 4) ? 'wifi2' : 'default';
 
		$this->_doQuery($this->_baseUrl . 'wirelesssetting.wl?' . http_build_query($wifi, '', '&'));
		$this->_sleep(5);
	}
 
	protected function _disactivation($wifi)
	{
		$this->_echo('Disactivation ...', self::LINE_NO_BREAK);
 
		$wifiDown = array(
			'wlEnbl'	=> 0,
			'wlSsidIdx'	=> $wifi['wlSsidIdx'],
			'wlCountry'	=> $wifi['wlCountry'],
		);
 
		$this->_doQuery($this->_baseUrl . 'wirelesssetting.wl?' . http_build_query($wifiDown, '', '&'));
		$this->_sleep(5);
	}
 
	protected function _doQuery($url, $post = '')
	{
		curl_setopt($this->_ch, CURLOPT_URL, $url);
 
		if (!empty($post))
		{
			curl_setopt($this->_ch, CURLOPT_POST, true);
			curl_setopt($this->_ch, CURLOPT_POSTFIELDS, $post);
		}
		else
		{
			curl_setopt($this->_ch, CURLOPT_HTTPGET, true);
		}
 
		if(curl_exec($this->_ch) === false)
		{
			$this->_echo('', self::LINE_BREAK);
			$this->_echo('Error Curl : ' . curl_error($this->ch), self::LINE_BREAK);
		}
		else
		{
			$this->_echo('DONE', self::LINE_BREAK);
		}
	}
 
	protected function _auth($login, $password)
	{
		$this->_echo('Authentification ...', self::LINE_NO_BREAK);
 
		$post = array(
			'username'	=> $login,
			'password'	=> $password
		);
 
		$this->_doQuery($this->_baseUrl . 'index.html', http_build_query($post, '', '&'));
	}
}
 
if ($argc != 2)
{
	echo ' synthaxe : scriptname.php 1 for activation or 0 for desactivation ';
	exit();
}
 
new wifi($wifi, $ip, $login, $password, $argv[1]);
 
# EOF

Certes, le script ne gère pas tout, mais le but était de jouer avec la ligne de commande tout en n’allant pas dans les extensions exotiques de gestion de celle-ci ….

java : Drag & Drop sur un JTable

Drag & Drop sur un JTable

Dans nos application moderne il semble logique de pouvoir faire du DND à gogo, pourtant ce n’est pas des plus simple, avec certain langage de le faire,  d’où cette exemple qui m’a fait un peu travaillez et arrachez un ou deux cheveux de ma longue chevelure de geek…

Bref, voici l’essentiel :

  1. Il faut que le composant puisse être pris (drag) et/ou déposé (drop)
  2. Il faut convertir le composant en donnée exportable et transportable (Transferable)
  3. Il faut pouvoir restaurer les donnée correctement et suivant le type les restaurer de tel ou tel manière …

Lire la suite

Questionnaire – sondage en ligne

J’en ai vu passé des questionnaires de fin de thèse ou des sondage pour tel ou tel société mais jamais je n’avais songé prendre note des références des logiciel ou des sociétés utilisé pour créer ces sondages-enquêtes! Du coup, en ayant eu besoin j’ai du chercher…

Et là cela se complique, on se rend vite compte que beaucoup de société propose des service payant et là ou pour n’importe quel script on trouve facilement des réponses à droite et à gauche, ici rien! Bien embêté me voila sur le chemin de la recherche.

Bref après quelques recherche et élimination je trouve deux sites proposant des services gratuits et qui semble correcte :
http://www.paxonta.com et http://www.sondageonline.com

Cependant, je me dit qu’il y avait certainement un projet open-source qui se devait d’exister et que si ce n’est pas le cas, alors le moment de hurler et de se lancer dans la bataille en faisant son William Walace devait arriver. Mais heureusement, pas besoin de tête tranchée le script fut trouvé :  LimeSurvey

Je ne suis pas déçu et ils propose même un service en ligne : http://www.limeservice.com
Par contre, il m’a fallu un peu de temps pour comprendre …. En gros, toujours cliquer sur l’icône à droite (l’espèce de feuille ….) et voila!

Perso je trouve que c’est encore fort compliqué … mais bon on peux pas tout avoir ….

J’en profite pour vous le faire tester en répondant a ce magnifique questionnaire sur les forums!