Support Forums

Full Version: SMF Modification Parser
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
This neat little script uses SAX and PHP's Zip extension to parse either a single XML file or a packaged zip archive. This script looks for elements used only by SMF and displays their instructions. Think of it as how its done on SMF's mod site. Since I am nice guy I thought I would release the c0dez. So, where you place the parseXML.php, be sure to create a directory named zip. Or you can edit the script as you like. The zip directory stores uploaded xml files. Why didnt I just use PHP's temp directory? Because it spits out errors when trying to extract and retrieve the extracted xml files. Instead, if you can, head into your php.ini file and change the upload_tmp_dir setting. Smile

See it in action,
http://smf.projectevolution.net76.net/smfparse/

index.php

Code:
<?php
// Upload XML stuff here
echo '<fieldset style="width: 50%;">
<form action="parseXML.php" method="post" enctype="multipart/form-data">
  <legend>Upload XML or zip file</legend>
  File Location: <input type="file" name="file" /><br />
  <b style="font-size: 10pt;">zip archive or XML file only</b><br /><br />
  <input type="submit" name="submit" value="Submit" />
</form>
</fieldset>';
?>

parseXML.php

Code:
<?php
// set this for ZIP archives
//@ini_set('upload_tmp_dir', 'PATH TO ZIP DIR');
$filename = $_FILES['file']['name'];
// rely on file extensions rather than MIME types
if (substr($filename, -4) == '.zip') {
$file_ext = 'zip';
} elseif (substr($filename, -4) == '.xml') {
$file_ext = 'xml';
} else {
// kill the script if the uploaded file wasnt a zip archive or xml file
die('Invalid upload!');
}
// make sure the uploaded file is the one we retrieved from the form
if (!is_uploaded_file($_FILES['file']['tmp_name']))
die('Possible hacking attempt...');
// an array containing SMF-specific elements
$valid_elements = array('id', 'version', 'type', 'file', 'operation', 'search', 'add');
$current_element = '';
// handle each element along with its attributes
function startElementHandler($parser, $name, $attributes) {
global $valid_elements, $current_element;

$current_element = strtolower($name);
if (!checkValidElements())
  return;
switch($current_element) {
  case 'id':
   echo 'Modification id: ';
   break;
  case 'version':
   echo 'File version: ';
   break;
  case 'type':
   echo 'Type: ';
   break;
  case 'file':
   echo '<hr />In file: ';
         while (list($key, $value) = each($attributes)) {
          if ($key == "NAME") {
            echo '<b>' . $value . '</b>';
           } elseif ($key == "ERROR") {
            echo ' (skip on error)';
           }
         }
         echo '<br />';
   break;
  case 'operation':
   break;
  case 'search':
   echo 'Search for ';
         while (list($key, $value) = each($attributes)) {
          if ($key == "POSITION") {
            echo ' (' . $value . ')';
           }
         }
         echo ':<pre>';
   break;
  case 'add':
   echo 'Then add:<pre>';
   break;
}
}
// handle each ending element
function endElementHandler($parser, $name) {
global $current_element;
if (!checkValidElements())
  return;

switch($current_element) {
  case 'id':
  case 'version':
   echo '<br />';
   break;
  case 'add':
  case 'search':
   echo '</pre>';
   break;
  default:
   break;
}
       $current_element = '';
}
// handle character data between element tags
function characterDataHandler($parser, $cdata) {
global $valid_elements;
if (!checkValidElements())
  return;

echo '<i>' . htmlspecialchars($cdata) . '</i>';
}
function checkValidElements() {
global $valid_elements, $current_element;
for ($i = 0; $i < count($valid_elements); $i++)
  if ($valid_elements[$i] == $current_element)
   return true;
return false;
}

// creates xml parser for uploaded file and sets callback functions
$xml_files = array();
if ($file_ext == 'zip') {
$zip_archive = new ZipArchive();
$zip_archive->open($_FILES['file']['tmp_name']);
$zip_archive->extractTo(getcwd() . '/zip');
for ($i = 0; $i < $zip_archive->numFiles; $i++) {
  $file = $zip_archive->statIndex($i);
  if (substr($file['name'], -4) == '.xml')
       $xml_files[] = array(
    'name' => $file['name'],
    'path' => getcwd() . '/zip/' . $file['name']
   );
}
$zip_archive->close();
} else {
$xml_files[] = array(
  'name' => $_FILES['file']['name'],
  'path' => $_FILES['file']['tmp_name']
);
}
for ($i = 0; $i < count($xml_files); $i++) {
$xml_parser = xml_parser_create();
xml_set_element_handler($xml_parser, "startElementHandler", "endElementHandler");  
xml_set_character_data_handler($xml_parser, "characterDataHandler");
if (!($fp = fopen($xml_files[$i]['path'], "r"))) {
        die("File I/O error: " . $xml_files[$i]);
}
echo '<fieldset>
<legend><b>Parsing: ' . $xml_files[$i]['name'] . '</b></legend>';
// parse each XML chunk
while ($data = fread($fp, 4096)) {
      if (!xml_parse($xml_parser, $data, feof($fp))) {
            die("XML parser error: " .
xml_error_string(xml_get_error_code($xml_parser)));
      }
}
echo '</fieldset>';
}
// free parser memory
xml_parser_free($xml_parser);
?>