Return false

Un blog IT de plus le blog de Hubebert.

Articles taggés avec ‘php’

Tu as un serveur hébergé chez toi? Une box qui change d’IP quand ça lui chante? Voici une solution pour y pallier.

Cet article fait suite à celui d’ecaheti du 16 Août concernant la configuration de son Raspberry Pi le changement d’IP de sa box.  Il a lui même réalisé une solution expliquée dans son article, mais celle-ci nécessite qu’un moteur PHP tourne sur le Rasp. Bien qu’il éxiste des outils pour gérer ça de façon automatique, il peut être préférable de le faire soi même, c’est pourquoi je propose ici une autre approche, moins gourmande pour le serveur local et plus simple à mettre en place à mon goût.

Voici la configuration d'origine

La configuration d'origine

Ingrédients:

  • Un serveur chez soi (Raspberry ou autre, peu importe)
  • Un serveur web avec PHP (free.fr en fournit gracieusement, ça fait parfaitement l’affaire)
  • Une box permettant le NAT (la redirection des ports)

L'objectif final: mise à jour de l'IP et redirection automatique

L'objectif final: mise à jour de l'IP et redirection automatique

Sur la box:

Rediriger les ports auquels ont veut accéder depuis l’extérieur vers l’adresse IP locale du serveur. Je ne rentrerais pas dans les détails, on trouve de très bons tutos un peu partout pour ça.

Espace Web 1/2 :

Comment connaître l’ip de ma box/mon serveur local?

La meilleure façon de connaître l’IP de mon serveur local est encore de regarder l’adresse d’origine d’une requête allant de mon serveur local à mon espace web.

Pour différencier une requête qui provient d’un visiteur “normal” de celles servant a mettre à jour l’adresse de ma box on va utiliser des variables POST. On va même “sécuriser” ça sous la forme d’un ensemble clé-valeur pour éviter que n’importe qui puisse changer l’IP de référence.
On va ensuite stocker l’IP d’ou provient la requête valide dans un fichier texte. Pour récupérer l’ip d’origine d’une requête en PHP, on utilise la variable $_SERVER["REMOTE_ADDR"]. C’est pratique d’autant plus qu’en ouvrant le fichier avec l’attribut "w+" on ne se préoccupe même pas de l’effacer, le nouveau contenu remplacera toujours l’ancien contenu du dit fichier.

$KEY      =    "le_serveur";
$VALEUR =    "c'est moi!";
$FICHIER =    "ip.txt";

if (isset($_POST[$KEY]) && $_POST[$KEY] === $VALEUR) {
$file = fopen($FICHIER, "w+");
fwrite($file, $_SERVER["REMOTE_ADDR"]);
fclose($file);
}

Voilà pour la partie mise à jour de l’IP côté PHP. Rien de bien méchant. Chaque fois qu’une requête contenant “le serveur=c’est moi” sera envoyée sur ce fichier, le fichier “ip.txt” sera mis à jour avec l’adresse d’origine. Il ne reste plus qu’a le faire régulièrement…

Serveur personnel:

La partie la plus facile. On va demander l’envoi de l’ensemble clé-valeur vers le serveur web. Pour gérer les tâches répétitives on utilise le cron, auquel on ajoute la ligne suivante:

user$: crontab -e #edition du fichier crontab avec votre editeur par défaut

#Ajout d'une ligne pour envoyer la requête toutes les 5 minutes
*/5 * * * * curl --silent -F le_serveur="c'est moi!" http://addresse/de/mon/fichier.php

Espace Web 2/2 :

Revenons à l’espace Web. Pour l’instant, le fichier PHP permet de mettre à jour l’IP de notre auto-hébergement automatiquement, mais si un visiteur arrive sur la page, il ne se passe rien (page blanche). À mon goût, il y a deux trucs sympas a faire pour un visiteur:

  • Une redirection transparente et instantanée vers le serveur local
  • Une liste des services proposés par le serveur local

Option 1: Redirection transparente

Sur le fichier côté serveur on va tout simplement… rediriger le navigateur, d’où le titre ! Pour cela il existe une fonction PHP: header(). Sans rentrer dans les détails, celle-ci ne fonctionnera si elle est utilisée en tête de fichier. Si on veut rediriger, il est important de l’appeler le plus tôt possible. (Typiquement: avant le code HTML s’il y en a). La fonction header prends comme paramètre une chaîne de caractères. Si elle content “location: http://uneurl“, elle va nous rediriger vers une adresse du type: http://uneurl. On déclare donc deux variables en tête de fichier: $PORT et $PROTOCOL.

Port étant le port sur lequel rediriger (par défaut :80 pour le web), et le protocole a utiliser (http://, https:// …). À nouveau je ne vais pas rentrer dans les détails, le port 80 et le http couvrant la majorité des cas.

<?php
$KEY        =    "le_serveur";
$VALEUR     =    "c'est moi!";
$FICHIER    =    "ip.txt";
$PORT       =    ":80";
$PROTOCOL   =    "http://";

if (isset($_POST[$KEY]) && $_POST[$KEY] === $VALEUR) {//Mise à jour de l'ip
$file = fopen($FICHIER, "w+");
fwrite($file, $_SERVER["REMOTE_ADDR"]);
fclose($file);
}else{//Redirection du client
$addresse   =   file_get_contents($FICHIER);
$addresse   =   $PROTOCOL . $addresse . $PORT;
header("location: $addresse");
}
?>

Protip: En PHP, lorsqu’on utilise des guillements doubles, on peut mettre nos variables directement entre les guillements. (Comme dans la ligne 15)

Option 2: Liste des services

Exemple de rendu de la liste de services

Exemple de rendu de la liste de services

On peut tout à fait s’arrêter ici et faire une page d’accueil sur le serveur local, permettant de lister les services dispos. Cependant, dans certains cas, il peut être utile de faire cela directement sur le serveur distant : pour économiser les (maigres) ressources d’un Raspberry Pi par exemple, et éviter d’y faire tourner un PHP juste pour afficher une page.

Pour lister les différents services, on va faire ça “en dur” ou de façon statique, pour éviter de scanner systématiquement tous les ports de votre serveur local à chaque visite. On va donc faire une liste des différents services que procure notre serveur. Cette liste va prendre la  forme d’un tableau associatif contenant le nom du service, et le port sur lequel il est publié.

Voici un exemple pour mon serveur.

$SERVICES    =    Array(
"Pages Web"=>":80",
"Streaming Video"=>":1234",
"Interface web qBittorrent"=>":8112",
"Interface web Transmission"=>":9091"
);

On va ensuite réaliser une boucle qui parcours ce tableau pour nous réaliser une liste au format HTML qu’il nous suffira ensuite d’afficher dans le corps d’une page HTML.

$IP = file_get_contents($FICHIER);
$listeHTML = "<ul>";
foreach($SERVICES as $nom => $port){
$URL = $PROTOCOL . $IP . $port;
$listeHTML .= "<li><a href='$URL'>$nom</a></li>";
}
$listeHTML .= "</ul>";

Pour les fénants, le code de la page HTML entière:


<?php
$KEY        =    "le_serveur";
$VALEUR     =    "c'est moi!";
$FICHIER    =    "ip.txt";
$PORT       =    ":80";
$PROTOCOL   =    "http://";
$SERVICES    =    Array(
"Web"=>":80",
"Streaming"=>":1234",
"qBittorrent"=>":8112",
"Transmission"=>":9091"
);

if (isset($_POST[$KEY]) && $_POST[$KEY] === $VALEUR) {
$file = fopen($FICHIER, "w+");
fwrite($file, $_SERVER["REMOTE_ADDR"]);
fclose($file);
}else{
$IP = file_get_contents($FICHIER);
$listeHTML = "<ul>";
foreach($SERVICES as $nom => $port){
$URL = $PROTOCOL . $IP . $port;
$listeHTML .= "<li><a href='$URL'>$nom</a></li>";
}
$listeHTML .= "</ul>";
}
?>
<!DOCTYPE HTML>
<html lang="en">
<head>
<link href='http://fonts.googleapis.com/css?family=Ubuntu' rel='stylesheet' type='text/css'>
<title>Mon chouette serveur Perso!</title>
<style type="text/css" media="screen">
*{
text-align:center;
}
h1{
font-family:'Ubuntu';
}
ul{
list-style-type:none;
}
</style>
</head>

<body>
<h1>Mon chouette serveur Perso...</h1>
<p>...est à votre disposition, et fournit les services suivants:</p>
<?php echo $listeHTML;?>
</body>
</html>
Voilà, en espérant avoir été clair et que cela resserve à d’autres.
Avec la démocratisation du Raspbery Pi, ce genre de petit script peut éviter des déboires à certains d’entre vous et vous permettre de vous concentrer sur des problèmes plus intérressants.

Avec un icône dédié pour mettre sur son menu iPhone...

Avec un icône dédié pour mettre sur son menu iPhone...

Ayant enfin, après un cursus plus qu’aléatoire commencé mes études en informatique. Du coup j’ai développé par un après midi de temps libre deux pages PHP pour stocker mes ebooks en ligne, afin que mes amis lisant sur iPhone puisse se servir dans ma petite collection. C’est un tout petit truc sans ambition, mais étant donné la rareté de la documentation pour iui sur internet, cela ne fera de mal a personne.

Un simple répertoire ftp aurait suffit, mais ça n’a rien de convivial ni de pratique. Lorsque l’on utilise Stanza (l’application gratuite la plus répandue pour lire sur iPhone), cela nécessite de cliquer sur ajouter un catalogue, choisir l’option web, taper l’adresse et galérer un peu avec le zoom pour sélectionner le livre que l’ont veut télécharger.

J’ai donc été chercher du coté des librairies iui de Joe Hewitt. En l’absence de documentation j’ai vraiment fait un truc balbutiant et non fini, mais qui à le mérite de fonctionner et de faire ce que j’attends de lui.

But : lister les fichiers d’un répertoire et de ses sous répertoires et faire un lien vers ceux-ci permettant un import direct dans Stanza. Le contenu des sous répertoires apparaîtra dans une sous-liste.

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Berru2 - iPhone</title>
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
<link rel="apple-touch-icon" href="../err/iui/iui-logo-touch-icon.png" />
<meta name="apple-touch-fullscreen" content="YES" />
<style type="text/css" media="screen">@import "../err/iui/iui.css";</style>
<script type="application/x-javascript" src="../err/iui/iui.js"></script>
</head>

Dans le header on inclue les fichiers de la librairie iui préalablement installée  sur le ftp, ici dans ../err/iui. Le fichier iui.css qui permet d’utiliser les class qui donneront le look iPhone et le iui.js qui permet de faire des transitions animées entre les liens : le petit effet de glissement que l’on à lorsque l’on passe d’un menu à un sous menu dans l’iphone OS.  On donne le lien vers l’icône qui sera utilisé quand l’utilisateur crée un lien vers le site, au format PNG et en 57px par 57px.

Les fichiers .epub sont des fichiers ebooks faciles à lire sur iPhone, de plus lorsqu’un iPhone/iPod Touch à le logiciel Stanza d’installé les liens utilisant le protocole epub:// permettent de dire à l’iPhone de lancer Stanza et de commencer l’importation du fichier vers lequel le lien pointe.

<ul id="home" title="eBooks" selected="true">

<? //----Boucle d'affichage des FOLDER
$folder = "./";
$dossier = opendir($folder);
while ($Fichier = readdir($dossier)) {
if(is_dir($Fichier) && $Fichier != '.' && $Fichier != '..' ){
$nomFichier = $folder.$Fichier;
$nomFichier2 = substr(str_replace('./','',$nomFichier),0,20);
echo '<li><a href="#_'.$nomFichier2.'" target="_self">'.$nomFichier2.'</a></li></br>';

}
}
closedir($dossier);
?>

<li> <a href='#root'> Local </a></li>
</ul>

On débute le contenu de la page lui même : la classe toolbar permet d’afficher le haut de la page d’une appli iPhone, et à lui intégrer un bouton retour lorsque l’on est dans une sous liste. La première boucle en PHP permet de regarder dans le dossier actuel et d’y trouver tous les répertoires. Pour chaque répertoire trouvé, un lien relatif vers une ancre (#_nom_du_répertoire) est créé. Le tout est placé dans des balises <ul> </ul> afin d’apparaître dans une même page, la page home qui sert de page d’accueil. Remarquez la présence du lien vers l’ancre #_root appellélocal“. C’est le lien qui servira à entrer dans le sous menu qui liste les fichiers à la racine du répertoire.

<?php //Affichage du contenu EPUB des sous répertoires
$folder = "./";
$dossier = opendir($folder);
while ($Fichier = readdir($dossier)) {
if(is_dir($Fichier) && $Fichier != '.' && $Fichier != '..' ){
$nomFichier = $folder.$Fichier;
$nomFichier2 = substr(str_replace('./','',$nomFichier),0,20);
echo '<ul id="'.$nomFichier2.'" title="'.$nomFichier2.'">';
$sdossier = opendir($nomFichier.'/');
while ($sFichier = readdir($sdossier)) {
if (substr($sFichier,-4,4)== 'epub') {
$nomsFichier = $folder.$sFichier; // Attention $nomFichier != $nomsFichier
$nomRep = opendir('../');
$nomsFichier2 = str_replace('./', 'epub://berru2.free.fr/', $nomsFichier);
$nomsFichier3 = str_replace('./','',$nomsFichier);
$urlFichier = $nomFichier2.'/'.$nomsFichier3;
$urlFichierStanza = 'epub://berru2.free.fr/ebooks/'.$urlFichier;
echo '<li><a href="'.$urlFichierStanza.'" target="_self">'.str_replace('_',' ',substr($nomsFichier3,0,30)).'</a></li></br>';
}
}
echo '</ul>';

}
}
?>

<ul id="root" title="Racine">

Ici on exécute une boucle qui ouvre les sous répertoires du répertoire courant à la recherche des fichiers .epub
Tous ces fichiers seront donc listés entre deux balises <ul></ul> pour apparaître à chaque fois dans un sous menu portant le nom du répertoire dans lequel on les à trouvés.
Enfin, on remplace le protocole http:// du lien vers le fichier par le protocole epub://.

</pre>
<ul id="root" title="Racine">
<?php
//-------Boucle d'affichage des fichiers EPUB
$folder = "./";
$dossier = opendir($folder);
while ($Fichier = readdir($dossier)) {
if (substr($Fichier,-4,4)== 'epub') {
$nomFichier = $folder.$Fichier;
$nomFichier2 = str_replace('./', 'epub://berru2.free.fr/', $nomFichier);
$nomFichier3 = substr(str_replace('./','',$nomFichier),0,20);
echo '<li><a href="'.$nomFichier2.'" target="_self">'.$nomFichier3.'</a></li></br>';
}
}
closedir($dossier);
?>
</ul>

</body>

La dernière boucle parcours les fichiers du répertoire courant à la recherche des fichiers .epub. Même principe que plus haut, on remplace le protocole http:// par epub:// et on stocke tous les liens relatifs dans le sous menu appelé “Local”.

Pour finir, une petite redirection, en javascript sur ma home afin de rediriger les possesseurs d’iPhone/iPod touch vers la page que l’on viens de voir, sinon vers une page pour permettre d’uploader des fichiers .epub.


<script type="text/javascript">
if (navigator.userAgent.indexOf('iPhone') != -1)
{
if(confirm('Vous êtes sur un iPhone/iTouch, voulez vous accèder au catalogue ebook?'))
window.location="http://berru2.free.fr/ebooks/iphone.php";
}
else if (navigator.userAgent.indexOf('iPod') != -1)
{
if(confirm('Vous êtes sur un iPhone/iTouch, voulez vous accèder au catalogue ebook?'))
window.location="http://berru2.free.fr/ebooks/iphone.php";
}
</script>

Vous pourrez tester la page en vous rendant à l’adresse suivante si vous avez un iPhone : http://berru2.free.fr/

Et si vous n’avez pas d’iPhone vous pourrez essayer la page (dont la mise en forme sera proche de ce qu’on voit sur iPhone sans être identique) ici. Par contre les liens vers le ebooks ne seront du coup pas fonctionnel à moins que vous n’ayez associé un programme au protocole epub:// sur votre machine.

Si vous avez des suggestions concernant le code ou les fonctionnalités, elles sont les bienvenues, c’est toujours formateur d’avoir un retour.

L'aspect final en version iPhone.

L'aspect final en version iPhone.

Edit: Les bugs remontés par Caroline sont corrigés, et les underscore dans les menus sont désormais masqués. Le code ci dessus est mis à jour.