<?php
error_reporting(E_ALL & ~E_WARNING & ~E_NOTICE & ~E_DEPRECATED);
ob_start();
ini_set("memory_limit",-1);
ini_set('max_execution_time', 9999);
set_time_limit(9999);
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");

require_once(__DIR__."/../db/connection.php");
require_once(__DIR__."/../backend/functions.php");
$debug = false;
$force = false;
$generation_mode = 'auto';
$api_key = "ef6e1fd351061564ebe63d780cffa9e3cfc29a40";

if($debug) {
    $ip = get_client_ip();
    $date = date('Y-m-d H:i');
    register_shutdown_function( "fatal_handler" );
}

$settings = get_settings();
$logo_backend = $settings['logo'];


if(isset($_GET['url'])) {
    $url = $_GET['url'];
    $url = str_replace("/backend/ajax","",$url);
} else {
    if(isset($argv[1])) {
        $url = $argv[1];
        $url = str_replace("/backend/ajax","",$url);
    } else {
        $currentPath = $_SERVER['PHP_SELF'];
        $pathInfo = pathinfo($currentPath);
        $hostName = $_SERVER['HTTP_HOST'];
        if (is_ssl()) { $protocol = 'https'; } else { $protocol = 'http'; }
        $url = $protocol."://".$hostName.$pathInfo['dirname'];
        $url = str_replace("/services","",$url);
    }
}

if(isset($_GET['what'])) {
    $what = $_GET['what'];
} else {
    if(isset($argv[2])) {
        $what = $argv[2];
    } else {
        $what = 'all';
    }
}

if(isset($_GET['id'])) {
    $id = $_GET['id'];
} else {
    if(isset($argv[3])) {
        $id = $argv[3];
    } else {
        $id = 0;
    }
}

if($debug) {
    if(isset($argv[1])) {
        file_put_contents(realpath(dirname(__FILE__))."/log_favicons.txt",$date." - ".$ip." "."ARGV: ".serialize($argv).PHP_EOL,FILE_APPEND);
    }
    file_put_contents(realpath(dirname(__FILE__))."/log_favicons.txt",$date." - ".$ip." "."GET: ".serialize($_GET).PHP_EOL,FILE_APPEND);
}

$path = realpath(dirname(__FILE__) . '/..');

if($what=='backend' || $what=='all') {
    if(!empty($logo_backend)) {
        if (!file_exists($path.DIRECTORY_SEPARATOR.'favicons'.DIRECTORY_SEPARATOR.'custom'.DIRECTORY_SEPARATOR)) {
            mkdir($path.DIRECTORY_SEPARATOR.'favicons'.DIRECTORY_SEPARATOR.'custom'.DIRECTORY_SEPARATOR, 0775);
            chmod($path.DIRECTORY_SEPARATOR.'favicons'.DIRECTORY_SEPARATOR.'custom'.DIRECTORY_SEPARATOR, 0775);
        }
        $url_backend_logo = $url.'/backend/assets/'.$logo_backend;
        $lang = $settings['language'];
        $lang = strtok($lang, '_');
        $description = $settings['name']." - "."BACKEND";
        $theme_color = $settings['theme_color'];
        execute_favicon_generation($api_key,$settings['name'],'../../backend/',$url_backend_logo,$path.DIRECTORY_SEPARATOR.'favicons'.DIRECTORY_SEPARATOR.'custom'.DIRECTORY_SEPARATOR);
        fix_manifest($path.DIRECTORY_SEPARATOR.'favicons'.DIRECTORY_SEPARATOR.'custom'.DIRECTORY_SEPARATOR,'../../backend/',$settings['name'],$lang,$description,"backend");
    }
}

if($what=='map' || $what=='all') {
    if($what=='all') {
        $query = "SELECT id,code,logo,logo_mobile,name,meta_description,language,main_color_hex FROM sml_maps;";
    } else {
        $query = "SELECT id,code,logo,logo_mobile,name,meta_description,language,main_color_hex FROM sml_maps WHERE id=$id;";
    }
    $result = $mysqli->query($query);
    if($result) {
        if($result->num_rows>0) {
            while($row = $result->fetch_array(MYSQLI_ASSOC)) {
                $id_map = $row['id'];
                $code = $row['code'];
                $logo = $row['logo'];
                if(!empty($row['logo_mobile'])) {
                    $logo = $row['logo_mobile'];
                }
                $name = $row['name'];
                $lang = $row['language'];
                if(empty($lang)) {
                    $lang = $settings['language'];
                }
                $lang = strtok($lang, '_');
                $description = $row['meta_description'];
                if (!file_exists($path.DIRECTORY_SEPARATOR.'favicons'.DIRECTORY_SEPARATOR.'m_'.$code.DIRECTORY_SEPARATOR)) {
                    mkdir($path.DIRECTORY_SEPARATOR.'favicons'.DIRECTORY_SEPARATOR.'m_'.$code.DIRECTORY_SEPARATOR, 0775);
                }
                $theme_color = $row['main_color_hex'];
                if(!empty($logo)) {
                    $url_logo = $url.'/viewer/logos/'.$logo;
                    execute_favicon_generation($api_key,$name,'../../viewer/'.$code,$url_logo,$path.DIRECTORY_SEPARATOR.'favicons'.DIRECTORY_SEPARATOR.'m_'.$code.DIRECTORY_SEPARATOR);
                }
                fix_manifest($path.DIRECTORY_SEPARATOR.'favicons'.DIRECTORY_SEPARATOR.'m_'.$code.DIRECTORY_SEPARATOR,'../../viewer/'.$code,$name,$lang,$description,"m_$id_map");
            }
        }
    }
}

if($what=='showcase' || $what=='all') {
    if($what=='all') {
        $query = "SELECT id,code,logo,name,header_html,meta_description,bg_color FROM sml_showcases;";
    } else {
        $query = "SELECT id,code,logo,name,header_html,meta_description,bg_color FROM sml_showcases WHERE id=$id;";
    }
    $result = $mysqli->query($query);
    if($result) {
        if($result->num_rows>0) {
            while($row = $result->fetch_array(MYSQLI_ASSOC)) {
                $id_showcase = $row['id'];
                $code = $row['code'];
                $logo = $row['logo'];
                $name = $row['name'];
                if(empty($row['meta_description'])) {
                    $description = strip_tags($row['header_html']);
                } else {
                    $description = $row['meta_description'];
                }
                if (!file_exists($path.DIRECTORY_SEPARATOR.'favicons'.DIRECTORY_SEPARATOR.'s_'.$code.DIRECTORY_SEPARATOR)) {
                    mkdir($path.DIRECTORY_SEPARATOR.'favicons'.DIRECTORY_SEPARATOR.'s_'.$code.DIRECTORY_SEPARATOR, 0775);
                }
                $theme_color = $row['bg_color'];
                if(!empty($logo)) {
                    $url_logo = $url.'/viewer/content/'.$logo;
                    execute_favicon_generation($api_key,$name,'../../showcase/'.$code,$url_logo,$path.DIRECTORY_SEPARATOR.'favicons'.DIRECTORY_SEPARATOR.'s_'.$code.DIRECTORY_SEPARATOR);
                }
                $lang = $settings['language'];
                $lang = strtok($lang, '_');
                fix_manifest($path.DIRECTORY_SEPARATOR.'favicons'.DIRECTORY_SEPARATOR.'s_'.$code.DIRECTORY_SEPARATOR,'../../showcase/'.$code,$name,$lang,$description,"s_$id_showcase");
            }
        }
    }
}
ob_end_clean();
echo "ok";

function execute_favicon_generation($api_key, $name, $start_url, $url_logo, $destination) {
    global $generation_mode;

    $mode = $generation_mode;
    if ($mode === 'auto') {
        if (extension_loaded('gd') && function_exists('imagecreatefromstring') && function_exists('imagecreatetruecolor')) {
            $mode = 'local';
        } else {
            $mode = 'api';
        }
    }

    if ($mode === 'api') {
        generate_favicons_api($api_key, $name, $start_url, $url_logo, $destination);
    } else {
        generate_favicons_local($name, $start_url, $url_logo, $destination);
    }
}

function generate_favicons_local($name, $start_url, $url_logo, $destination) {
    global $what, $debug, $date, $ip, $theme_color, $force;

    if(!$force) {
        if($what=='all' && file_exists($destination."favicon.ico")) return;
    }

    if($debug) {
        file_put_contents(realpath(dirname(__FILE__))."/log_favicons.txt",$date." - ".$ip." "."GENERATE LOCAL: ".$destination.PHP_EOL,FILE_APPEND);
    }

    if(function_exists('ini_get') && ini_get('allow_url_fopen')) {
        $source_data = @file_get_contents($url_logo);
    } else {
        $source_data = curl_get_file_contents($url_logo);
    }

    if ($source_data === false || empty($source_data)) return;

    $source_image = @imagecreatefromstring($source_data);
    if (!$source_image) return;

    $width = imagesx($source_image);
    $height = imagesy($source_image);

    $theme_color_hex = ltrim($theme_color, '#');
    if (strlen($theme_color_hex) == 3) {
        $theme_color_hex = str_repeat(substr($theme_color_hex, 0, 1), 2) . str_repeat(substr($theme_color_hex, 1, 1), 2) . str_repeat(substr($theme_color_hex, 2, 1), 2);
    }
    if (empty($theme_color_hex) || strlen($theme_color_hex) != 6) {
        $theme_color_hex = 'FFFFFF';
    }
    $bg_r = hexdec(substr($theme_color_hex, 0, 2));
    $bg_g = hexdec(substr($theme_color_hex, 2, 2));
    $bg_b = hexdec(substr($theme_color_hex, 4, 2));

    $sizes = [
        'android-chrome-192x192.png' => 192,
        'android-chrome-512x512.png' => 512,
        'apple-touch-icon.png'       => 180,
        'favicon-96x96.png'          => 96,
        'favicon-32x32.png'          => 32,
        'favicon-16x16.png'          => 16,
        'mstile-150x150.png'         => 150
    ];

    foreach ($sizes as $filename => $size) {
        $new_image = imagecreatetruecolor($size, $size);

        if ($filename === 'apple-touch-icon.png') {
            $fill = imagecolorallocate($new_image, $bg_r, $bg_g, $bg_b);
            imagefilledrectangle($new_image, 0, 0, $size, $size, $fill);
        } else {
            imagealphablending($new_image, false);
            imagesavealpha($new_image, true);
            $transparent = imagecolorallocatealpha($new_image, 255, 255, 255, 127);
            imagefilledrectangle($new_image, 0, 0, $size, $size, $transparent);
        }

        $aspect_ratio = $width / $height;
        $new_w = $size;
        $new_h = $size;
        $dst_x = 0;
        $dst_y = 0;

        if ($aspect_ratio > 1) {
            $new_h = $size / $aspect_ratio;
            $dst_y = ($size - $new_h) / 2;
        } else if ($aspect_ratio < 1) {
            $new_w = $size * $aspect_ratio;
            $dst_x = ($size - $new_w) / 2;
        }

        imagecopyresampled($new_image, $source_image, $dst_x, $dst_y, 0, 0, $new_w, $new_h, $width, $height);
        imagepng($new_image, $destination . $filename, 9);
        imagedestroy($new_image);
    }

    try {
        $ico_lib = new PHP_ICO($destination . 'android-chrome-512x512.png', array(array(16, 16), array(32, 32)));
        $ico_lib->save_ico($destination . 'favicon.ico');
    } catch (Exception $e) {
        copy($destination . 'favicon-32x32.png', $destination . 'favicon.ico');
    }

    $browserconfig = '<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
    <msapplication>
        <tile>
            <square150x150logo src="mstile-150x150.png"/>
            <TileColor>#'.$theme_color_hex.'</TileColor>
        </tile>
    </msapplication>
</browserconfig>';
    file_put_contents($destination . 'browserconfig.xml', $browserconfig);

    imagedestroy($source_image);
}

function generate_favicons_api($api_key,$name,$start_url,$url_logo,$destination) {
    global $what,$debug,$date,$ip,$theme_color,$force;
    if(!$force) {
        if($what=='all' && file_exists($destination."favicon.ico")) return;
    }
    if($debug) {
        file_put_contents(realpath(dirname(__FILE__))."/log_favicons.txt",$date." - ".$ip." "."GENERATE: ".$destination.PHP_EOL,FILE_APPEND);
    }
    $json = '{
        "favicon_generation": {
            "api_key": "'.$api_key.'",
            "master_picture": {
                "type": "url",
                "url": "'.$url_logo.'"
            },
            "files_location": {
                "type": "path",
                "path": "."
            },
            "favicon_design": {
                "desktop_browser": {},
                "ios": {
                    "picture_aspect": "background_and_margin",
                    "margin": "4",
                    "background_color": "'.$theme_color.'",
                    "assets": {
                        "ios6_and_prior_icons": false,
                        "ios7_and_later_icons": true,
                        "precomposed_icons": false,
                        "declare_only_default_icon": true
                    }
                },
                "windows": {
                    "picture_aspect": "white_silhouette",
                    "background_color": "'.$theme_color.'",
                    "assets": {
                        "windows_80_ie_10_tile": true,
                        "windows_10_ie_11_edge_tiles": {
                            "small": false,
                            "medium": true,
                            "big": true,
                            "rectangle": false
                        }
                    }
                },
                "android_chrome": {
                    "picture_aspect": "shadow",
                    "assets": {
                        "legacy_icon": true,
                        "low_resolution_icons": false
                    },
                    "manifest": {
                        "name": "'.$name.'",
                        "display": "standalone",
                        "orientation": "natural",
                        "start_url": "'.$start_url.'"
                    },
                    "theme_color": "'.$theme_color.'"
                },
                "safari_pinned_tab": {
                    "picture_aspect": "black_and_white",
                    "threshold": 60,
                    "theme_color": "'.$theme_color.'"
                }
            },
            "settings": {
                "compression": "3",
                "scaling_algorithm": "Mitchell",
                "error_on_image_too_small": false,
                "readme_file": false,
                "html_code_file": false,
                "use_path_as_is": false
            }
        }
    }';
    $url = 'https://realfavicongenerator.net/api/favicon';
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $result = curl_exec($ch);
    if($debug) {
        file_put_contents(realpath(dirname(__FILE__))."/log_favicons.txt",$date." - ".$ip." "."API: ".serialize($result).PHP_EOL,FILE_APPEND);
    }
    curl_close($ch);
    $array = json_decode($result,true);
    $files_url = $array['favicon_generation_result']['favicon']['files_urls'];
    $opts = array(
        'http'=>array(
            'method'=>"GET",
            'timeout'=>60,
            'ignore_errors'=> true,
            'header'=>"Accept-language: en\r\n" .
                "Cookie: foo=bar\r\n" .
                "User-Agent: Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.102011-10-16 20:23:10\r\n"

        )
    );
    $context = stream_context_create($opts);
    foreach ($files_url as $file_url) {
        $file_name = basename($file_url);
        if(function_exists('ini_get') && ini_get('allow_url_fopen')) {
            $file_data = file_get_contents($file_url,false,$context);
        } else {
            $file_data = curl_get_file_contents($file_url);
        }
        if($file_data==false) {
            if(function_exists('ini_get') && ini_get('allow_url_fopen')) {
                $file_data = file_get_contents($file_url,false,$context);
            } else {
                $file_data = curl_get_file_contents($file_url);
            }
        }
        file_put_contents($destination.$file_name,$file_data);
    }
}

function fix_manifest($path_dir,$url,$name,$lang,$description,$id) {
    global $theme_color;
    if(empty($description)) { $description = $name; }
    if (file_exists($path_dir.'site.webmanifest') && filesize($path_dir.'site.webmanifest') > 0) {
        if(function_exists('ini_get') && ini_get('allow_url_fopen')) {
            $content = file_get_contents($path_dir.'site.webmanifest');
        } else {
            $content = curl_get_file_contents($path_dir.'site.webmanifest');
        }
        $array = json_decode($content,true);
        if ($array === null) {
            $array = [];
        }
        if(!array_key_exists('start_url',$array)) {
            $array['start_url'] = $url;
        }
        if(!array_key_exists('url',$array)) {
            $array['url'] = $url;
        }
        if(!array_key_exists('scope',$array)) {
            $array['scope'] = $url;
        }
        if(!array_key_exists('dir',$array)) {
            $array['dir'] = 'ltr';
        }
        if(!array_key_exists('categories',$array)) {
            $array['categories'] = ["map"];
        }
    } else {
        $content = '{"name":"","short_name":"","icons":[{"src":"","sizes":"512x512","type":"image\/png"}],"theme_color":"'.$theme_color.'","background_color":"'.$theme_color.'","start_url":"","display":"standalone","orientation":"natural","url":"","scope":""}';
        $array = json_decode($content,true);
        $array['start_url'] = $url;
        $array['url'] = $url;
        $array['scope'] = $url;
        $array['dir'] = 'ltr';
        $array['categories'] = ["map"];
    }
    $array['display'] = 'standalone';
    $array['display_override'] = ["standalone","fullscreen","minimal-ui","window-controls-overlay"];
    $array['launch_handler']['client_mode'] = "auto";
    $array['lang'] = $lang;
    $array['id'] = $id;
    $array['name'] = $name;
    $array['short_name'] = $name;
    $array['orientation']="natural";
    $array['description'] = $description;
    $array['background_color'] = $theme_color;
    $array['theme_color'] = $theme_color;
    $array['prefer_related_applications']=false;
    if(empty($array['icons'][0]['src'])) {
        $array['icons'][0]['type']="image/png";
        $array['icons'][0]['purpose']='any';
        if(file_exists($path_dir."web-app-manifest-512x512.png")) {
            $array['icons'][0]['sizes']="512x512";
            $array['icons'][0]['src']="web-app-manifest-512x512.png";
        } else if(file_exists($path_dir."android-chrome-512x512.png")) {
            $array['icons'][0]['sizes']="512x512";
            $array['icons'][0]['src']="android-chrome-512x512.png";
        } elseif(file_exists($path_dir."..".DIRECTORY_SEPARATOR."custom".DIRECTORY_SEPARATOR."web-app-manifest-512x512.png")) {
            $array['icons'][0]['sizes']="512x512";
            $array['icons'][0]['src']="../custom/web-app-manifest-512x512.png";
        } elseif(file_exists($path_dir."..".DIRECTORY_SEPARATOR."android-chrome-512x512.png")) {
            $array['icons'][0]['sizes']="512x512";
            $array['icons'][0]['src']="../android-chrome-512x512.png";
        } elseif(file_exists($path_dir."web-app-manifest-192x192.png")) {
            $array['icons'][0]['sizes']="192x192";
            $array['icons'][0]['src']="web-app-manifest-192x192.png";
        } else if(file_exists($path_dir."android-chrome-192x192.png")) {
            $array['icons'][0]['sizes']="192x192";
            $array['icons'][0]['src']="android-chrome-192x192.png";
        } elseif(file_exists($path_dir."..".DIRECTORY_SEPARATOR."custom".DIRECTORY_SEPARATOR."web-app-manifest-192x192.png")) {
            $array['icons'][0]['sizes']="192x192";
            $array['icons'][0]['src']="../custom/web-app-manifest-192x192.png";
        } elseif(file_exists($path_dir."..".DIRECTORY_SEPARATOR."android-chrome-192x192.png")) {
            $array['icons'][0]['sizes']="192x192";
            $array['icons'][0]['src']="../android-chrome-192x192.png";
        }
    } else {
        for($i=0;$i<count($array['icons']);$i++) {
            if (strpos($array['icons'][$i]['src'], '..') !== 0) {
                $array['icons'][$i]['src'] = ltrim($array['icons'][$i]['src'], '.');
            }
            $array['icons'][$i]['purpose']='any';
            if(!file_exists($path_dir.$array['icons'][$i]['src'])) {
                if (file_exists($path_dir . "web-app-manifest-512x512.png")) {
                    $array['icons'][$i]['sizes']="512x512";
                    $array['icons'][$i]['src'] = "web-app-manifest-512x512.png";
                } else if(file_exists($path_dir."android-chrome-512x512.png")) {
                    $array['icons'][$i]['sizes']="512x512";
                    $array['icons'][$i]['src']="android-chrome-512x512.png";
                } elseif (file_exists($path_dir . ".." . DIRECTORY_SEPARATOR . "custom" . DIRECTORY_SEPARATOR . "web-app-manifest-512x512.png")) {
                    $array['icons'][$i]['sizes']="512x512";
                    $array['icons'][$i]['src'] = "../custom/web-app-manifest-512x512.png";
                } elseif (file_exists($path_dir . ".." . DIRECTORY_SEPARATOR . "android-chrome-512x512.png")) {
                    $array['icons'][$i]['sizes']="512x512";
                    $array['icons'][$i]['src'] = "../android-chrome-512x512.png";
                } elseif (file_exists($path_dir . "web-app-manifest-192x192.png")) {
                    $array['icons'][$i]['sizes']="192x192";
                    $array['icons'][$i]['src'] = "web-app-manifest-192x192.png";
                } else if(file_exists($path_dir."android-chrome-192x192.png")) {
                    $array['icons'][$i]['sizes']="192x192";
                    $array['icons'][$i]['src']="android-chrome-192x192.png";
                } elseif (file_exists($path_dir . ".." . DIRECTORY_SEPARATOR . "custom" . DIRECTORY_SEPARATOR . "web-app-manifest-192x192.png")) {
                    $array['icons'][$i]['sizes']="192x192";
                    $array['icons'][$i]['src'] = "../custom/web-app-manifest-192x192.png";
                } elseif (file_exists($path_dir . ".." . DIRECTORY_SEPARATOR . "android-chrome-192x192.png")) {
                    $array['icons'][$i]['sizes']="192x192";
                    $array['icons'][$i]['src'] = "../android-chrome-192x192.png";
                }
            }
        }
    }
    $json = json_encode($array);
    file_put_contents($path_dir.'site.webmanifest',$json);
}

function get_client_ip() {
    $ipaddress = '';
    if (getenv('HTTP_CLIENT_IP'))
        $ipaddress = getenv('HTTP_CLIENT_IP');
    else if(getenv('HTTP_X_FORWARDED_FOR'))
        $ipaddress = getenv('HTTP_X_FORWARDED_FOR');
    else if(getenv('HTTP_X_FORWARDED'))
        $ipaddress = getenv('HTTP_X_FORWARDED');
    else if(getenv('HTTP_FORWARDED_FOR'))
        $ipaddress = getenv('HTTP_FORWARDED_FOR');
    else if(getenv('HTTP_FORWARDED'))
        $ipaddress = getenv('HTTP_FORWARDED');
    else if(getenv('REMOTE_ADDR'))
        $ipaddress = getenv('REMOTE_ADDR');
    else
        $ipaddress = 'UNKNOWN';
    return $ipaddress;
}

function fatal_handler() {
    global $debug,$date,$ip;
    $errfile = "unknown file";
    $errstr  = "shutdown";
    $errno   = E_CORE_ERROR;
    $errline = 0;
    $error = error_get_last();
    if($error !== NULL) {
        $errno   = $error["type"];
        $errfile = $error["file"];
        $errline = $error["line"];
        $errstr  = $error["message"];
        if($debug) {
            file_put_contents(realpath(dirname(__FILE__))."/log_favicons.txt",$date." - ".$ip." "."FATAL: ".format_error( $errno, $errstr, $errfile, $errline).PHP_EOL,FILE_APPEND);
        }
    }
}

function format_error( $errno, $errstr, $errfile, $errline ) {
    $trace = print_r( debug_backtrace( false ), true );
    $content = "File: $errfile, Error: $errstr, Line:$errline";
    return $content;
}

class PHP_ICO {
    var $_images = array();
    var $_has_requirements = false;
    function __construct( $file = false, $sizes = array() ) {
        $required_functions = array(
            'getimagesize', 'imagecreatefromstring', 'imagecreatetruecolor', 'imagecolortransparent',
            'imagecolorallocatealpha', 'imagealphablending', 'imagesavealpha', 'imagesx', 'imagesy',
            'imagecopyresampled',
        );
        foreach ( $required_functions as $function ) {
            if ( ! function_exists( $function ) ) {
                trigger_error( "The PHP_ICO class was unable to find the $function function, which is part of the GD library. Ensure that the system has the GD library installed and that PHP has access to it through a PHP interface, such as PHP's GD module. Since this function was not found, the library will be unable to create ICO files." );
                return;
            }
        }
        $this->_has_requirements = true;
        if ( false !== $file )
            $this->add_image( $file, $sizes );
    }
    function add_image( $file, $sizes = array() ) {
        if ( ! $this->_has_requirements ) return false;
        if ( false === ( $im = $this->_load_image_data( $file ) ) ) return false;
        if ( empty( $sizes ) ) $sizes = array( imagesx( $im ), imagesy( $im ) );
        if ( ! is_array( $sizes[0] ) ) $sizes = array( $sizes );
        foreach ( (array) $sizes as $size ) {
            list( $width, $height ) = $size;
            $new_im = imagecreatetruecolor( $width, $height );
            imagecolortransparent( $new_im, imagecolorallocatealpha( $new_im, 0, 0, 0, 127 ) );
            imagealphablending( $new_im, false );
            imagesavealpha( $new_im, true );
            $source_width = imagesx( $im );
            $source_height = imagesy( $im );
            if ( false === imagecopyresampled( $new_im, $im, 0, 0, 0, 0, $width, $height, $source_width, $source_height ) ) continue;
            $this->_add_image_data( $new_im );
        }
        return true;
    }
    function save_ico( $file ) {
        if ( ! $this->_has_requirements ) return false;
        if ( false === ( $data = $this->_get_ico_data() ) ) return false;
        if ( false === ( $fh = fopen( $file, 'w' ) ) ) return false;
        if ( false === ( fwrite( $fh, $data ) ) ) { fclose( $fh ); return false; }
        fclose( $fh );
        return true;
    }
    function _add_image_data( $im ) {
        $width = imagesx( $im );
        $height = imagesy( $im );
        $pixel_data = array();
        $opacity_data = array();
        $current_opacity_val = 0;
        for ( $y = $height - 1; $y >= 0; $y-- ) {
            for ( $x = 0; $x < $width; $x++ ) {
                $color = imagecolorat( $im, $x, $y );
                $alpha = ( $color & 0x7F000000 ) >> 24;
                $alpha = ( 1 - ( $alpha / 127 ) ) * 255;
                $color &= 0xFFFFFF;
                $color |= 0xFF000000 & ( $alpha << 24 );
                $pixel_data[] = $color;
                $opacity = ( $alpha <= 127 ) ? 1 : 0;
                $current_opacity_val = ( $current_opacity_val << 1 ) | $opacity;
                if ( ( ( $x + 1 ) % 32 ) == 0 ) {
                    $opacity_data[] = $current_opacity_val;
                    $current_opacity_val = 0;
                }
            }
            if ( ( $width % 32 ) > 0 ) {
                while ( ( $x++ % 32 ) > 0 )
                    $current_opacity_val = $current_opacity_val << 1;
                $opacity_data[] = $current_opacity_val;
                $current_opacity_val = 0;
            }
        }
        $image_header_size = 40;
        $color_mask_size = $width * $height * 4;
        $opacity_mask_size = ( ceil( $width / 32 ) * 4 ) * $height;
        $data = pack( 'VVVvvVVVVVV', 40, $width, ( $height * 2 ), 1, 32, 0, 0, 0, 0, 0, 0 );
        foreach ( $pixel_data as $color )
            $data .= pack( 'V', $color );
        foreach ( $opacity_data as $opacity )
            $data .= pack( 'N', $opacity );
        $image = array(
            'width'                => $width,
            'height'               => $height,
            'color_palette_colors' => 0,
            'bits_per_pixel'       => 32,
            'size'                 => $image_header_size + $color_mask_size + $opacity_mask_size,
            'data'                 => $data,
        );
        $this->_images[] = $image;
    }
    function _load_image_data( $file ) {
        if ( false === ( $data = file_get_contents( $file ) ) ) return false;
        if ( false === ( $im = imagecreatefromstring( $data ) ) ) return false;
        return $im;
    }
    function _get_ico_data() {
        if ( ! is_array( $this->_images ) || empty( $this->_images ) ) return false;
        $data = pack( 'vvv', 0, 1, count( $this->_images ) );
        $pixel_data_offset = 6 + ( count( $this->_images ) * 16 );
        foreach ( $this->_images as $image ) {
            $data .= pack( 'CCCCvvVV', $image['width'], $image['height'], $image['color_palette_colors'], 0, 1, $image['bits_per_pixel'], $image['size'], $pixel_data_offset );
            $pixel_data_offset += $image['size'];
        }
        foreach ( $this->_images as $image )
            $data .= $image['data'];
        return $data;
    }
}