upload avec barre de progression

dans cet article-tuto nous allons voir comment mettre en place un système d’upload avec une sympathique barre de progression.

les pré-requis :
– un serveur web Apache
– PHP5 avec l’extension APC
jquery

dans ce tuto je pars du principe qu’Apache et PHP sont installés et fonctionnels, on va juste voir comment installer APC et activer le suivi de la progression d’upload :

apt-get install php-apc
vim /etc/php5/apache2/conf.d/apc.ini

ajouter à la fin du fichier :

apc.rfc1867 = on

cette ligne magique, activera la suivi de progression d’upload sur le serveur.

on reload apache :

/etc/init.d/apache2 reload

le coté système de la chose est maintenant terminé, passons à l’upload :

pour la petite histoire, voici ce que l’on va faire :
on va créer un formulaire, qui sera validé vers (target) une iframe invisible, le temps que l’upload se passe, on va contacter un petit script php en ajax (très souvent) qui va nous dire où en est l’upload, en nous retournant le pourcentage d’avancement (tout simplement), avec cette valeur, on va pouvoir mettre en place une barre de progression très facilement.

pour commencer, le formulaire :

<?php $unique_id = uniqid(); //id unique de notre formulaire ?>
 
<!-- iframe caché en javascript dans laquelle se fait l'upload, elle affichera le message de confirmation / ou erreur à la fin de l'upload -->
<iframe frameborder="0" border="0" id="upload_to" name="upload_to" style="width: 100%; border:none; border-color: #fff;" scrolling="no"></iframe>
 
<!-- le formulaire d'upload -->
<form id="upload_form" enctype="multipart/form-data" action="upload.php" method="post" target="upload_to">
<input type="hidden" name="APC_UPLOAD_PROGRESS" id="progress_key" value="<?php echo $unique_id?>"/>
<div id="progressouter">
	<div id="progressinner"><span id="progression_percent">0&nbsp;%</span></div>
</div>
<p><input id="file" type="file" name="file" size="30" /></p>
<p><input type="submit" value="valider" /></p>
</form>

le bout de php au début, permet de donner un id unique au formulaire
il est renseigné dans le champ « APC_UPLOAD_PROGRESS » ceci permet au système de donner un id à l’upload en cours, ce qui nous permettra de consulter la progression en le connaissant (l’id).

l’iframe n’a rien de spéciale, elle est caché en javascript (voir plus bas).

le formulaire contient l’HTML de la barre de progression (la div progressouter, on pourrait la mettre ailleurs, chacun fait ce qu’il veut. et le champ hidden APC_UPLOAD_PROGRESS comme dit plus haut, obligatoire pour le suivi de l’upload.

passons maintenant à notre script d’upload : upload.php
l’upload en lui même n’est pas vraiment notre sujet du jour, donc, je prends l’exemple d’upload le plus simple au monde (donné sur php.net)

$uploaddir = '/var/www/uploads/';
$uploadfile = $uploaddir . basename($_FILES['file']['name']);
 
if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)) {
    echo "File is valid, and was successfully uploaded.\n";
} else {
    echo "Possible file upload attack!\n";
}

on aura besoin du fameux script qui retourne le pourcentage d’avancement de l’upload : progress.php

header("Cache-Control: no-cache"); //utile pour IE (problème avec l'ajax)
//progression
if(isset($_GET['progress_key'])) {
    $upload = apc_fetch('upload_'.$_GET['progress_key']);
    $percent = 1000;
    if ($upload) {
        if ($upload['done'])
            $percent = 100;
        elseif ($upload['total'] == 0)
            $percent = 0;
        else
            $percent = $upload['current'] / $upload['total'] * 100;
    }
 
    echo number_format($percent, 2);
}

c’est presque fini, il ne reste plus que le javascript :

function getProgress(){
    var count = Math.random(); /// Math.random sélectionne un nombre entre 0 et 1 ( ex: 0.6489534931546957) pour IE aussi (même si le header no-cache devrait suffire)
    $.ajax({
        type: "GET",
        url: "/progress.php?progress_key=<?php echo($unique_id)?>&count="+count,
        success: function(percent) {
            if (percent <= 100){
                $("#progressinner").css("width", percent+"%");
                $("#progression_percent").text(percent+" %");
            }
            if (percent < 100){
                setTimeout("getProgress()", 100);
            }
            if (percent == 100){
                $("#upload_to").show("slow");
                $("#file").val('');
            }
        }
    });
}
 
function startProgress(){
    $("#progressouter, #progression_percent").show(200);
    setTimeout("getProgress()", 1000);
}
 
 
$(document).ready(function(){
    $("#upload_to").hide();
    $('#upload_form').submit(function () {
        startProgress();
    });
});

en gros (très gros même) ce js va cacher l’iframe au chargement de la page, et à la validation du formulaire, il va lancer la fonction startProgress(), qui elle, va afficher la barre de progression et lancer régulièrement getProgress, qui elle, fait un appel ajax à notre script progress.php et lui indiquant l’unique id généré tout au début de la page et en fonction du retour, elle va ajuster la largeur de la barre de progression.

si vous avez des questions, n’hésitez pas à les poser dans les commentaires.

Share

Sécuriser un serveur MySQL avec iptables

quand on a plusieurs serveurs avec un mysql sur chacun, on aimerait parfois avoir un seul phpmyadmin dans lequel tous les serveurs mysql remontent, la solution est très simple, il suffit d’aller dans /etc/mysql/my.cnf et de commenter la ligne :

bind-address           = 127.0.0.1

en ajoutant un # devant.

ça s’applique aussi quand on a un seul serveur mysql accessible par plusieurs serveurs web par exemple.

en faisant cela, on vient d’autoriser les connexions au serveur depuis… partout ! (alors que par défaut il ne les accepte que depuis localhost) ce qui va nous permettre d’avoir un phpmyadmin unique pour pleins de serveurs mysql.

le problème, c’est qu’en terme de sécurité, la règle est simple, « Je ferme tout, puis j’ouvre ce dont j’ai besoin »
ici le besoin est d’ouvrir l’accès à Mysql depuis le serveur qui héberge phpmyadmin, or, avec notre modification, on vient d’ouvrir l’accès à tout le monde (encore faut-il avoir des login/password valides pour se connecter, mais vaut mieux ne pas tenter le diable^^).

pour remédier au problème, on va avoir recours au firewall, sous debain (et linux en général) c’est iptables

on va explicitement permettre l’accès à notre mysql depuis le serveur hébergeant phpmyadmin, et… le refuser à tout le reste

iptables -A INPUT -p tcp -s IP_DU_SERVEUR_PHPMYADMIN --dport 3306 -j ACCEPT
iptables -A INPUT -p tcp --dport 3306 -j DROP

et voilà, en 2 lignes c’est fait.
la première autorise le serveur qui héberge phpmyadmin, la 2ème ferme tout.

il est à noter que ces règles seront perdues si le serveur redémarre, donc, si redémarrage, il faudra les retaper, ou sinon les mettre dans un script exécuté au démarrage, comment faire ? c’est le sujet d’un prochain post :)

Share

Changer le hostname d’un serveur sous debian

ayant pris possession d’un petit kimsufi récemment je me suis dit qu’il serait bien de changer ksXXYYZZ par un hostname qui me parle un peu plus :), donc, si comme moi, un jour vous voulez changer le hostname d’un serveur, voici ce qu’il faut faire :

changer le ici mettant le nouveau hostname :

vim /etc/hostname

ensuite ouvrez le fichier hosts et AJOUTER (dans le cas du kimsufi, il faut qu’il réponde toujours au nom ksXXYYZZ donc ne remplacez pas, mais ajouter) le nouveau hostname (en face des ip locales)

vi /etc/hosts

ce qui donne (par exemple):

127.0.0.1       localhost.localdomain localhost
WW.XX.YY.YY     ksXXYYZZ.kimsufi.com monNouveauHostname

rendre la modification effective :

/etc/init.d/hostname.sh start

et c’est tout :), il faut se déconnecter/reconnecter pour voir le changement.

Share

installer memcached sous debian lenny

avec ce post nous allons voir la procédure pour installer memcache sur une debian lenny afin de l’utiliser avec php.

Pour commencer installer memcached :

apt-get install memcached

ensuite, installer l’extension php

pecl install memcache

si l’installation échoue avec le message suivant :

downloading memcache-2.2.6.tgz ...
Starting to download memcache-2.2.6.tgz (35,957 bytes)
..........done: 35,957 bytes
11 source files, building
running: phpize
sh: phpize: command not found
ERROR: `phpize' failed

Allez faire un tour ici : Installation de fileinfo on a déjà rencontré ce problème :)

Pour rappel, il faut faire un simple :

apt-get install php5-dev
et retenter le :
pecl install memcache

il va surement vous poser une question, appuyez sur « entrée »

maintenant que memcache est correctement installer il faut l’activer en créant un fichier memcached.ini dans le dossier conf.d utilisé par le serveur (dans mon cas pour apache c’est : /etc/php5/apache2/conf.d) pour lighttpd par exemple c’est /etc/php5/cgi/conf.d) (cela évite de modifier les php.ini)
memcached.ini doit contenir :

extension=memcache.so

pour s’assurer que l’extension est bien installée, créer un fichier php contenant :

et aller voir dedans, normalement vous devriez voir l’extension activée.

phpinfo memecache

pour l’utilisation, rien de bien méchant, la doc php (http://php.net/manual/fr/book.memcache.php) est très bien faite :)

petit bonus :
pour vérifier que le service est bien lancé, faite :

netstat -latupen |grep memcached
résultat :
tcp        0      0 127.0.0.1:11211         0.0.0.0:*               LISTEN      0          157533      5952/memcached
Share

Utiliser des paquets de différentes versions de debian

Aujourd’hui on va voir comment customiser les fichier source.list de debian afin de pouvoir installer des paquets de versions autres que la stable.

avant de commencer, il faut savoir que la version actuelle de debian (donc la version stable) est : lenny

la version qui nous intéresse est la testing ou bien squeeze (on pourrait s’intéresser à la sid (non stable) mais c’est à éviter)

pour plus d’infos sur ces versions : http://wiki.debian.org/DebianReleases

pour pouvoir installer des paquets de la squeeze sous lenny il faut éditer son fichier /etc/apt/sources.list en ajoutant :

deb http://ftp.fr.debian.org/debian squeeze main
deb http://security.debian.org/ squeeze/updates main

en gros dupliquer les lignes existantes en remplaçant lenny (ou stable) par squeeze (on pourrait ajouter non-free après main en cas de besoin ; pour installer jdk par exemple…)

maintenant notre debian est configurée pour aller chercher ces paquets dans la branche squeeze, cool, mais c’est un peu la cata quand même :-) en fait, on ne veut prendre dans squeeze que certains paquets, et par défaut on voudrait garder lenny quand même, pour cela il faut tout simplement le dire à la machine :

on édite le fichier /etc/apt/apt.conf (le créer si non existant)
on met dedans la ligne suivante :

APT::Default-Release "stable";

et maintenant un simple apt-get install va aller chercher les paquets au bon endroit (c’est à dire : lenny)

et si on veut installer un paquet de squeeze, on fait :

apt-get install --target-release squeeze MON-SUPPER-PAQUET-DE-SQUEEZE

et le tour est joué :)

à l’heure actuelle lenny est la version stable, le jour où la stable change, il suffira d’adapter un peu tout ça.

Share