<h2>But de ce document</h2>
<p class="spip">Ce document contient un programme PHP permettant de sauvegarder et dupliquer sur un serveur local l’ensemble des fichiers d’un site distant.</p>

<p class="spip">Le but final étant de dupliquer un site sous Spip ou un Wikini ou tout autre programme en PHP+MySQL d’un serveur distant sur un serveur local sans aucune intervention manuelle. Pour cela, j’utilise un autre programme en complément de celui-ci pour sauvegarder la base de données MySQL.</p>

<h2>Description des fonctionnalités du programme</h2>
<p class="spip">Ce programme permet via FTP de sauvegarder toute l’architecture du site et donc de faire une sauvegarde récursive de tous les répertoires.</p>

<p class="spip">L’architecture des répertoires distants est reconstituée en local.</p>

<p class="spip">Dans le but d’optimiser le temps de téléchargement, le programme ne télécharge les fichiers que ci ceux-ci sont plus récents que les fichiers en local.</p>

<p class="spip">Il est possible également d’indiquer une taille maxi des fichiers à télécharger (Par défaut 1024 Ko).</p>

<p class="spip">Il est possible également d’indiquer une liste de dossiers à exclure du téléchargement.</p>

<p class="spip">Ce programme tient compte de la date de modifications des fichiers et ne télécharge les fichiers que si ceux-ci sont plus récents que les fichiers présents en local.</p>

<h2>Le programme</h2>
<p class="spip">Pour faire fonctionner ce programme, il faut renseigner le nom du serveur, l’utilisateur, le mot de passe, le dossier local de destination, le dossier distant à sauvegarder et la taille maxi des fichiers à télécharger.</p>

<p class="spip">Il est possible d’indiquer dans la variable « $Exclure_Dossier » la liste des dossiers à exclure du téléchargement.</p>

<p class="spip">Ce programme se lance sur le poste local directement en ligne de commande.</p>

<div style='text-align: left;' class='spip_code' dir='ltr'><code><br />
<br />
#!/usr/bin/php<br />
<br />
<?php<br />
<br />
        $Serveur="ftp.coagul.org";<br />
<br />
        $Login="MON_LOGIN";<br />
<br />
        $MotDePasse="MON-PASS";<br />
<br />
        <br />
<br />
        $DossierLocal="/var/www/coagul";<br />
<br />
        $DossierDistant="html";<br />
<br />
        $TailleMaxi=1024; // Taille maxi en Ko à télécharger<br />
<br />
        <br />
<br />
        //** Liste des dossiers distant à exclure du téléchargement ***<br />
<br />
        $Exclure_Dossier=array(<br />
<br />
                "html/CACHE");<br />
<br />
        //*************************************************************<br />
<br />
<br />
<br />
        echo "Sauvegarde débuté à ".date("G:i:s")."\n\n";<br />
<br />
        <br />
<br />
        chdir($DossierLocal); //Change le répertoire de destination des fichiers<br />
<br />
        <br />
<br />
        $Connexion=ftp_connect($Serveur)<br />
<br />
                or die ("Serveur $Serveur non disponible ! \n");<br />
<br />
        <br />
<br />
        ftp_login($Connexion, $Login, $MotDePasse)<br />
<br />
                or die ("Utilisateur $Login ou mot de passe inconnu ! \n");<br />
<br />
        <br />
<br />
        //ftp_chdir($Connexion, $DossierDistant);<br />
<br />
        $ftpclose=ftp_close ($Connexion);        <br />
<br />
        $ListFich = scan_ftp($Serveur , $Login , $MotDePasse , $DossierDistant , $depth=-1, $TailleMaxi, $Exclure_Dossier);<br />
<br />
        //$ftpclose=ftp_close ($Connexion);        <br />
<br />
<br />
<br />
        echo "Sauvegarde terminée à ".date("G:i:s")."\n\n";<br />
<br />
        <br />
<br />
        <br />
<br />
function scan_ftp($host , $login , $pass , $path="/" , $depth=-1, $TailleMaxi, $Exclure_Dossier) {<br />
<br />
<br />
<br />
        //echo "\n\n\n $path \n\n\n";<br />
<br />
        if (in_array($path,$Exclure_Dossier)==TRUE) {<br />
<br />
                echo "ATTENTION : Dossier $path exclu ! \n";<br />
<br />
        }<br />
<br />
        else {<br />
<br />
                <br />
<br />
<br />
<br />
                if (is_string($host)){<br />
<br />
                <br />
<br />
                        $conn_id = ftp_connect($host);<br />
<br />
                        $login_result = ftp_login($conn_id, $login, $pass);<br />
<br />
                        if ((!$conn_id) || (!$login_result)) {<br />
<br />
                                echo "Impossible de se connecter à $host sous $login ! \n";<br />
<br />
                                return array();<br />
<br />
                        }<br />
<br />
                } <br />
<br />
                else {<br />
<br />
                        $conn_id = $host;<br />
<br />
                }<br />
<br />
                <br />
<br />
                $retour = array();<br />
<br />
                $fichiers = ftp_rawlist($conn_id, $path);<br />
<br />
                foreach($fichiers as $fichier){<br />
<br />
                <br />
<br />
                        $details = preg_split("/\s+/", $fichier);<br />
<br />
                        // si la premiere lettre est un d, c'est un dossier<br />
<br />
                        if (substr($details[0],0,1) == "d"){<br />
<br />
                                // le nom du fichier est en neuvieme position<br />
<br />
                                if ($depth == 0){<br />
<br />
                                        $retour[$details[8]] = array("Dossier non scanne");<br />
<br />
                                } else {<br />
<br />
                                        $DossierDest=$details[8];<br />
<br />
                                        echo "\nTraitement du dossier $DossierDest \n";<br />
<br />
                                        if (file_exists($DossierDest)==FALSE) mkdir ($DossierDest, 0700);<br />
<br />
                                        chdir($DossierDest); //Change le répertoire de destination des fichiers<br />
<br />
                                        $retour[$details[8]] = scan_ftp($conn_id, "", "", $path."/".$details[8], $depth -1, $TailleMaxi, $Exclure_Dossier);<br />
<br />
                                }<br />
<br />
                        } else {<br />
<br />
                                $LeFichier=$details[8];<br />
<br />
                                $retour[] = $LeFichier;        <br />
<br />
                                $TailleFichier=round(ftp_size($conn_id, "$path/$LeFichier")/1024);<br />
<br />
                                $DateDistant = ftp_mdtm($conn_id, "$path/$LeFichier");<br />
<br />
                                <br />
<br />
                                if (file_exists($LeFichier)) $DateLocal=filemtime($LeFichier); else $DateLocal=0;<br />
<br />
                                //$TOTO=filemtime($LeFichier);<br />
<br />
                                //echo getcwd()." $TOTO \n ";  //Affiche le répertoire en cours<br />
<br />
                                //echo "$TOTO \n";<br />
<br />
                                <br />
<br />
                                if ($DateDistant>$DateLocal) {<br />
<br />
                                        if ($TailleFichier<=$TailleMaxi) {<br />
<br />
                                                echo "-> $LeFichier ($TailleFichier $Kp) " . date("F d Y H:i:s.", $DateDistant)." <-> ".date("F d Y H:i:s.", $DateLocal)." \n";<br />
<br />
                                                ftp_get ($conn_id, "file.tmp", "$path/$LeFichier", FTP_BINARY);<br />
<br />
                                                rename("file.tmp", $LeFichier);<br />
<br />
                                                touch($LeFichier, $DateDistant); // Permet de changer la date de modification du fichier<br />
<br />
                                        }<br />
<br />
                                        else {<br />
<br />
                                                echo "-> ATTENTION : $LeFichier de $TailleFichier Ko non téléchargé car supérieur à $TailleMaxi Ko \n";<br />
<br />
                                        }<br />
<br />
                                }<br />
<br />
                                <br />
<br />
                        }<br />
<br />
                }<br />
<br />
        }<br />
<br />
        chdir("..");<br />
<br />
        return $retour;<br />
<br />
}        <br />
<br />
?><br />
<br />
</code></div>
<h2>Modifier les fichiers de configuration des programmes en local </h2>
<p class="spip">Pour fonctionner, un programme en PHP, a besoins de plusieurs paramètres pour se connecter à la base de données MySQL.</p>

<p class="spip">Chaque programme PHP+MySQL dispose donc d’un fichier de configuration spécial qu’il est nécessaire de modifier manuellement au moins lors de la première duplication pour pouvoir fonctionner en local. Normalement, lors des duplications suivantes, cette étape ne sera pas nécessaire, car le fichier local sera plus récent que le fichier distant et ne sera donc pas remplacé par le script de duplication.</p>

<h3>SPIP ->   ecrire/inc_connect.php3</h3>
<p class="spip">Pour faire fonctionner Spip en local, il faut supprimer (ou renommer) le fichier « ecrire/inc_connect.php3 » et écrire l’url suivant dans un navigateur et répondre aux questions posées :</p>

<p class="spip"><code class='spip_code' dir='ltr'>http://localhost/Dossier_Du_Site_Spip/ecrire/</code></p>

<p class="spip">Il faut aller ensuite dans « Administration du site » et renseigner la zone « Adresse (URL) du site public »</p>

<h3>WIKINI ->  wakka.config.php</h3>
<p class="spip">Pour faire fonctionner un Wikini, il faut modifier manuellement le fichier « wakka.config.php »</p>

<h3>PhpMyAdmin -> config.inc.php</h3>
<p class="spip">Pour faire fonctionner PhpMyAdmin, il faut modifier manuellement le fichier « config.inc.php »</p>

<h2>Historique des modifications</h2>
<table class="spip">
<thead><tr class='row_first'><th scope='col'><strong class="spip">Version</strong></th><th scope='col'><strong class="spip">Date</strong></th><th scope='col'><strong class="spip">Commentaire</strong></th></tr></thead>
<tbody>
<tr class="row_even"><td>0.1</td><td>04/05/05</td><td>Création par Tony GALMICHE</td></tr>
<tr class="row_odd"><td> </td><td> </td><td> </td></tr>
</tbody>
</table>