Search code examples
phpxmlscandir

PHP : list files in directory and sub-directories into an XML file


[EDIT : fixed typos and updated script]

Hello,

I'm trying to list files stored on a remote server and store that list into an XML file, which will be used in a software updater. For this, I wrote a recursive function which, for each file, calls another function that write all necessary information (file name, md5 hash and path).

However, it seems it's only listing the first set of sub-directories when I need the function to go to the bottom of the file tree.

Here is the code that I use, if somebody can tell me what I'm missing ?

<?php

error_reporting(E_ALL);
ini_set('display_errors', 1);

function writeXml($pathInfo)
{
    if(!file_exists("file_listing.xml"))
            {
                //XML creation
                $dom = new DomDocument("1.0", "ISO-8859-15");
                $dom->preserveWhiteSpace = false;
                $dom->formatOutput = true;

                $root = $dom->createElement("FileList");
                $dom->appendChild($root);

                echo "Treating ".$pathInfo['basename']." in ".$pathInfo['dirname']."<br>";
                $xmlNodeFile = $dom->createElement("Name");
                $xmlNodeFileText = $dom->createTextNode($pathInfo['basename']);
                $root->appendChild($xmlNodeFile);
                $xmlNodeFile->appendChild($xmlNodeFileText);

                $xmlPath = $dom->createElement("Path");
                $xmlPathText = $dom->createTextNode($pathInfo['dirname'].DIRECTORY_SEPARATOR.$pathInfo['basename']);
                $xmlNodeFile->appendChild($xmlPath);
                $xmlPath->appendChild($xmlPathText);
                echo "----Directory : ".$pathInfo['dirname']."<br>";

                $xmlMd5 = $dom->createElement("MD5");
                $fileMd5 = md5_file($pathInfo['dirname'].DIRECTORY_SEPARATOR.$pathInfo['basename']);
                $xmlMd5Text = $dom->createTextNode($fileMd5);
                $xmlNodeFile->appendChild($xmlMd5);
                $xmlMd5->appendChild($xmlMd5Text);
                echo "----MD5 : ".$fileMd5."<br>";

                $xmlSha1 = $dom->createElement("SHA1");
                $fileSha1 = sha1_file($pathInfo['dirname'].DIRECTORY_SEPARATOR.$pathInfo['basename']);
                $xmlSha1Text = $dom->createTextNode($fileSha1);
                $xmlNodeFile->appendChild($xmlSha1);
                $xmlSha1->appendChild($xmlSha1Text);
                echo "----SHA1 : ".$fileSha1."<br>";

                $dom->save('file_listing.xml');
                echo $pathInfo['basename']." written. <br><br>";
            }
            elseif(file_exists("file_listing.xml"))
            {
                //XML loading
                $dom = new DomDocument();
                $dom->preserveWhiteSpace = false;
                $dom->formatOutput = true;
                $dom->load("file_listing.xml", LIBXML_PARSEHUGE);

                $root = $dom->documentElement;

                echo "Treating ".$pathInfo['basename']." in ".$pathInfo['dirname']."<br>";
                $xmlNodeFile = $dom->createElement("Name");
                $xmlNodeFileText = $dom->createTextNode($pathInfo['basename']);
                $root->appendChild($xmlNodeFile);
                $xmlNodeFile->appendChild($xmlNodeFileText);

                $xmlPath = $dom->createElement("Path");
                $xmlPathText = $dom->createTextNode($pathInfo['dirname'].DIRECTORY_SEPARATOR.$pathInfo['basename']);
                $xmlNodeFile->appendChild($xmlPath);
                $xmlPath->appendChild($xmlPathText);
                echo "----Directory : ".$pathInfo['dirname']."<br>";

                $xmlMd5 = $dom->createElement("MD5");
                $fileMd5 = md5_file($pathInfo['dirname'].DIRECTORY_SEPARATOR.$pathInfo['basename']);
                $xmlMd5Text = $dom->createTextNode($fileMd5);
                $xmlNodeFile->appendChild($xmlMd5);
                $xmlMd5->appendChild($xmlMd5Text);
                echo "----MD5 : ".$fileMd5."<br>";

                $xmlSha1 = $dom->createElement("SHA1");
                $fileSha1 = sha1_file($pathInfo['dirname'].DIRECTORY_SEPARATOR.$pathInfo['basename']);
                $xmlSha1Text = $dom->createTextNode($fileSha1);
                $xmlNodeFile->appendChild($xmlSha1);
                $xmlSha1->appendChild($xmlSha1Text);
                echo "----SHA1 : ".$fileSha1."<br>";

                $dom->save('file_listing.xml');
                echo $pathInfo['basename']." written. <br><br>";
            }

} //endof writeXml function


function scanRecursToXml($dirToScan = '.') //scandir recursive function
{
    //echo "Reading in ".$dirToScan.DIRECTORY_SEPARATOR."<br>";

    $dir = opendir($dirToScan);

    while(false !== ($file = readdir($dir)))
    {   
        //Skip '.' and '..'
        if($file == '.' || $file == '..')
        {
            continue;
        }

        $followUp = $dirToScan.DIRECTORY_SEPARATOR.$file;

        if(!is_dir($file) && $file != 'index.php' && $file !='file_listing.php' && $file !='file_listing.xml')
        {
            echo "Listing ".$file." in ".$dirToScan."<br>";

            $filePathInfos = realpath($followUp);
            writeXml(pathinfo($filePathInfos));        

        }
        elseif (is_dir($followUp))
        {
                scanRecursToXml($followUp);
        }

    }
    closedir($dir);
}   //endof scanRecurs function

//We start the process with a scanRecurs()
$localDir = '.';
scanRecursToXml($localDir);

//In the end, we check the presence of the XML file
if(file_exists('file_listing.xml'))
{
    echo "Done";
}
else
{
    echo "Something went wrong :s";
}

?>

Thank you.


Solution

  • I've tidied up a lot of the code as you were repeating some things, I've also reduced it so that the document is created/opened in the first level of the scanRecurs function...

    function writeXml(&$node, $pathInfo)
    {
        $dom = $node->ownerDocument;
        $file = $dom->createElement("File");
        $node->appendChild($file);
    
    //     echo "Treating ".$pathInfo['basename']." in ".$pathInfo['dirname']."<br>";
        $xmlNodeFile = $dom->createElement("Name", $pathInfo['basename']);
        $file->appendCHild($xmlNodeFile);
    
        $xmlPath = $dom->createElement("Path", $pathInfo['dirname'].DIRECTORY_SEPARATOR.$pathInfo['basename']);
        $file->appendChild($xmlPath);
    //     echo "----Directory : ".$pathInfo['dirname']."<br>";
    
        $fileMd5 = md5_file($pathInfo['dirname'].DIRECTORY_SEPARATOR.$pathInfo['basename']);
        $xmlMd5 = $dom->createElement("MD5", $fileMd5);
        $file->appendChild($xmlMd5);
    //     echo "----MD5 : ".$fileMd5."<br>";
    
        $fileSha1 = sha1_file($pathInfo['dirname'].DIRECTORY_SEPARATOR.$pathInfo['basename']);
        $xmlSha1 = $dom->createElement("SHA1", $fileSha1);
        $file->appendChild($xmlSha1);
    //     echo "----SHA1 : ".$fileSha1."<br>";
    
    } //endof writeXml function
    
    
    function scanRecursToXml($dirToScan = '.', $rootNode = null) //scandir recursive function
    {
        $newFile = false;
        if ( $rootNode == null )
        {
            $newFile = true;
            $dom = new DomDocument();
            $dom->preserveWhiteSpace = false;
            $dom->formatOutput = true;
            if(!file_exists("file_listing.xml"))
            {
                //XML creation
                $rootNode = $dom->createElement("FileList");
                $dom->appendChild($rootNode);
                echo "Creating".PHP_EOL;
            }
            else    {
                //XML loading
                $dom->load("file_listing.xml", LIBXML_PARSEHUGE);
                $rootNode = $dom->documentElement;
                echo "Loading".PHP_EOL;
            }
        }
        $dir = opendir($dirToScan);
        while(false !== ($file = readdir($dir)))
        {
            //Skip '.' and '..'
            if($file == '.' || $file == '..')
            {
                continue;
            }
    
            $followUp = $dirToScan.DIRECTORY_SEPARATOR.$file;
    
            echo $followUp.PHP_EOL;
            if(!is_dir($followUp) && $followUp != 'index.php' && $followUp !='file_listing.php' && $followUp !='file_listing.xml')
            {
                echo "Listing ".$followUp." in ".$dirToScan."<br>";
    
                $filePathInfos = realpath($followUp);
                writeXml($rootNode, pathinfo($filePathInfos));
    
            }
            elseif (is_dir($followUp))
            {
                scanRecursToXml($followUp, $rootNode);
            }
    
        }
        closedir($dir);
        if ( $newFile )    {
            echo "Saving";
            $dom->save('file_listing.xml');
        }
    }   //endof scanRecurs function
    
    //We start the process with a scanRecurs()
    $localDir = '.';
    scanRecursToXml($localDir);
    
    //In the end, we check the presence of the XML file
    if(file_exists('file_listing.xml'))
    {
        echo "Done";
    }
    else
    {
        echo "Something went wrong :s";
    }