<?php
/**
 * Rage randomizer
 * (c) 2010 Ian McCall, Chad Maron
 *
 * Current file format (in horrible pseudo regex):
 *   fu([0-9]+)_[nsfw].(jpeg|jpg|gif)
 *   Examples:
 *    - fu07.gif: Could be not safe for work, could be puppies, no one knows
 *    - fu69_1.jpg: Not safe for work. Think of the children!
 *    - fu14_0.gif: Safe for work. Show your boss!
 */

// This is a convenient but potentially inefficient way to specify which GET variable goes where. Storing
// them here means we can easily change or re-arrange them later. If this is slow, we can duplicate the loops
// below.
$get_frame_bindings   = array(  'fffff' => array('frame' => 1),
                                'fuuuu' => array('frame' => 2),
                                'uuuuu' => array('frame' => 3),
                                'uuu'   => array('frame' => 4));

// Some variables we can change if we want to rename directories and such

// Base path for frame directories.
$base_frame_name = str_replace('//','/',$_SERVER['DOCUMENT_ROOT'] . '/frame');

// What file extensions will we allow?
$file_extensions = array('.jpeg','.jpg','.gif','.png');

// Image to show if we have an error somewhere. THIS MUST BE A GIF!
$error_image = '/error.gif';

// Tag image when saving
$tag_image   = '/tag.gif';

/*
// Cache directory for combined images
$cache_dir  = '/tmp/ragecache/';
if ( !is_dir($cache_dir) ) {
    if ( !mkdir($cache_dir, 0755, true) ) {
        // Error!
    }
}
*/
$frame_data       = array();

// Look for any options for images (NSFW, true random, etc)
$nsfw = false;
if ( isset($_REQUEST['nsfw']) ) {
    $nsfw = true;
}

$anyframe = false;
if ( isset($_REQUEST['anyframe']) ) {
    $anyframe = true;
}

$saving = false;
if ( isset($_REQUEST['save']) ) {
    $saving = true;
}

// Sanitize the GET values to help prevent attacks. We don't want to feed something potentially malicious to
// glob (even though it's somewhat safe), so we remove anything that's not what we expect.
foreach ( $get_frame_bindings as $variable_name => $data ) {
    // 'Save' checkbox
    if ( isset($_REQUEST['save_' . $variable_name]) ) {
        if ( !isset($frame_data[$variable_name]) ) {
            $frame_data[$variable_name] = array();
        }
        $frame_data[$variable_name]['save'] = true;

        // Do we have file data as well?
        if ( isset($_REQUEST['data_' . $variable_name]) ) {
            // Yes we do! Check it.
            list($file, $frame) = check_file_data($data['frame'],$_REQUEST['data_' . $variable_name]);
            if ( $file !== false ) {
                $frame_data[$variable_name]['file']      = $file;
                $frame_data[$variable_name]['src_frame'] = $frame;
                $frame_data[$variable_name]['frame']     = $data['frame'];
            } else {
                // Cleanup
                unset($frame_data[$variable_name]);
            }
        } else {
            // No. Pretend we never tried this
            unset($frame_data[$variable_name]);
        }
    }

    // Files in the GET. They take priority.
    if ( isset($_GET[$variable_name]) ) {
        // Check our file
        list($file, $frame) = check_file_data($data['frame'],$_GET[$variable_name]);
        if ( $file !== false ) {
            $frame_data[$variable_name] = array('file' => $file, 'src_frame' => $frame, 'frame' => $data['frame'], 'save' => false);
        }
    }
}

// If we do not have an image for a given frame, find one based on the current options. Also store some more file data
foreach ( $get_frame_bindings as $variable_name => $data ) {
    if ( !isset($frame_data[$variable_name]) ) {
        list($file, $frame) = find_image_file($data['frame']);
        $frame_data[$variable_name] = array('file' => $file , 'src_frame' => $frame, 'frame' => $data['frame'], 'save' => false);
    }
    // Find the image sizes
    if ( function_exists('getimagesize') ) {
        $width = $height = 0;
        // Oh man... this is gross
        if ( ('/' . basename($frame_data[$variable_name]['file'])) == $error_image ) {
            list($width, $height) = getimagesize( $_SERVER['DOCUMENT_ROOT'] . $error_image );
        } else {
            list($width, $height) = getimagesize(str_replace('frame/frame','frame', str_replace('//','/',$base_frame_name . $frame_data[$variable_name]['file'])) );
        }
        $frame_data[$variable_name]['size'] = array('width' => $width, 'height' => $height);
    }
}

// Sort the frames to maintain order
$frame_data = sortArrayByArray($frame_data, array_keys($get_frame_bindings));

// Generate a link for this set
$url_data = array();
foreach ( $frame_data as $variable_name => $data ) {
    $frame_data[$variable_name]['url_file'] = $data['src_frame'] . '_' . str_replace('fu','',str_replace($file_extensions,'',basename($data['file'])));
    $url_data[] = $variable_name . '=' . $frame_data[$variable_name]['url_file'];
}
$url = join('&', $url_data) . ($nsfw?'&nsfw=1':'');
$save_url = $url . '&save=1';

// Are we saving the image?
if ( $saving && function_exists('imagecreate') )  {
    // Some shortcuts for MIME types
    $image_types = array('gif'     => IMAGETYPE_GIF,
                         'jpg'     => IMAGETYPE_JPEG,
                         'jpeg'    => IMAGETYPE_JPEG,
                         'png'     => IMAGETYPE_PNG);

/*
    // Before we do anything, see if we have a cache file on disk
    $cache_file_data = array();
    foreach ( $frame_data as $variable_name => $data ) {
        $cache_file_data[] = $data['url_file'];
    }
    $cache_file = join('f',$cache_file_data) . '.gif';

    $cache_file = $cache_dir . $cache_file;
    if ( is_file($cache_file) ) {
        header("Content-type: " . image_type_to_mime_type($image_types['gif']));
        header('Content-Disposition: attachment; filename="' . basename($cache_file) . '"');
        readfile( $cache_file );
    }
*/

    // Determine the total image size
    $width  = 0;
    $height = 0;
    $count  = 0;
    foreach ( $frame_data as $variable_name => $data ) {
        if ( isset($data['size']) ) {
            if ( $count < 2 ) {
                $width  += $data['size']['width'] + 2;
            }
            if ( $count % 2 == 0 ) {
                $height += $data['size']['height'] + 2;
            }
        } else {
            // Error! Output the error image
            header("Content-type: " . image_type_to_mime_type($image_types['png']));
            header('Content-Disposition: attachment; filename="' . basename($cache_file) . '"');
            readfile( $_SERVER['DOCUMENT_ROOT'] . $error_image );
            exit;
        }
        $count++;
    }

    // Tag image
    $tag_width  = 0;
    $tag_height = 0;
    $tag_im     = false;
    if ( is_file($_SERVER['DOCUMENT_ROOT'] . $tag_image ) ) {
        list($tag_width, $tag_height)   = getimagesize( $_SERVER['DOCUMENT_ROOT'] . $tag_image );
        $tag_im                         = imagecreatefromgif($_SERVER['DOCUMENT_ROOT'] . $tag_image);
        $height                         += $tag_height;
    }

    // Determine the image sizes
    $im         = @imagecreatetruecolor($width - 1, $height - 1); // Off by one error... my math is wrong somewhere
    $border     = imagecolorallocate($im,0,0,0);
    $matches    = array();
    $count      = 0;
    $current_x  = 0;
    $current_y  = 0;
    $max_height = 0;
    foreach ( $frame_data as $variable_name => $data ) {
        $frame_image    = false;
        $type           = false;
        $full_file_path = str_replace('frame/frame','frame', str_replace('//','/',$base_frame_name . $data['file']));

        // Deal with the error image
        if ( '/' . basename($data['file']) == $error_image ) {
            $full_file_path =  $_SERVER['DOCUMENT_ROOT'] . $error_image;
        }

        // Find the extension
        if ( preg_match('/\.(.*)$/',basename($data['file']),$matches ) ) {
            $type = $matches[1];
        }

        // Load the image, using the error if we have to.
        switch ($type) {
            case 'jpeg':
            case 'jpg':
                $frame_image    = imagecreatefromjpeg($full_file_path);
                break;
            case 'gif':
                $frame_image    = imagecreatefromgif($full_file_path);
                break;
            case 'png':
                $frame_image    = imagecreatefrompng($full_file_path);
                break;
            default:
                $full_file_path = $_SERVER['DOCUMENT_ROOT'] . $error_image;
                $frame_image    = imagecreatefromgif($full_file_path);
        }

        // Place the image
        imagecopy($im, $frame_image, $current_x + 2, $current_y + 2, 0, 0, $data['size']['width'], $data['size']['height']);
        // This is... lazy
        imagerectangle($im, $current_x , $current_y , $current_x + $data['size']['width']+1, $current_y + $data['size']['height']+1, $border);
        imagerectangle($im, $current_x + 1, $current_y + 1, $current_x + $data['size']['width']+2, $current_y + $data['size']['height']+2, $border);

        // Update the position(s)
        $current_x += $data['size']['width'];
        if ( $count > 0 && $count % 2 == 1 ) {
            $current_x = 0;
            $current_y += $data['size']['height'];
        }

        $count++;
    }

    // Apply the tag
    if ( $tag_im !== false ) {
        imagecopymerge($im, $tag_im, $width - $tag_width, $height - $tag_height, 0, 0, $tag_width, $tag_height, 100);
    }

    // Output!
    header("Content-type: " . image_type_to_mime_type($image_types['png']));
    header('Content-Disposition: attachment; filename="randomffuu"');
    imagepng($im);
    readfile($im);
	imagedestroy($im);

    exit;
}


/**
 * Functions
 */
// Yay for stack overflow! http://stackoverflow.com/questions/348410/php-sort-an-array-based-on-another-array
function sortArrayByArray($array,$orderArray) {
    $ordered = array();
    foreach($orderArray as $key) {
        if(array_key_exists($key,$array)) {
                $ordered[$key] = $array[$key];
                unset($array[$key]);
        }
    }
    return $ordered + $array;
}

// Check if the given file from the user exits. Returns the relative path if found or false if not
function check_file_data($frame, $file_name) {
    // Basic conf data
    global $base_frame_name, $file_extensions;

    // Remove anything that's not a-z, 0-9, or an underscore.
    $file_name =  preg_replace('/([^a-z0-9_]+)/i','',$file_name);

    // See if the frame is encoded in the file name (\d+)_
    $matches = array();
    if ( preg_match('/^(\d+)_(\d+)_(\d+)/',$file_name,$matches) ) {
        $frame      = $matches[1];
        $file_name  = preg_replace('/^(\d+)_/','',$file_name);
    }

    // Make sure it exists
    $path       = $base_frame_name . $frame . '/fu' . $file_name;

    // This is a bit, lame. We could just include the full image name in the URL to make things easier
    foreach ( $file_extensions as $extension ) {
        if ( is_file($path . $extension) ) {
            // Strip the document root so we get the relative path to the image
            return array(str_replace('//','/',str_replace($_SERVER['DOCUMENT_ROOT'],'/',$path . $extension)), $frame);
            break;
        }
    }
    return array(false, false);
}

// Function to run glob for the given frame. This will take into account any options/restrictions for the frame
function find_image_file($frame_number) {
    // Basic conf data
    global $base_frame_name, $file_extensions, $error_image;

    if ( !is_dir($base_frame_name . $frame_number . '/') ) {
        // Error! Return path to some default "rage generator is broken" image.
        return array($error_image, $frame_number);
    }

    // We need access to the option variable(s) above.
    global $nsfw, $anyframe;

    $path = $base_frame_name . ($anyframe?'*':$frame_number) . '/';

    // most specific glob string
    $glob_str = $path . 'fu' . '[0-9]*_' . ($nsfw?'{0,1}':'0') . '{' . join(',',$file_extensions).'}';

    // Just in case the glob sting above fails. Skip this if we don't set nsfw, we want no surprises here!
    $default_glob_str = false;
    if ( $nsfw ) {
        $default_glob_str = $path . 'fu' . '[0-9]*{' . join(',',$file_extensions).'}';
    }

    $files = array();
    foreach ( glob($glob_str, GLOB_NOSORT | GLOB_BRACE) as $file_name ) {
        // Strip the document root so we get the relative path to the image
        $files[] = str_replace('//','/',str_replace($_SERVER['DOCUMENT_ROOT'],'/',$file_name));
    }

    // Because of this check we will only use the default glob if there are no images fitting the given options.
    if ( count($files) == 0 && $default_glob_str !== false ) {
        foreach ( glob($default_glob_str, GLOB_NOSORT | GLOB_BRACE) as $file_name ) {
            // Strip the document root so we get the relative path to the image
            $files[] = str_replace('//','/',str_replace($_SERVER['DOCUMENT_ROOT'],'/',$file_name));
        }
    }

    if ( count($files) == 0 ) {
        // Error! Return path to some default "rage generator is broken" image.
        return array($error_image, $frame_number);
    }

    $file = $files[array_rand($files,1)];
    // Find the frame number
    // See if the frame is encoded in the file name (\d+)_
    $matches = array();
    if ( preg_match('/frame(\d+)/',$file,$matches) ) {
        $frame = $matches[1];
    }
    
    return array($file, $frame);
}


/**
 * HTML
 */
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="description" content="Random Image Generator CGI Program Demo">
<meta name="keywords" content="CGI, PERL, random image generator, FFFFUUUU, rage">
<link rel="canonical" href="http://www.cloverpatchwork.com/ffffuuuu.php" /> 
<title>Random FFFFUUUU</title>
<style type="text/css">
<!--

body,td,th {
	font-family: Verdana, Geneva, sans-serif;
	color: #FFF;
	font-size: small;
}
body {
	background-color: #333;
}
a:link {
	font-weight: normal;
	color: #9CF;
	text-shadow: #003 0.2em 0.2em 0em;
	text-decoration: overline;
}
a:visited {
	font-weight: bold;
	color: #99C;
	text-shadow: #303 0.2em 0.2em 0em;
	text-decoration: none;
}
a:active {
	font-weight: normal;
	color: #9CF;
	text-shadow: #003 0.2em 0.2em 0em;
	text-decoration: underline;
}
h1,h2,h3,h4,h5,h6 {
	color: #FFF;
	text-shadow: #003 0.1em 0.1em 0em;
}
a:hover {
	font-weight: bold;
	text-decoration: none;
	color: #FFF;
	text-shadow: #006 0.2em 0.2em 0em;
}

img {
	border: 2px solid #000000;
}

table {
    border-collapse: collapse;
}

table td {
    margin: 0px;
    padding: 0px;
}
input.big {
 font-size: 48pt;
}
-->
</style><body>
Permalink: <a href="http://www.cloverpatchwork.com/ffffuuuu.php?<?php echo($url); ?>">http://www.cloverpatchwork.com/ffffuuuu.php?<?php echo($url); ?></a>
<form method='post' action='<?php echo $_SERVER["SCRIPT_NAME"]; ?>'>
<table border="0">
  <tr>
    <td><table>
      <tr>
        <?php
$count = 0;
foreach ( $frame_data as $variable_name => $data ):
?>
        <?php
    if ( $count > 0 && $count % 2 == 0 ): ?>
      </tr>
      <tr>
        <?php
    endif;
    if ( $count % 2 == 0 ): ?>
        <td><input name='save_<?php echo $variable_name; ?>' type='checkbox'<?php echo ($data['save']?" checked='checked'":''); ?>/>
            <input type='hidden' name='data_<?php echo $variable_name; ?>' value='<?php echo $data['url_file']; ?>'/>        </td>
        <?php
    endif;
?>
        <td bgcolor="#000"><a href="http://www.cloverpatchwork.com/ffffuuuu.php"><img src="<?php echo $data['file']; ?>" alt="Frame <?php echo $data['frame']; ?>" /></a> </td>
        <?php
    if ( $count % 2 != 0 ): ?>
        <td><input name='save_<?php echo $variable_name; ?>' type='checkbox'<?php echo ($data['save']?" checked='checked'":''); ?>/>
            <input type='hidden' name='data_<?php echo $variable_name; ?>' value='<?php echo $data['url_file']; ?>'/></td>
        <?php
    endif;
    $count++;
endforeach;
?>
          <?php
          $redditurl = str_replace("&", "%26", "http://www.reddit.com/r/RandomFFFUUUUUU/submit?url=http://www.cloverpatchwork.com/ffffuuuu.php?" . $url);
          ?>              
        <a href='<?php echo($_SERVER["SCRIPT_NAME"] . '?' . $save_url); ?>'>
      </a>
      </tr>
    </table></td>
    <td><h1 align="center">Random FFFFUUUU rage comic generator</h1>
    <p align="center"><i>over 909 trillion unfunny combinations<br>
    </i>
    </br><input type='submit' class='big' value='RELOAD!'/>
        </p>
      <p align="center">
        <input type='checkbox' name='nsfw'<?php echo ($nsfw?" checked='checked'":''); ?>/>
        (even more) NSFW/NSFL</br><input type='checkbox' name='anyframe'<?php echo ($anyframe?" checked='checked'":''); ?>/>
          randomize frame order
        </p>
      <h2 align="center" font-size="2em">
          <a href="<?php echo($redditurl); ?>">post to reddit</a><br/>
        <a href='<?php echo($_SERVER["SCRIPT_NAME"] . '?' . $save_url); ?>'>download .png</a></h2>
      <p align="center">
<a href="http://www.cloverpatchwork.com/ffffuuuu.php?fffff=random&fuuuu=random&uuuuu=random&uuu=4_001_0">Classic</a> | 
<a href="http://www.cloverpatchwork.com/ffffuuuu.php?fffff=random&fuuuu=random&uuuuu=random&uuu=4_200_1">Fuck Yea</a> | 
<a href="http://www.cloverpatchwork.com/ffffuuuu.php?fffff=random&fuuuu=random&uuuuu=random&uuu=4_924_0">EWBTE</a> | 
<a href="http://www.cloverpatchwork.com/ffffuuuu.php?fffff=random&fuuuu=random&uuuuu=random&uuu=4_926_0">Troll</a> | 
<a href="http://www.cloverpatchwork.com/ffffuuuu.php?fffff=random&fuuuu=random&uuuuu=random&uuu=4_504_0">Okay</a> | 
<a href="http://www.cloverpatchwork.com/ffffuuuu.php?fffff=random&fuuuu=random&uuuuu=random&uuu=4_508_0">Forever Alone</a> | 
<a href="http://www.cloverpatchwork.com/ffffuuuu.php?fffff=random&fuuuu=random&uuuuu=random&uuu=4_713_0">LOL</a> | 
<a href="http://www.cloverpatchwork.com/ffffuuuu.php?fffff=random&fuuuu=random&uuuuu=random&uuu=4_1083_0">Terrified</a> |          
<a href="http://www.cloverpatchwork.com/ffffuuuu.php?fffff=random&fuuuu=random&uuuuu=random&uuu=4_1741_0">Cereal Spit</a> |          
<a href="http://www.cloverpatchwork.com/ffffuuuu.php?fffff=random&fuuuu=random&uuuuu=random&uuu=4_938_0">Maximum Lean</a> |        
<a href="http://www.cloverpatchwork.com/ffffuuuu.php?fffff=random&fuuuu=random&uuuuu=random&uuu=4_1740_1">Fap Fap Fap</a> |          
<a href="http://www.cloverpatchwork.com/ffffuuuu.php?fffff=random&fuuuu=random&uuuuu=random&uuu=4_1747_0">Seriously?</a> |       
<a href="http://www.cloverpatchwork.com/ffffuuuu.php?fffff=random&fuuuu=random&uuuuu=random&uuu=4_1139_0">&#3232 _ &#3232</a> |         
<a href="http://www.cloverpatchwork.com/ffffuuuu.php?fffff=random&fuuuu=random&uuuuu=random&uuu=4_2005_0">AYFKM?</a> | 
<a href="http://www.cloverpatchwork.com/ffffuuuu.php?fffff=random&fuuuu=random&uuuuu=random&uuu=4_901_0">!?!?!?!?</a> |         
<a href="http://www.cloverpatchwork.com/ffffuuuu.php?fffff=random&fuuuu=random&uuuuu=random&uuu=4_722_0">WUT</a> |     
<a href="http://www.cloverpatchwork.com/ffffuuuu.php?fffff=random&fuuuu=random&uuuuu=random&uuu=4_634_0">What?!</a>          
         <br/>
All images &#169 their original, mostly anonymous or pseudonymous, authors. Send takedown notices, etc. to ian@cloverpatchwork.com</p>
</td>
  </tr>
</table>
</form>
</body>
</html>
