WordPress.org

Make WordPress Core

Ticket #16434: trac-16434-05.patch

File trac-16434-05.patch, 56.0 KB (added by tomauger, 6 years ago)

Re-integrated ico library, large scale refactoring, same great taste.

  • wp-admin/css/wp-admin.dev.css

     
    48524852        vertical-align: middle;
    48534853}
    48544854
     4855.options-general-php img.favicon {
     4856        vertical-align:middle;
     4857       
     4858        -moz-box-shadow:    1px 1px 3px 0px #aaa;
     4859        -webkit-box-shadow: 1px 1px 3px 0px #aaa;
     4860        box-shadow:         1px 1px 3px 0px #aaa;
     4861}
    48554862
     4863#remove-favicon-button {
     4864        margin-left:5px;
     4865}
     4866
     4867/* Favicon upload error messages */
     4868#favicon-invalid-filetype-error {
     4869        display:none;
     4870        color:red;
     4871        font-style: italic;
     4872}
     4873
     4874
    48564875/*------------------------------------------------------------------------------
    48574876  21.0 - Admin Footer
    48584877------------------------------------------------------------------------------*/
  • wp-admin/favicon-upload.php

     
     1<?php
     2/**
     3 * Handles the uploading, cropping and scaling of favicons.
     4 *
     5 * @package WordPress
     6 * @subpackage Administration
     7 * @since 3.4.1
     8 */
     9
     10// Bootstrap admin and all its goodies
     11require_once( 'admin.php' );
     12
     13define( 'DEFAULT_FAVICON_SIZE', 32 ); // Width (and height) of the favicon (in pixels). Use 'favicon_size' filter to over-ride this value
     14
     15if (! current_user_can('manage_options') )
     16    wp_die( __( 'Cheatin&#8217; eh?' ) );
     17
     18check_admin_referer( 'favicon_upload-options' );
     19
     20$title = __( 'Crop Favicon' );
     21$parent_file = 'options-general.php';
     22
     23// Main workflow
     24// Favicon removal
     25if ( isset( $_REQUEST['REMOVE_FAVICON'] ) ) {
     26        remove_favicon();
     27        wp_redirect( admin_url( $parent_file ) );
     28        exit;
     29}
     30
     31// Process crop operation
     32if ( isset( $_POST['CROP_AND_SAVE'] ) ) {
     33        if ( isset( $_POST['attachment_id'] ) && is_numeric( $_POST['attachment_id'] ) ){
     34                $favicon_image_res = process_crop_thumbnail( $_POST['attachment_id'] );
     35                if (! is_wp_error( $favicon_image_res ) ){
     36                        if (! is_wp_error( generate_favicon_formats( $favicon_image_res, $_POST['attachment_id'] ) ) ){
     37                                // And save the basename out to options.
     38                                update_option( 'sitefavicon', basename( generate_favicon_basename( $_POST['attachment_id'] ) ) );
     39                                // We're done.
     40                                wp_redirect( admin_url( $parent_file ) );
     41                                exit;
     42                        } else {
     43                                _show_favicon_error_page( __( 'Error generating favicon files.' ) );
     44                        }
     45                } else {
     46                        _show_favicon_error_page( $image_basename->get_error_message() );
     47                }
     48        } else {
     49                _show_favicon_error_page();
     50        }
     51}
     52// Process image upload
     53else {
     54        $upload_results = process_thumbnail_upload();
     55       
     56        if (! is_wp_error( $upload_results ) ){
     57                // Does it need to be scaled / cropped?
     58                if ( $upload_results['width'] > 32 || $upload_results['height'] > 32 ){
     59                        display_crop_form( $upload_results );
     60                } else {
     61                        // Short-circuit the crop operation and just save the raw unscaled image
     62                        if (! is_wp_error( generate_favicon_formats( load_favicon_image( $upload_results['file'] ), $upload_results['attachment_id'] ) ) ){
     63                                // And save the basename out to options.
     64                                update_option( 'sitefavicon', basename( generate_favicon_basename( $upload_results['attachment_id'] ) ) );
     65                                wp_redirect( admin_url( $parent_file ) );
     66                                exit;
     67                        } else {
     68                                _show_favicon_error_page( __( 'Error generating favicon files.' ) );
     69                        }
     70                }
     71        } else {
     72                // Some kind of upload error
     73                _show_favicon_error_page( $upload_results->get_error_message() );
     74        }
     75}
     76
     77
     78/**
     79 * Generic utility function to display a general error message within the options page structure.
     80 *
     81 * @param string $message optional. A specific message describing the error condition for the end user.
     82 * @param string $title optional. The heading for this error.
     83 */
     84function _show_favicon_error_page( $message = '', $title = '' ){
     85        if ( empty( $message ) ) $message = __( 'Image upload failed. Please try again.' );
     86        if ( empty( $title ) ) $title = __( 'Favicon upload error' );
     87       
     88        include_once('./admin-header.php');
     89                echo '<div class="wrap favicon-error">';
     90                        echo "<h2>{$title}</h2>";
     91                        echo "<p>{$message}</p>";
     92                        echo '<p><a href="' . admin_url( $parent_file ) . '">&laquo;' . __( 'Back to Settings &gt; General' ) . '</a></p>';
     93                echo '</div><!-- .wrap -->';
     94        include_once('./admin-footer.php');
     95}
     96
     97/**
     98 * Process the image file upload and return a WP_Error or details about the attachment image file.
     99 * Image results will return an array consisting of:
     100 *              'attachment_id' => ID of the attachment DB record
     101 *              'src' => URL of the img src
     102 *              'width' => width ( = height )
     103 *              'type' => the image type
     104 *              'attr' => other attributes
     105 *              'file' => the uploaded file path
     106 *
     107 * @uses apply_filters( 'wp_favicon_max_crop_size' ) to set the maximum display size of the image in the crop form
     108 *
     109 * @return mixed WP_Error | $image_info array
     110 */
     111function process_thumbnail_upload(){
     112        $file = wp_handle_upload( $_FILES['avatarfile'], array( 'action' => 'update') );
     113        if ( isset($file['error']) ) die( $file['error'] );
     114       
     115        $url = $file['url'];
     116        $file = $file['file'];
     117       
     118        // Check image file format
     119        $image_type = exif_imagetype( $file );
     120        if (! in_array( $image_type, array( IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF, IMAGETYPE_ICO ) ) )
     121                return new WP_Error( 'bad_file_format', __( 'Please only use PNG (.png), JPEG (.jpg), GIF (.gif) or ICO (.ico) image files for favicons.' ) );
     122       
     123        $filename = basename( $file );
     124       
     125        // Construct the object array
     126        $object = array(
     127                'post_title' => $filename,
     128                'post_content' => $url,
     129                'post_mime_type' => 'import',
     130                'guid' => $url
     131        );
     132
     133        // Save the data.  Also makes replication work
     134        $id = wp_insert_attachment( $object, $file );
     135
     136        // Retrieve the image dimensions
     137        list( $width, $height, $type, $attr ) = getimagesize( $file );
     138
     139        return array(
     140                'attachment_id' => $id,
     141                'src' => $url,
     142                'width' => $width,
     143                'height' => $height,
     144                'type' => $type,
     145                'attr' => $attr,
     146                'file' => $file
     147        );
     148}
     149
     150
     151function load_favicon_image( $file ){
     152        $file_info = pathinfo( $file );
     153        if ( strtolower( $file_info['extension'] ) == 'ico' ){
     154                return imageCreateFromIco( $file, ICO_MAX_COLOR, ICO_MAX_SIZE );
     155        } else {
     156                return wp_load_image( $file );
     157        }
     158}
     159
     160
     161/**
     162 * Displays the form for cropping the thumbnail. Leverages the jcrop javascript library.
     163 *
     164 * @uses wp_create_thumbnail()
     165 *
     166 * @param array $image_info Array of properties as output by {@link process_thumbnail_upload()}
     167 */
     168function display_crop_form( $image_info ){
     169        // Do we need to scale down the image so we can display it nicely in the interactive Crop tool?
     170        $max_crop_display_size = apply_filters( 'wp_favicon_max_crop_size', 600 );
     171        if ( $image_info['width'] > $max_crop_display_size || $image_info['height'] > $max_crop_display_size ) {
     172                // Create and save a new thumbnail file at the new size
     173                $image = wp_create_thumbnail( $image_info['file'], $max_crop_display_size );
     174                list( $width, $height, $type, $attr ) = getimagesize( $image );
     175               
     176                 // Update the attachment record to reflect the newly-scaled thumbnail image
     177                $thumb = basename( $image );
     178                $metadata = array( 'thumb' => $thumb );
     179                wp_update_attachment_metadata( $id, $metadata );
     180
     181                $url = str_replace( basename( $url ), $thumb, $url );
     182
     183                $scaling = $image_info['width'] / $width;
     184        } else {
     185                // No scaling required; just copy original values.
     186                $width = $image_info['width'];
     187                $height = $image_info['height'];
     188                $scaling = 1;
     189        }
     190       
     191        /**
     192         * Display the crop form, leveraging the jcrop library.
     193         */
     194       
     195        // Enqueue the JS for the cropper...
     196        add_action( 'admin_enqueue_scripts', 'enqueue_cropper' );
     197        // ...and our own script for populating the crop form
     198        add_action( 'admin_footer', 'cropping_js', 10,  1);
     199       
     200        include_once('./admin-header.php');
     201
     202        echo '<div class="wrap">';
     203                // Now we can hook in our javascript and provide the width/height of our image as the default crop size
     204                $crop_size = min( $width, $height ); //because it's gotta be square...
     205                echo '<script type="text/javascript">var jcrop_starting_size = ' . $crop_size . '; // Initialize jcrop crop area starting size</script>';
     206       
     207                echo '<h2>' . __( 'Crop uploaded image' ) . '</h2>';
     208                echo '<p>' . __( 'Choose the part of the image you want to use for your favicon.' ) . '</p>';
     209               
     210                echo '<form id="favicon-crop-form" method="post" action="' . $_SERVER['REQUEST_URI'] . '">'; // Point the form action back to this script
     211        settings_fields( 'favicon_upload' );   
     212                ?>
     213                        <input type="hidden" name="x1" id="x1" />
     214                        <input type="hidden" name="y1" id="y1" />
     215                        <input type="hidden" name="x2" id="x2" />
     216                        <input type="hidden" name="y2" id="y2" />
     217                        <input type="hidden" name="width" id="width" />
     218                        <input type="hidden" name="height" id="height" />
     219                        <input type="hidden" name="attachment_id" id="attachment_id" value="<?php echo $image_info['attachment_id']?>" />
     220                        <input type="hidden" name="scaling_factor" id="scaling_factor" value="<?php echo $scaling ?>" />
     221                <?php
     222               
     223                        echo '<img src="' . $image_info['src'] . '" id="upload" width="' . $width . '" height="' . $height . '" />';           
     224                        echo '<p class="submit"><input type="submit" name="CROP_AND_SAVE" value="' . __( 'Crop image' ) . ' &raquo;" /></p>';
     225                echo '</form>';
     226       
     227        echo '</div><!-- .wrap -->';
     228       
     229        include_once('./admin-footer.php');
     230}
     231
     232/**
     233 * Create PNG and BMP image resources based on the form submission of the cropped thumbnail.
     234 *
     235 * @uses apply_filters( 'favicon_size' ) to set the favicon size in pixels.
     236 *
     237 * @param int $attachment_id The ID of the original attachment's post record.
     238 * @return mixed WP_Error | scaled and cropped image resource
     239 */
     240function process_crop_thumbnail( $attachment_id ){
     241        $src_file = get_attached_file( $attachment_id );
     242
     243        // Highly unlikely, but let's check
     244        if (! file_exists( $src_file ) )
     245                return new WP_Error( 'file_missing', __( 'Attachment image file missing (possible save error: check space on web server).' ) );
     246
     247        // Make sure we're still within accepted image types
     248        $image_type = exif_imagetype( $src_file );
     249        if (! $image_type || ! in_array( $image_type, array( IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_BMP ) ) )
     250                return new WP_Error( 'bad_file_format', __( 'Please only use PNG (.png), JPEG (.jpg) or BMP (.bmp) image files for favicons. ' ) );
     251
     252        // Parse image file bytes
     253        $src_image = wp_load_image( $src_file );
     254        if ( !is_resource($src_image) )
     255                return new WP_Error( 'is_not_resource', __( 'Error loading image. You got me: I\'m stumped.' ) );
     256
     257        // We crop from the original, not the medium sized, display-only thumbnail
     258        $src_x = $_POST['x1'] * $_POST['scaling_factor'];
     259        $src_y = $_POST['y1'] * $_POST['scaling_factor'];
     260        $src_width = $_POST['width'] * $_POST['scaling_factor'];
     261        $src_height = $_POST['height'] * $_POST['scaling_factor'];
     262
     263        $dst_width = $dst_height = apply_filters( 'favicon_size', DEFAULT_FAVICON_SIZE );
     264        // Avoid upscaling
     265        if ( $src_width < $dst_width || $src_height < $dst_height ) {
     266                $dst_width = $src_width;
     267                $dst_height = $src_height;
     268        }
     269
     270        $dst_image = wp_imagecreatetruecolor( $dst_width, $dst_height );
     271        if ( function_exists( 'imageantialias' ) ) imageantialias( $dst_image, true );
     272        imagealphablending( $dst_image, false );
     273        imagesavealpha( $dst_image, true );
     274        imagecopyresampled( $dst_image, $src_image, 0, 0, $src_x, $src_y, $dst_width, $dst_height, $src_width, $src_height );
     275        imagedestroy( $src_image );
     276
     277        return $dst_image;
     278}
     279
     280/**
     281 * Generate the base filename. The .png and .ico versions will be this base name + the appropriate 3 letter extension (tla)
     282 * This will be in the form of "filename-32x32" where '32' in this case is replaced by the actual icon dimensions
     283 *
     284 * @param int $attachment_id The uploaded (and possibly cropped) attachment ID
     285 * @returns string the base name of the favicon thumbnail, stripped of any file extension
     286 */
     287function generate_favicon_basename( $attachment_id ) {
     288        /** @TODO rename and move this to image.php and refactor image_resize() to use this function so we're not duplicating efforts */
     289        $src_file = get_attached_file( $attachment_id );
     290       
     291        list ( $width, $height ) = getimagesize( $src_file );
     292
     293        $file_info = pathinfo( $src_file );
     294        $src_basename = basename( $src_file, '.' . $file_info['extension'] );
     295        $dst_filename = str_replace( $src_basename, $src_basename . '-' . $width . 'x' . $height, $src_file );
     296        // Strip the TLA from the filename (shouldn't be there anymore, but you can't be too careful...)
     297        $dst_filename = preg_replace( '/\\.[^\\.]+$/', '', $dst_filename );
     298       
     299        return $dst_filename;
     300}
     301
     302/**
     303 * Creates and saves out the PNG and the ICO version of the thumbnail, when provided with the source resource.
     304 * Also creates an attachment record for each.
     305 *
     306 * @uses save_thumbnail_attachment();
     307 *
     308 * @param type $source_image_resource
     309 * @param type $file_basename
     310 * @return \WP_Error
     311 */
     312function generate_favicon_formats( $source_image_resource, $attachment_id ) {
     313        if (! is_resource( $source_image_resource ) ) die( 'No resource provided. Cannot generate favicon files.' );
     314
     315        $file_basename = generate_favicon_basename( $attachment_id );
     316       
     317        // Save out the PNG
     318        $png_filename = $file_basename . '.png';
     319        if (! imagepng( $source_image_resource, $png_filename, 0 ) )
     320                return new WP_Error( 'png_write_error', 'Error writing PNG favicon file.' );
     321        save_thumbnail_attachment( $png_filename, $attachment_id );
     322       
     323        //Save out the ICO
     324        $ico_filename = $file_basename . '.ico';
     325        imageIco( $source_image_resource, $ico_filename );
     326        /** @TODO refactor the ico2_3.php library to add error checking and possibly encapsulate the class */
     327        //if (! imageIco( $dst_image, $ico_filename ) )
     328                //return new WP_Error( 'ico_write_error', 'Error writing ICO favicon file.' );
     329                save_thumbnail_attachment( $ico_filename, $attachment_id );
     330
     331        imagedestroy( $dst_image );
     332}
     333
     334/**
     335 * Creates an attachment post record for a newly created thumbnail
     336 *
     337 * @param string $file_name Fully qualified file name for the image asset file.
     338 * @param int $parent_attachment_id The ID of the original thumbnail's attachment post record
     339 *
     340 * @return int The ID of the newly-created thumbnail attachment post record
     341 */
     342function save_thumbnail_attachment( $file_name, $parent_attachment_id ){
     343        $file_info = pathinfo( $file_name ); // So we can get the TLA later on
     344       
     345        $file_name = apply_filters( 'wp_create_file_in_uploads', $file_name, $parent_attachment_id ); // For replication
     346
     347        $parent = get_post( $parent_attachment_id );
     348        $parent_url = $parent->guid;
     349       
     350        // Update the attachment
     351        $mimes = get_allowed_mime_types();
     352        $attachment_id = wp_insert_attachment( array(
     353                'post_title' => basename( $file_name ),
     354                'post_mime_type' => $mimes[ $file_info['extension'] ],
     355                'context' => 'favicon'
     356        ), $file_name );
     357        wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $file_name ) );
     358       
     359        return $attachment_id;
     360}
     361
     362/**
     363 * Currently, doesn't actually "remove" the favicon images. It only deletes the option
     364 * that tells us there's a favicon, so the code isn't generated (or the default is used)
     365 */
     366function remove_favicon(){
     367        update_option( 'sitefavicon', false );
     368                       
     369        /** @TODO need to find a way to notify the user that the process has completed successfully - admin_notices? */
     370}
     371
     372
     373/**
     374 * Called in admin_enqueue_scripts to add the cropper.js script and styles
     375 */
     376function enqueue_cropper(){
     377        wp_enqueue_script( 'jcrop', 'jquery' );
     378        wp_enqueue_style('jcrop'); // We can enqueue styles within the admin_enqueue_script action hook {@link http://wpdevel.wordpress.com/2011/12/12/use-wp_enqueue_scripts-not-wp_print_styles-to-enqueue-scripts-and-styles-for-the-frontend/}
     379}
     380
     381/**
     382 * Output the JavaScript that drives the jcrop cropping process.
     383 *
     384 * @uses apply_filters( 'favicon_size' ) to set the favicon size in pixels
     385 */
     386function cropping_js(){
     387        // Purely for coding convenience and legibility
     388        $favicon_size = apply_filters( 'favicon_size', DEFAULT_FAVICON_SIZE );
     389       
     390        echo <<<CROP_JS
     391        <!-- Favicon cropping -->
     392        <script type="text/javascript">
     393                // Update the crop form
     394                function onEndCrop( coords ) {
     395                        jQuery( '#x1' ).val(coords.x);
     396                        jQuery( '#y1' ).val(coords.y);
     397                        jQuery( '#x2' ).val(coords.x2);
     398                        jQuery( '#y2' ).val(coords.y2);
     399                        jQuery( '#width' ).val(coords.w);
     400                        jQuery( '#height' ).val(coords.h);
     401                }
     402
     403                // with a supplied ratio
     404                jQuery(function($) {
     405                        if (! jcrop_starting_size) jcrop_starting_size = {$favicon_size}; // jcrop_starting_size should be set in the body once the image has been processed
     406
     407                        // Set up default values on the crop form
     408                        jQuery( '#x1' ).val(0);
     409                        jQuery( '#y1' ).val(0);
     410                        jQuery( '#x2' ).val(jcrop_starting_size);
     411                        jQuery( '#y2' ).val(jcrop_starting_size);
     412                        jQuery( '#width' ).val(jcrop_starting_size);
     413                        jQuery( '#height' ).val(jcrop_starting_size);
     414
     415                        // Initialize Jcrop
     416                        $('#upload').Jcrop({
     417                                aspectRatio: 1,
     418                                setSelect: [0, 0, jcrop_starting_size, jcrop_starting_size],
     419                                onSelect: onEndCrop
     420                        });
     421                });
     422        </script>
     423CROP_JS;
     424
     425}
     426
     427
     428
     429
     430
     431
     432/**
     433 * @package com.jpexs.image.ico
     434 *
     435 * JPEXS ICO Image functions
     436 * @version 2.3
     437 * @author JPEXS
     438 * @copyright (c) JPEXS 2004-2012
     439 *
     440 * Webpage: http://www.jpexs.com
     441 * Email: jpexs@jpexs.com
     442 *
     443 * If you like my script, you can donate... visit my webpages or email me for more info.
     444 *
     445 *        Version changes:
     446 *          2012-02-25 v2.3 - License changed to GNU/GPL v2 or v3
     447 *          2012-02-18 v2.2 - License changed to GNU/GPL v3
     448 *          2009-02-23 v2.1 - redesigned sourcecode, phpdoc included, all internal functions and global variables have prefix "jpexs_"
     449 *                     v2.0 - For icons with Alpha channel now you can set background color
     450 *                          - ImageCreateFromExeIco added
     451 *                          - Fixed ICO_MAX_SIZE and ICO_MAX_COLOR values
     452 *
     453 * TODO list:
     454 *      - better error handling
     455 *      - better internal function handling
     456 *      - class encapsulation
     457 *
     458 * License:
     459 *  This program is free software: you can redistribute it and/or modify
     460 *  it under the terms of the GNU General Public License as published by
     461 *  the Free Software Foundation, either version 2 or version 3 of the License, or
     462 *  (at your option) any later version.
     463 *
     464 *  This program is distributed in the hope that it will be useful,
     465 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     466 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     467 *  GNU General Public License for more details.
     468 *
     469 *  You should have received a copy of the GNU General Public License
     470 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
     471 */
     472
     473/** TrueColor images constant  */
     474define( "ICO_TRUE_COLOR", 0x1000000 );
     475/** XPColor images constant (Alpha channel) */
     476define( "ICO_XP_COLOR", 4294967296 );
     477/** Image with maximum colors */
     478define( "ICO_MAX_COLOR", -2 );
     479/** Image with maximal size */
     480define( "ICO_MAX_SIZE", -2 );
     481
     482
     483/** TrueColor images constant
     484 * @deprecated Deprecated since version 2.1, please use ICO_ constants
     485 */
     486define( "TRUE_COLOR", 0x1000000 );
     487/** XPColor images constant (Alpha channel)
     488 * @deprecated Deprecated since version 2.1, please use ICO_ constants
     489 */
     490define( "XP_COLOR", 4294967296 );
     491/** Image with maximum colors
     492 * @deprecated Deprecated since version 2.1, please use ICO_ constants
     493 */
     494define( "MAX_COLOR", -2 );
     495/** Image with maximal size
     496 * @deprecated Deprecated since version 2.1, please use ICO_ constants
     497 */
     498define( "MAX_SIZE", -2 );
     499
     500
     501/**
     502 * Reads image from a ICO file
     503 *
     504 * @param string $filename Target ico file to load
     505 * @param int $icoColorCount Icon color count (For multiple icons ico file) - 2,16,256, ICO_TRUE_COLOR, ICO_XP_COLOR or ICO_MAX_COLOR
     506 * @param int $icoSize Icon width (For multiple icons ico file) or ICO_MAX_SIZE
     507 * @param int $alphaBgR Background color R value for alpha-channel images (Default is White)
     508 * @param int $alphaBgG Background color G value for alpha-channel images (Default is White)
     509 * @param int $alphaBgB Background color B value for alpha-channel images (Default is White)
     510 * @return resource Image resource
     511 */
     512function imageCreateFromIco( $filename, $icoColorCount = 16, $icoSize = 16, $alphaBgR = 255, $alphaBgG = 255, $alphaBgB = 255 ) {
     513        $Ikona = jpexs_GetIconsInfo( $filename );
     514       
     515        $IconID = -1;
     516       
     517        $ColMax = -1;
     518        $SizeMax = -1;
     519       
     520        for ( $p = 0; $p < count( $Ikona ); $p++ ) {
     521                $Ikona[ $p ][ "NumberOfColors" ] = pow( 2, $Ikona[ $p ][ "Info" ][ "BitsPerPixel" ] );
     522        }
     523       
     524       
     525        for ( $p = 0; $p < count( $Ikona ); $p++ ) {
     526                if ( ( $ColMax == -1 ) or ( $Ikona[ $p ][ "NumberOfColors" ] >= $Ikona[ $ColMax ][ "NumberOfColors" ] ) )
     527                        if ( ( $icoSize == $Ikona[ $p ][ "Width" ] ) or ( $icoSize == ICO_MAX_SIZE ) ) {
     528                                $ColMax = $p;
     529                        }
     530               
     531                if ( ( $SizeMax == -1 ) or ( $Ikona[ $p ][ "Width" ] >= $Ikona[ $SizeMax ][ "Width" ] ) )
     532                        if ( ( $icoColorCount == $Ikona[ $p ][ "NumberOfColors" ] ) or ( $icoColorCount == ICO_MAX_COLOR ) ) {
     533                                $SizeMax = $p;
     534                        }
     535               
     536               
     537                if ( $Ikona[ $p ][ "NumberOfColors" ] == $icoColorCount )
     538                        if ( $Ikona[ $p ][ "Width" ] == $icoSize ) {
     539                                $IconID = $p;
     540                        }
     541        }
     542       
     543        if ( $icoColorCount == ICO_MAX_COLOR )
     544                $IconID = $ColMax;
     545        if ( $icoSize == ICO_MAX_SIZE )
     546                $IconID = $SizeMax;
     547       
     548        $ColName = $icoColorCount;
     549       
     550        if ( $icoSize == ICO_MAX_SIZE )
     551                $icoSize = "Max";
     552        if ( $ColName == ICO_TRUE_COLOR )
     553                $ColName = "True";
     554        if ( $ColName == ICO_XP_COLOR )
     555                $ColName = "XP";
     556        if ( $ColName == ICO_MAX_COLOR )
     557                $ColName = "Max";
     558        if ( $IconID == -1 )
     559                die( "Icon with $ColName colors and $icoSize x $icoSize size doesn't exist in this file!" );
     560       
     561       
     562        jpexs_readIcon( $filename, $IconID, $Ikona );
     563       
     564        $biBitCount = $Ikona[ $IconID ][ "Info" ][ "BitsPerPixel" ];
     565       
     566       
     567        if ( $Ikona[ $IconID ][ "Info" ][ "BitsPerPixel" ] == 0 ) {
     568                $Ikona[ $IconID ][ "Info" ][ "BitsPerPixel" ] = 24;
     569        }
     570       
     571        $biBitCount = $Ikona[ $IconID ][ "Info" ][ "BitsPerPixel" ];
     572        if ( $biBitCount == 0 )
     573                $biBitCount = 1;
     574       
     575       
     576        $Ikona[ $IconID ][ "BitCount" ] = $Ikona[ $IconID ][ "Info" ][ "BitsPerPixel" ];
     577       
     578       
     579       
     580        if ( $Ikona[ $IconID ][ "BitCount" ] >= 24 ) {
     581                $img = imagecreatetruecolor( $Ikona[ $IconID ][ "Width" ], $Ikona[ $IconID ][ "Height" ] );
     582                if ( $Ikona[ $IconID ][ "BitCount" ] == 32 ):
     583                        $backcolor = imagecolorallocate( $img, $alphaBgR, $alphaBgG, $alphaBgB );
     584                        imagefilledrectangle( $img, 0, 0, $Ikona[ $IconID ][ "Width" ] - 1, $Ikona[ $IconID ][ "Height" ] - 1, $backcolor );
     585                endif;
     586                for ( $y = 0; $y < $Ikona[ $IconID ][ "Height" ]; $y++ )
     587                        for ( $x = 0; $x < $Ikona[ $IconID ][ "Width" ]; $x++ ) {
     588                                $R = $Ikona[ $IconID ][ "Data" ][ $x ][ $y ][ "r" ];
     589                                $G = $Ikona[ $IconID ][ "Data" ][ $x ][ $y ][ "g" ];
     590                                $B = $Ikona[ $IconID ][ "Data" ][ $x ][ $y ][ "b" ];
     591                                if ( $Ikona[ $IconID ][ "BitCount" ] == 32 ) {
     592                                        $Alpha = 127 - round( $Ikona[ $IconID ][ "Data" ][ $x ][ $y ][ "alpha" ] * 127 / 255 );
     593                                        if ( $Ikona[ $IconID ][ "Maska" ][ $x ][ $y ] == 1 )
     594                                                $Alpha = 127;
     595                                        $color = imagecolorexactalpha( $img, $R, $G, $B, $Alpha );
     596                                        if ( $color == -1 )
     597                                                $color = imagecolorallocatealpha( $img, $R, $G, $B, $Alpha );
     598                                } else {
     599                                        $color = imagecolorexact( $img, $R, $G, $B );
     600                                        if ( $color == -1 )
     601                                                $color = imagecolorallocate( $img, $R, $G, $B );
     602                                }
     603                               
     604                                imagesetpixel( $img, $x, $y, $color );
     605                               
     606                        }
     607               
     608        } else {
     609                $img = imagecreate( $Ikona[ $IconID ][ "Width" ], $Ikona[ $IconID ][ "Height" ] );
     610                for ( $p = 0; $p < count( $Ikona[ $IconID ][ "Paleta" ] ); $p++ )
     611                        $Paleta[ $p ] = imagecolorallocate( $img, $Ikona[ $IconID ][ "Paleta" ][ $p ][ "r" ], $Ikona[ $IconID ][ "Paleta" ][ $p ][ "g" ], $Ikona[ $IconID ][ "Paleta" ][ $p ][ "b" ] );
     612               
     613                for ( $y = 0; $y < $Ikona[ $IconID ][ "Height" ]; $y++ )
     614                        for ( $x = 0; $x < $Ikona[ $IconID ][ "Width" ]; $x++ ) {
     615                                imagesetpixel( $img, $x, $y, $Paleta[ $Ikona[ $IconID ][ "Data" ][ $x ][ $y ] ] );
     616                        }
     617        }
     618        $IsTransparent = false;
     619        for ( $y = 0; $y < $Ikona[ $IconID ][ "Height" ]; $y++ )
     620                for ( $x = 0; $x < $Ikona[ $IconID ][ "Width" ]; $x++ )
     621                        if ( $Ikona[ $IconID ][ "Maska" ][ $x ][ $y ] == 1 ) {
     622                                $IsTransparent = true;
     623                                break;
     624                        }
     625        if ( $Ikona[ $IconID ][ "BitCount" ] == 32 ) {
     626                imagealphablending( $img, false );
     627                if ( function_exists( "imagesavealpha" ) )
     628                        imagesavealpha( $img, true );
     629        }
     630       
     631        if ( $IsTransparent ) {
     632                if ( ( $Ikona[ $IconID ][ "BitCount" ] >= 24 ) or ( imagecolorstotal( $img ) >= 256 ) ) {
     633                        $img2 = imagecreatetruecolor( imagesx( $img ), imagesy( $img ) );
     634                        imagecopy( $img2, $img, 0, 0, 0, 0, imagesx( $img ), imagesy( $img ) );
     635                        imagedestroy( $img );
     636                        $img = $img2;
     637                        imagetruecolortopalette( $img, true, 255 );
     638                       
     639                }
     640                $Pruhledna = imagecolorallocate( $img, 0, 0, 0 );
     641                for ( $y = 0; $y < $Ikona[ $IconID ][ "Height" ]; $y++ )
     642                        for ( $x = 0; $x < $Ikona[ $IconID ][ "Width" ]; $x++ )
     643                                if ( $Ikona[ $IconID ][ "Maska" ][ $x ][ $y ] == 1 ) {
     644                                        imagesetpixel( $img, $x, $y, $Pruhledna );
     645                                }
     646                imagecolortransparent( $img, $Pruhledna );
     647        }
     648       
     649        return $img;
     650       
     651       
     652}
     653
     654
     655
     656
     657function jpexs_readIcon( $filename, $id, &$Ikona ) {
     658        global $jpexs_currentBit;
     659       
     660        $f = fopen( $filename, "rb" );
     661       
     662        fseek( $f, 6 + $id * 16 );
     663        $Width = jpexs_freadbyte( $f );
     664        $Height = jpexs_freadbyte( $f );
     665        fseek( $f, 6 + $id * 16 + 12 );
     666        $OffSet = jpexs_freaddword( $f );
     667        fseek( $f, $OffSet );
     668       
     669        $p = $id;
     670       
     671        $Ikona[ $p ][ "Info" ][ "HeaderSize" ] = jpexs_freadlngint( $f );
     672        $Ikona[ $p ][ "Info" ][ "ImageWidth" ] = jpexs_freadlngint( $f );
     673        $Ikona[ $p ][ "Info" ][ "ImageHeight" ] = jpexs_freadlngint( $f );
     674        $Ikona[ $p ][ "Info" ][ "NumberOfImagePlanes" ] = jpexs_freadword( $f );
     675        $Ikona[ $p ][ "Info" ][ "BitsPerPixel" ] = jpexs_freadword( $f );
     676        $Ikona[ $p ][ "Info" ][ "CompressionMethod" ] = jpexs_freadlngint( $f );
     677        $Ikona[ $p ][ "Info" ][ "SizeOfBitmap" ] = jpexs_freadlngint( $f );
     678        $Ikona[ $p ][ "Info" ][ "HorzResolution" ] = jpexs_freadlngint( $f );
     679        $Ikona[ $p ][ "Info" ][ "VertResolution" ] = jpexs_freadlngint( $f );
     680        $Ikona[ $p ][ "Info" ][ "NumColorUsed" ] = jpexs_freadlngint( $f );
     681        $Ikona[ $p ][ "Info" ][ "NumSignificantColors" ] = jpexs_freadlngint( $f );
     682       
     683       
     684        $biBitCount = $Ikona[ $p ][ "Info" ][ "BitsPerPixel" ];
     685       
     686        if ( $Ikona[ $p ][ "Info" ][ "BitsPerPixel" ] <= 8 ) {
     687                $barev = pow( 2, $biBitCount );
     688               
     689                for ( $b = 0; $b < $barev; $b++ ) {
     690                        $Ikona[ $p ][ "Paleta" ][ $b ][ "b" ] = jpexs_freadbyte( $f );
     691                        $Ikona[ $p ][ "Paleta" ][ $b ][ "g" ] = jpexs_freadbyte( $f );
     692                        $Ikona[ $p ][ "Paleta" ][ $b ][ "r" ] = jpexs_freadbyte( $f );
     693                        jpexs_freadbyte( $f );
     694                }
     695               
     696                $Zbytek = ( 4 - ceil( ( $Width / ( 8 / $biBitCount ) ) ) % 4 ) % 4;
     697               
     698               
     699                for ( $y = $Height - 1; $y >= 0; $y-- ) {
     700                        $jpexs_currentBit = 0;
     701                        for ( $x = 0; $x < $Width; $x++ ) {
     702                                $C = jpexs_freadbits( $f, $biBitCount );
     703                                $Ikona[ $p ][ "Data" ][ $x ][ $y ] = $C;
     704                        }
     705                       
     706                        if ( $jpexs_currentBit != 0 ) {
     707                                jpexs_freadbyte( $f );
     708                        }
     709                        for ( $g = 0; $g < $Zbytek; $g++ )
     710                                jpexs_freadbyte( $f );
     711                }
     712               
     713        } elseif ( $biBitCount == 24 ) {
     714                $Zbytek = $Width % 4;
     715               
     716                for ( $y = $Height - 1; $y >= 0; $y-- ) {
     717                        for ( $x = 0; $x < $Width; $x++ ) {
     718                                $B = jpexs_freadbyte( $f );
     719                                $G = jpexs_freadbyte( $f );
     720                                $R = jpexs_freadbyte( $f );
     721                                $Ikona[ $p ][ "Data" ][ $x ][ $y ][ "r" ] = $R;
     722                                $Ikona[ $p ][ "Data" ][ $x ][ $y ][ "g" ] = $G;
     723                                $Ikona[ $p ][ "Data" ][ $x ][ $y ][ "b" ] = $B;
     724                        }
     725                        for ( $z = 0; $z < $Zbytek; $z++ )
     726                                jpexs_freadbyte( $f );
     727                }
     728        } elseif ( $biBitCount == 32 ) {
     729                $Zbytek = $Width % 4;
     730               
     731                for ( $y = $Height - 1; $y >= 0; $y-- ) {
     732                        for ( $x = 0; $x < $Width; $x++ ) {
     733                                $B = jpexs_freadbyte( $f );
     734                                $G = jpexs_freadbyte( $f );
     735                                $R = jpexs_freadbyte( $f );
     736                                $Alpha = jpexs_freadbyte( $f );
     737                                $Ikona[ $p ][ "Data" ][ $x ][ $y ][ "r" ] = $R;
     738                                $Ikona[ $p ][ "Data" ][ $x ][ $y ][ "g" ] = $G;
     739                                $Ikona[ $p ][ "Data" ][ $x ][ $y ][ "b" ] = $B;
     740                                $Ikona[ $p ][ "Data" ][ $x ][ $y ][ "alpha" ] = $Alpha;
     741                        }
     742                        for ( $z = 0; $z < $Zbytek; $z++ )
     743                                jpexs_freadbyte( $f );
     744                }
     745        }
     746       
     747       
     748        //Maska
     749        $Zbytek = ( 4 - ceil( ( $Width / ( 8 ) ) ) % 4 ) % 4;
     750        for ( $y = $Height - 1; $y >= 0; $y-- ) {
     751                $jpexs_currentBit = 0;
     752                for ( $x = 0; $x < $Width; $x++ ) {
     753                        $C = jpexs_freadbits( $f, 1 );
     754                        $Ikona[ $p ][ "Maska" ][ $x ][ $y ] = $C;
     755                }
     756                if ( $jpexs_currentBit != 0 ) {
     757                        jpexs_freadbyte( $f );
     758                }
     759                for ( $g = 0; $g < $Zbytek; $g++ )
     760                        jpexs_freadbyte( $f );
     761        }
     762        //--------------
     763       
     764        fclose( $f );
     765       
     766}
     767
     768function jpexs_GetIconsInfo( $filename ) {
     769        global $jpexs_currentBit;
     770       
     771        $f = fopen( $filename, "rb" );
     772       
     773        $Reserved = jpexs_freadword( $f );
     774        $Type = jpexs_freadword( $f );
     775        $Count = jpexs_freadword( $f );
     776        for ( $p = 0; $p < $Count; $p++ ) {
     777                $Ikona[ $p ][ "Width" ] = jpexs_freadbyte( $f );
     778                $Ikona[ $p ][ "Height" ] = jpexs_freadbyte( $f );
     779                $Ikona[ $p ][ "ColorCount" ] = jpexs_freadword( $f );
     780                if ( $Ikona[ $p ][ "ColorCount" ] == 0 )
     781                        $Ikona[ $p ][ "ColorCount" ] = 256;
     782                $Ikona[ $p ][ "Planes" ] = jpexs_freadword( $f );
     783                $Ikona[ $p ][ "BitCount" ] = jpexs_freadword( $f );
     784                $Ikona[ $p ][ "BytesInRes" ] = jpexs_freaddword( $f );
     785                $Ikona[ $p ][ "ImageOffset" ] = jpexs_freaddword( $f );
     786        }
     787       
     788        if ( !feof( $f ) ):
     789                for ( $p = 0; $p < $Count; $p++ ) {
     790                        fseek( $f, $Ikona[ $p ][ "ImageOffset" ] + 14 );
     791                        $Ikona[ $p ][ "Info" ][ "BitsPerPixel" ] = jpexs_freadword( $f );
     792                }
     793        endif;
     794        fclose( $f );
     795        return $Ikona;
     796}
     797
     798
     799
     800
     801/**
     802 * Reads image from a icon in exe file
     803 * @param string $filename Target exefile
     804 * @param int $icoIndex Index of the icon in exefile
     805 * @param int $icoColorCount Icon color count (For multiple icons ico file) - 2,16,256, ICO_TRUE_COLOR, ICO_XP_COLOR or ICO_MAX_COLOR
     806 * @param int $icoSize Icon width (For multiple icons ico file) or ICO_MAX_SIZE
     807 * @param int $alphaBgR Background color R value for alpha-channel images (Default is White)
     808 * @param int $alphaBgG Background color G value for alpha-channel images (Default is White)
     809 * @param int $alphaBgB Background color B value for alpha-channel images (Default is White)
     810 * @return resource Image resource or false on error
     811 */
     812function imageCreateFromExeIco( $filename, $icoIndex, $icoColorCount = 16, $icoSize = 16, $alphaBgR = 255, $alphaBgG = 255, $alphaBgB = 255 ) {
     813        $ok = saveExeIcon( $filename, "icotemp.dat", $icoIndex );
     814        if ( !$ok ):
     815                $im = false;
     816        else:
     817                $im = imageCreateFromIco( "icotemp.dat", $icoColorCount, $icoSize, $alphaBgR, $alphaBgG, $alphaBgB );
     818                unlink( "icotemp.dat" );
     819        endif;
     820        return $im;
     821}
     822
     823
     824/**
     825 * Saves icon(s) from the exe file
     826 * @global int $jpexs_StartOfRsrc Internal reserved variable
     827 * @global int $jpexs_ImageBase Internal reserved variable
     828 * @global int $jpexs_ResVirtualAddress Internal reserved variable
     829 * @param string $filename Target exefile
     830 * @param string $icoFileNameOrPath Filename to save ico or path (Default "") Path if you want more than 1 icon. If "", the filename is "$icoIndex.ico"
     831 * @param int|array $iconIndex Index(es) of the icon in exefile  (Default -1) If -1, all icons are saved, Can be an array of indexes.
     832 * @return boolean True on successful save
     833 */
     834function saveExeIcon( $filename, $icoFileNameOrPath = "", $iconIndex = -1 ) /*-1 for all,or can be array*/ {
     835        global $jpexs_f, $jpexs_StartOfRsrc, $jpexs_ImageBase, $jpexs_ResVirtualAddress;
     836        $jpexs_f = fopen( $filename, "r" );
     837        $MZ = fread( $jpexs_f, 2 );
     838        if ( $MZ != "MZ" )
     839                NotValidExe();
     840        fseek( $jpexs_f, 60 );
     841        $OffsetToNewHeader = jpexs_freaddword( $jpexs_f );
     842        fseek( $jpexs_f, $OffsetToNewHeader );
     843        $PE = fread( $jpexs_f, 2 );
     844        if ( $PE != "PE" )
     845                NotValidExe();
     846        fread( $jpexs_f, 4 );
     847        $NumberOfSections = jpexs_freadword( $jpexs_f );
     848        fseek( $jpexs_f, ftell( $jpexs_f ) + 12 );
     849        $SizeOfOptionalHeader = jpexs_freadword( $jpexs_f );
     850        $PosMagic = ftell( $jpexs_f ) + 2;
     851        fseek( $jpexs_f, $PosMagic + $SizeOfOptionalHeader );
     852       
     853        for ( $p = 0; $p < $NumberOfSections; $p++ ):
     854                $SectionName[ $p ] = trim( fread( $jpexs_f, 8 ) );
     855                $VirtualSize[ $p ] = jpexs_freaddword( $jpexs_f );
     856                $VirtualAddress[ $p ] = jpexs_freaddword( $jpexs_f );
     857                $PhysicalSize[ $p ] = jpexs_freaddword( $jpexs_f );
     858                $PhysicalOffset[ $p ] = jpexs_freaddword( $jpexs_f );
     859                fread( $jpexs_f, 16 );
     860                if ( $SectionName[ $p ] == ".rsrc" ):
     861                        $jpexs_ResVirtualAddress = $VirtualAddress[ $p ];
     862                        fseek( $jpexs_f, $PhysicalOffset[ $p ] );
     863                        $jpexs_StartOfRsrc = $PhysicalOffset[ $p ];
     864                        jpexs_readResDirectoryEntry( $R, $PhysicalOffset[ $p ] );
     865                        $IconCount = null;
     866                        $Ikona = null;
     867                        while ( list( $key, $val ) = each( $R[ "Subdir" ] ) ):
     868                                if ( $key == 14 ):
     869                                        $r = 0;
     870                                        while ( list( $key2, $val2 ) = each( $R[ "Subdir" ][ $key ][ "Subdir" ] ) ):
     871                                                while ( list( $key3, $val3 ) = each( $R[ "Subdir" ][ $key ][ "Subdir" ][ $key2 ][ "Subdir" ] ) ):
     872                                                        fseek( $jpexs_f, $val3[ "DataOffset" ] );
     873                                                        $Reserved = jpexs_freadword( $jpexs_f );
     874                                                        $Type = jpexs_freadword( $jpexs_f );
     875                                                        $ic = jpexs_freadword( $jpexs_f );
     876                                                        $IconCount[] = $ic;
     877                                                        for ( $s = 0; $s < $ic; $s++ ) {
     878                                                                $Ikona[ $r ][ $s ][ "Width" ] = jpexs_freadbyte( $jpexs_f );
     879                                                                $Ikona[ $r ][ $s ][ "Height" ] = jpexs_freadbyte( $jpexs_f );
     880                                                                $Ikona[ $r ][ $s ][ "ColorCount" ] = jpexs_freadword( $jpexs_f );
     881                                                                $Ikona[ $r ][ $s ][ "Planes" ] = jpexs_freadword( $jpexs_f );
     882                                                                $Ikona[ $r ][ $s ][ "BitCount" ] = jpexs_freadword( $jpexs_f );
     883                                                                $Ikona[ $r ][ $s ][ "BytesInRes" ] = jpexs_freaddword( $jpexs_f );
     884                                                                $Ikona[ $r ][ $s ][ "IconId" ] = jpexs_freadword( $jpexs_f );
     885                                                        }
     886                                                        fseek( $jpexs_f, $val3[ "DataOffset" ] );
     887                                                        $r++;
     888                                                endwhile;
     889                                        endwhile;
     890                                endif;
     891                        endwhile;
     892                       
     893                        reset( $R[ "Subdir" ] );
     894                       
     895                        while ( list( $key, $val ) = each( $R[ "Subdir" ] ) ):
     896                                if ( $key == 3 ):
     897                                        while ( list( $key2, $val2 ) = each( $R[ "Subdir" ][ $key ][ "Subdir" ] ) ):
     898                                                for ( $r = 0; $r < count( $Ikona ); $r++ ):
     899                                                        for ( $s = 0; $s < count( $Ikona[ $r ] ); $s++ ):
     900                                                                while ( list( $key3, $val3 ) = each( $R[ "Subdir" ][ $key ][ "Subdir" ][ $Ikona[ $r ][ $s ][ "IconId" ] ][ "Subdir" ] ) ):
     901                                                                        if ( ( $iconIndex == $r ) or ( $iconIndex == -1 ) or ( ( is_array( $iconIndex ) ) and ( in_array( $r, $iconIndex ) ) ) ):
     902                                                                                fseek( $jpexs_f, $val3[ "DataOffset" ] );
     903                                                                                $Ikona[ $r ][ $s ][ "Data" ] = fread( $jpexs_f, $val3[ "DataSize" ] );
     904                                                                                $Ikona[ $r ][ $s ][ "DataSize" ] = $val3[ "DataSize" ];
     905                                                                        endif;
     906                                                                endwhile;
     907                                                        endfor;
     908                                                endfor;
     909                                        endwhile;
     910                                endif;
     911                        endwhile;
     912                        $ok = false;
     913                        for ( $r = 0; $r < count( $Ikona ); $r++ ):
     914                                if ( ( $iconIndex == $r ) or ( $iconIndex == -1 ) or ( ( is_array( $iconIndex ) ) and ( in_array( $r, $iconIndex ) ) ) ):
     915                                        $savefile = $icoFileNameOrPath;
     916                                        if ( $icoFileNameOrPath == "" ) {
     917                                                $savefile = "$r.ico";
     918                                        } else {
     919                                                if ( ( $iconIndex == -1 ) or ( is_array( $iconIndex ) ) )
     920                                                        $savefile = $icoFileNameOrPath . "$r.ico";
     921                                        }
     922                                        $f2 = fopen( $savefile, "w" );
     923                                        fwrite( $f2, jpexs_inttoword( 0 ) );
     924                                        fwrite( $f2, jpexs_inttoword( 1 ) );
     925                                        fwrite( $f2, jpexs_inttoword( count( $Ikona[ $r ] ) ) );
     926                                        $Offset = 6 + 16 * count( $Ikona[ $r ] );
     927                                        for ( $s = 0; $s < count( $Ikona[ $r ] ); $s++ ):
     928                                                fwrite( $f2, jpexs_inttobyte( $Ikona[ $r ][ $s ][ "Width" ] ) );
     929                                                fwrite( $f2, jpexs_inttobyte( $Ikona[ $r ][ $s ][ "Height" ] ) );
     930                                                fwrite( $f2, jpexs_inttoword( $Ikona[ $r ][ $s ][ "ColorCount" ] ) );
     931                                                fwrite( $f2, jpexs_inttoword( $Ikona[ $r ][ $s ][ "Planes" ] ) );
     932                                                fwrite( $f2, jpexs_inttoword( $Ikona[ $r ][ $s ][ "BitCount" ] ) );
     933                                                fwrite( $f2, jpexs_inttodword( $Ikona[ $r ][ $s ][ "BytesInRes" ] ) );
     934                                                fwrite( $f2, jpexs_inttodword( $Offset ) );
     935                                                $Offset += $Ikona[ $r ][ $s ][ "DataSize" ];
     936                                        endfor;
     937                                        for ( $s = 0; $s < count( $Ikona[ $r ] ); $s++ ):
     938                                                fwrite( $f2, $Ikona[ $r ][ $s ][ "Data" ] );
     939                                        endfor;
     940                                        fclose( $f2 );
     941                                        $ok = true;
     942                                endif;
     943                        endfor;
     944                        return $ok;
     945                endif;
     946        endfor;
     947       
     948        fclose( $jpexs_f );
     949}
     950
     951/**
     952 * Internal function for reading exe icons
     953 */
     954function jpexs_readResDirectoryEntry( &$parentRes, $offset ) {
     955        global $jpexs_f, $jpexs_StartOfRsrc, $jpexs_ImageBase, $jpexs_ResVirtualAddress;
     956        $lastPos = ftell( $jpexs_f );
     957        $Res = null;
     958        fseek( $jpexs_f, $offset );
     959        //IMAGE_RESOURCE_DIRECTORY
     960        $Characteristics = jpexs_freaddword( $jpexs_f );
     961        $TimeDateStamp = jpexs_freaddword( $jpexs_f );
     962        $MajorVersion = jpexs_freadword( $jpexs_f );
     963        $MinorVersion = jpexs_freadword( $jpexs_f );
     964        $NumberOfNamedEntries = jpexs_freadword( $jpexs_f );
     965        $NumberOfIdEntries = jpexs_freadword( $jpexs_f );
     966        for ( $q = 0; $q < $NumberOfNamedEntries + $NumberOfIdEntries; $q++ ):
     967        //IMAGE_RESOURCE_DIRECTORY_ENTRY
     968                $ResName = jpexs_freaddword( $jpexs_f );
     969                $lastPos2 = ftell( $jpexs_f );
     970                if ( $ResName >= 0x80000000 ):
     971                //String Name
     972                        $ResNameOffset = $ResName - 0x80000000;
     973                        fseek( $jpexs_f, $jpexs_StartOfRsrc + $ResNameOffset );
     974                        $StringLength = jpexs_freadword( $jpexs_f );
     975                        $Identificator = ( fread( $jpexs_f, $StringLength * 2 ) );
     976                        fseek( $jpexs_f, $lastPos2 );
     977                else:
     978                //Integer Id
     979                        $Identificator = $ResName;
     980                endif;
     981               
     982                $ResOffsetToData = jpexs_freaddword( $jpexs_f );
     983                if ( $ResOffsetToData >= 0x80000000 ):
     984                        $SubResOffset = $ResOffsetToData - 0x80000000;
     985                        jpexs_readResDirectoryEntry( $Res[ "$Identificator" ], $jpexs_StartOfRsrc + $SubResOffset );
     986                else:
     987                        $RawDataOffset = $ResOffsetToData;
     988                        $lastPos2 = ftell( $jpexs_f );
     989                        fseek( $jpexs_f, $jpexs_StartOfRsrc + $RawDataOffset );
     990                        //IMAGE_RESOURCE_DATA_ENTRY
     991                        $OffsetToData = jpexs_freaddword( $jpexs_f );
     992                        $Res[ "$Identificator" ][ "DataOffset" ] = $jpexs_StartOfRsrc - $jpexs_ResVirtualAddress + $OffsetToData;
     993                        $Res[ "$Identificator" ][ "DataSize" ] = jpexs_freaddword( $jpexs_f );
     994                        $CodePage = jpexs_freaddword( $jpexs_f );
     995                        $Reserved = jpexs_freaddword( $jpexs_f );
     996                        fseek( $jpexs_f, $lastPos2 );
     997                endif;
     998        endfor;
     999        fseek( $jpexs_f, $lastPos );
     1000        $parentRes[ "Subdir" ] = $Res;
     1001}
     1002
     1003/**
     1004 * Creates ico file from image resource(s)
     1005 * @param resource|array $images Target Image resource (Can be array of image resources)
     1006 * @param string $filename Target ico file to save icon to, If ommited or "", image is written to snadard output - use header("Content-type: image/x-icon"); */
     1007function imageIco( $images, $filename = "" ) {
     1008        if ( is_array( $images ) ) {
     1009                $ImageCount = count( $images );
     1010                $Image = $images;
     1011        } else {
     1012                $Image[ 0 ] = $images;
     1013                $ImageCount = 1;
     1014        }
     1015       
     1016       
     1017        $WriteToFile = false;
     1018       
     1019        if ( $filename != "" ) {
     1020                $WriteToFile = true;
     1021        }
     1022       
     1023       
     1024        $ret = "";
     1025       
     1026        $ret .= jpexs_inttoword( 0 ); //PASSWORD
     1027        $ret .= jpexs_inttoword( 1 ); //SOURCE
     1028        $ret .= jpexs_inttoword( $ImageCount ); //ICONCOUNT
     1029       
     1030       
     1031        for ( $q = 0; $q < $ImageCount; $q++ ) {
     1032                $img = $Image[ $q ];
     1033               
     1034                $Width = imagesx( $img );
     1035                $Height = imagesy( $img );
     1036               
     1037                $ColorCount = imagecolorstotal( $img );
     1038               
     1039                $Transparent = imagecolortransparent( $img );
     1040                $IsTransparent = $Transparent != -1;
     1041               
     1042               
     1043                if ( $IsTransparent )
     1044                        $ColorCount--;
     1045               
     1046                if ( $ColorCount == 0 ) {
     1047                        $ColorCount = 0;
     1048                        $BitCount = 24;
     1049                }
     1050                if ( ( $ColorCount > 0 ) and ( $ColorCount <= 2 ) ) {
     1051                        $ColorCount = 2;
     1052                        $BitCount = 1;
     1053                }
     1054                if ( ( $ColorCount > 2 ) and ( $ColorCount <= 16 ) ) {
     1055                        $ColorCount = 16;
     1056                        $BitCount = 4;
     1057                }
     1058                if ( ( $ColorCount > 16 ) and ( $ColorCount <= 256 ) ) {
     1059                        $ColorCount = 0;
     1060                        $BitCount = 8;
     1061                }
     1062               
     1063               
     1064               
     1065               
     1066               
     1067                //ICONINFO:
     1068                $ret .= jpexs_inttobyte( $Width ); //
     1069                $ret .= jpexs_inttobyte( $Height ); //
     1070                $ret .= jpexs_inttobyte( $ColorCount ); //
     1071                $ret .= jpexs_inttobyte( 0 ); //RESERVED
     1072               
     1073                $Planes = 0;
     1074                if ( $BitCount >= 8 )
     1075                        $Planes = 1;
     1076               
     1077                $ret .= jpexs_inttoword( $f, $Planes ); //PLANES
     1078                if ( $BitCount >= 8 )
     1079                        $WBitCount = $BitCount;
     1080                if ( $BitCount == 4 )
     1081                        $WBitCount = 0;
     1082                if ( $BitCount == 1 )
     1083                        $WBitCount = 0;
     1084                $ret .= jpexs_inttoword( $WBitCount ); //BITS
     1085               
     1086                $Zbytek = ( 4 - ( $Width / ( 8 / $BitCount ) ) % 4 ) % 4;
     1087                $ZbytekMask = ( 4 - ( $Width / 8 ) % 4 ) % 4;
     1088               
     1089                $PalSize = 0;
     1090               
     1091                $Size = 40 + ( $Width / ( 8 / $BitCount ) + $Zbytek ) * $Height + ( ( $Width / 8 + $ZbytekMask ) * $Height );
     1092                if ( $BitCount < 24 )
     1093                        $Size += pow( 2, $BitCount ) * 4;
     1094                $IconId = 1;
     1095                $ret .= jpexs_inttodword( $Size ); //SIZE
     1096                $OffSet = 6 + 16 * $ImageCount + $FullSize;
     1097                $ret .= jpexs_inttodword( 6 + 16 * $ImageCount + $FullSize ); //OFFSET
     1098                $FullSize += $Size;
     1099                //-------------
     1100               
     1101        }
     1102       
     1103       
     1104        for ( $q = 0; $q < $ImageCount; $q++ ) {
     1105                $img = $Image[ $q ];
     1106                $Width = imagesx( $img );
     1107                $Height = imagesy( $img );
     1108                $ColorCount = imagecolorstotal( $img );
     1109               
     1110                $Transparent = imagecolortransparent( $img );
     1111                $IsTransparent = $Transparent != -1;
     1112               
     1113                if ( $IsTransparent )
     1114                        $ColorCount--;
     1115                if ( $ColorCount == 0 ) {
     1116                        $ColorCount = 0;
     1117                        $BitCount = 24;
     1118                }
     1119                if ( ( $ColorCount > 0 ) and ( $ColorCount <= 2 ) ) {
     1120                        $ColorCount = 2;
     1121                        $BitCount = 1;
     1122                }
     1123                if ( ( $ColorCount > 2 ) and ( $ColorCount <= 16 ) ) {
     1124                        $ColorCount = 16;
     1125                        $BitCount = 4;
     1126                }
     1127                if ( ( $ColorCount > 16 ) and ( $ColorCount <= 256 ) ) {
     1128                        $ColorCount = 0;
     1129                        $BitCount = 8;
     1130                }
     1131               
     1132               
     1133               
     1134                //ICONS
     1135                $ret .= jpexs_inttodword( 40 ); //HEADSIZE
     1136                $ret .= jpexs_inttodword( $Width ); //
     1137                $ret .= jpexs_inttodword( 2 * $Height ); //
     1138                $ret .= jpexs_inttoword( 1 ); //PLANES
     1139                $ret .= jpexs_inttoword( $BitCount ); //
     1140                $ret .= jpexs_inttodword( 0 ); //Compress method
     1141               
     1142               
     1143                $ZbytekMask = ( $Width / 8 ) % 4;
     1144               
     1145                $Zbytek = ( $Width / ( 8 / $BitCount ) ) % 4;
     1146                $Size = ( $Width / ( 8 / $BitCount ) + $Zbytek ) * $Height + ( ( $Width / 8 + $ZbytekMask ) * $Height );
     1147               
     1148                $ret .= jpexs_inttodword( $Size ); //SIZE
     1149               
     1150                $ret .= jpexs_inttodword( 0 ); //HPIXEL_M
     1151                $ret .= jpexs_inttodword( 0 ); //V_PIXEL_M
     1152                $ret .= jpexs_inttodword( $ColorCount ); //UCOLORS
     1153                $ret .= jpexs_inttodword( 0 ); //DCOLORS
     1154                //---------------
     1155               
     1156               
     1157                $CC = $ColorCount;
     1158                if ( $CC == 0 )
     1159                        $CC = 256;
     1160               
     1161                if ( $BitCount < 24 ) {
     1162                        $ColorTotal = imagecolorstotal( $img );
     1163                        if ( $IsTransparent )
     1164                                $ColorTotal--;
     1165                       
     1166                        for ( $p = 0; $p < $ColorTotal; $p++ ) {
     1167                                $color = imagecolorsforindex( $img, $p );
     1168                                $ret .= jpexs_inttobyte( $color[ "blue" ] );
     1169                                $ret .= jpexs_inttobyte( $color[ "green" ] );
     1170                                $ret .= jpexs_inttobyte( $color[ "red" ] );
     1171                                $ret .= jpexs_inttobyte( 0 ); //RESERVED
     1172                        }
     1173                       
     1174                        $CT = $ColorTotal;
     1175                        for ( $p = $ColorTotal; $p < $CC; $p++ ) {
     1176                                $ret .= jpexs_inttobyte( 0 );
     1177                                $ret .= jpexs_inttobyte( 0 );
     1178                                $ret .= jpexs_inttobyte( 0 );
     1179                                $ret .= jpexs_inttobyte( 0 ); //RESERVED
     1180                        }
     1181                }
     1182               
     1183               
     1184               
     1185               
     1186               
     1187               
     1188                if ( $BitCount <= 8 ) {
     1189                        for ( $y = $Height - 1; $y >= 0; $y-- ) {
     1190                                $bWrite = "";
     1191                                for ( $x = 0; $x < $Width; $x++ ) {
     1192                                        $color = imagecolorat( $img, $x, $y );
     1193                                        if ( $color == $Transparent )
     1194                                                $color = imagecolorexact( $img, 0, 0, 0 );
     1195                                        if ( $color == -1 )
     1196                                                $color = 0;
     1197                                        if ( $color > pow( 2, $BitCount ) - 1 )
     1198                                                $color = 0;
     1199                                       
     1200                                        $bWrite .= jpexs_decbinx( $color, $BitCount );
     1201                                        if ( strlen( $bWrite ) == 8 ) {
     1202                                                $ret .= jpexs_inttobyte( bindec( $bWrite ) );
     1203                                                $bWrite = "";
     1204                                        }
     1205                                }
     1206                               
     1207                                if ( ( strlen( $bWrite ) < 8 ) and ( strlen( $bWrite ) != 0 ) ) {
     1208                                        $sl = strlen( $bWrite );
     1209                                        for ( $t = 0; $t < 8 - $sl; $t++ )
     1210                                                $sl .= "0";
     1211                                        $ret .= jpexs_inttobyte( bindec( $bWrite ) );
     1212                                }
     1213                                for ( $z = 0; $z < $Zbytek; $z++ )
     1214                                        $ret .= jpexs_inttobyte( 0 );
     1215                        }
     1216                }
     1217               
     1218               
     1219               
     1220                if ( $BitCount >= 24 ) {
     1221                        for ( $y = $Height - 1; $y >= 0; $y-- ) {
     1222                                for ( $x = 0; $x < $Width; $x++ ) {
     1223                                        $color = imagecolorsforindex( $img, imagecolorat( $img, $x, $y ) );
     1224                                        $ret .= jpexs_inttobyte( $color[ "blue" ] );
     1225                                        $ret .= jpexs_inttobyte( $color[ "green" ] );
     1226                                        $ret .= jpexs_inttobyte( $color[ "red" ] );
     1227                                        if ( $BitCount == 32 )
     1228                                                $ret .= jpexs_inttobyte( 0 ); //Alpha for ICO_XP_COLORS
     1229                                }
     1230                                for ( $z = 0; $z < $Zbytek; $z++ )
     1231                                        $ret .= jpexs_inttobyte( 0 );
     1232                        }
     1233                }
     1234               
     1235               
     1236                //MASK
     1237               
     1238                for ( $y = $Height - 1; $y >= 0; $y-- ) {
     1239                        $byteCount = 0;
     1240                        $bOut = "";
     1241                        for ( $x = 0; $x < $Width; $x++ ) {
     1242                                if ( ( $Transparent != -1 ) and ( imagecolorat( $img, $x, $y ) == $Transparent ) ) {
     1243                                        $bOut .= "1";
     1244                                } else {
     1245                                        $bOut .= "0";
     1246                                }
     1247                        }
     1248                        for ( $p = 0; $p < strlen( $bOut ); $p += 8 ) {
     1249                                $byte = bindec( substr( $bOut, $p, 8 ) );
     1250                                $byteCount++;
     1251                                $ret .= jpexs_inttobyte( $byte );
     1252                        }
     1253                        $Zbytek = $byteCount % 4;
     1254                        for ( $z = 0; $z < $Zbytek; $z++ ) {
     1255                                $ret .= jpexs_inttobyte( 0xff );
     1256                        }
     1257                }
     1258               
     1259                //------------------
     1260               
     1261        } //q
     1262       
     1263       
     1264       
     1265       
     1266       
     1267        if ( $WriteToFile ) {
     1268                $f = fopen( $filename, "w" );
     1269                fwrite( $f, $ret );
     1270                fclose( $f );
     1271        } else {
     1272                echo $ret;
     1273        }
     1274       
     1275}
     1276
     1277
     1278
     1279
     1280/*
     1281 * Internal functions:
     1282 *-------------------------
     1283 * jpexs_inttobyte($n) - returns chr(n)
     1284 * jpexs_inttodword($n) - returns dword (n)
     1285 * jpexs_inttoword($n) - returns word(n)
     1286 * jpexs_freadbyte($file) - reads 1 byte from $file
     1287 * jpexs_freadword($file) - reads 2 bytes (1 word) from $file
     1288 * jpexs_freaddword($file) - reads 4 bytes (1 dword) from $file
     1289 * jpexs_freadlngint($file) - same as freaddword($file)
     1290 * jpexs_decbin8($d) - returns binary string of d zero filled to 8
     1291 * jpexs_RetBits($byte,$start,$len) - returns bits $start->$start+$len from $byte
     1292 * jpexs_freadbits($file,$count) - reads next $count bits from $file
     1293 */
     1294
     1295
     1296function jpexs_decbin8( $d ) {
     1297        return jpexs_decbinx( $d, 8 );
     1298}
     1299
     1300function jpexs_decbinx( $d, $n ) {
     1301        $bin = decbin( $d );
     1302        $sbin = strlen( $bin );
     1303        for ( $j = 0; $j < $n - $sbin; $j++ )
     1304                $bin = "0$bin";
     1305        return $bin;
     1306}
     1307
     1308function jpexs_retBits( $byte, $start, $len ) {
     1309        $bin = jpexs_decbin8( $byte );
     1310        $r = bindec( substr( $bin, $start, $len ) );
     1311        return $r;
     1312       
     1313}
     1314
     1315
     1316
     1317$jpexs_currentBit = 0;
     1318function jpexs_freadbits( $f, $count ) {
     1319        global $jpexs_currentBit, $jpexs_SMode;
     1320        $Byte = jpexs_freadbyte( $f );
     1321        $LastCBit = $jpexs_currentBit;
     1322        $jpexs_currentBit += $count;
     1323        if ( $jpexs_currentBit == 8 ) {
     1324                $jpexs_currentBit = 0;
     1325        } else {
     1326                fseek( $f, ftell( $f ) - 1 );
     1327        }
     1328        return jpexs_retBits( $Byte, $LastCBit, $count );
     1329}
     1330
     1331
     1332function jpexs_freadbyte( $f ) {
     1333        return ord( fread( $f, 1 ) );
     1334}
     1335
     1336function jpexs_freadword( $f ) {
     1337        $b1 = jpexs_freadbyte( $f );
     1338        $b2 = jpexs_freadbyte( $f );
     1339        return $b2 * 256 + $b1;
     1340}
     1341
     1342
     1343function jpexs_freadlngint( $f ) {
     1344        return jpexs_freaddword( $f );
     1345}
     1346
     1347function jpexs_freaddword( $f ) {
     1348        $b1 = jpexs_freadword( $f );
     1349        $b2 = jpexs_freadword( $f );
     1350        return $b2 * 65536 + $b1;
     1351}
     1352
     1353function jpexs_inttobyte( $n ) {
     1354        return chr( $n );
     1355}
     1356
     1357function jpexs_inttodword( $n ) {
     1358        return chr( $n & 255 ) . chr( ( $n >> 8 ) & 255 ) . chr( ( $n >> 16 ) & 255 ) . chr( ( $n >> 24 ) & 255 );
     1359}
     1360
     1361function jpexs_inttoword( $n ) {
     1362        return chr( $n & 255 ) . chr( ( $n >> 8 ) & 255 );
     1363}
     1364 No newline at end of file
  • wp-admin/js/wp-favicon.dev.js

     
     1(function($){
     2    $('#faviconfile').change(function(){
     3        // check the file extension
     4        if ( $.inArray( $(this).val().split('.').pop().toLowerCase(), ['ico', 'png', 'bmp', 'jpg', 'jpeg'] ) < 0 ) {
     5            $('#favicon-invalid-filetype-error').show();
     6                        $('#faviconupload')[0].reset();
     7                }
     8        else
     9        {
     10            $('#faviconupload').submit();
     11        }
     12    });
     13
     14})(jQuery);
  • wp-admin/js/wp-favicon.js

     
     1(function($){
     2    $('#faviconfile').change(function(){
     3        // check the file extention
     4        if (! $.inArray( $(this).val().split('.').pop().toLowerCase() , /* valid file extentions */ ['gif','png','jpg','jpeg'] ) )
     5            $('#favicon-invalid-filetype').show();
     6        else
     7        {
     8            $('#faviconupload').submit();
     9        }
     10    });
     11
     12})(jQuery);
  • wp-admin/options-general.php

     
    8181        '<p>' . __('<a href="http://wordpress.org/support/" target="_blank">Support Forums</a>') . '</p>'
    8282);
    8383
     84wp_enqueue_script('wp-favicon');
     85
    8486include('./admin-header.php');
    8587?>
    8688
     
    8890<?php screen_icon(); ?>
    8991<h2><?php echo esc_html( $title ); ?></h2>
    9092
     93<form action="<?php echo admin_url('favicon-upload.php')?>" method="post" enctype="multipart/form-data" id="faviconupload">
     94    <?php settings_fields('favicon_upload') ?>
     95        <table class="form-table">
     96                <tr valign="top">
     97                        <th scope="row"><label for="sitefavicon"><?php _e('Favicon') ?></label></th>
     98                        <td>
     99                                <?php
     100                                        // display the icon and the remove link if appropriate
     101                                        if ( has_custom_favicon() ){
     102                                                if ( $thumbnail = get_favicon_img() ) echo $thumbnail;
     103                                                echo "\t" . '<input type="submit" name="REMOVE_FAVICON" value="Remove Favicon" id="remove-favicon-button" />';
     104                                                echo ' <span class="description no-js">' . __( 'The image at right is used as your site\'s favicon. To change it, first remove this one.' ) . '</span>';
     105                                        } else {
     106                                ?>
     107                                        <input class="button" name="avatarfile" type="file" id="faviconfile" size="35" />
     108                                        <p class="submit no-js hide-if-js"><input type="submit" name="Submit" value="Upload Image &raquo;" id="faviconsubmit" /></p>
     109                                        <span class="description no-js"><?php _e('Click to upload your own custom icon ("favicon") for your blog. You\'ll be able to crop and scale it once it\'s uploaded.') ?></span>
     110                                        <span id="favicon-invalid-filetype-error"><?php _e( 'Please only upload files in the following formats: .ico, .png, .bmp, .jpg' ) ?></span>
     111                                <?php } ?>
     112                        </td>
     113                </tr>
     114        </table>
     115</form>
     116
    91117<form method="post" action="options.php">
    92118<?php settings_fields('general'); ?>
    93119
  • wp-includes/functions.php

     
    17731773                'png' => 'image/png',
    17741774                'bmp' => 'image/bmp',
    17751775                'tif|tiff' => 'image/tiff',
    1776                 'ico' => 'image/x-icon',
     1776                'ico' => 'image/vnd.microsoft.icon',
    17771777                'asf|asx|wax|wmv|wmx' => 'video/asf',
    17781778                'avi' => 'video/avi',
    17791779                'divx' => 'video/divx',
  • wp-includes/general-template.php

     
    15871587}
    15881588
    15891589/**
     1590 * Convenience function that echoes the HTML for the site's favicon icon.
     1591 * By default, automatically included in the header via the 'wp_head' action, which can be removed by themes if a custom favicon is desired.
     1592 *
     1593 * @uses generate_site_favicon_html() to do the actual heavy lifting
     1594 */
     1595function site_favicon(){
     1596        echo generate_site_favicon_html();
     1597}
     1598add_action( 'wp_head', 'site_favicon' );
     1599add_action( 'admin_head', 'site_favicon' );
     1600
     1601/**
     1602 * Return the HTML for the site's favicon icon, if such has been defined.
     1603 *
     1604 * @uses get_site_favicon_uri();
     1605 *
     1606 * Includes the conditional tag wrapper for an IE (.ico) version.
     1607 */
     1608function generate_site_favicon_html() {
     1609        $favicon_uri = get_site_favicon_uri();
     1610        $ie_favicon_uri = get_site_favicon_uri( 'ico' );
     1611
     1612        $content = "";
     1613        if (! empty( $favicon_uri ) ){
     1614                $content .= "\n\n<!--favicon (via 'wp_head' action) -->\n";
     1615
     1616                if (! empty( $ie_favicon_uri )) $content .= <<<IE_FAVICON_1
     1617<!--[if IE]>
     1618        <link rel="shortcut icon" href="{$ie_favicon_uri}" />
     1619<![endif]-->
     1620<!--[if !IE]>-->\n
     1621IE_FAVICON_1;
     1622
     1623                $content .= "\t<link href=\"{$favicon_uri}\" rel=\"icon\" type=\"image/png\" />\n";
     1624               
     1625                if (! empty( $ie_favicon_uri )) $content .= "<!--<![endif]-->";
     1626                $content .= "\n<!-- /favicon -->\n\n";
     1627    }
     1628        return $content;
     1629}
     1630
     1631/**
     1632 * Get the attachment post object associated with the current site favicon, based on the 'sitefavicon' option
     1633 *
     1634 * @param string $format Default 'png'. Format of the file we're looking for
     1635 * @return object If found, returns the post object; if not, a WP_Error object
     1636 */
     1637function get_site_favicon_attachment( $format = 'png' ){
     1638        $favicon_basename = get_option ( 'sitefavicon' );
     1639       
     1640        if ( ! empty( $favicon_basename ) ) {
     1641                $favicon_fullname = $favicon_basename . '-' . $format;
     1642               
     1643                $posts = get_posts( array( 'name' => $favicon_fullname, 'post_type' => 'attachment' ) );
     1644                if ( $posts[0] ){
     1645                        return $posts[0];
     1646                } else {
     1647                        return new WP_Error( 'attachment_missing', __( "No attachment for '$favicon_fullname' was found." ) );
     1648                }
     1649        } else {
     1650                return new WP_Error( 'not_defined', __( "No favicon file provided." ) );
     1651        }
     1652}
     1653
     1654/**
     1655 * Returns the URI for the site's favicon based on the option set in  Admin > Settings > General.
     1656 *
     1657 * @param string $format png|ico default 'png'. Use 'ico' for serving up an IE-compatible ICO file
     1658 * @return string fully qualified URI
     1659 */
     1660function get_site_favicon_uri( $format = 'png' ){
     1661        /** @TODO provide error checking for validity of $format and $size */
     1662        $favicon_attachment = get_site_favicon_attachment( $format );
     1663       
     1664        /** @TODO provide the ability to define a 'default' favicon that would be distributed with fresh WP installations */
     1665        if ( ! is_wp_error( $favicon_attachment ) ) {
     1666                return wp_get_attachment_url( $favicon_attachment->ID );
     1667        }
     1668       
     1669        // We get here because of an error condition
     1670        /** @TODO default to the theme's favicon **/
     1671        // ATM do nothing (so URI is blank, rather than a WP_Error)
     1672}
     1673
     1674/**
     1675 * Gets the path to the favicon file, or returns a WP_Error
     1676 * @param string $format Default 'png'
     1677 * @return mixed File string or WP_Error object
     1678 */
     1679function get_site_favicon_file( $format = 'png' ){
     1680        $favicon_attachment = get_site_favicon_attachment( $format );
     1681       
     1682        /** @TODO provide the ability to define a 'default' favicon that would be distributed with fresh WP installations */
     1683        if ( ! is_wp_error( $favicon_attachment ) ) {
     1684                $file = get_attached_file( $favicon_attachment->ID );
     1685                if ( file_exists( $file ) ) return $file;
     1686                else return new WP_Error( 'file_missing', __( 'Favicon image file missing.' ) );
     1687        } else {
     1688                return $favicon_attachment; // returns the WP_Error object
     1689        }
     1690}
     1691
     1692/**
     1693 * Returns true or false depending on whether a custom favicon has been defined in Admin
     1694 * @return boolean
     1695 */
     1696function has_custom_favicon(){
     1697        return ( get_option ( 'sitefavicon' ) && ! is_wp_error( get_site_favicon_file() ) );
     1698}
     1699
     1700/**
     1701 * Returns an HTML <img> tag populated with the site favicon, in the format specified (usually PNG)
     1702 * @param string $format Default 'png'. Valid values are 'png', 'bmp' (note 'ico' is NOT valid)
     1703 * @return mixed Returns HTML <img> tag or WP_Error if invalid format given. Returns nothing if the file is missing.
     1704 */
     1705function get_favicon_img( $format = 'png' ){
     1706        if (in_array( strtolower( $format ), array( 'png', 'bmp' ) ) ){
     1707                // Does the file actually exist?
     1708                $file = get_site_favicon_file( $format );
     1709                if (! is_wp_error( $file ) && file_exists( $file ) ){
     1710                        $src = get_site_favicon_uri( $format );
     1711                        if (!is_wp_error( $src ) ){
     1712                                return '<img src="' . $src . '" class="favicon" alt="' . _x( 'Site favicon thumbnail', 'Thumbnail image accessibility text' ) .'" />';
     1713                        }
     1714                }
     1715        } else {
     1716                return new WP_Error( 'invalid_file_format', __( 'Invalid file format. Valid formats are "png", "bmp".' ) );
     1717        }
     1718}
     1719
     1720/**
    15901721 * Display the links to the general feeds.
    15911722 *
    15921723 * @since 2.8.0
  • wp-includes/script-loader.php

     
    8888
    8989        $scripts->add( 'wp-fullscreen', "/wp-admin/js/wp-fullscreen$suffix.js", array('jquery'), false, 1 );
    9090
     91        $scripts->add( 'wp-favicon', "/wp-admin/js/wp-favicon$suffix.js", array('jquery'), false, 1 );
     92
    9193        $scripts->add( 'prototype', '/wp-includes/js/prototype.js', array(), '1.6.1');
    9294
    9395        $scripts->add( 'wp-ajax-response', "/wp-includes/js/wp-ajax-response$suffix.js", array('jquery'), false, 1 );