<?php
/*  v.1.2
    charset: UTF-8 [visual check: äÄßçÇ €©—√øØ]
    © freiherr von hermes [http://www.cloudwork-orange.com/]
    licence: EUPL v.1.1 [http://ec.europa.eu/idabc/eupl.html]
*/

    // cache the image up to a year
    /*
        to force an update use a get variable like v=123 and increment it.
        e.g.: src="images/svg.php?f=smile.svg&amp;v=01b"
        i'm using a global variable defined in my config.php file: $GLOBALS['assetsVersion']
        that way i can force an update of all design/script files at once after making changes (including css, js, svg)
    */
    $cacheForThisManySeconds=31536000; //60*60*24*365;

    // compress the image using gzip.
    /*
        i am unaware of any browser that supports svg but not gzip compression
        so i'm not checking the accept encoding header ... correct me if i'm wrong
    */
    function gz_ob_callback($bufferString){
        if (function_exists('header_remove')) header_remove('X-Powered-By');
        header('Content-Type: image/svg+xml');
        header('Content-Transfer-Encoding: binary', true);

        $bufferString=gzencode($bufferString, 9);
        header('Vary: Accept-Encoding');
        header('Content-Encoding: gzip');
        header('Content-Length: '.strlen($bufferString), true);

        return($bufferString);
    }
    ob_start('gz_ob_callback');

    // minifying the svg while trying to not reduce it's quality
    function minifySvgContent ($svgContent){
        // removing Illustrator metadata
        $svgContent = preg_replace('/<i:pgf\s+id="adobe_illustrator_pgf">.*<\/i:pgf>/Uims', '', $svgContent);
        // removing foreign object tags
        $svgContent = preg_replace('/<foreignObject.*\/foreignObject>/Uims', '', $svgContent);
        // removing sodipodi tags
        $svgContent = preg_replace('/<sodipodi.*\/sodipodi[^>]*>/Uims', '', $svgContent);
        // removing non-standard attributes:
        $svgContent = preg_replace('/\si:extraneous="[^"]+"/', '', $svgContent);
        $svgContent = preg_replace('/\sinkscape:[^=]+="[^"]+"/', '', $svgContent);
        $svgContent = preg_replace('/\ssodipodi:[^=]+="[^"]+"/', '', $svgContent);
        // removing switch tag:
        $svgContent = preg_replace('/<\/?switch>/', '', $svgContent);
        // removing comments
        $svgContent = preg_replace('/\/\*[^*]*\*+([^\/][^*]*\*+)*\//', '', $svgContent);
        // removing multiline comments ... I'm looking at YOU Adobe Illustrator!
        $svgContent = preg_replace('/<!--.*-->/Uims', '', $svgContent);
        // removing empty groups - AI - I'm still watching you ...
        $svgContent = preg_replace('/<g>\s*<\/g>/im', '', $svgContent);
        // replacing 0px values with 0 - you again,  AI?
        $svgContent = str_ireplace('"0px"', '"0"', $svgContent);
        // removing groups without attributes or content - what the use? again AI? allright. you just made my list
        $svgContent = preg_replace('/<g>(.*)<\/g>/Uims', '$1', $svgContent);
        // removing leading and trailing whitespaces
        $svgContent = preg_replace('/^\s+|\s+$/mi', '', $svgContent);
        // removing xml and doctype header
        $svgContent = preg_replace('/<\?xml[^>]+\?>/', '', $svgContent);
        // removing doctype with namespace extensions array
        $svgContent = preg_replace('/<!DOCTYPE[\[^>]+>/', '', $svgContent);
        // removing doctype without namespace extensions array
        $svgContent = preg_replace('/<!DOCTYPE[^>]+\[[^\]]+\]>/', '', $svgContent);
        // removing even more whitespaces ...
        $svgContent = preg_replace('/>\s+</im', '><', $svgContent);
        // removing whitespaces at the end of attributes?
        $svgContent = preg_replace('/="([^"]+[^\s])\s+"/im', '="$1"', $svgContent);
        // shortening websave colors
        $svgContent = preg_replace('/#(([0-9a-f])\2)(([0-9a-f])\4)(([0-9a-f])\6)/i', '#$2$4$6', $svgContent);
        // cleaning up the svg tag ...
        if (1 === preg_match('/<svg[^>]+>/', $svgContent, $svgTag)){
            if (1 === preg_match('/\swidth="([^"]+)"/', $svgTag[0], $svgWidth) ){
                $svgWidth = ' width="' . $svgWidth[1] . '"';
            }else{
                $svgWidth = '';
            }
            if (1 === preg_match('/\sheight="([^"]+)"/', $svgTag[0], $svgHeight) ){
                $svgHeight = ' height="' . $svgHeight[1] . '"';
            }else{
                $svgHeight = '';
            }
            if (1 === preg_match('/\sviewBox="([^"]+)"/', $svgTag[0], $svgViewBox) ){
                $svgViewBox = ' viewBox="' . $svgViewBox[1] . '"';
            }else{
                $svgViewBox = '';
            }
            if (1 === preg_match('/\sx="([^"]+)"/', $svgTag[0], $svgX) && 0 != (int)$svgX[1]){
                $svgX = ' x="' . $svgX[1] . '"';
            }else{
                $svgX = '';
            }
            if (1 === preg_match('/\sy="([^"]+)"/', $svgTag[0], $svgY) && 0 != (int)$svgY[1]){
                $svgY = ' y="' . $svgY[1] . '"';
            }else{
                $svgY = '';
            }
            // actually replacing the svg tag with a minimalistic one
            $svgContent = preg_replace('/<svg[^>]+>/', '<svg xmlns="http://www.w3.org/2000/svg"' . $svgWidth . $svgHeight . $svgViewBox . $svgX . $svgY . '>', $svgContent);    
        }
        // and at last we're trimming the result
        $svgContent = trim($svgContent);
                
        return($svgContent);
    }

    // check if a filename has been submitted, is not empty, remove any characters that are not allowed (a-z, A-Z, 0-9, dot, hyphen and underscore) and check if the file exists
    if ( isset($_REQUEST['f']) && '' !== trim($_REQUEST['f']) && is_file( $filename = realpath( dirname( $_SERVER['PHP_SELF'] ) ) . preg_replace('/[^a-zA-Z0-9.\-_]/', '',$_REQUEST['f'] ) ) ){

        // minify the svg content
        $svgContent = minifySvgContent( file_get_contents( $filename ) );

        // make the browser cache the image
        header('Pragma: public', true);
        header('Cache-Control: public, max-age=' . $cacheForThisManySeconds, true);
        header('Last-Modified: ' . gmdate("D, d M Y H:i:s", filemtime( $filename) ) . ' GMT', true);
        header('Expires: '.gmdate( 'D, d M Y H:i:s', time() + $cacheForThisManySeconds) . ' GMT', true);

        // send the appropriate headers for svg files
        header('Content-Length: ' . strlen($svgContent), true);
        header('Content-Disposition: inline; filename="' . $_REQUEST['f'] . '"', true);

        // submit the minified file
        die( $svgContent );

    }else{ // no filename requested or file not found

        header('Cache-Control: no-cache, no-store', true);
        header('Expires: ' . gmdate('D, d M Y H:i:s', -1) . ' GMT', true);
        header('Content-Disposition: inline; filename="404.svg"', true);

        // submit an error image
        die('<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96"><rect x="2" y="2" width="92" height="92"/><rect x="2" y="2" width="92" height="92" style="fill:none;stroke-width:4;stroke:#000"/><rect x="2" y="2" width="92" height="92" fill="#ccc"/><path d="M27.5 62.8v-8.1H13.7v-2.6l13.2-18.9h4.3v18.4h4.2v3.1h-4.2v8.1H27.5zM27.5 51.6v-9.9c0-1.6 0-3.1 0.1-4.7h-0.1c-0.9 1.7-1.6 3-2.5 4.4l-7.3 10.1v0.1H27.5zM58.2 47.7c0 10.1-3.7 15.6-10.3 15.6-5.8 0-9.7-5.4-9.8-15.2 0-9.9 4.3-15.4 10.3-15.4C54.6 32.7 58.2 38.2 58.2 47.7zM42.1 48.1c0 7.7 2.4 12.1 6 12.1 4.1 0 6.1-4.8 6.1-12.4 0-7.3-1.9-12.1-6-12.1C44.6 35.8 42.1 40.1 42.1 48.1zM74.3 62.8v-8.1H60.5v-2.6l13.2-18.9h4.3v18.4h4.2v3.1h-4.1v8.1H74.3zM74.3 51.6v-9.9c0-1.6 0-3.1 0.1-4.7h-0.1c-0.9 1.7-1.6 3-2.5 4.4l-7.3 10.1v0.1H74.3z"/></svg>');

    }
?>
