<?php
################################################################################
# GraphViz Site Map Generator
# Author: Michael Angeles (http://urlgreyhot.com/)
# Copyright (c) 2002-2003, Michael Angeles
# http://urlgreyhot.com/graphviz/
#
# This script sends UNIX shell commands to graphviz in order to generate
# site maps from tab-delimmited files. To get this to work, you will need
# to have GraphViz (dot, neato) installed on your server. For details about
# AT&T Labs' GraphViz application, see http://graphviz.org
#
# I'd be happy to know if you are able to use this script somewhere. Send me
# email (michael@studioid.com) if you do. 
#
# GraphViz Site Map Generator comes with ABSOLUTELY NO WARRANTY.
# This is free software, and you are welcome to redistribute it
# under certain conditions. See http://urlgreyhot.com/graphviz/LICENSE 
# for details.
###############################################################################

################################################################################
# INSTALLATION
################################################################################

# 1. Download and install the GraphViz application. See: 
# http://www.research.att.com/sw/tools/graphviz/download.html
# 2. Install/download True Type fonts to be used by GraphViz.
# 3. Create directories on server for index.php script and 
# input/output files
#  Directories to create:
#  [path to script]/
#  [path to script]/input/
#  [path to script]/output/
# 4. Change the sub-directory permissions for input/ and output/ to 0775
# 5. Modify configuration values to reflect your directory set up.
# 6. Access the index.php script from your server.


################################################################################
# CONFIGURATION
################################################################################

# include sanitizing script
require('/usr/www/users/jibjab/php/sanitize.php');

# 1. The 2 following variables refer to the SAME directory where your script
# is located/installed
# 1a. Server path (without trailing slash)
$base "/usr/www/users/jibjab/graphviz";
# 1b. URL (without trailing slash)
$baseurl "http://urlgreyhot.com/graphviz";

# 2. Directory where the input files should be saved
$filedir "/usr/www/users/jibjab/graphviz/input";

# 3. Location of dot executable
$dotbase "/usr/home/jibjab/apps/bin";

# 4. Location of true type fonts
$fontbase "/usr/home/jibjab/fonts";

# You shouldn't need to modify anything below this line
$vers "0.5.3";
$self $PHP_SELF;
import_request_variables('GPC'); 

// header and footer
function page_header() {
  echo 
'<html>
  <style type="text/css" media="Screen">
    @import "all.css";
  </style>
  <body>
  '
;
}

function 
page_footer() {
  global 
$baseurl;
  global 
$vers;
  echo 
"
  <div id=\"Footer\"><p><a href=\"http://urlgreyhot.com\">UrlGreyHot</a> | <a href=\"$baseurl\">GraphViz Sitemap Generator</a></p></div>
  </body></html>"
;
}

################################################################################
# do stuff
################################################################################

page_header();
  global 
$baseurl;
  global 
$filedir;

// execute modules
if ($q) {
  
$a1 sanitize($a1,SYSTEM);
  
$a2 sanitize($a2,SYSTEM);
  
$a3 sanitize($a3,SYSTEM);
  
$mod sanitize($q,SYSTEM);
  
module_invoke($mod$a1$a2$a3);
} else {

// show the submit form
  
if(!$submit=="Submit"){

print <<< END
  <h1>GraphViz Site Map Generator</h1>
  <div id="ColTwo">
<p><b>About this application</b><br />This web application accepts uploaded tab delimmited text files and converts them into clickable site maps using the <a href="http://www.research.att.com/sw/tools/graphviz/">GraphViz</a> application. The application was created to demonstrate how GraphViz can be used as a tool for Information Architecture work.</p>
<p><b>Getting started</b><br />
To get started you will have to <a href="$baseurl/help.php">prepare your upload file</a>. </p>
<p>If you're interested in seeing the output of this application, take a look at the <a href="$baseurl/help.php">demo diagrams</a>.</p>
<p>NOTE: Because of the memory limitation on this shared server, presently this demonstration can only render GIFs for files containing about 438 lines, although SVGs should be generated above that limit. Remember that this is a demonstration and that your mileage will vary. Better results can be expected on your system.</p>
<p><b>Download</b><br /></p>
<ul><li><a href="http://urlgreyhot.com/graphviz/index.phps">Download php script (index.phps)</a></li><li><a href="http://urlgreyhot.com/graphviz/LICENSE">LICENSE (GPL)</a></li></ul></p>
<p>Feel free to send me <a href="http://urlgreyhot.com/personal/about/contact_me">feedback</a>.</p>
  </div>
  <div id="ColOne">
<p><b style="color: red">Please note</b>. The output from the site map generator is now being expunged regularly, so you MUST SAVE YOUR WORK, including all GIFs, SVGs and .map files. Lost work is not recoverable once it has been expunged. -Michael Angeles</p>
  <form enctype="multipart/form-data" action="$PHP_SELF" method="POST">
  <fieldset>
    <legend>1. Upload your file (required)</legend>
    <label for="fname">Name your diagram</label><br />
    <small>This should be one word with no spaces. Underscores and hyphens are ok. Used to identify your diagram.</small><br />
  <input type="text" name="fname" size="25" /><br /><br />
    <label for="upload">Upload tab delimmited description file</label><br />
    <small>This is your file describing nodes in the tree. <a href="$baseurl/help.php" target="_blank">How to prepare your upload file.</a></small><br />
    <input type="file" size="25" name ="fupload" /><br />
  </fieldset>
  <br />
  <fieldset>
    <legend>2. Set graph attributes (optional)</legend>
    <label for="defaulturl">The default (root) URL for your site</label><br />
    <small>This URL is used for mis-clicks in the image map.</small><br />
    <input type="text" name="defaulturl" size="25" /><br /><br />
    <label for="layout">Layout</label><br />
      <input type="radio" name="layout" value="hierarchical" checked="checked" /> Hierarchical
     <input type="radio" name="layout" value="radial" /> Radial<br /><br />
    <label for="shape">Shape</label><br />
      <input type="radio" name="shape" value="box" checked="checked" />Box
      <input type="radio" name="shape" value="circle">Circle<br /><br />
  </fieldset>
  <br />
  <fieldset>
    <legend>3. Click and start the automagic</legend>
    <input type="submit" name="submit" value="Submit" class="butgreen" />
  </fieldset>
  </form>
  </div>
END;

  }

  
// error checking
  
elseif ( ($submit=="Submit") && (($fname=='') || ($fupload=='')) ){
    echo 
'<h1><a href=\"$baseurl\">GraphViz sitemap generator</a> / Error</h1><p class="error">The following errors were detected:</p><blockquote>';
    if (
$fname=='') {
      echo 
'<p>You need to enter a name for your diagram.</p>';
    }
    if (
$fupload=='') {
      echo 
'<p>You need to select a tab delimmited file to submit.</p>';
    }
    echo 
'</blockquote><p><a href="javascript:history.go(-1);">&laquo; Go back and try again.</a></p>';

  } else {
    
  
// process submitted form
        
        // while we have uploaded file

        
foreach( $HTTP_POST_FILES as $file_name => $file_array ) {
        
          
// process file
          
if ( 
            (
is_uploaded_file$file_array['tmp_name'] )) 
            
// && (!eregi("application", $file_array['type']))
            // && (!eregi("image", $file_array['type']))
            
&& (!eregi(" "$fname))
            )
            {

            
// move uploaded file to new location
            
move_uploaded_file$file_array['tmp_name'], "$filedir/$file_name") or die ("Couldn't copy");
            
chmod ("$filedir/$file_name"0775);
            
copy ("$filedir/$file_name""$filedir/$fname");
            
chmod ("$filedir/$fname"0775);
        
            
// now create the dot file
            
dot_create_dot_file($fname$defaulturl$shape$edge);
        
            
// create image and image map
            
dot_create_images($fname$layout); 

            
// create image and image map
            
modify_svg($fname); 

            
// link to image
            
view($fname);
          } else {
              
error("Sorry. Your diagram cannot be processed. Likely cause may be that you have a space in your project name or your file is not in ASCII (plain text) format");
          } 
// end process file
            
        
// end while we have uploaded file
        
    
// submit form
    
}
page_footer();

################################################################################
# modules
################################################################################

// invoke module $name with optional arguments:
function module_invoke($name$a1 NULL$a2 NULL$a3 NULL$a4 NULL$a5 NULL$a6 NULL) {
  
$function $name;
  if (
function_exists($function)) {
    return 
$function($a1$a2$a3$a4$a5$a6);
  } else {
    
error("Sorry. You got here by mistake.");
  }
}

// create dot files in ./input/
function dot_create_dot_file($a1 NULL$a2 NULL$a3 NULL$a4 NULL$a5 NULL$a6 NULL

  global 
$base;
  global 
$fontbase;
  
// get arguments, assign var values
  
$infilename "$base/input/$a1";  
  
$outfilename "$base/input/$a1.dot";
  
// get arguments, set defaults
  
$defaulturl $a2;
  
$shape = ($a3 == "box") ? "box" "circle";
  
$edge $a4;

  
// read uploaded file
  
$fhin fopen($infilename"r");
    
$file_contents = @fread($fhinfilesize($infilename));
    
$line explode("\n"$file_contents);
  
fclose($fhin);

  
// convert lines to dot format
  
$i 0;
  
$size sizeof($line) - 1;
  while(
$i <= $size) {
    
# split lines and assign values to fields
    
$dat explode("\t"$line[$i]);
    
$datid rtrim($dat[0]);
    
$datparent rtrim($dat[1]);
    (
$dat[2] == '') ? $datlabel addslashes(rtrim($dat[3])) : $datlabel addslashes(rtrim($dat[2]));
    
$datlabel eregi_replace ("<nl>""\\n "$datlabel); 
    
$daturl addslashes(rtrim($dat[3]));
    
$datcolor rtrim($dat[4]);
    
$datfontcolor rtrim($dat[5]);
    
$datstyle rtrim($dat[6]);
    
# output the nav links
    
if ($datid != ''){
      
$dotlines .= "  $datid [label=\"$datlabel\", URL=\"$daturl\", fillcolor=\"$datcolor\", fontcolor=\"$datfontcolor\", style=\"$datstyle\", fontsize=\"10\", fontname=\"Verdana Bold\"];\n";
    }
    if (
$datid != $datparent){
      
$dotlines .= "  $datparent -> $datid;\n";
    }              
    
$i++;
  }
  
  
// prepare dot options
  
$dotfile "digraph G {\n";
  
$dotfile .= "  URL=\"$defaulturl\";\n";
  
$dotfile .= "  fontpath=\"$fontbase\";\n";
  
$dotfile .= "  overlap=\"false\";\n";
  
$dotfile .= "  node [shape=\"$shape\",color=\"#cccccc\",fontname=\"Verdana Bold\", fontsize=\"10\",fontcolor=\"#000000\"];\n";
  
$dotfile .= "  edge [color=\"#cccccc\",arrowhead=\"none\"];\n";
  
$dotfile .= $dotlines;
  
$dotfile .= "}";

  
// write everything to the dot input file
  
$fhout fopen($outfilename'w');
  
fwrite($fhout$dotfile);
  
fclose($fhout);

  
chmod ($infilename0775);
  
chmod ($outfilename0775);
  }


// create the dot files in ./output/
function dot_create_images($a1 NULL$a2 NULL)
{
  global 
$base;
  global 
$dotbase;
  (
$a2 == 'hierarchical') ? $layout 'dot' $layout 'twopi';
  
  
// create gif and image map   
  
passthru("touch $base/output/$a1.gif");
  
passthru("touch $base/output/$a1.map");
  
passthru("cp $base/output/$a1.map $base/output/$a1.txt");
  
passthru("$dotbase/$layout -o $base/output/$a1.gif -Tgif $base/input/$a1.dot");
  
passthru("$dotbase/$layout -o $base/output/$a1.map -Timap $base/input/$a1.dot");
  
// passthru("$dotbase/$layout -Tcmap $base/input/$a1.dot > $base/output/$a1.cmap");
  
  // create svg
  
passthru("$dotbase/$layout -o $base/output/$a1.svg -Tsvg $base/input/$a1.dot");
  
/* open file, remove comment and rewrite file */
  
  //change permissions on files
  
chmod ("$base/output/$a1.gif"0775);
  
chmod ("$base/output/$a1.svg"0775);
  
chmod ("$base/output/$a1.map"0775);
}

function 
view($a1)
{
  global 
$baseurl;
  echo 
"<h1><a href=\"$baseurl\">GraphViz sitemap generator</a> / $a1</h1>
  <a href=\"$baseurl/output/$a1.map\"><img src=\"$baseurl/output/$a1.gif\" ismap=\"ismap\" border=\"0\" ></a><br /><br />
  <small>
  <b>Please note</b>. All files generated by this application are removed DAILY at midnight, Eastern Time. You must save your work locally. No files will be archived.<br /><br /> 
  GIF: <a href=\"$baseurl/output/$a1.gif\">$baseurl/output/$a1.gif</a><br />
  SVG: <a href=\"$baseurl/output/$a1.svg\">$baseurl/output/$a1.svg</a><br />
  Image Map: <a href=\"$baseurl/output/$a1.txt\">$baseurl/output/$a1.map</a><br />
  </small>"
;
}

function 
viewsitemap($a1
{
  global 
$baseurl;
  echo 
"<a href=\"$baseurl/output/$a1.map\"><img src=\"$baseurl/output/$a1.gif\" ismap=\"ismap\" border=\"0\" ></a><br /><br />";
}

// modify svg files in ./output/
function modify_svg($a1 NULL
{
  global 
$base;
  
// get arguments, assign var values
  
$infilename "$base/output/$a1.svg";
  
$outfilename $infilename;
  
  
// read uploaded file
  
$fhin fopen($infilename"r");
    
$file_contents = @fread($fhinfilesize($infilename));
     
$outfile preg_replace('/<!--(.|\s)*?-->/'''$file_contents); 
  
fclose($fhin);

  
// write everything to the dot input file
  
$fhout fopen($outfilename'w');
  
fwrite($fhout$outfile);
  
fclose($fhout);

}

// version info
function vers(){
  global 
$baseurl;
  echo 
"
  <h1><a href=\"$baseurl\">GraphViz sitemap generator</a> / Version info</h1>
  <b>0.1</b><br />
  First version released with minimal configuration options.<br />
  <br />
  <b>0.1.1</b><br />
  Fixed bug caused by single and double quotes in upload files.<br />
  <br />
  <b>0.2</b><br />
  Added layout, shape and style attributes.<br />
  <br /> 
  <b>0.3</b><br />
  Fixed bug that was producing unusable SVG output. SVG files should now work, but font size is rather large.<br />
  <br /> 
  <b>0.4</b><br />
  Added minor feature to break up labels by using a newline marker <nl> in tab delimmited file.<br />
  <br />
  <b>0.5</b><br />
  Added error recovery messages.<br />
  <br /> 
  <b>0.5.1</b><br />
  Added direct links to view a) image map, b) gif and c) sitemap without navigation links. Set SVG files with smaller fonts to make more readable. Released under GPL.<br />
  <br /> 
  <b>0.5.2</b><br />
  Added some installation documentation and import_request_variables('GPC'); per Gilbert Grosdidier's suggestion.<br />
  <br /> 
  <b>0.5.3</b><br />
  Fixed bug when using tab character instead of \t in replacement string.<br />
  <br />
  "
;
}

// error messages
function error($msg) {
  echo 
"<h1>Error</h1><p>$msg</p>";
}

################################################################################
?>