Overview

Namespaces

  • Composer
    • Autoload
  • Geekwright
    • RegDom
  • League
    • OAuth2
      • Client
        • Provider
  • None
  • Xmf
    • Database
    • Jwt
    • Key
    • Module
      • Helper

Classes

  • ArtObject
  • ArtObjectHandler
  • BloggerApi
  • CGIF
  • CGIFCOLORTABLE
  • CGIFFILEHEADER
  • CGIFIMAGE
  • CGIFIMAGEHEADER
  • CGIFLZW
  • Composer\Autoload\ClassLoader
  • Composer\Autoload\ComposerStaticInit274e5fff219a4f27a346e611b0580d6a
  • ComposerAutoloaderInit274e5fff219a4f27a346e611b0580d6a
  • Config_File
  • Cookie
  • Criteria
  • CriteriaCompo
  • CriteriaElement
  • Database
  • Db_manager
  • ErrorHandler
  • FormDhtmlTextArea
  • FormTextArea
  • Geekwright\RegDom\PublicSuffixList
  • Geekwright\RegDom\RegisteredDomain
  • HTMLPurifier
  • League\OAuth2\Client\Provider\Google
  • MetaWeblogApi
  • ModuleAdmin
  • MovableTypeApi
  • MyTextSanitizer
  • MyTextSanitizerExtended
  • MyTextSanitizerExtension
  • MytsCensor
  • MytsFlash
  • MytsIframe
  • MytsImage
  • MytsLi
  • MytsMms
  • MytsMp3
  • MytsRtsp
  • MytsSoundcloud
  • MytsSyntaxhighlight
  • MytsTextfilter
  • MytsUl
  • MytsWiki
  • MytsWmp
  • MytsYoutube
  • PathStuffController
  • PHPMailer
  • PHPMailerOAuth
  • PHPMailerOAuthGoogle
  • phpthumb
  • phpthumb_bmp
  • phpthumb_filters
  • phpthumb_functions
  • phpthumb_ico
  • phpUnsharpMask
  • PmCorePreload
  • PmMessage
  • PmMessageHandler
  • PmSystemPreload
  • POP3
  • ProfileCategory
  • ProfileCategoryHandler
  • ProfileCorePreload
  • ProfileField
  • ProfileFieldHandler
  • ProfileProfile
  • ProfileProfileHandler
  • ProfileRegstep
  • ProfileRegstepHandler
  • ProfileVisibility
  • ProfileVisibilityHandler
  • Protector
  • Protector_bruteforce_overrun_message
  • Protector_crawler_overrun_message
  • Protector_f5attack_overrun_message
  • Protector_postcommon_post_deny_by_httpbl
  • Protector_postcommon_post_deny_by_rbl
  • Protector_postcommon_post_htmlpurify4everyone
  • Protector_postcommon_post_htmlpurify4guest
  • Protector_postcommon_post_language_match
  • Protector_postcommon_post_need_multibyte
  • Protector_postcommon_post_register_moratorium
  • Protector_postcommon_post_stopforumspam
  • Protector_postcommon_register_insert_js_check
  • Protector_postcommon_register_stopforumspam
  • Protector_precommon_badip_errorlog
  • Protector_precommon_badip_message
  • Protector_precommon_badip_redirection
  • Protector_precommon_bwlimit_errorlog
  • Protector_precommon_bwlimit_message
  • Protector_prepurge_exit_message
  • Protector_spamcheck_overrun_message
  • ProtectorCorePreload
  • ProtectorFilterAbstract
  • ProtectorFilterHandler
  • ProtectorMySQLDatabase
  • ProtectorRegistry
  • ReCaptchaResponse
  • RpcArrayHandler
  • RpcBase64Handler
  • RpcBooleanHandler
  • RpcDateTimeHandler
  • RpcDoubleHandler
  • RpcIntHandler
  • RpcMemberHandler
  • RpcMethodNameHandler
  • RpcNameHandler
  • RpcStringHandler
  • RpcStructHandler
  • RpcValueHandler
  • RssAuthorHandler
  • RssCategoryHandler
  • RssChannelHandler
  • RssCommentsHandler
  • RssCopyrightHandler
  • RssDescriptionHandler
  • RssDocsHandler
  • RssGeneratorHandler
  • RssGuidHandler
  • RssHeightHandler
  • RssImageHandler
  • RssItemHandler
  • RssLanguageHandler
  • RssLastBuildDateHandler
  • RssLinkHandler
  • RssManagingEditorHandler
  • RssNameHandler
  • RssPubDateHandler
  • RssSourceHandler
  • RssTextInputHandler
  • RssTitleHandler
  • RssTtlHandler
  • RssUrlHandler
  • RssWebMasterHandler
  • RssWidthHandler
  • SaxParser
  • Smarty
  • Smarty_Compiler
  • SMTP
  • Snoopy
  • SqlUtility
  • SystemAvatar
  • SystemAvatarHandler
  • SystemBanner
  • SystemBannerclient
  • SystemBannerclientHandler
  • SystemBannerFinish
  • SystemBannerfinishHandler
  • SystemBannerHandler
  • SystemBlock
  • SystemBlockHandler
  • SystemBlockLinkModule
  • SystemBlockLinkModuleHandler
  • SystemBreadcrumb
  • SystemCorePreload
  • SystemFineAvatarUploadHandler
  • SystemFineImUploadHandler
  • SystemFineUploadHandler
  • SystemGroup
  • SystemGroupHandler
  • SystemMaintenance
  • SystemMenuHandler
  • SystemSmilies
  • SystemsmiliesHandler
  • SystemUserrank
  • SystemuserrankHandler
  • SystemUsers
  • SystemUsersHandler
  • Tar
  • ThemeSetAuthorHandler
  • ThemeSetDateCreatedHandler
  • ThemeSetDescriptionHandler
  • ThemeSetEmailHandler
  • ThemeSetFileTypeHandler
  • ThemeSetGeneratorHandler
  • ThemeSetImageHandler
  • ThemeSetLinkHandler
  • ThemeSetModuleHandler
  • ThemeSetNameHandler
  • ThemeSetTagHandler
  • ThemeSetTemplateHandler
  • TinyMCE
  • Xmf\Assert
  • Xmf\Database\Migrate
  • Xmf\Database\TableLoad
  • Xmf\Database\Tables
  • Xmf\Debug
  • Xmf\FilterInput
  • Xmf\Highlighter
  • Xmf\IPAddress
  • Xmf\Jwt\JsonWebToken
  • Xmf\Jwt\KeyFactory
  • Xmf\Jwt\TokenFactory
  • Xmf\Jwt\TokenReader
  • Xmf\Key\ArrayStorage
  • Xmf\Key\Basic
  • Xmf\Key\FileStorage
  • Xmf\Key\KeyAbstract
  • Xmf\Language
  • Xmf\Metagen
  • Xmf\Module\Admin
  • Xmf\Module\Helper
  • Xmf\Module\Helper\AbstractHelper
  • Xmf\Module\Helper\Cache
  • Xmf\Module\Helper\GenericHelper
  • Xmf\Module\Helper\Permission
  • Xmf\Module\Helper\Session
  • Xmf\Random
  • Xmf\Request
  • Xmf\StopWords
  • Xmf\Yaml
  • XmlTagHandler
  • XoopsApi
  • xoopsart
  • XoopsAuth
  • XoopsAuthAds
  • XoopsAuthFactory
  • XoopsAuthLdap
  • XoopsAuthProvisionning
  • XoopsAuthXoops
  • XoopsAvatar
  • XoopsAvatarHandler
  • XoopsBlock
  • XoopsBlockHandler
  • XoopsBlockInstance
  • XoopsBlockInstanceHandler
  • XoopsCache
  • XoopsCacheApc
  • XoopsCacheEngine
  • XoopsCacheFile
  • XoopsCacheMemcache
  • XoopsCacheModel
  • XoopsCacheModelHandler
  • XoopsCacheModelObject
  • XoopsCacheXcache
  • XoopsCaptcha
  • XoopsCaptchaImage
  • XoopsCaptchaImageHandler
  • XoopsCaptchaMethod
  • XoopsCaptchaRecaptcha
  • XoopsCaptchaRecaptcha2
  • XoopsCaptchaText
  • XoopsComment
  • XoopsCommentHandler
  • XoopsCommentRenderer
  • XoopsComments
  • XoopsConfigCategory
  • XoopsConfigCategoryHandler
  • XoopsConfigHandler
  • XoopsConfigItem
  • XoopsConfigItemHandler
  • XoopsConfigOption
  • XoopsConfigOptionHandler
  • XoopsDatabase
  • XoopsDatabaseFactory
  • XoopsDownloader
  • XoopsEditor
  • XoopsEditorHandler
  • XoopsErrorHandler
  • XoopsFile
  • XoopsFileHandler
  • XoopsFilterInput
  • XoopsFolderHandler
  • XoopsForm
  • XoopsFormButton
  • XoopsFormButtonTray
  • XoopsFormCaptcha
  • XoopsFormCheckBox
  • XoopsFormColorPicker
  • XoopsFormDateTime
  • XoopsFormDhtmlTextArea
  • XoopsFormEditor
  • XoopsFormElement
  • XoopsFormElementTray
  • XoopsFormFile
  • XoopsFormHidden
  • XoopsFormHiddenToken
  • XoopsFormLabel
  • XoopsFormPassword
  • XoopsFormRadio
  • XoopsFormRadioYN
  • XoopsFormRenderer
  • XoopsFormRendererBootstrap3
  • XoopsFormRendererLegacy
  • XoopsFormSelect
  • XoopsFormSelectCheckGroup
  • XoopsFormSelectCountry
  • XoopsFormSelectEditor
  • XoopsFormSelectGroup
  • XoopsFormSelectLang
  • XoopsFormSelectMatchOption
  • XoopsFormSelectTheme
  • XoopsFormSelectTimezone
  • XoopsFormSelectUser
  • XoopsFormText
  • XoopsFormTextArea
  • XoopsFormTextDateSelect
  • XoopsFormTinymce
  • XoopsGroup
  • XoopsGroupFormCheckBox
  • XoopsGroupHandler
  • XoopsGroupPerm
  • XoopsGroupPermForm
  • XoopsGroupPermHandler
  • XoopsGTicket
  • XoopsGuestUser
  • XoopsGuiDefault
  • XoopsGuiThadmin
  • XoopsGuiTransition
  • XoopsGuiZetadigme
  • XoopsHandlerRegistry
  • XoopsImage
  • XoopsImagecategory
  • XoopsImagecategoryHandler
  • XoopsImageHandler
  • XoopsImageSet
  • XoopsImagesetHandler
  • XoopsImagesetimg
  • XoopsImagesetimgHandler
  • XoopsInstallWizard
  • XoopsLists
  • XoopsLoad
  • XoopsLocal
  • XoopsLocalAbstract
  • XoopsLocalWrapper
  • XoopsLogger
  • XoopsMailer
  • XoopsMailerLocal
  • XoopsMediaUploader
  • XoopsMemberHandler
  • XoopsMembership
  • XoopsMembershipHandler
  • XoopsModelAbstract
  • XoopsModelFactory
  • XoopsModelJoint
  • XoopsModelRead
  • XoopsModelStats
  • XoopsModelSync
  • XoopsModelWrite
  • XoopsModule
  • XoopsModuleHandler
  • XoopsMultiMailer
  • XoopsMySQLDatabase
  • XoopsMySQLDatabaseProxy
  • XoopsMySQLDatabaseSafe
  • XoopsNotification
  • XoopsNotificationHandler
  • XoopsObject
  • XoopsObjectHandler
  • XoopsObjectTree
  • XoopsOnlineHandler
  • XoopsPageNav
  • XoopsPersistableObjectHandler
  • XoopsPreload
  • XoopsPreloadItem
  • XoopsPrivmessage
  • XoopsPrivmessageHandler
  • XoopsRank
  • XoopsRankHandler
  • XoopsRequest
  • XoopsSecurity
  • XoopsSessionHandler
  • XoopsSimpleForm
  • XoopsStory
  • XoopsSystemCpanel
  • XoopsSystemGui
  • XoopsTableForm
  • XoopsTarDownloader
  • XoopsThemeForm
  • XoopsThemeSetParser
  • XoopsTopic
  • XoopsTpl
  • XoopsTplfile
  • XoopsTplfileHandler
  • XoopsTplset
  • XoopsTplsetHandler
  • XoopsTree
  • XoopsUser
  • XoopsUserHandler
  • XoopsUserUtility
  • XoopsUtility
  • XoopsXmlRpcApi
  • XoopsXmlRpcArray
  • XoopsXmlRpcBase64
  • XoopsXmlRpcBoolean
  • XoopsXmlRpcDatetime
  • XoopsXmlRpcDocument
  • XoopsXmlRpcDouble
  • XoopsXmlRpcFault
  • XoopsXmlRpcInt
  • XoopsXmlRpcParser
  • XoopsXmlRpcRequest
  • XoopsXmlRpcResponse
  • XoopsXmlRpcString
  • XoopsXmlRpcStruct
  • XoopsXmlRpcTag
  • XoopsXmlRss2Parser
  • XoopsZipDownloader
  • xos_kernel_Xoops2
  • xos_logos_PageBuilder
  • xos_opal_AdminThemeFactory
  • xos_opal_Theme
  • xos_opal_ThemeFactory
  • XoUser
  • XoUserHandler
  • Zipfile

Interfaces

  • Xmf\Key\StorageInterface
  • XoopsFormRendererInterface

Exceptions

  • phpmailerException

Functions

  • __autoload
  • _recaptcha_aes_encrypt
  • _recaptcha_aes_pad
  • _recaptcha_http_post
  • _recaptcha_mailhide_email_parts
  • _recaptcha_mailhide_urlbase64
  • _recaptcha_qsencode
  • _smarty_regex_replace_check
  • _smarty_sort_length
  • admin_refcheck
  • b_system_comments_edit
  • b_system_comments_show
  • b_system_info_edit
  • b_system_info_show
  • b_system_login_show
  • b_system_main_show
  • b_system_newmembers_edit
  • b_system_newmembers_show
  • b_system_notification_show
  • b_system_online_show
  • b_system_search_show
  • b_system_themes_edit
  • b_system_themes_show
  • b_system_topposters_edit
  • b_system_topposters_show
  • b_system_user_show
  • b_system_waiting_show
  • bannerstats
  • change_banner_url_by_client
  • checkEmail
  • clickbanner
  • clientlogin
  • closeTable
  • closeThread
  • CloseWaitBox
  • Composer\Autoload\includeFile
  • composerRequire274e5fff219a4f27a346e611b0580d6a
  • createConfigform
  • createThemeform
  • doConditionalGet
  • emailStats
  • exit404BadReq
  • fatalPhpErrorHandler
  • file_get_contents
  • file_put_contents
  • findSharp
  • form_user
  • formatTimestamp
  • formatURL
  • gd_info
  • genPathCheckHtml
  • get_request_method
  • get_writeoks_from_protector
  • getcss
  • getDbCharsets
  • getDbCollations
  • getDirList
  • getMailer
  • getTheme
  • gif_getSize
  • gif_loadFile
  • gif_loadFileToGDimageResource
  • gif_outputAsBmp
  • gif_outputAsJpeg
  • gif_outputAsPng
  • HTMLPurifier
  • imagealphablending
  • imageBrowser
  • imageCreateCorners
  • imageFilenameCheck
  • imagesavealpha
  • install_acceptUser
  • install_finalize
  • is_executable
  • kses
  • langDropdown
  • load_functions
  • load_object
  • load_objectHandler
  • loadModuleAdminMenu
  • make_cblock
  • make_data
  • make_groups
  • make_sidebar
  • mod_clearCacheFile
  • mod_clearConfg
  • mod_clearConfig
  • mod_clearFile
  • mod_clearSmartyCache
  • mod_constant
  • mod_createCacheFile
  • mod_createCacheFile_byGroup
  • mod_createFile
  • mod_DB_prefix
  • mod_fetchConfg
  • mod_fetchConfig
  • mod_generateCacheId
  • mod_generateCacheId_byGroup
  • mod_getDirname
  • mod_getIP
  • mod_getMysqlVersion
  • mod_getUnameFromId
  • mod_getUnameFromIds
  • mod_isModuleAction
  • mod_loadCacheFile
  • mod_loadCacheFile_byGroup
  • mod_loadConfg
  • mod_loadConfig
  • mod_loadFile
  • mod_loadFunctions
  • mod_loadRenderer
  • mod_message
  • modify_chmod
  • myTextForm
  • notificationCategoryInfo
  • notificationCommentCategoryInfo
  • notificationEnabled
  • notificationEventEnabled
  • notificationEventInfo
  • notificationEvents
  • notificationGenerateConfig
  • notificationSubscribableCategoryInfo
  • openTable
  • openThread
  • OpenWaitBox
  • PHPMailerAutoload
  • phpThumbURL
  • preg_quote
  • profile_getFieldForm
  • profile_getRegisterForm
  • profile_getStepForm
  • profile_getUserForm
  • profile_install_addCategory
  • profile_install_addField
  • profile_install_addStep
  • profile_install_initializeProfiles
  • profile_install_setPermissions
  • protector_message_append_oninstall
  • protector_message_append_onuninstall
  • protector_message_append_onupdate
  • protector_notify_base
  • protector_oninstall_base
  • protector_onuninstall_base
  • protector_onupdate_base
  • protector_postcommon
  • protector_prepare
  • recaptcha_check_answer
  • recaptcha_get_html
  • recaptcha_get_signup_url
  • recaptcha_mailhide_html
  • recaptcha_mailhide_url
  • redirect_header
  • RedirectToCachedFile
  • SendSaveAsFileHeaderIfNeeded
  • showbanner
  • showThread
  • smarty_block_textformat
  • smarty_compiler_assign
  • smarty_compiler_foreachq
  • smarty_compiler_includeq
  • smarty_compiler_xoAdminIcons
  • smarty_compiler_xoAdminNav
  • smarty_compiler_xoAppUrl
  • smarty_compiler_xoImgUrl
  • smarty_compiler_xoModuleIcons16
  • smarty_compiler_xoModuleIcons32
  • smarty_compiler_xoModuleIconsBookmarks
  • smarty_core_assemble_plugin_filepath
  • smarty_core_assign_smarty_interface
  • smarty_core_create_dir_structure
  • smarty_core_display_debug_console
  • smarty_core_get_include_path
  • smarty_core_get_microtime
  • smarty_core_get_php_resource
  • smarty_core_is_secure
  • smarty_core_is_trusted
  • smarty_core_load_plugins
  • smarty_core_load_resource_plugin
  • smarty_core_process_cached_inserts
  • smarty_core_process_compiled_include
  • smarty_core_read_cache_file
  • smarty_core_rm_auto
  • smarty_core_rmdir
  • smarty_core_run_insert_handler
  • smarty_core_smarty_include_php
  • smarty_core_write_cache_file
  • smarty_core_write_compiled_include
  • smarty_core_write_compiled_resource
  • smarty_core_write_file
  • smarty_function_assign_debug_info
  • smarty_function_block
  • smarty_function_config_load
  • smarty_function_counter
  • smarty_function_cycle
  • smarty_function_debug
  • smarty_function_escape_special_chars
  • smarty_function_eval
  • smarty_function_fetch
  • smarty_function_html_checkboxes
  • smarty_function_html_checkboxes_output
  • smarty_function_html_image
  • smarty_function_html_options
  • smarty_function_html_options_optgroup
  • smarty_function_html_options_optoutput
  • smarty_function_html_radios
  • smarty_function_html_radios_output
  • smarty_function_html_select_date
  • smarty_function_html_select_time
  • smarty_function_html_table
  • smarty_function_html_table_cycle
  • smarty_function_mailto
  • smarty_function_math
  • smarty_function_popup
  • smarty_function_popup_init
  • smarty_function_securityToken
  • smarty_function_xoInboxCount
  • smarty_function_xoMemberInfo
  • smarty_function_xoops_link
  • smarty_function_xoPageNav
  • smarty_make_timestamp
  • smarty_modifier_capitalize
  • smarty_modifier_capitalize_ucfirst
  • smarty_modifier_cat
  • smarty_modifier_count_characters
  • smarty_modifier_count_paragraphs
  • smarty_modifier_count_sentences
  • smarty_modifier_count_words
  • smarty_modifier_date_format
  • smarty_modifier_debug_print_var
  • smarty_modifier_default
  • smarty_modifier_escape
  • smarty_modifier_indent
  • smarty_modifier_lower
  • smarty_modifier_nl2br
  • smarty_modifier_regex_replace
  • smarty_modifier_replace
  • smarty_modifier_spacify
  • smarty_modifier_string_format
  • smarty_modifier_strip
  • smarty_modifier_strip_tags
  • smarty_modifier_truncate
  • smarty_modifier_upper
  • smarty_modifier_wordwrap
  • smarty_outputfilter_trimwhitespace
  • smarty_outputfilter_trimwhitespace_replace
  • smarty_resource_db_secure
  • smarty_resource_db_source
  • smarty_resource_db_timestamp
  • smarty_resource_db_tplinfo
  • smarty_resource_db_trusted
  • synchronize
  • system_AdminIcons
  • system_adminVersion
  • system_CleanVars
  • system_loadLanguage
  • system_loadTemplate
  • themecenterposts
  • update_system_v211
  • userCheck
  • userTimeToServerTime
  • validateDbCharset
  • writeLicenseKey
  • xoBuildLicenceKey
  • xoDiag
  • xoDiagBoolSetting
  • xoDiagIfWritable
  • xoFormBlockCollation
  • xoFormField
  • xoFormFieldCharset
  • xoFormFieldCollation
  • xoFormSelect
  • xoops_aw_decode
  • xoops_aw_encode
  • xoops_bin2hex
  • xoops_comment_count
  • xoops_comment_delete
  • xoops_confirm
  • xoops_convert_decode
  • xoops_convert_encode
  • xoops_convert_encoding
  • xoops_cp_footer
  • xoops_cp_header
  • xoops_error
  • xoops_footer
  • xoops_getActiveModules
  • xoops_getbanner
  • xoops_getBaseDomain
  • xoops_getConfigOption
  • xoops_getcss
  • xoops_getenv
  • xoops_getHandler
  • xoops_getLinkedUnameFromId
  • xoops_getMailer
  • xoops_getModuleHandler
  • xoops_getModuleOption
  • xoops_getOption
  • xoops_getrank
  • xoops_getUrlDomain
  • xoops_getUserTimestamp
  • xoops_groupperm_deletebymoditem
  • xoops_header
  • xoops_hex2bin
  • xoops_isActiveModule
  • xoops_ishexstr
  • xoops_load
  • xoops_load_lang_file
  • xoops_loadLanguage
  • xoops_local
  • xoops_makepass
  • xoops_message
  • xoops_module_activate
  • xoops_module_change
  • xoops_module_deactivate
  • xoops_module_delayed_clean_cache
  • xoops_module_get_admin_menu
  • xoops_module_gettemplate
  • xoops_module_install
  • xoops_module_install_pm
  • xoops_module_install_profile
  • xoops_module_log_header
  • xoops_module_uninstall
  • xoops_module_update
  • xoops_module_update_pm
  • xoops_module_update_profile
  • xoops_module_update_system
  • xoops_module_write_admin_menu
  • xoops_notification_deletebyitem
  • xoops_notification_deletebymodule
  • xoops_notification_deletebyuser
  • xoops_refcheck
  • xoops_result
  • xoops_setActiveModules
  • xoops_setConfigOption
  • xoops_substr
  • xoops_template_clear_module_cache
  • xoops_template_touch
  • xoops_trim
  • xoops_utf8_encode
  • xoops_write_index_file
  • xoopsCodeTarea
  • xoopseditor_get_rootpath
  • XoopsErrorHandler_HandleError
  • xoopsfwrite
  • xoopsSmilies
  • xoPassField
  • xoPhpVersion
  • xoPutLicenseKey
  • xoStripeKey
  • Overview
  • Namespace
  • Class
  • Tree
   1: <?php
   2: //////////////////////////////////////////////////////////////
   3: //   phpThumb() by James Heinrich <info@silisoftware.com>   //
   4: //        available at http://phpthumb.sourceforge.net      //
   5: //         and/or https://github.com/JamesHeinrich/phpThumb //
   6: //////////////////////////////////////////////////////////////
   7: ///                                                         //
   8: // See: phpthumb.readme.txt for usage instructions          //
   9: //                                                         ///
  10: //////////////////////////////////////////////////////////////
  11: 
  12: ob_start();
  13: if (!include_once(dirname(__FILE__).'/phpthumb.functions.php')) {
  14:     ob_end_flush();
  15:     die('failed to include_once("'.dirname(__FILE__).'/phpthumb.functions.php")');
  16: }
  17: ob_end_clean();
  18: 
  19: class phpthumb {
  20: 
  21:     // public:
  22:     // START PARAMETERS (for object mode and phpThumb.php)
  23:     // See phpthumb.readme.txt for descriptions of what each of these values are
  24:     var $src  = null;     // SouRCe filename
  25:     var $new  = null;     // NEW image (phpThumb.php only)
  26:     var $w    = null;     // Width
  27:     var $h    = null;     // Height
  28:     var $wp   = null;     // Width  (Portrait Images Only)
  29:     var $hp   = null;     // Height (Portrait Images Only)
  30:     var $wl   = null;     // Width  (Landscape Images Only)
  31:     var $hl   = null;     // Height (Landscape Images Only)
  32:     var $ws   = null;     // Width  (Square Images Only)
  33:     var $hs   = null;     // Height (Square Images Only)
  34:     var $f    = null;     // output image Format
  35:     var $q    = 75;       // jpeg output Quality
  36:     var $sx   = null;     // Source crop top-left X position
  37:     var $sy   = null;     // Source crop top-left Y position
  38:     var $sw   = null;     // Source crop Width
  39:     var $sh   = null;     // Source crop Height
  40:     var $zc   = null;     // Zoom Crop
  41:     var $bc   = null;     // Border Color
  42:     var $bg   = null;     // BackGround color
  43:     var $fltr = array();  // FiLTeRs
  44:     var $goto = null;     // GO TO url after processing
  45:     var $err  = null;     // default ERRor image filename
  46:     var $xto  = null;     // extract eXif Thumbnail Only
  47:     var $ra   = null;     // Rotate by Angle
  48:     var $ar   = null;     // Auto Rotate
  49:     var $aoe  = null;     // Allow Output Enlargement
  50:     var $far  = null;     // Fixed Aspect Ratio
  51:     var $iar  = null;     // Ignore Aspect Ratio
  52:     var $maxb = null;     // MAXimum Bytes
  53:     var $down = null;     // DOWNload thumbnail filename
  54:     var $md5s = null;     // MD5 hash of Source image
  55:     var $sfn  = 0;        // Source Frame Number
  56:     var $dpi  = 150;      // Dots Per Inch for vector source formats
  57:     var $sia  = null;     // Save Image As filename
  58: 
  59:     var $file = null;     // >>>deprecated, DO NOT USE, will be removed in future versions<<<
  60: 
  61:     var $phpThumbDebug = null;
  62:     // END PARAMETERS
  63: 
  64: 
  65:     // public:
  66:     // START CONFIGURATION OPTIONS (for object mode only)
  67:     // See phpThumb.config.php for descriptions of what each of these settings do
  68: 
  69:     // * Directory Configuration
  70:     var $config_cache_directory                      = null;
  71:     var $config_cache_directory_depth                = 0;
  72:     var $config_cache_disable_warning                = true;
  73:     var $config_cache_source_enabled                 = false;
  74:     var $config_cache_source_directory               = null;
  75:     var $config_temp_directory                       = null;
  76:     var $config_document_root                        = null;
  77: 
  78:     // * Default output configuration:
  79:     var $config_output_format                        = 'jpeg';
  80:     var $config_output_maxwidth                      = 0;
  81:     var $config_output_maxheight                     = 0;
  82:     var $config_output_interlace                     = true;
  83: 
  84:     // * Error message configuration
  85:     var $config_error_image_width                    = 400;
  86:     var $config_error_image_height                   = 100;
  87:     var $config_error_message_image_default          = '';
  88:     var $config_error_bgcolor                        = 'CCCCFF';
  89:     var $config_error_textcolor                      = 'FF0000';
  90:     var $config_error_fontsize                       = 1;
  91:     var $config_error_die_on_error                   = false;
  92:     var $config_error_silent_die_on_error            = false;
  93:     var $config_error_die_on_source_failure          = true;
  94: 
  95:     // * Anti-Hotlink Configuration:
  96:     var $config_nohotlink_enabled                    = true;
  97:     var $config_nohotlink_valid_domains              = array();
  98:     var $config_nohotlink_erase_image                = true;
  99:     var $config_nohotlink_text_message               = 'Off-server thumbnailing is not allowed';
 100:     // * Off-server Linking Configuration:
 101:     var $config_nooffsitelink_enabled                = false;
 102:     var $config_nooffsitelink_valid_domains          = array();
 103:     var $config_nooffsitelink_require_refer          = false;
 104:     var $config_nooffsitelink_erase_image            = true;
 105:     var $config_nooffsitelink_watermark_src          = '';
 106:     var $config_nooffsitelink_text_message           = 'Off-server linking is not allowed';
 107: 
 108:     // * Border & Background default colors
 109:     var $config_border_hexcolor                      = '000000';
 110:     var $config_background_hexcolor                  = 'FFFFFF';
 111: 
 112:     // * TrueType Fonts
 113:     var $config_ttf_directory                        = './fonts';
 114: 
 115:     var $config_max_source_pixels                    = null;
 116:     var $config_use_exif_thumbnail_for_speed         = false;
 117:     var $allow_local_http_src                        = false;
 118: 
 119:     var $config_imagemagick_path                     = null;
 120:     var $config_prefer_imagemagick                   = true;
 121:     var $config_imagemagick_use_thumbnail            = true;
 122: 
 123:     var $config_cache_maxage                         = null;
 124:     var $config_cache_maxsize                        = null;
 125:     var $config_cache_maxfiles                       = null;
 126:     var $config_cache_source_filemtime_ignore_local  = false;
 127:     var $config_cache_source_filemtime_ignore_remote = true;
 128:     var $config_cache_default_only_suffix            = false;
 129:     var $config_cache_force_passthru                 = true;
 130:     var $config_cache_prefix                         = '';    // default value set in the constructor below
 131: 
 132:     // * MySQL
 133:     var $config_mysql_extension                      = null;
 134:     var $config_mysql_query                          = null;
 135:     var $config_mysql_hostname                       = null;
 136:     var $config_mysql_username                       = null;
 137:     var $config_mysql_password                       = null;
 138:     var $config_mysql_database                       = null;
 139: 
 140:     // * Security
 141:     var $config_high_security_enabled                = true;
 142:     var $config_high_security_password               = null;
 143:     var $config_high_security_url_separator          = '&';
 144:     var $config_disable_debug                        = true;
 145:     var $config_allow_src_above_docroot              = false;
 146:     var $config_allow_src_above_phpthumb             = true;
 147:     var $config_auto_allow_symlinks                  = true;    // allow symlink target directories without explicitly whitelisting them
 148:     var $config_additional_allowed_dirs              = array(); // additional directories to allow source images to be read from
 149:     var $config_file_create_mask                     = 0755;
 150:     var $config_dir_create_mask                      = 0755;
 151: 
 152:     // * HTTP fopen
 153:     var $config_http_fopen_timeout                   = 10;
 154:     var $config_http_follow_redirect                 = true;
 155: 
 156:     // * Compatability
 157:     var $config_disable_pathinfo_parsing             = false;
 158:     var $config_disable_imagecopyresampled           = false;
 159:     var $config_disable_onlycreateable_passthru      = false;
 160:     var $config_disable_realpath                     = false;
 161: 
 162:     var $config_http_user_agent                      = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7';
 163: 
 164:     // END CONFIGURATION OPTIONS
 165: 
 166: 
 167:     // public: error messages (read-only; persistant)
 168:     var $debugmessages = array();
 169:     var $debugtiming   = array();
 170:     var $fatalerror    = null;
 171: 
 172: 
 173:     // private: (should not be modified directly)
 174:     var $thumbnailQuality = 75;
 175:     var $thumbnailFormat  = null;
 176: 
 177:     var $sourceFilename   = null;
 178:     var $rawImageData     = null;
 179:     var $IMresizedData    = null;
 180:     var $outputImageData  = null;
 181: 
 182:     var $useRawIMoutput   = false;
 183: 
 184:     var $gdimg_output     = null;
 185:     var $gdimg_source     = null;
 186: 
 187:     var $getimagesizeinfo = null;
 188: 
 189:     var $source_width  = null;
 190:     var $source_height = null;
 191: 
 192:     var $thumbnailCropX = null;
 193:     var $thumbnailCropY = null;
 194:     var $thumbnailCropW = null;
 195:     var $thumbnailCropH = null;
 196: 
 197:     var $exif_thumbnail_width  = null;
 198:     var $exif_thumbnail_height = null;
 199:     var $exif_thumbnail_type   = null;
 200:     var $exif_thumbnail_data   = null;
 201:     var $exif_raw_data         = null;
 202: 
 203:     var $thumbnail_width        = null;
 204:     var $thumbnail_height       = null;
 205:     var $thumbnail_image_width  = null;
 206:     var $thumbnail_image_height = null;
 207: 
 208:     var $tempFilesToDelete = array();
 209:     var $cache_filename    = null;
 210: 
 211:     var $AlphaCapableFormats = array('png', 'ico', 'gif');
 212:     var $is_alpha = false;
 213: 
 214:     var $iswindows        = null;
 215:     var $issafemode       = null;
 216:     var $php_memory_limit = null;
 217: 
 218:     var $phpthumb_version = '1.7.14-201608101311';
 219: 
 220:     //////////////////////////////////////////////////////////////////////
 221: 
 222:     // public: constructor
 223:     function __construct() {
 224:         $this->phpThumb();
 225:     }
 226: 
 227:     function phpThumb() {
 228:         $this->DebugTimingMessage('phpThumb() constructor', __FILE__, __LINE__);
 229:         $this->DebugMessage('phpThumb() v'.$this->phpthumb_version, __FILE__, __LINE__);
 230: 
 231:         foreach (array(ini_get('memory_limit'), get_cfg_var('memory_limit')) as $php_config_memory_limit) {
 232:             if (strlen($php_config_memory_limit)) {
 233:                 if (substr($php_config_memory_limit, -1, 1) == 'G') { // PHP memory limit expressed in Gigabytes
 234:                     $php_config_memory_limit = intval(substr($php_config_memory_limit, 0, -1)) * 1073741824;
 235:                 } elseif (substr($php_config_memory_limit, -1, 1) == 'M') { // PHP memory limit expressed in Megabytes
 236:                     $php_config_memory_limit = intval(substr($php_config_memory_limit, 0, -1)) * 1048576;
 237:                 }
 238:                 $this->php_memory_limit = max($this->php_memory_limit, $php_config_memory_limit);
 239:             }
 240:         }
 241:         if ($this->php_memory_limit > 0) { // could be "-1" for "no limit"
 242:             $this->config_max_source_pixels = round($this->php_memory_limit * 0.20); // 20% of memory_limit
 243:         }
 244: 
 245:         $this->iswindows  = (bool) (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN');
 246:         $this->issafemode = (bool) preg_match('#(1|ON)#i', ini_get('safe_mode'));
 247:         $this->config_document_root = (!empty($_SERVER['DOCUMENT_ROOT']) ? $_SERVER['DOCUMENT_ROOT']   : $this->config_document_root);
 248:         $this->config_cache_prefix  = ( isset($_SERVER['SERVER_NAME'])   ? $_SERVER['SERVER_NAME'].'_' : '');
 249: 
 250:         $this->purgeTempFiles(); // purge existing temp files if re-initializing object
 251: 
 252:         $php_sapi_name = strtolower(function_exists('php_sapi_name') ? php_sapi_name() : '');
 253:         if ($php_sapi_name == 'cli') {
 254:             $this->config_allow_src_above_docroot = true;
 255:         }
 256: 
 257:         if (!$this->config_disable_debug) {
 258:             // if debug mode is enabled, force phpThumbDebug output, do not allow normal thumbnails to be generated
 259:             $this->phpThumbDebug = (is_null($this->phpThumbDebug) ? 9 : max(1, intval($this->phpThumbDebug)));
 260:         }
 261:     }
 262: 
 263:     function __destruct() {
 264:         $this->purgeTempFiles();
 265:     }
 266: 
 267:     // public:
 268:     function purgeTempFiles() {
 269:         foreach ($this->tempFilesToDelete as $tempFileToDelete) {
 270:             if (file_exists($tempFileToDelete)) {
 271:                 $this->DebugMessage('Deleting temp file "'.$tempFileToDelete.'"', __FILE__, __LINE__);
 272:                 @unlink($tempFileToDelete);
 273:             }
 274:         }
 275:         $this->tempFilesToDelete = array();
 276:         return true;
 277:     }
 278: 
 279:     // public:
 280:     function setSourceFilename($sourceFilename) {
 281:         //$this->resetObject();
 282:         //$this->rawImageData   = null;
 283:         $this->sourceFilename = $sourceFilename;
 284:         $this->src            = $sourceFilename;
 285:         if (is_null($this->config_output_format)) {
 286:             $sourceFileExtension = strtolower(substr(strrchr($sourceFilename, '.'), 1));
 287:             if (preg_match('#^[a-z]{3,4}$#', $sourceFileExtension)) {
 288:                 $this->config_output_format = $sourceFileExtension;
 289:                 $this->DebugMessage('setSourceFilename('.$sourceFilename.') set $this->config_output_format to "'.$sourceFileExtension.'"', __FILE__, __LINE__);
 290:             } else {
 291:                 $this->DebugMessage('setSourceFilename('.$sourceFilename.') did NOT set $this->config_output_format to "'.$sourceFileExtension.'" because it did not seem like an appropriate image format', __FILE__, __LINE__);
 292:             }
 293:         }
 294:         $this->DebugMessage('setSourceFilename('.$sourceFilename.') set $this->sourceFilename to "'.$this->sourceFilename.'"', __FILE__, __LINE__);
 295:         return true;
 296:     }
 297: 
 298:     // public:
 299:     function setSourceData($rawImageData, $sourceFilename='') {
 300:         //$this->resetObject();
 301:         //$this->sourceFilename = null;
 302:         $this->rawImageData   = $rawImageData;
 303:         $this->DebugMessage('setSourceData() setting $this->rawImageData ('.strlen($this->rawImageData).' bytes; magic="'.substr($this->rawImageData, 0, 4).'" ('.phpthumb_functions::HexCharDisplay(substr($this->rawImageData, 0, 4)).'))', __FILE__, __LINE__);
 304:         if ($this->config_cache_source_enabled) {
 305:             $sourceFilename = ($sourceFilename ? $sourceFilename : md5($rawImageData));
 306:             if (!is_dir($this->config_cache_source_directory)) {
 307:                 $this->ErrorImage('$this->config_cache_source_directory ('.$this->config_cache_source_directory.') is not a directory');
 308:             } elseif (!@is_writable($this->config_cache_source_directory)) {
 309:                 $this->ErrorImage('$this->config_cache_source_directory ('.$this->config_cache_source_directory.') is not writable');
 310:             }
 311:             $this->DebugMessage('setSourceData() attempting to save source image to "'.$this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename).'"', __FILE__, __LINE__);
 312:             if ($fp = @fopen($this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename), 'wb')) {
 313:                 fwrite($fp, $rawImageData);
 314:                 fclose($fp);
 315:             } elseif (!$this->phpThumbDebug) {
 316:                 $this->ErrorImage('setSourceData() failed to write to source cache ('.$this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename).')');
 317:             }
 318:         }
 319:         return true;
 320:     }
 321: 
 322:     // public:
 323:     function setSourceImageResource($gdimg) {
 324:         //$this->resetObject();
 325:         $this->gdimg_source = $gdimg;
 326:         return true;
 327:     }
 328: 
 329:     // public:
 330:     function setParameter($param, $value) {
 331:         if ($param == 'src') {
 332:             $this->setSourceFilename($this->ResolveFilenameToAbsolute($value));
 333:         } elseif (@is_array($this->$param)) {
 334:             if (is_array($value)) {
 335:                 foreach ($value as $arraykey => $arrayvalue) {
 336:                     array_push($this->$param, $arrayvalue);
 337:                 }
 338:             } else {
 339:                 array_push($this->$param, $value);
 340:             }
 341:         } else {
 342:             $this->$param = $value;
 343:         }
 344:         return true;
 345:     }
 346: 
 347:     // public:
 348:     function getParameter($param) {
 349:         //if (property_exists('phpThumb', $param)) {
 350:             return $this->$param;
 351:         //}
 352:         //$this->DebugMessage('setParameter() attempting to get non-existant parameter "'.$param.'"', __FILE__, __LINE__);
 353:         //return false;
 354:     }
 355: 
 356: 
 357:     // public:
 358:     function GenerateThumbnail() {
 359: 
 360:         $this->setOutputFormat();
 361:             $this->phpThumbDebug('8a');
 362:         $this->ResolveSource();
 363:             $this->phpThumbDebug('8b');
 364:         $this->SetCacheFilename();
 365:             $this->phpThumbDebug('8c');
 366:         $this->ExtractEXIFgetImageSize();
 367:             $this->phpThumbDebug('8d');
 368:         if ($this->useRawIMoutput) {
 369:             $this->DebugMessage('Skipping rest of GenerateThumbnail() because ($this->useRawIMoutput == true)', __FILE__, __LINE__);
 370:             return true;
 371:         }
 372:             $this->phpThumbDebug('8e');
 373:         if (!$this->SourceImageToGD()) {
 374:             $this->DebugMessage('SourceImageToGD() failed', __FILE__, __LINE__);
 375:             return false;
 376:         }
 377:             $this->phpThumbDebug('8f');
 378:         $this->Rotate();
 379:             $this->phpThumbDebug('8g');
 380:         $this->CreateGDoutput();
 381:             $this->phpThumbDebug('8h');
 382: 
 383:         // default values, also applicable for far="C"
 384:         $destination_offset_x = round(($this->thumbnail_width  - $this->thumbnail_image_width)  / 2);
 385:         $destination_offset_y = round(($this->thumbnail_height - $this->thumbnail_image_height) / 2);
 386:         if (($this->far == 'L') || ($this->far == 'TL') || ($this->far == 'BL')) {
 387:             $destination_offset_x = 0;
 388:         }
 389:         if (($this->far == 'R') || ($this->far == 'TR') || ($this->far == 'BR')) {
 390:             $destination_offset_x =  round($this->thumbnail_width  - $this->thumbnail_image_width);
 391:         }
 392:         if (($this->far == 'T') || ($this->far == 'TL') || ($this->far == 'TR')) {
 393:             $destination_offset_y = 0;
 394:         }
 395:         if (($this->far == 'B') || ($this->far == 'BL') || ($this->far == 'BR')) {
 396:             $destination_offset_y =  round($this->thumbnail_height - $this->thumbnail_image_height);
 397:         }
 398: 
 399: //      // copy/resize image to appropriate dimensions
 400: //      $borderThickness = 0;
 401: //      if (!empty($this->fltr)) {
 402: //          foreach ($this->fltr as $key => $value) {
 403: //              if (preg_match('#^bord\|([0-9]+)#', $value, $matches)) {
 404: //                  $borderThickness = $matches[1];
 405: //                  break;
 406: //              }
 407: //          }
 408: //      }
 409: //      if ($borderThickness > 0) {
 410: //          //$this->DebugMessage('Skipping ImageResizeFunction() because BorderThickness="'.$borderThickness.'"', __FILE__, __LINE__);
 411: //          $this->thumbnail_image_height /= 2;
 412: //      }
 413:         $this->ImageResizeFunction(
 414:             $this->gdimg_output,
 415:             $this->gdimg_source,
 416:             $destination_offset_x,
 417:             $destination_offset_y,
 418:             $this->thumbnailCropX,
 419:             $this->thumbnailCropY,
 420:             $this->thumbnail_image_width,
 421:             $this->thumbnail_image_height,
 422:             $this->thumbnailCropW,
 423:             $this->thumbnailCropH
 424:         );
 425: 
 426:         $this->DebugMessage('memory_get_usage() after copy-resize = '.(function_exists('memory_get_usage') ? @memory_get_usage() : 'n/a'), __FILE__, __LINE__);
 427:         imagedestroy($this->gdimg_source);
 428:         $this->DebugMessage('memory_get_usage() after imagedestroy = '.(function_exists('memory_get_usage') ? @memory_get_usage() : 'n/a'), __FILE__, __LINE__);
 429: 
 430:             $this->phpThumbDebug('8i');
 431:         $this->AntiOffsiteLinking();
 432:             $this->phpThumbDebug('8j');
 433:         $this->ApplyFilters();
 434:             $this->phpThumbDebug('8k');
 435:         $this->AlphaChannelFlatten();
 436:             $this->phpThumbDebug('8l');
 437:         $this->MaxFileSize();
 438:             $this->phpThumbDebug('8m');
 439: 
 440:         $this->DebugMessage('GenerateThumbnail() completed successfully', __FILE__, __LINE__);
 441:         return true;
 442:     }
 443: 
 444: 
 445:     // public:
 446:     function RenderOutput() {
 447:         if (!$this->useRawIMoutput && !is_resource($this->gdimg_output)) {
 448:             $this->DebugMessage('RenderOutput() failed because !is_resource($this->gdimg_output)', __FILE__, __LINE__);
 449:             return false;
 450:         }
 451:         if (!$this->thumbnailFormat) {
 452:             $this->DebugMessage('RenderOutput() failed because $this->thumbnailFormat is empty', __FILE__, __LINE__);
 453:             return false;
 454:         }
 455:         if ($this->useRawIMoutput) {
 456:             $this->DebugMessage('RenderOutput copying $this->IMresizedData ('.strlen($this->IMresizedData).' bytes) to $this->outputImage', __FILE__, __LINE__);
 457:             $this->outputImageData = $this->IMresizedData;
 458:             return true;
 459:         }
 460: 
 461:         $builtin_formats = array();
 462:         if (function_exists('imagetypes')) {
 463:             $imagetypes = imagetypes();
 464:             $builtin_formats['wbmp'] = (bool) ($imagetypes & IMG_WBMP);
 465:             $builtin_formats['jpg']  = (bool) ($imagetypes & IMG_JPG);
 466:             $builtin_formats['gif']  = (bool) ($imagetypes & IMG_GIF);
 467:             $builtin_formats['png']  = (bool) ($imagetypes & IMG_PNG);
 468:         }
 469: 
 470:         $this->DebugMessage('imageinterlace($this->gdimg_output, '.intval($this->config_output_interlace).')', __FILE__, __LINE__);
 471:         imageinterlace($this->gdimg_output, intval($this->config_output_interlace));
 472: 
 473:         $this->DebugMessage('RenderOutput() attempting image'.strtolower(@$this->thumbnailFormat).'($this->gdimg_output)', __FILE__, __LINE__);
 474:         ob_start();
 475:         switch ($this->thumbnailFormat) {
 476:             case 'wbmp':
 477:                 if (empty($builtin_formats['wbmp'])) {
 478:                     $this->DebugMessage('GD does not have required built-in support for WBMP output', __FILE__, __LINE__);
 479:                     ob_end_clean();
 480:                     return false;
 481:                 }
 482:                 imagejpeg($this->gdimg_output, null, $this->thumbnailQuality);
 483:                 $this->outputImageData = ob_get_contents();
 484:                 break;
 485: 
 486:             case 'jpeg':
 487:             case 'jpg':  // should be "jpeg" not "jpg" but just in case...
 488:                 if (empty($builtin_formats['jpg'])) {
 489:                     $this->DebugMessage('GD does not have required built-in support for JPEG output', __FILE__, __LINE__);
 490:                     ob_end_clean();
 491:                     return false;
 492:                 }
 493:                 imagejpeg($this->gdimg_output, null, $this->thumbnailQuality);
 494:                 $this->outputImageData = ob_get_contents();
 495:                 break;
 496: 
 497:             case 'png':
 498:                 if (empty($builtin_formats['png'])) {
 499:                     $this->DebugMessage('GD does not have required built-in support for PNG output', __FILE__, __LINE__);
 500:                     ob_end_clean();
 501:                     return false;
 502:                 }
 503:                 if (phpthumb_functions::version_compare_replacement(phpversion(), '5.1.2', '>=')) {
 504:                     // https://github.com/JamesHeinrich/phpThumb/issues/24
 505: 
 506:                     /* http://php.net/manual/en/function.imagepng.php:
 507:                     from php source (gd.h):
 508:                     2.0.12: Compression level: 0-9 or -1, where 0 is NO COMPRESSION at all,
 509:                     :: 1 is FASTEST but produces larger files, 9 provides the best
 510:                     :: compression (smallest files) but takes a long time to compress, and
 511:                     :: -1 selects the default compiled into the zlib library.
 512:                     Conclusion: Based on the Zlib manual (http://www.zlib.net/manual.html) the default compression level is set to 6.
 513:                     */
 514:                     if (($this->thumbnailQuality >= -1) && ($this->thumbnailQuality <= 9)) {
 515:                         $PNGquality = $this->thumbnailQuality;
 516:                     } else {
 517:                         $this->DebugMessage('Specified thumbnailQuality "'.$this->thumbnailQuality.'" is outside the accepted range (0-9, or -1). Using 6 as default value.', __FILE__, __LINE__);
 518:                         $PNGquality = 6;
 519:                     }
 520:                     imagepng($this->gdimg_output, null, $PNGquality);
 521:                 } else {
 522:                     imagepng($this->gdimg_output);
 523:                 }
 524:                 $this->outputImageData = ob_get_contents();
 525:                 break;
 526: 
 527:             case 'gif':
 528:                 if (empty($builtin_formats['gif'])) {
 529:                     $this->DebugMessage('GD does not have required built-in support for GIF output', __FILE__, __LINE__);
 530:                     ob_end_clean();
 531:                     return false;
 532:                 }
 533:                 imagegif($this->gdimg_output);
 534:                 $this->outputImageData = ob_get_contents();
 535:                 break;
 536: 
 537:             case 'bmp':
 538:                 if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) {
 539:                     $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.bmp.php" which is required for BMP format output', __FILE__, __LINE__);
 540:                     ob_end_clean();
 541:                     return false;
 542:                 }
 543:                 $phpthumb_bmp = new phpthumb_bmp();
 544:                 $this->outputImageData = $phpthumb_bmp->GD2BMPstring($this->gdimg_output);
 545:                 unset($phpthumb_bmp);
 546:                 break;
 547: 
 548:             case 'ico':
 549:                 if (!@include_once(dirname(__FILE__).'/phpthumb.ico.php')) {
 550:                     $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.ico.php" which is required for ICO format output', __FILE__, __LINE__);
 551:                     ob_end_clean();
 552:                     return false;
 553:                 }
 554:                 $phpthumb_ico = new phpthumb_ico();
 555:                 $arrayOfOutputImages = array($this->gdimg_output);
 556:                 $this->outputImageData = $phpthumb_ico->GD2ICOstring($arrayOfOutputImages);
 557:                 unset($phpthumb_ico);
 558:                 break;
 559: 
 560:             default:
 561:                 $this->DebugMessage('RenderOutput failed because $this->thumbnailFormat "'.$this->thumbnailFormat.'" is not valid', __FILE__, __LINE__);
 562:                 ob_end_clean();
 563:                 return false;
 564:         }
 565:         ob_end_clean();
 566:         if (!$this->outputImageData) {
 567:             $this->DebugMessage('RenderOutput() for "'.$this->thumbnailFormat.'" failed', __FILE__, __LINE__);
 568:             ob_end_clean();
 569:             return false;
 570:         }
 571:         $this->DebugMessage('RenderOutput() completing with $this->outputImageData = '.strlen($this->outputImageData).' bytes', __FILE__, __LINE__);
 572:         return true;
 573:     }
 574: 
 575: 
 576:     // public:
 577:     function RenderToFile($filename) {
 578:         if (preg_match('#^[a-z0-9]+://#i', $filename)) {
 579:             $this->DebugMessage('RenderToFile() failed because $filename ('.$filename.') is a URL', __FILE__, __LINE__);
 580:             return false;
 581:         }
 582:         // render thumbnail to this file only, do not cache, do not output to browser
 583:         //$renderfilename = $this->ResolveFilenameToAbsolute(dirname($filename)).DIRECTORY_SEPARATOR.basename($filename);
 584:         $renderfilename = $filename;
 585:         if (($filename{0} != '/') && ($filename{0} != '\\') && ($filename{1} != ':')) {
 586:             $renderfilename = $this->ResolveFilenameToAbsolute($renderfilename);
 587:         }
 588:         if (!@is_writable(dirname($renderfilename))) {
 589:             $this->DebugMessage('RenderToFile() failed because "'.dirname($renderfilename).'/" is not writable', __FILE__, __LINE__);
 590:             return false;
 591:         }
 592:         if (@is_file($renderfilename) && !@is_writable($renderfilename)) {
 593:             $this->DebugMessage('RenderToFile() failed because "'.$renderfilename.'" is not writable', __FILE__, __LINE__);
 594:             return false;
 595:         }
 596: 
 597:         if ($this->RenderOutput()) {
 598:             if (file_put_contents($renderfilename, $this->outputImageData)) {
 599:                 @chmod($renderfilename, $this->getParameter('config_file_create_mask'));
 600:                 $this->DebugMessage('RenderToFile('.$renderfilename.') succeeded', __FILE__, __LINE__);
 601:                 return true;
 602:             }
 603:             if (!@file_exists($renderfilename)) {
 604:                 $this->DebugMessage('RenderOutput ['.$this->thumbnailFormat.'('.$renderfilename.')] did not appear to fail, but the output image does not exist either...', __FILE__, __LINE__);
 605:             }
 606:         } else {
 607:             $this->DebugMessage('RenderOutput ['.$this->thumbnailFormat.'('.$renderfilename.')] failed', __FILE__, __LINE__);
 608:         }
 609:         return false;
 610:     }
 611: 
 612: 
 613:     // public:
 614:     function OutputThumbnail() {
 615:         $this->purgeTempFiles();
 616: 
 617:         if (!$this->useRawIMoutput && !is_resource($this->gdimg_output)) {
 618:             $this->DebugMessage('OutputThumbnail() failed because !is_resource($this->gdimg_output)', __FILE__, __LINE__);
 619:             return false;
 620:         }
 621:         if (headers_sent()) {
 622:             return $this->ErrorImage('OutputThumbnail() failed - headers already sent');
 623:         }
 624: 
 625:         $downloadfilename = phpthumb_functions::SanitizeFilename(is_string($this->sia) ? $this->sia : ($this->down ? $this->down : 'phpThumb_generated_thumbnail'.'.'.$this->thumbnailFormat));
 626:         $this->DebugMessage('Content-Disposition header filename set to "'.$downloadfilename.'"', __FILE__, __LINE__);
 627:         if ($downloadfilename) {
 628:             header('Content-Disposition: '.($this->down ? 'attachment' : 'inline').'; filename="'.$downloadfilename.'"');
 629:         } else {
 630:             $this->DebugMessage('failed to send Content-Disposition header because $downloadfilename is empty', __FILE__, __LINE__);
 631:         }
 632: 
 633:         if ($this->useRawIMoutput) {
 634: 
 635:             header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat));
 636:             echo $this->IMresizedData;
 637: 
 638:         } else {
 639: 
 640:             $this->DebugMessage('imageinterlace($this->gdimg_output, '.intval($this->config_output_interlace).')', __FILE__, __LINE__);
 641:             imageinterlace($this->gdimg_output, intval($this->config_output_interlace));
 642:             switch ($this->thumbnailFormat) {
 643:                 case 'jpeg':
 644:                     header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat));
 645:                     $ImageOutFunction = 'image'.$this->thumbnailFormat;
 646:                     @$ImageOutFunction($this->gdimg_output, null, $this->thumbnailQuality);
 647:                     break;
 648: 
 649:                 case 'png':
 650:                 case 'gif':
 651:                     header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat));
 652:                     $ImageOutFunction = 'image'.$this->thumbnailFormat;
 653:                     @$ImageOutFunction($this->gdimg_output);
 654:                     break;
 655: 
 656:                 case 'bmp':
 657:                     if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) {
 658:                         $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.bmp.php" which is required for BMP format output', __FILE__, __LINE__);
 659:                         return false;
 660:                     }
 661:                     $phpthumb_bmp = new phpthumb_bmp();
 662:                     if (is_object($phpthumb_bmp)) {
 663:                         $bmp_data = $phpthumb_bmp->GD2BMPstring($this->gdimg_output);
 664:                         unset($phpthumb_bmp);
 665:                         if (!$bmp_data) {
 666:                             $this->DebugMessage('$phpthumb_bmp->GD2BMPstring() failed', __FILE__, __LINE__);
 667:                             return false;
 668:                         }
 669:                         header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat));
 670:                         echo $bmp_data;
 671:                     } else {
 672:                         $this->DebugMessage('new phpthumb_bmp() failed', __FILE__, __LINE__);
 673:                         return false;
 674:                     }
 675:                     break;
 676: 
 677:                 case 'ico':
 678:                     if (!@include_once(dirname(__FILE__).'/phpthumb.ico.php')) {
 679:                         $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.ico.php" which is required for ICO format output', __FILE__, __LINE__);
 680:                         return false;
 681:                     }
 682:                     $phpthumb_ico = new phpthumb_ico();
 683:                     if (is_object($phpthumb_ico)) {
 684:                         $arrayOfOutputImages = array($this->gdimg_output);
 685:                         $ico_data = $phpthumb_ico->GD2ICOstring($arrayOfOutputImages);
 686:                         unset($phpthumb_ico);
 687:                         if (!$ico_data) {
 688:                             $this->DebugMessage('$phpthumb_ico->GD2ICOstring() failed', __FILE__, __LINE__);
 689:                             return false;
 690:                         }
 691:                         header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat));
 692:                         echo $ico_data;
 693:                     } else {
 694:                         $this->DebugMessage('new phpthumb_ico() failed', __FILE__, __LINE__);
 695:                         return false;
 696:                     }
 697:                     break;
 698: 
 699:                 default:
 700:                     $this->DebugMessage('OutputThumbnail failed because $this->thumbnailFormat "'.$this->thumbnailFormat.'" is not valid', __FILE__, __LINE__);
 701:                     return false;
 702:                     break;
 703:             }
 704: 
 705:         }
 706:         return true;
 707:     }
 708: 
 709: 
 710:     // public:
 711:     function CleanUpCacheDirectory() {
 712:         $this->DebugMessage('CleanUpCacheDirectory() set to purge ('.(is_null($this->config_cache_maxage) ? 'NULL' : number_format($this->config_cache_maxage / 86400, 1)).' days; '.(is_null($this->config_cache_maxsize) ? 'NULL' : number_format($this->config_cache_maxsize / 1048576, 2)).' MB; '.(is_null($this->config_cache_maxfiles) ? 'NULL' : number_format($this->config_cache_maxfiles)).' files)', __FILE__, __LINE__);
 713: 
 714:         if (!is_writable($this->config_cache_directory)) {
 715:             $this->DebugMessage('CleanUpCacheDirectory() skipped because "'.$this->config_cache_directory.'" is not writable', __FILE__, __LINE__);
 716:             return true;
 717:         }
 718: 
 719:         // cache status of cache directory for 1 hour to avoid hammering the filesystem functions
 720:         $phpThumbCacheStats_filename = $this->config_cache_directory.DIRECTORY_SEPARATOR.'phpThumbCacheStats.txt';
 721:         if (file_exists($phpThumbCacheStats_filename) && is_readable($phpThumbCacheStats_filename) && (filemtime($phpThumbCacheStats_filename) >= (time() - 3600))) {
 722:             $this->DebugMessage('CleanUpCacheDirectory() skipped because "'.$phpThumbCacheStats_filename.'" is recently modified', __FILE__, __LINE__);
 723:             return true;
 724:         }
 725:         if (!@touch($phpThumbCacheStats_filename)) {
 726:             $this->DebugMessage('touch('.$phpThumbCacheStats_filename.') failed', __FILE__, __LINE__);
 727:         }
 728: 
 729:         $DeletedKeys = array();
 730:         $AllFilesInCacheDirectory = array();
 731:         if (($this->config_cache_maxage > 0) || ($this->config_cache_maxsize > 0) || ($this->config_cache_maxfiles > 0)) {
 732:             $CacheDirOldFilesAge  = array();
 733:             $CacheDirOldFilesSize = array();
 734:             $AllFilesInCacheDirectory = phpthumb_functions::GetAllFilesInSubfolders($this->config_cache_directory);
 735:             foreach ($AllFilesInCacheDirectory as $fullfilename) {
 736:                 if (preg_match('#'.preg_quote($this->config_cache_prefix).'#i', $fullfilename) && file_exists($fullfilename)) {
 737:                     $CacheDirOldFilesAge[$fullfilename] = @fileatime($fullfilename);
 738:                     if ($CacheDirOldFilesAge[$fullfilename] == 0) {
 739:                         $CacheDirOldFilesAge[$fullfilename] = @filemtime($fullfilename);
 740:                     }
 741:                     $CacheDirOldFilesSize[$fullfilename] = @filesize($fullfilename);
 742:                 }
 743:             }
 744:             if (empty($CacheDirOldFilesSize)) {
 745:                 $this->DebugMessage('CleanUpCacheDirectory() skipped because $CacheDirOldFilesSize is empty (phpthumb_functions::GetAllFilesInSubfolders('.$this->config_cache_directory.') found no files)', __FILE__, __LINE__);
 746:                 return true;
 747:             }
 748:             $DeletedKeys['zerobyte'] = array();
 749:             foreach ($CacheDirOldFilesSize as $fullfilename => $filesize) {
 750:                 // purge all zero-size files more than an hour old (to prevent trying to delete just-created and/or in-use files)
 751:                 $cutofftime = time() - 3600;
 752:                 if (($filesize == 0) && ($CacheDirOldFilesAge[$fullfilename] < $cutofftime)) {
 753:                     $this->DebugMessage('deleting "'.$fullfilename.'"', __FILE__, __LINE__);
 754:                     if (@unlink($fullfilename)) {
 755:                         $DeletedKeys['zerobyte'][] = $fullfilename;
 756:                         unset($CacheDirOldFilesSize[$fullfilename]);
 757:                         unset($CacheDirOldFilesAge[$fullfilename]);
 758:                     }
 759:                 }
 760:             }
 761:             $this->DebugMessage('CleanUpCacheDirectory() purged '.count($DeletedKeys['zerobyte']).' zero-byte files', __FILE__, __LINE__);
 762:             asort($CacheDirOldFilesAge);
 763: 
 764:             if ($this->config_cache_maxfiles > 0) {
 765:                 $TotalCachedFiles = count($CacheDirOldFilesAge);
 766:                 $DeletedKeys['maxfiles'] = array();
 767:                 foreach ($CacheDirOldFilesAge as $fullfilename => $filedate) {
 768:                     if ($TotalCachedFiles > $this->config_cache_maxfiles) {
 769:                         $this->DebugMessage('deleting "'.$fullfilename.'"', __FILE__, __LINE__);
 770:                         if (@unlink($fullfilename)) {
 771:                             $TotalCachedFiles--;
 772:                             $DeletedKeys['maxfiles'][] = $fullfilename;
 773:                         }
 774:                     } else {
 775:                         // there are few enough files to keep the rest
 776:                         break;
 777:                     }
 778:                 }
 779:                 $this->DebugMessage('CleanUpCacheDirectory() purged '.count($DeletedKeys['maxfiles']).' files based on (config_cache_maxfiles='.$this->config_cache_maxfiles.')', __FILE__, __LINE__);
 780:                 foreach ($DeletedKeys['maxfiles'] as $fullfilename) {
 781:                     unset($CacheDirOldFilesAge[$fullfilename]);
 782:                     unset($CacheDirOldFilesSize[$fullfilename]);
 783:                 }
 784:             }
 785: 
 786:             if ($this->config_cache_maxage > 0) {
 787:                 $mindate = time() - $this->config_cache_maxage;
 788:                 $DeletedKeys['maxage'] = array();
 789:                 foreach ($CacheDirOldFilesAge as $fullfilename => $filedate) {
 790:                     if ($filedate > 0) {
 791:                         if ($filedate < $mindate) {
 792:                             $this->DebugMessage('deleting "'.$fullfilename.'"', __FILE__, __LINE__);
 793:                             if (@unlink($fullfilename)) {
 794:                                 $DeletedKeys['maxage'][] = $fullfilename;
 795:                             }
 796:                         } else {
 797:                             // the rest of the files are new enough to keep
 798:                             break;
 799:                         }
 800:                     }
 801:                 }
 802:                 $this->DebugMessage('CleanUpCacheDirectory() purged '.count($DeletedKeys['maxage']).' files based on (config_cache_maxage='.$this->config_cache_maxage.')', __FILE__, __LINE__);
 803:                 foreach ($DeletedKeys['maxage'] as $fullfilename) {
 804:                     unset($CacheDirOldFilesAge[$fullfilename]);
 805:                     unset($CacheDirOldFilesSize[$fullfilename]);
 806:                 }
 807:             }
 808: 
 809:             if ($this->config_cache_maxsize > 0) {
 810:                 $TotalCachedFileSize = array_sum($CacheDirOldFilesSize);
 811:                 $DeletedKeys['maxsize'] = array();
 812:                 foreach ($CacheDirOldFilesAge as $fullfilename => $filedate) {
 813:                     if ($TotalCachedFileSize > $this->config_cache_maxsize) {
 814:                         $this->DebugMessage('deleting "'.$fullfilename.'"', __FILE__, __LINE__);
 815:                         if (@unlink($fullfilename)) {
 816:                             $TotalCachedFileSize -= $CacheDirOldFilesSize[$fullfilename];
 817:                             $DeletedKeys['maxsize'][] = $fullfilename;
 818:                         }
 819:                     } else {
 820:                         // the total filesizes are small enough to keep the rest of the files
 821:                         break;
 822:                     }
 823:                 }
 824:                 $this->DebugMessage('CleanUpCacheDirectory() purged '.count($DeletedKeys['maxsize']).' files based on (config_cache_maxsize='.$this->config_cache_maxsize.')', __FILE__, __LINE__);
 825:                 foreach ($DeletedKeys['maxsize'] as $fullfilename) {
 826:                     unset($CacheDirOldFilesAge[$fullfilename]);
 827:                     unset($CacheDirOldFilesSize[$fullfilename]);
 828:                 }
 829:             }
 830: 
 831:         } else {
 832:             $this->DebugMessage('skipping CleanUpCacheDirectory() because config set to not use it', __FILE__, __LINE__);
 833:         }
 834:         $totalpurged = 0;
 835:         foreach ($DeletedKeys as $key => $value) {
 836:             $totalpurged += count($value);
 837:         }
 838:         $this->DebugMessage('CleanUpCacheDirectory() purged '.$totalpurged.' files (from '.count($AllFilesInCacheDirectory).') based on config settings', __FILE__, __LINE__);
 839:         if ($totalpurged > 0) {
 840:             $empty_dirs = array();
 841:             foreach ($AllFilesInCacheDirectory as $fullfilename) {
 842:                 if (is_dir($fullfilename)) {
 843:                     $empty_dirs[$this->realPathSafe($fullfilename)] = 1;
 844:                 } else {
 845:                     unset($empty_dirs[$this->realPathSafe(dirname($fullfilename))]);
 846:                 }
 847:             }
 848:             krsort($empty_dirs);
 849:             $totalpurgeddirs = 0;
 850:             foreach ($empty_dirs as $empty_dir => $dummy) {
 851:                 if ($empty_dir == $this->config_cache_directory) {
 852:                     // shouldn't happen, but just in case, don't let it delete actual cache directory
 853:                     continue;
 854:                 } elseif (@rmdir($empty_dir)) {
 855:                     $totalpurgeddirs++;
 856:                 } else {
 857:                     $this->DebugMessage('failed to rmdir('.$empty_dir.')', __FILE__, __LINE__);
 858:                 }
 859:             }
 860:             $this->DebugMessage('purged '.$totalpurgeddirs.' empty directories', __FILE__, __LINE__);
 861:         }
 862:         return true;
 863:     }
 864: 
 865:     //////////////////////////////////////////////////////////////////////
 866: 
 867:     // private: re-initializator (call between rendering multiple images with one object)
 868:     function resetObject() {
 869:         $class_vars = get_class_vars(get_class($this));
 870:         foreach ($class_vars as $key => $value) {
 871:             // do not clobber debug or config info
 872:             if (!preg_match('#^(config_|debug|fatalerror)#i', $key)) {
 873:                 $this->$key = $value;
 874:             }
 875:         }
 876:         $this->phpThumb(); // re-initialize some class variables
 877:         return true;
 878:     }
 879: 
 880:     //////////////////////////////////////////////////////////////////////
 881: 
 882:     function ResolveSource() {
 883:         if (is_resource($this->gdimg_source)) {
 884:             $this->DebugMessage('ResolveSource() exiting because is_resource($this->gdimg_source)', __FILE__, __LINE__);
 885:             return true;
 886:         }
 887:         if ($this->rawImageData) {
 888:             $this->sourceFilename = null;
 889:             $this->DebugMessage('ResolveSource() exiting because $this->rawImageData is set ('.number_format(strlen($this->rawImageData)).' bytes)', __FILE__, __LINE__);
 890:             return true;
 891:         }
 892:         if ($this->sourceFilename) {
 893:             $this->sourceFilename = $this->ResolveFilenameToAbsolute($this->sourceFilename);
 894:             $this->DebugMessage('$this->sourceFilename set to "'.$this->sourceFilename.'"', __FILE__, __LINE__);
 895:         } elseif ($this->src) {
 896:             $this->sourceFilename = $this->ResolveFilenameToAbsolute($this->src);
 897:             $this->DebugMessage('$this->sourceFilename set to "'.$this->sourceFilename.'" from $this->src ('.$this->src.')', __FILE__, __LINE__);
 898:         } else {
 899:             return $this->ErrorImage('$this->sourceFilename and $this->src are both empty');
 900:         }
 901:         if ($this->iswindows && ((substr($this->sourceFilename, 0, 2) == '//') || (substr($this->sourceFilename, 0, 2) == '\\\\'))) {
 902:             // Windows \\share\filename.ext
 903:         } elseif (preg_match('#^[a-z0-9]+://#i', $this->sourceFilename, $protocol_matches)) {
 904:             if (preg_match('#^(f|ht)tps?\://#i', $this->sourceFilename)) {
 905:                 // URL
 906:                 if ($this->config_http_user_agent) {
 907:                     ini_set('user_agent', $this->config_http_user_agent);
 908:                 }
 909:             } else {
 910:                 return $this->ErrorImage('only FTP and HTTP/HTTPS protocols are allowed, "'.$protocol_matches[1].'" is not');
 911:         }
 912:         } elseif (!@file_exists($this->sourceFilename)) {
 913:             return $this->ErrorImage('"'.$this->sourceFilename.'" does not exist');
 914:         } elseif (!@is_file($this->sourceFilename)) {
 915:             return $this->ErrorImage('"'.$this->sourceFilename.'" is not a file');
 916:         }
 917:         return true;
 918:     }
 919: 
 920: 
 921:     function setOutputFormat() {
 922:         static $alreadyCalled = false;
 923:         if ($this->thumbnailFormat && $alreadyCalled) {
 924:             return true;
 925:         }
 926:         $alreadyCalled = true;
 927: 
 928:         $AvailableImageOutputFormats = array();
 929:         $AvailableImageOutputFormats[] = 'text';
 930:         if (@is_readable(dirname(__FILE__).'/phpthumb.ico.php')) {
 931:             $AvailableImageOutputFormats[] = 'ico';
 932:         }
 933:         if (@is_readable(dirname(__FILE__).'/phpthumb.bmp.php')) {
 934:             $AvailableImageOutputFormats[] = 'bmp';
 935:         }
 936: 
 937:         $this->thumbnailFormat = 'ico';
 938: 
 939:         // Set default output format based on what image types are available
 940:         if (function_exists('imagetypes')) {
 941:             $imagetypes = imagetypes();
 942:             if ($imagetypes & IMG_WBMP) {
 943:                 $this->thumbnailFormat         = 'wbmp';
 944:                 $AvailableImageOutputFormats[] = 'wbmp';
 945:             }
 946:             if ($imagetypes & IMG_GIF) {
 947:                 $this->thumbnailFormat         = 'gif';
 948:                 $AvailableImageOutputFormats[] = 'gif';
 949:             }
 950:             if ($imagetypes & IMG_PNG) {
 951:                 $this->thumbnailFormat         = 'png';
 952:                 $AvailableImageOutputFormats[] = 'png';
 953:             }
 954:             if ($imagetypes & IMG_JPG) {
 955:                 $this->thumbnailFormat         = 'jpeg';
 956:                 $AvailableImageOutputFormats[] = 'jpeg';
 957:             }
 958:         } else {
 959:             $this->DebugMessage('imagetypes() does not exist - GD support might not be enabled?',  __FILE__, __LINE__);
 960:         }
 961:         if ($this->ImageMagickVersion()) {
 962:             $IMformats = array('jpeg', 'png', 'gif', 'bmp', 'ico', 'wbmp');
 963:             $this->DebugMessage('Addding ImageMagick formats to $AvailableImageOutputFormats ('.implode(';', $AvailableImageOutputFormats).')', __FILE__, __LINE__);
 964:             foreach ($IMformats as $key => $format) {
 965:                 $AvailableImageOutputFormats[] = $format;
 966:             }
 967:         }
 968:         $AvailableImageOutputFormats = array_unique($AvailableImageOutputFormats);
 969:         $this->DebugMessage('$AvailableImageOutputFormats = array('.implode(';', $AvailableImageOutputFormats).')', __FILE__, __LINE__);
 970: 
 971:         $this->f = preg_replace('#[^a-z]#', '', strtolower($this->f));
 972:         if (strtolower($this->config_output_format) == 'jpg') {
 973:             $this->config_output_format = 'jpeg';
 974:         }
 975:         if (strtolower($this->f) == 'jpg') {
 976:             $this->f = 'jpeg';
 977:         }
 978:         if (phpthumb_functions::CaseInsensitiveInArray($this->config_output_format, $AvailableImageOutputFormats)) {
 979:             // set output format to config default if that format is available
 980:             $this->DebugMessage('$this->thumbnailFormat set to $this->config_output_format "'.strtolower($this->config_output_format).'"', __FILE__, __LINE__);
 981:             $this->thumbnailFormat = strtolower($this->config_output_format);
 982:         } elseif ($this->config_output_format) {
 983:             $this->DebugMessage('$this->thumbnailFormat staying as "'.$this->thumbnailFormat.'" because $this->config_output_format ('.strtolower($this->config_output_format).') is not in $AvailableImageOutputFormats', __FILE__, __LINE__);
 984:         }
 985:         if ($this->f && (phpthumb_functions::CaseInsensitiveInArray($this->f, $AvailableImageOutputFormats))) {
 986:             // override output format if $this->f is set and that format is available
 987:             $this->DebugMessage('$this->thumbnailFormat set to $this->f "'.strtolower($this->f).'"', __FILE__, __LINE__);
 988:             $this->thumbnailFormat = strtolower($this->f);
 989:         } elseif ($this->f) {
 990:             $this->DebugMessage('$this->thumbnailFormat staying as "'.$this->thumbnailFormat.'" because $this->f ('.strtolower($this->f).') is not in $AvailableImageOutputFormats', __FILE__, __LINE__);
 991:         }
 992: 
 993:         // for JPEG images, quality 1 (worst) to 99 (best)
 994:         // quality < 25 is nasty, with not much size savings - not recommended
 995:         // problems with 100 - invalid JPEG?
 996:         $this->thumbnailQuality = max(1, min(99, ($this->q ? intval($this->q) : 75)));
 997:         $this->DebugMessage('$this->thumbnailQuality set to "'.$this->thumbnailQuality.'"', __FILE__, __LINE__);
 998: 
 999:         return true;
1000:     }
1001: 
1002: 
1003:     function setCacheDirectory() {
1004:         // resolve cache directory to absolute pathname
1005:         $this->DebugMessage('setCacheDirectory() starting with config_cache_directory = "'.$this->config_cache_directory.'"', __FILE__, __LINE__);
1006:         if (substr($this->config_cache_directory, 0, 1) == '.') {
1007:             if (preg_match('#^(f|ht)tps?\://#i', $this->src)) {
1008:                 if (!$this->config_cache_disable_warning) {
1009:                     $this->ErrorImage('$this->config_cache_directory ('.$this->config_cache_directory.') cannot be used for remote images. Adjust "cache_directory" or "cache_disable_warning" in phpThumb.config.php');
1010:                 }
1011:             } elseif ($this->src) {
1012:                 // resolve relative cache directory to source image
1013:                 $this->config_cache_directory = dirname($this->ResolveFilenameToAbsolute($this->src)).DIRECTORY_SEPARATOR.$this->config_cache_directory;
1014:             } else {
1015:                 // $this->new is probably set
1016:             }
1017:         }
1018:         if (substr($this->config_cache_directory, -1) == '/') {
1019:             $this->config_cache_directory = substr($this->config_cache_directory, 0, -1);
1020:         }
1021:         if ($this->iswindows) {
1022:             $this->config_cache_directory = str_replace('/', DIRECTORY_SEPARATOR, $this->config_cache_directory);
1023:         }
1024:         if ($this->config_cache_directory) {
1025:             $real_cache_path = $this->realPathSafe($this->config_cache_directory);
1026:             if (!$real_cache_path) {
1027:                 $this->DebugMessage('$this->realPathSafe($this->config_cache_directory) failed for "'.$this->config_cache_directory.'"', __FILE__, __LINE__);
1028:                 if (!is_dir($this->config_cache_directory)) {
1029:                     $this->DebugMessage('!is_dir('.$this->config_cache_directory.')', __FILE__, __LINE__);
1030:                 }
1031:             }
1032:             if ($real_cache_path) {
1033:                 $this->DebugMessage('setting config_cache_directory to $this->realPathSafe('.$this->config_cache_directory.') = "'.$real_cache_path.'"', __FILE__, __LINE__);
1034:                 $this->config_cache_directory = $real_cache_path;
1035:             }
1036:         }
1037:         if (!is_dir($this->config_cache_directory)) {
1038:             if (!$this->config_cache_disable_warning) {
1039:                 $this->ErrorImage('$this->config_cache_directory ('.$this->config_cache_directory.') does not exist. Adjust "cache_directory" or "cache_disable_warning" in phpThumb.config.php');
1040:             }
1041:             $this->DebugMessage('$this->config_cache_directory ('.$this->config_cache_directory.') is not a directory', __FILE__, __LINE__);
1042:             $this->config_cache_directory = null;
1043:         } elseif (!@is_writable($this->config_cache_directory)) {
1044:             $this->DebugMessage('$this->config_cache_directory is not writable ('.$this->config_cache_directory.')', __FILE__, __LINE__);
1045:         }
1046: 
1047:         $this->InitializeTempDirSetting();
1048:         if (!@is_dir($this->config_temp_directory) && !@is_writable($this->config_temp_directory) && @is_dir($this->config_cache_directory) && @is_writable($this->config_cache_directory)) {
1049:             $this->DebugMessage('setting $this->config_temp_directory = $this->config_cache_directory ('.$this->config_cache_directory.')', __FILE__, __LINE__);
1050:             $this->config_temp_directory = $this->config_cache_directory;
1051:         }
1052:         return true;
1053:     }
1054: 
1055:     /* Takes the array of path segments up to now, and the next segment (maybe a modifier: empty, . or ..)
1056:        Applies it, adding or removing from $segments as a result. Returns nothing. */
1057:     // http://support.silisoftware.com/phpBB3/viewtopic.php?t=961
1058:     function applyPathSegment(&$segments, $segment) {
1059:         if ($segment == '.') {
1060:             return; // always remove
1061:         }
1062:         if ($segment == '') {
1063:             $test = array_pop($segments);
1064:             if (is_null($test)) {
1065:                 $segments[] = $segment; // keep the first empty block
1066:             } elseif ($test == '') {
1067:                 $test = array_pop($segments);
1068:                 if (is_null($test)) {
1069:                     $segments[] = $test;
1070:                     $segments[] = $segment; // keep the second one too
1071:                 } else { // put both back and ignore segment
1072:                     $segments[] = $test;
1073:                     $segments[] = $test;
1074:                 }
1075:             } else {
1076:                 $segments[] = $test; // ignore empty blocks
1077:             }
1078:         } else {
1079:             if ($segment == '..') {
1080:                 $test = array_pop($segments);
1081:                 if (is_null($test)) {
1082:                     $segments[] = $segment;
1083:                 } elseif ($test == '..') {
1084:                     $segments[] = $test;
1085:                     $segments[] = $segment;
1086:                 } else {
1087:                     if ($test == '') {
1088:                         $segments[] = $test;
1089:                     } // else nothing, remove both
1090:                 }
1091:             } else {
1092:                 $segments[] = $segment;
1093:             }
1094:         }
1095:     }
1096: 
1097:     /* Takes array of path components, normalizes it: removes empty slots and '.', collapses '..' and folder names.  Returns array. */
1098:     // http://support.silisoftware.com/phpBB3/viewtopic.php?t=961
1099:     function normalizePath($segments) {
1100:         $parts = array();
1101:         foreach ($segments as $segment) {
1102:             $this->applyPathSegment($parts, $segment);
1103:         }
1104:         return $parts;
1105:     }
1106: 
1107:     /* True if the provided path points (without resolving symbolic links) into one of the allowed directories. */
1108:     // http://support.silisoftware.com/phpBB3/viewtopic.php?t=961
1109:     function matchPath($path, $allowed_dirs) {
1110:         if (!empty($allowed_dirs)) {
1111:             foreach ($allowed_dirs as $one_dir) {
1112:                 if (preg_match('#^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', $this->realPathSafe($one_dir))).'#', $path)) {
1113:                     return true;
1114:                 }
1115:             }
1116:         }
1117:         return false;
1118:     }
1119: 
1120:     /* True if the provided path points inside one of open_basedirs (or if open_basedirs are disabled) */
1121:     // http://support.silisoftware.com/phpBB3/viewtopic.php?t=961
1122:     function isInOpenBasedir($path) {
1123:         static $open_basedirs = null;
1124:         if (is_null($open_basedirs)) {
1125:             $ini_text = ini_get('open_basedir');
1126:             $this->DebugMessage('open_basedir: "'.$ini_text.'"', __FILE__, __LINE__);
1127:             $open_basedirs = array();
1128:             if (strlen($ini_text) > 0) {
1129:                 foreach (preg_split('#[;:]#', $ini_text) as $key => $value) {
1130:                     $open_basedirs[$key] = $this->realPathSafe($value);
1131:                 }
1132:             }
1133:         }
1134:         return (empty($open_basedirs) || $this->matchPath($path, $open_basedirs));
1135:     }
1136: 
1137:     /* Resolves all symlinks in $path, checking that each continuous part ends in an allowed zone. Returns null, if any component leads outside of allowed zone. */
1138:     // http://support.silisoftware.com/phpBB3/viewtopic.php?t=961
1139:     function resolvePath($path, $allowed_dirs) {
1140:         $this->DebugMessage('resolvePath: '.$path.' (allowed_dirs: '.print_r($allowed_dirs, true).')', __FILE__, __LINE__);
1141: 
1142:         // add base path to the top of the list
1143:         if (!$this->config_allow_src_above_docroot) {
1144:             array_unshift($allowed_dirs, $this->realPathSafe($this->config_document_root));
1145:         } else {
1146:             if (!$this->config_allow_src_above_phpthumb) {
1147:                 array_unshift($allowed_dirs, $this->realPathSafe(dirname(__FILE__)));
1148:             } else {
1149:                 // no checks are needed, offload the work to realpath and forget about it
1150:                 $this->DebugMessage('resolvePath: checks disabled, returning '.$this->realPathSafe($path), __FILE__, __LINE__);
1151:                 return $this->realPathSafe($path);
1152:             }
1153:         }
1154:         if ($path == '') {
1155:             return null; // save us trouble
1156:         }
1157: 
1158:         do {
1159:             $this->DebugMessage('resolvePath: iteration, path='.$path.', base path = '.$allowed_dirs[0], __FILE__, __LINE__);
1160: 
1161:             $parts = array();
1162:             // do not use "cleaner" foreach version of this loop as later code relies on both $segments and $i
1163:             // http://support.silisoftware.com/phpBB3/viewtopic.php?t=964
1164:             $segments = explode(DIRECTORY_SEPARATOR, $path);
1165:             for ($i = 0; $i < count($segments); $i++) {
1166:                 $this->applyPathSegment($parts, $segments[$i]);
1167:                 $thispart = implode(DIRECTORY_SEPARATOR, $parts);
1168:                 if ($this->isInOpenBasedir($thispart)) {
1169:                     if (is_link($thispart)) {
1170:                         break;
1171:                     }
1172:                 }
1173:             }
1174: 
1175:             $this->DebugMessage('resolvePath: stop at component '.$i, __FILE__, __LINE__);
1176:             // test the part up to here
1177:             $path = implode(DIRECTORY_SEPARATOR, $parts);
1178:             $this->DebugMessage('resolvePath: stop at path='.$path, __FILE__, __LINE__);
1179:             if (!$this->matchPath($path, $allowed_dirs)) {
1180:                 $this->DebugMessage('resolvePath: no match, returning null', __FILE__, __LINE__);
1181:                 return null;
1182:             }
1183:             if ($i >= count($segments)) { // reached end
1184:                 $this->DebugMessage('resolvePath: path parsed, over', __FILE__, __LINE__);
1185:                 break;
1186:             }
1187:             // else it's symlink, rewrite path
1188:             $path = readlink($path);
1189:             $this->DebugMessage('resolvePath: symlink matched, target='.$path, __FILE__, __LINE__);
1190: 
1191:             /*
1192:             Replace base path with symlink target.
1193:             Assuming:
1194:               /www/img/external -> /external
1195:             This is allowed:
1196:               GET /www/img/external/../external/test/pic.jpg
1197:             This isn't:
1198:               GET /www/img/external/../www/img/pic.jpg
1199:             So there's only one base path which is the last symlink target, but any number of stable whitelisted paths.
1200:             */
1201:             if ($this->config_auto_allow_symlinks) {
1202:                 $allowed_dirs[0] = $path;
1203:             }
1204:             $path = $path.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, array_slice($segments,$i + 1));
1205:         } while (true);
1206:         return $path;
1207:     }
1208: 
1209: 
1210:     function realPathSafe($filename) {
1211:         // http://php.net/manual/en/function.realpath.php -- "Note: The running script must have executable permissions on all directories in the hierarchy, otherwise realpath() will return FALSE"
1212:         // realPathSafe() provides a reasonable facsimile of realpath() but does not resolve symbolic links, nor does it check that the file/path actually exists
1213:         if (!$this->config_disable_realpath) {
1214:             return realpath($filename);
1215:         }
1216: 
1217:         // http://stackoverflow.com/questions/21421569
1218:         $newfilename = preg_replace('#[\\/]+#', DIRECTORY_SEPARATOR, $filename);
1219:         if (!preg_match('#^'.DIRECTORY_SEPARATOR.'#', $newfilename)) {
1220:             $newfilename = dirname(__FILE__).DIRECTORY_SEPARATOR.$newfilename;
1221:         }
1222:         do {
1223:             $beforeloop = $newfilename;
1224: 
1225:             // Replace all sequences of more than one / with a single one [[ If you're working on a system that treats // at the start of a path as special, make sure you replace multiple / characters at the start with two of them. This is the only place where POSIX allows (but does not mandate) special handling for multiples, in all other cases, multiple / characters are equivalent to a single one.]]
1226:             $newfilename = preg_replace('#'.DIRECTORY_SEPARATOR.'+#', DIRECTORY_SEPARATOR, $newfilename);
1227: 
1228:             // Replace all occurrences of /./ with /
1229:             $newfilename = preg_replace('#'.DIRECTORY_SEPARATOR.'\\.'.DIRECTORY_SEPARATOR.'#', DIRECTORY_SEPARATOR, $newfilename);
1230: 
1231:             // Remove ./ if at the start
1232:             $newfilename = preg_replace('#^\\.'.DIRECTORY_SEPARATOR.'#', '', $newfilename);
1233: 
1234:             // Remove /. if at the end
1235:             $newfilename = preg_replace('#'.DIRECTORY_SEPARATOR.'\\.$#', '', $newfilename);
1236: 
1237:             // Replace /anything/../ with /
1238:             $newfilename = preg_replace('#'.DIRECTORY_SEPARATOR.'[^'.DIRECTORY_SEPARATOR.']+'.DIRECTORY_SEPARATOR.'\\.\\.'.DIRECTORY_SEPARATOR.'#', DIRECTORY_SEPARATOR, $newfilename);
1239: 
1240:             // Remove /anything/.. if at the end
1241:             $newfilename = preg_replace('#'.DIRECTORY_SEPARATOR.'[^'.DIRECTORY_SEPARATOR.']+'.DIRECTORY_SEPARATOR.'\\.\\.$#', '', $newfilename);
1242: 
1243:         } while ($newfilename != $beforeloop);
1244:         return $newfilename;
1245:     }
1246: 
1247: 
1248:     function ResolveFilenameToAbsolute($filename) {
1249:         if (empty($filename)) {
1250:             return false;
1251:         }
1252: 
1253:         if (preg_match('#^[a-z0-9]+\:/{1,2}#i', $filename)) {
1254:             // eg: http://host/path/file.jpg (HTTP URL)
1255:             // eg: ftp://host/path/file.jpg  (FTP URL)
1256:             // eg: data1:/path/file.jpg      (Netware path)
1257: 
1258:             //$AbsoluteFilename = $filename;
1259:             return $filename;
1260: 
1261:         } elseif ($this->iswindows && isset($filename{1}) && ($filename{1} == ':')) {
1262: 
1263:             // absolute pathname (Windows)
1264:             $AbsoluteFilename = $filename;
1265: 
1266:         } elseif ($this->iswindows && ((substr($filename, 0, 2) == '//') || (substr($filename, 0, 2) == '\\\\'))) {
1267: 
1268:             // absolute pathname (Windows)
1269:             $AbsoluteFilename = $filename;
1270: 
1271:         } elseif ($filename{0} == '/') {
1272: 
1273:             if (@is_readable($filename) && !@is_readable($this->config_document_root.$filename)) {
1274: 
1275:                 // absolute filename (*nix)
1276:                 $AbsoluteFilename = $filename;
1277: 
1278:             } elseif (isset($filename{1}) && ($filename{1} == '~')) {
1279: 
1280:                 // /~user/path
1281:                 if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray($filename)) {
1282:                     $AbsoluteFilename = $ApacheLookupURIarray['filename'];
1283:                 } else {
1284:                     $AbsoluteFilename = $this->realPathSafe($filename);
1285:                     if (@is_readable($AbsoluteFilename)) {
1286:                         $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'", but the correct filename ('.$AbsoluteFilename.') seems to have been resolved with $this->realPathSafe($filename)', __FILE__, __LINE__);
1287:                     } elseif (is_dir(dirname($AbsoluteFilename))) {
1288:                         $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname($filename).'", but the correct directory ('.dirname($AbsoluteFilename).') seems to have been resolved with $this->realPathSafe(.)', __FILE__, __LINE__);
1289:                     } else {
1290:                         return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'". This has been known to fail on Apache2 - try using the absolute filename for the source image (ex: "/home/user/httpdocs/image.jpg" instead of "/~user/image.jpg")');
1291:                     }
1292:                 }
1293: 
1294:             } else {
1295: 
1296:                 // relative filename (any OS)
1297:                 if (preg_match('#^'.preg_quote($this->config_document_root).'#', $filename)) {
1298:                     $AbsoluteFilename = $filename;
1299:                     $this->DebugMessage('ResolveFilenameToAbsolute() NOT prepending $this->config_document_root ('.$this->config_document_root.') to $filename ('.$filename.') resulting in ($AbsoluteFilename = "'.$AbsoluteFilename.'")', __FILE__, __LINE__);
1300:                 } else {
1301:                     $AbsoluteFilename = $this->config_document_root.$filename;
1302:                     $this->DebugMessage('ResolveFilenameToAbsolute() prepending $this->config_document_root ('.$this->config_document_root.') to $filename ('.$filename.') resulting in ($AbsoluteFilename = "'.$AbsoluteFilename.'")', __FILE__, __LINE__);
1303:                 }
1304: 
1305:             }
1306: 
1307:         } else {
1308: 
1309:             // relative to current directory (any OS)
1310:             $AbsoluteFilename = dirname(__FILE__).DIRECTORY_SEPARATOR.preg_replace('#[/\\\\]#', DIRECTORY_SEPARATOR, $filename);
1311: 
1312:             if (substr(dirname(@$_SERVER['PHP_SELF']), 0, 2) == '/~') {
1313:                 if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray(dirname(@$_SERVER['PHP_SELF']))) {
1314:                     $AbsoluteFilename = $ApacheLookupURIarray['filename'].DIRECTORY_SEPARATOR.$filename;
1315:                 } else {
1316:                     $AbsoluteFilename = $this->realPathSafe('.').DIRECTORY_SEPARATOR.$filename;
1317:                     if (@is_readable($AbsoluteFilename)) {
1318:                         $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'", but the correct filename ('.$AbsoluteFilename.') seems to have been resolved with $this->realPathSafe(.)/$filename', __FILE__, __LINE__);
1319:                     } elseif (is_dir(dirname($AbsoluteFilename))) {
1320:                         $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'", but the correct directory ('.dirname($AbsoluteFilename).') seems to have been resolved with $this->realPathSafe(.)', __FILE__, __LINE__);
1321:                     } else {
1322:                         return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'". This has been known to fail on Apache2 - try using the absolute filename for the source image');
1323:                     }
1324:                 }
1325:             }
1326: 
1327:         }
1328:         /*
1329:         // removed 2014-May-30: http://support.silisoftware.com/phpBB3/viewtopic.php?t=961
1330:         if (is_link($AbsoluteFilename)) {
1331:             $this->DebugMessage('is_link()==true, changing "'.$AbsoluteFilename.'" to "'.readlink($AbsoluteFilename).'"', __FILE__, __LINE__);
1332:             $AbsoluteFilename = readlink($AbsoluteFilename);
1333:         }
1334:         if ($this->realPathSafe($AbsoluteFilename)) {
1335:             $AbsoluteFilename = $this->realPathSafe($AbsoluteFilename);
1336:         }
1337:         */
1338:         if ($this->iswindows) {
1339:             $AbsoluteFilename = preg_replace('#^'.preg_quote($this->realPathSafe($this->config_document_root)).'#i', str_replace('\\', '\\\\', $this->realPathSafe($this->config_document_root)), $AbsoluteFilename);
1340:             $AbsoluteFilename = str_replace(DIRECTORY_SEPARATOR, '/', $AbsoluteFilename);
1341:         }
1342:         $AbsoluteFilename = $this->resolvePath($AbsoluteFilename, $this->config_additional_allowed_dirs);
1343:         if (!$this->config_allow_src_above_docroot && !preg_match('#^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', $this->realPathSafe($this->config_document_root))).'#', $AbsoluteFilename)) {
1344:             $this->DebugMessage('!$this->config_allow_src_above_docroot therefore setting "'.$AbsoluteFilename.'" (outside "'.$this->realPathSafe($this->config_document_root).'") to null', __FILE__, __LINE__);
1345:             return false;
1346:         }
1347:         if (!$this->config_allow_src_above_phpthumb && !preg_match('#^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', dirname(__FILE__))).'#', $AbsoluteFilename)) {
1348:             $this->DebugMessage('!$this->config_allow_src_above_phpthumb therefore setting "'.$AbsoluteFilename.'" (outside "'.dirname(__FILE__).'") to null', __FILE__, __LINE__);
1349:             return false;
1350:         }
1351:         return $AbsoluteFilename;
1352:     }
1353: 
1354: 
1355:     function file_exists_ignoreopenbasedir($filename, $cached=true) {
1356:         static $open_basedirs = null;
1357:         static $file_exists_cache = array();
1358:         if (!$cached || !isset($file_exists_cache[$filename])) {
1359:             if (is_null($open_basedirs)) {
1360:                 $open_basedirs = preg_split('#[;:]#', ini_get('open_basedir'));
1361:             }
1362:             if (empty($open_basedirs) || in_array(dirname($filename), $open_basedirs)) {
1363:                 $file_exists_cache[$filename] = file_exists($filename);
1364:             } elseif ($this->iswindows) {
1365:                 $ls_filename = trim(phpthumb_functions::SafeExec('dir /b '.phpthumb_functions::escapeshellarg_replacement($filename)));
1366:                 $file_exists_cache[$filename] = ($ls_filename == basename($filename));  // command dir /b return only filename without path
1367:             } else {
1368:                 $ls_filename = trim(phpthumb_functions::SafeExec('ls '.phpthumb_functions::escapeshellarg_replacement($filename)));
1369:                 $file_exists_cache[$filename] = ($ls_filename == $filename);
1370:             }
1371:         }
1372:         return $file_exists_cache[$filename];
1373:     }
1374: 
1375: 
1376:     function ImageMagickWhichConvert() {
1377:         static $WhichConvert = null;
1378:         if (is_null($WhichConvert)) {
1379:             if ($this->iswindows) {
1380:                 $WhichConvert = false;
1381:             } else {
1382:                 $IMwhichConvertCacheFilename = $this->config_cache_directory.DIRECTORY_SEPARATOR.'phpThumbCacheIMwhichConvert.txt';
1383:                 if (($cachedwhichconvertstring = @file_get_contents($IMwhichConvertCacheFilename)) !== false) {
1384:                     $WhichConvert = $cachedwhichconvertstring;
1385:                 } else {
1386:                     $WhichConvert = trim(phpthumb_functions::SafeExec('which convert'));
1387:                     @file_put_contents($IMwhichConvertCacheFilename, $WhichConvert);
1388:                     @chmod($IMwhichConvertCacheFilename, $this->getParameter('config_file_create_mask'));
1389:                 }
1390:             }
1391:         }
1392:         return $WhichConvert;
1393:     }
1394: 
1395: 
1396:     function ImageMagickCommandlineBase() {
1397:         static $commandline = null;
1398:         if (is_null($commandline)) {
1399:             if ($this->issafemode) {
1400:                 $commandline = '';
1401:                 return $commandline;
1402:             }
1403: 
1404:             $IMcommandlineBaseCacheFilename = $this->config_cache_directory.DIRECTORY_SEPARATOR.'phpThumbCacheIMcommandlineBase.txt';
1405:             if (($commandline = @file_get_contents($IMcommandlineBaseCacheFilename)) !== false) {
1406:                 return $commandline;
1407:             }
1408: 
1409:             $commandline = (!is_null($this->config_imagemagick_path) ? $this->config_imagemagick_path : '');
1410: 
1411:             if ($this->config_imagemagick_path && ($this->config_imagemagick_path != $this->realPathSafe($this->config_imagemagick_path))) {
1412:                 if (@is_executable($this->realPathSafe($this->config_imagemagick_path))) {
1413:                     $this->DebugMessage('Changing $this->config_imagemagick_path ('.$this->config_imagemagick_path.') to $this->realPathSafe($this->config_imagemagick_path) ('.$this->realPathSafe($this->config_imagemagick_path).')', __FILE__, __LINE__);
1414:                     $this->config_imagemagick_path = $this->realPathSafe($this->config_imagemagick_path);
1415:                 } else {
1416:                     $this->DebugMessage('Leaving $this->config_imagemagick_path as ('.$this->config_imagemagick_path.') because !is_execuatable($this->realPathSafe($this->config_imagemagick_path)) ('.$this->realPathSafe($this->config_imagemagick_path).')', __FILE__, __LINE__);
1417:                 }
1418:             }
1419:             $this->DebugMessage('                  file_exists('.$this->config_imagemagick_path.') = '.intval(                        @file_exists($this->config_imagemagick_path)), __FILE__, __LINE__);
1420:             $this->DebugMessage('file_exists_ignoreopenbasedir('.$this->config_imagemagick_path.') = '.intval($this->file_exists_ignoreopenbasedir($this->config_imagemagick_path)), __FILE__, __LINE__);
1421:             $this->DebugMessage('                      is_file('.$this->config_imagemagick_path.') = '.intval(                            @is_file($this->config_imagemagick_path)), __FILE__, __LINE__);
1422:             $this->DebugMessage('                is_executable('.$this->config_imagemagick_path.') = '.intval(                      @is_executable($this->config_imagemagick_path)), __FILE__, __LINE__);
1423: 
1424:             if ($this->file_exists_ignoreopenbasedir($this->config_imagemagick_path)) {
1425: 
1426:                 $this->DebugMessage('using ImageMagick path from $this->config_imagemagick_path ('.$this->config_imagemagick_path.')', __FILE__, __LINE__);
1427:                 if ($this->iswindows) {
1428:                     $commandline = substr($this->config_imagemagick_path, 0, 2).' && cd '.phpthumb_functions::escapeshellarg_replacement(str_replace('/', DIRECTORY_SEPARATOR, substr(dirname($this->config_imagemagick_path), 2))).' && '.phpthumb_functions::escapeshellarg_replacement(basename($this->config_imagemagick_path));
1429:                 } else {
1430:                     $commandline = phpthumb_functions::escapeshellarg_replacement($this->config_imagemagick_path);
1431:                 }
1432: 
1433:             } else {
1434: 
1435:                 $which_convert = $this->ImageMagickWhichConvert();
1436:                 $IMversion     = $this->ImageMagickVersion();
1437: 
1438:                 if ($which_convert && ($which_convert{0} == '/') && $this->file_exists_ignoreopenbasedir($which_convert)) {
1439: 
1440:                     // `which convert` *should* return the path if "convert" exist, or nothing if it doesn't
1441:                     // other things *may* get returned, like "sh: convert: not found" or "no convert in /usr/local/bin /usr/sbin /usr/bin /usr/ccs/bin"
1442:                     // so only do this if the value returned exists as a file
1443:                     $this->DebugMessage('using ImageMagick path from `which convert` ('.$which_convert.')', __FILE__, __LINE__);
1444:                     $commandline = 'convert';
1445: 
1446:                 } elseif ($IMversion) {
1447: 
1448:                     $this->DebugMessage('setting ImageMagick path to $this->config_imagemagick_path ('.$this->config_imagemagick_path.') ['.$IMversion.']', __FILE__, __LINE__);
1449:                     $commandline = $this->config_imagemagick_path;
1450: 
1451:                 } else {
1452: 
1453:                     $this->DebugMessage('ImageMagickThumbnailToGD() aborting because cannot find convert in $this->config_imagemagick_path ('.$this->config_imagemagick_path.'), and `which convert` returned ('.$which_convert.')', __FILE__, __LINE__);
1454:                     $commandline = '';
1455: 
1456:                 }
1457: 
1458:             }
1459: 
1460:             @file_put_contents($IMcommandlineBaseCacheFilename, $commandline);
1461:             @chmod($IMcommandlineBaseCacheFilename, $this->getParameter('config_file_create_mask'));
1462:         }
1463:         return $commandline;
1464:     }
1465: 
1466: 
1467:     function ImageMagickVersion($returnRAW=false) {
1468:         static $versionstring = null;
1469:         if (is_null($versionstring)) {
1470:             $versionstring = array(0=>false, 1=>false);
1471: 
1472:             $IMversionCacheFilename = $this->config_cache_directory.DIRECTORY_SEPARATOR.'phpThumbCacheIMversion.txt';
1473:             if ($cachedversionstring = @file_get_contents($IMversionCacheFilename)) {
1474: 
1475:                 $versionstring = explode("\n", $cachedversionstring, 2);
1476:                 $versionstring[0] = ($versionstring[0] ? $versionstring[0] : false); // "false" is stored as an empty string in the cache file
1477:                 $versionstring[1] = ($versionstring[1] ? $versionstring[1] : false); // "false" is stored as an empty string in the cache file
1478: 
1479:             } else {
1480: 
1481:                 $commandline = $this->ImageMagickCommandlineBase();
1482:                 $commandline = (!is_null($commandline) ? $commandline : '');
1483:                 if ($commandline) {
1484:                     $commandline .= ' --version';
1485:                     $this->DebugMessage('ImageMagick version checked with "'.$commandline.'"', __FILE__, __LINE__);
1486:                     $versionstring[1] = trim(phpthumb_functions::SafeExec($commandline));
1487:                     if (preg_match('#^Version: [^0-9]*([ 0-9\\.\\:Q/\\-]+)#i', $versionstring[1], $matches)) {
1488:                         $versionstring[0] = trim($matches[1]);
1489:                     } else {
1490:                         $versionstring[0] = false;
1491:                         $this->DebugMessage('ImageMagick did not return recognized version string ('.$versionstring[1].')', __FILE__, __LINE__);
1492:                     }
1493:                     $this->DebugMessage('ImageMagick convert --version says "'.@$matches[0].'"', __FILE__, __LINE__);
1494:                 }
1495: 
1496:                 @file_put_contents($IMversionCacheFilename, $versionstring[0]."\n".$versionstring[1]);
1497:                 @chmod($IMversionCacheFilename, $this->getParameter('config_file_create_mask'));
1498: 
1499:             }
1500:         }
1501:         return $versionstring[intval($returnRAW)];
1502:     }
1503: 
1504: 
1505:     function ImageMagickSwitchAvailable($switchname) {
1506:         static $IMoptions = null;
1507:         if (is_null($IMoptions)) {
1508:             $IMoptions = array();
1509:             $commandline = $this->ImageMagickCommandlineBase();
1510:             if (!is_null($commandline)) {
1511:                 $commandline .= ' -help';
1512:                 $IMhelp_lines = explode("\n", phpthumb_functions::SafeExec($commandline));
1513:                 foreach ($IMhelp_lines as $line) {
1514:                     if (preg_match('#^[\\+\\-]([a-z\\-]+) #', trim($line), $matches)) {
1515:                         $IMoptions[$matches[1]] = true;
1516:                     }
1517:                 }
1518:             }
1519:         }
1520:         if (is_array($switchname)) {
1521:             $allOK = true;
1522:             foreach ($switchname as $key => $value) {
1523:                 if (!isset($IMoptions[$value])) {
1524:                     $allOK = false;
1525:                     break;
1526:                 }
1527:             }
1528:             $this->DebugMessage('ImageMagickSwitchAvailable('.implode(';', $switchname).') = '.intval($allOK).'', __FILE__, __LINE__);
1529:         } else {
1530:             $allOK = isset($IMoptions[$switchname]);
1531:             $this->DebugMessage('ImageMagickSwitchAvailable('.$switchname.') = '.intval($allOK).'', __FILE__, __LINE__);
1532:         }
1533:         return $allOK;
1534:     }
1535: 
1536: 
1537:     function ImageMagickFormatsList() {
1538:         static $IMformatsList = null;
1539:         if (is_null($IMformatsList)) {
1540:             $IMformatsList = '';
1541:             $commandline = $this->ImageMagickCommandlineBase();
1542:             if (!is_null($commandline)) {
1543:                 $commandline = dirname($commandline).DIRECTORY_SEPARATOR.str_replace('convert', 'identify', basename($commandline));
1544:                 $commandline .= ' -list format';
1545:                 $IMformatsList = phpthumb_functions::SafeExec($commandline);
1546:             }
1547:         }
1548:         return $IMformatsList;
1549:     }
1550: 
1551: 
1552:     function SourceDataToTempFile() {
1553:         if ($IMtempSourceFilename = $this->phpThumb_tempnam()) {
1554:             $IMtempSourceFilename = $this->realPathSafe($IMtempSourceFilename);
1555:             ob_start();
1556:             $fp_tempfile = fopen($IMtempSourceFilename, 'wb');
1557:             $tempfile_open_error  = ob_get_contents();
1558:             ob_end_clean();
1559:             if ($fp_tempfile) {
1560:                 fwrite($fp_tempfile, $this->rawImageData);
1561:                 fclose($fp_tempfile);
1562:                 @chmod($IMtempSourceFilename, $this->getParameter('config_file_create_mask'));
1563:                 $this->sourceFilename = $IMtempSourceFilename;
1564:                 $this->DebugMessage('ImageMagickThumbnailToGD() setting $this->sourceFilename to "'.$IMtempSourceFilename.'" from $this->rawImageData ('.strlen($this->rawImageData).' bytes)', __FILE__, __LINE__);
1565:             } else {
1566:                 $this->DebugMessage('ImageMagickThumbnailToGD() FAILED setting $this->sourceFilename to "'.$IMtempSourceFilename.'" (failed to open for writing: "'.$tempfile_open_error.'")', __FILE__, __LINE__);
1567:             }
1568:             unset($tempfile_open_error, $IMtempSourceFilename);
1569:             return true;
1570:         }
1571:         $this->DebugMessage('SourceDataToTempFile() FAILED because $this->phpThumb_tempnam() failed', __FILE__, __LINE__);
1572:         return false;
1573:     }
1574: 
1575: 
1576:     function ImageMagickThumbnailToGD() {
1577:         // http://www.imagemagick.org/script/command-line-options.php
1578: 
1579:         $this->useRawIMoutput = true;
1580:         if (phpthumb_functions::gd_version()) {
1581:             // if GD is not available, must use whatever ImageMagick can output
1582: 
1583:             // $UnAllowedParameters contains options that can only be processed in GD, not ImageMagick
1584:             // note: 'fltr' *may* need to be processed by GD, but we'll check that in more detail below
1585:             $UnAllowedParameters = array('xto', 'ar', 'bg', 'bc');
1586:             // 'ra' may be part of this list, if not a multiple of 90 degrees
1587:             foreach ($UnAllowedParameters as $parameter) {
1588:                 if (isset($this->$parameter)) {
1589:                     $this->DebugMessage('$this->useRawIMoutput=false because "'.$parameter.'" is set', __FILE__, __LINE__);
1590:                     $this->useRawIMoutput = false;
1591:                     break;
1592:                 }
1593:             }
1594:         }
1595:         $this->DebugMessage('$this->useRawIMoutput='.($this->useRawIMoutput ? 'true' : 'false').' after checking $UnAllowedParameters', __FILE__, __LINE__);
1596:         $ImageCreateFunction = '';
1597:         $outputFormat = $this->thumbnailFormat;
1598:         if (phpthumb_functions::gd_version()) {
1599:             if ($this->useRawIMoutput) {
1600:                 switch ($this->thumbnailFormat) {
1601:                     case 'gif':
1602:                         $ImageCreateFunction = 'imagecreatefromgif';
1603:                         $this->is_alpha = true;
1604:                         break;
1605:                     case 'png':
1606:                         $ImageCreateFunction = 'imagecreatefrompng';
1607:                         $this->is_alpha = true;
1608:                         break;
1609:                     case 'jpg':
1610:                     case 'jpeg':
1611:                         $ImageCreateFunction = 'imagecreatefromjpeg';
1612:                         break;
1613:                     default:
1614:                         $this->DebugMessage('Forcing output to PNG because $this->thumbnailFormat ('.$this->thumbnailFormat.' is not a GD-supported format)', __FILE__, __LINE__);
1615:                         $outputFormat = 'png';
1616:                         $ImageCreateFunction = 'imagecreatefrompng';
1617:                         $this->is_alpha = true;
1618:                         $this->useRawIMoutput = false;
1619:                         break;
1620:                 }
1621:                 if (!function_exists(@$ImageCreateFunction)) {
1622:                     // ImageMagickThumbnailToGD() depends on imagecreatefrompng/imagecreatefromgif
1623:                     //$this->DebugMessage('ImageMagickThumbnailToGD() aborting because '.@$ImageCreateFunction.'() is not available', __FILE__, __LINE__);
1624:                     $this->useRawIMoutput = true;
1625:                     //return false;
1626:                 }
1627:             } else {
1628:                 $outputFormat = 'png';
1629:                 $ImageCreateFunction = 'imagecreatefrompng';
1630:                 $this->is_alpha = true;
1631:                 $this->useRawIMoutput = false;
1632:             }
1633:         }
1634: 
1635:         // http://freealter.org/doc_distrib/ImageMagick-5.1.1/www/convert.html
1636:         if (!$this->sourceFilename && $this->rawImageData) {
1637:             $this->SourceDataToTempFile();
1638:         }
1639:         if (!$this->sourceFilename) {
1640:             $this->DebugMessage('ImageMagickThumbnailToGD() aborting because $this->sourceFilename is empty', __FILE__, __LINE__);
1641:             $this->useRawIMoutput = false;
1642:             return false;
1643:         }
1644:         if ($this->issafemode) {
1645:             $this->DebugMessage('ImageMagickThumbnailToGD() aborting because safe_mode is enabled', __FILE__, __LINE__);
1646:             $this->useRawIMoutput = false;
1647:             return false;
1648:         }
1649: // TO BE FIXED
1650: //if (true) {
1651: //  $this->DebugMessage('ImageMagickThumbnailToGD() aborting it is broken right now', __FILE__, __LINE__);
1652: //  $this->useRawIMoutput = false;
1653: //  return false;
1654: //}
1655: 
1656:         $commandline = $this->ImageMagickCommandlineBase();
1657:         if ($commandline) {
1658:             if ($IMtempfilename = $this->phpThumb_tempnam()) {
1659:                 $IMtempfilename = $this->realPathSafe($IMtempfilename);
1660: 
1661:                 $IMuseExplicitImageOutputDimensions = false;
1662:                 if ($this->ImageMagickSwitchAvailable('thumbnail') && $this->config_imagemagick_use_thumbnail) {
1663:                     $IMresizeParameter = 'thumbnail';
1664:                 } else {
1665:                     $IMresizeParameter = 'resize';
1666: 
1667:                     // some (older? around 2002) versions of IM won't accept "-resize 100x" but require "-resize 100x100"
1668:                     $commandline_test = $this->ImageMagickCommandlineBase().' logo: -resize 1x '.phpthumb_functions::escapeshellarg_replacement($IMtempfilename).' 2>&1';
1669:                     $IMresult_test = phpthumb_functions::SafeExec($commandline_test);
1670:                     $IMuseExplicitImageOutputDimensions = preg_match('#image dimensions are zero#i', $IMresult_test);
1671:                     $this->DebugMessage('IMuseExplicitImageOutputDimensions = '.intval($IMuseExplicitImageOutputDimensions), __FILE__, __LINE__);
1672:                     if ($fp_im_temp = @fopen($IMtempfilename, 'wb')) {
1673:                         // erase temp image so ImageMagick logo doesn't get output if other processing fails
1674:                         fclose($fp_im_temp);
1675:                         @chmod($IMtempfilename, $this->getParameter('config_file_create_mask'));
1676:                     }
1677:                 }
1678: 
1679: 
1680:                 if (!is_null($this->dpi) && $this->ImageMagickSwitchAvailable('density')) {
1681:                     // for vector source formats only (WMF, PDF, etc)
1682:                     $commandline .= ' -flatten';
1683:                     $commandline .= ' -density '.phpthumb_functions::escapeshellarg_replacement($this->dpi);
1684:                 }
1685:                 ob_start();
1686:                 $getimagesize = getimagesize($this->sourceFilename);
1687:                 $GetImageSizeError = ob_get_contents();
1688:                 ob_end_clean();
1689:                 if (is_array($getimagesize)) {
1690:                     $this->DebugMessage('getimagesize('.$this->sourceFilename.') SUCCEEDED: '.print_r($getimagesize, true), __FILE__, __LINE__);
1691:                 } else {
1692:                     $this->DebugMessage('getimagesize('.$this->sourceFilename.') FAILED with error "'.$GetImageSizeError.'"', __FILE__, __LINE__);
1693:                 }
1694:                 if (is_array($getimagesize)) {
1695:                     $this->DebugMessage('getimagesize('.$this->sourceFilename.') returned [w='.$getimagesize[0].';h='.$getimagesize[1].';f='.$getimagesize[2].']', __FILE__, __LINE__);
1696:                     $this->source_width  = $getimagesize[0];
1697:                     $this->source_height = $getimagesize[1];
1698:                     $this->DebugMessage('source dimensions set to '.$this->source_width.'x'.$this->source_height, __FILE__, __LINE__);
1699:                     $this->SetOrientationDependantWidthHeight();
1700: 
1701:                     if (!preg_match('#('.implode('|', $this->AlphaCapableFormats).')#i', $outputFormat)) {
1702:                         // not a transparency-capable format
1703:                         $commandline .= ' -background '.phpthumb_functions::escapeshellarg_replacement('#'.($this->bg ? $this->bg : 'FFFFFF'));
1704:                         if ($getimagesize[2] == IMAGETYPE_GIF) {
1705:                             $commandline .= ' -flatten';
1706:                         }
1707:                     }
1708:                     if ($getimagesize[2] == IMAGETYPE_GIF) {
1709:                         $commandline .= ' -coalesce'; // may be needed for animated GIFs
1710:                     }
1711:                     if ($this->source_width || $this->source_height) {
1712:                         if ($this->zc) {
1713: 
1714:                             $borderThickness = 0;
1715:                             if (!empty($this->fltr)) {
1716:                                 foreach ($this->fltr as $key => $value) {
1717:                                     if (preg_match('#^bord\|([0-9]+)#', $value, $matches)) {
1718:                                         $borderThickness = $matches[1];
1719:                                         break;
1720:                                     }
1721:                                 }
1722:                             }
1723:                             $wAll = intval(max($this->w, $this->wp, $this->wl, $this->ws)) - (2 * $borderThickness);
1724:                             $hAll = intval(max($this->h, $this->hp, $this->hl, $this->hs)) - (2 * $borderThickness);
1725:                             $imAR = $this->source_width / $this->source_height;
1726:                             $zcAR = (($wAll && $hAll) ? $wAll / $hAll : 1);
1727:                             $side  = phpthumb_functions::nonempty_min($this->source_width, $this->source_height, max($wAll, $hAll));
1728:                             $sideX = phpthumb_functions::nonempty_min($this->source_width,                       $wAll, round($hAll * $zcAR));
1729:                             $sideY = phpthumb_functions::nonempty_min(                     $this->source_height, $hAll, round($wAll / $zcAR));
1730: 
1731:                             $thumbnailH = round(max($sideY, ($sideY * $zcAR) / $imAR));
1732:                             $commandline .= ' -'.$IMresizeParameter.' '.phpthumb_functions::escapeshellarg_replacement(($IMuseExplicitImageOutputDimensions ? $thumbnailH : '').'x'.$thumbnailH);
1733: 
1734:                             switch (strtoupper($this->zc)) {
1735:                                 case 'T':
1736:                                     $commandline .= ' -gravity north';
1737:                                     break;
1738:                                 case 'B':
1739:                                     $commandline .= ' -gravity south';
1740:                                     break;
1741:                                 case 'L':
1742:                                     $commandline .= ' -gravity west';
1743:                                     break;
1744:                                 case 'R':
1745:                                     $commandline .= ' -gravity east';
1746:                                     break;
1747:                                 case 'TL':
1748:                                     $commandline .= ' -gravity northwest';
1749:                                     break;
1750:                                 case 'TR':
1751:                                     $commandline .= ' -gravity northeast';
1752:                                     break;
1753:                                 case 'BL':
1754:                                     $commandline .= ' -gravity southwest';
1755:                                     break;
1756:                                 case 'BR':
1757:                                     $commandline .= ' -gravity southeast';
1758:                                     break;
1759:                                 case '1':
1760:                                 case 'C':
1761:                                 default:
1762:                                     $commandline .= ' -gravity center';
1763:                                     break;
1764:                             }
1765: 
1766:                             if (($wAll > 0) && ($hAll > 0)) {
1767:                                 $commandline .= ' -crop '.phpthumb_functions::escapeshellarg_replacement($wAll.'x'.$hAll.'+0+0');
1768:                             } else {
1769:                                 $commandline .= ' -crop '.phpthumb_functions::escapeshellarg_replacement($side.'x'.$side.'+0+0');
1770:                             }
1771:                             if ($this->ImageMagickSwitchAvailable('repage')) {
1772:                                 $commandline .= ' +repage';
1773:                             } else {
1774:                                 $this->DebugMessage('Skipping "+repage" because ImageMagick (v'.$this->ImageMagickVersion().') does not support it', __FILE__, __LINE__);
1775:                             }
1776: 
1777:                         } elseif ($this->sw || $this->sh || $this->sx || $this->sy) {
1778: 
1779:                             $crop_param   = '';
1780:                             $crop_param  .=     ($this->sw ? (($this->sw < 2) ? round($this->sw * $this->source_width)  : $this->sw) : $this->source_width);
1781:                             $crop_param  .= 'x'.($this->sh ? (($this->sh < 2) ? round($this->sh * $this->source_height) : $this->sh) : $this->source_height);
1782:                             $crop_param  .= '+'.(($this->sx < 2) ? round($this->sx * $this->source_width)  : $this->sx);
1783:                             $crop_param  .= '+'.(($this->sy < 2) ? round($this->sy * $this->source_height) : $this->sy);
1784: // TO BE FIXED
1785: // makes 1x1 output
1786: // http://trainspotted.com/phpThumb/phpThumb.php?src=/content/CNR/47/CNR-4728-LD-L-20110723-898.jpg&w=100&h=100&far=1&f=png&fltr[]=lvl&sx=0.05&sy=0.25&sw=0.92&sh=0.42
1787: // '/usr/bin/convert' -density 150 -thumbnail 100x100 -contrast-stretch '0.1%' '/var/www/vhosts/trainspotted.com/httpdocs/content/CNR/47/CNR-4728-LD-L-20110723-898.jpg[0]' png:'/var/www/vhosts/trainspotted.com/httpdocs/phpThumb/_cache/pThumbIIUlvj'
1788:                             $commandline .= ' -crop '.phpthumb_functions::escapeshellarg_replacement($crop_param);
1789: 
1790:                             // this is broken for aoe=1, but unsure how to fix. Send advice to info@silisoftware.com
1791:                             if ($this->w || $this->h) {
1792:                                 //if ($this->ImageMagickSwitchAvailable('repage')) {
1793: if (false) {
1794: // TO BE FIXED
1795: // newer versions of ImageMagick require -repage <geometry>
1796:                                     $commandline .= ' -repage';
1797:                                 } else {
1798:                                     $this->DebugMessage('Skipping "-repage" because ImageMagick (v'.$this->ImageMagickVersion().') does not support it', __FILE__, __LINE__);
1799:                                 }
1800:                                 if ($IMuseExplicitImageOutputDimensions) {
1801:                                     if ($this->w && !$this->h) {
1802:                                         $this->h = ceil($this->w / ($this->source_width / $this->source_height));
1803:                                     } elseif ($this->h && !$this->w) {
1804:                                         $this->w = ceil($this->h * ($this->source_width / $this->source_height));
1805:                                     }
1806:                                 }
1807:                                 $commandline .= ' -'.$IMresizeParameter.' '.phpthumb_functions::escapeshellarg_replacement($this->w.'x'.$this->h);
1808:                             }
1809: 
1810:                         } else {
1811: 
1812:                             if ($this->iar && (intval($this->w) > 0) && (intval($this->h) > 0)) {
1813:                                 list($nw, $nh) = phpthumb_functions::TranslateWHbyAngle($this->w, $this->h, $this->ra);
1814:                                 $nw = ((round($nw) != 0) ? round($nw) : '');
1815:                                 $nh = ((round($nh) != 0) ? round($nh) : '');
1816:                                 $commandline .= ' -'.$IMresizeParameter.' '.phpthumb_functions::escapeshellarg_replacement($nw.'x'.$nh.'!');
1817:                             } else {
1818:                                 $this->w = ((($this->aoe || $this->far) && $this->w) ? $this->w : ($this->w ? phpthumb_functions::nonempty_min($this->w, $getimagesize[0]) : ''));
1819:                                 $this->h = ((($this->aoe || $this->far) && $this->h) ? $this->h : ($this->h ? phpthumb_functions::nonempty_min($this->h, $getimagesize[1]) : ''));
1820:                                 if ($this->w || $this->h) {
1821:                                     if ($IMuseExplicitImageOutputDimensions) {
1822:                                         if ($this->w && !$this->h) {
1823:                                             $this->h = ceil($this->w / ($this->source_width / $this->source_height));
1824:                                         } elseif ($this->h && !$this->w) {
1825:                                             $this->w = ceil($this->h * ($this->source_width / $this->source_height));
1826:                                         }
1827:                                     }
1828:                                     list($nw, $nh) = phpthumb_functions::TranslateWHbyAngle($this->w, $this->h, $this->ra);
1829:                                     $nw = ((round($nw) != 0) ? round($nw) : '');
1830:                                     $nh = ((round($nh) != 0) ? round($nh) : '');
1831:                                     $commandline .= ' -'.$IMresizeParameter.' '.phpthumb_functions::escapeshellarg_replacement($nw.'x'.$nh);
1832:                                 }
1833:                             }
1834:                         }
1835:                     }
1836: 
1837:                 } else {
1838: 
1839:                     $this->DebugMessage('getimagesize('.$this->sourceFilename.') failed', __FILE__, __LINE__);
1840:                     if ($this->w || $this->h) {
1841:                         $exactDimensionsBang = (($this->iar && (intval($this->w) > 0) && (intval($this->h) > 0)) ? '!' : '');
1842:                         if ($IMuseExplicitImageOutputDimensions) {
1843:                             // unknown source aspect ratio, just put large number and hope IM figures it out
1844:                             $commandline .= ' -'.$IMresizeParameter.' '.phpthumb_functions::escapeshellarg_replacement(($this->w ? $this->w : '9999').'x'.($this->h ? $this->h : '9999').$exactDimensionsBang);
1845:                         } else {
1846:                             $commandline .= ' -'.$IMresizeParameter.' '.phpthumb_functions::escapeshellarg_replacement($this->w.'x'.$this->h.$exactDimensionsBang);
1847:                         }
1848:                     }
1849: 
1850:                 }
1851: 
1852:                 if ($this->ra) {
1853:                     $this->ra = intval($this->ra);
1854:                     if ($this->ImageMagickSwitchAvailable('rotate')) {
1855:                         if (!preg_match('#('.implode('|', $this->AlphaCapableFormats).')#i', $outputFormat) || phpthumb_functions::version_compare_replacement($this->ImageMagickVersion(), '6.3.7', '>=')) {
1856:                             $this->DebugMessage('Using ImageMagick rotate', __FILE__, __LINE__);
1857:                             $commandline .= ' -rotate '.phpthumb_functions::escapeshellarg_replacement($this->ra);
1858:                             if (($this->ra % 90) != 0) {
1859:                                 if (preg_match('#('.implode('|', $this->AlphaCapableFormats).')#i', $outputFormat)) {
1860:                                     // alpha-capable format
1861:                                     $commandline .= ' -background rgba(255,255,255,0)';
1862:                                 } else {
1863:                                     $commandline .= ' -background '.phpthumb_functions::escapeshellarg_replacement('#'.($this->bg ? $this->bg : 'FFFFFF'));
1864:                                 }
1865:                             }
1866:                             $this->ra = 0;
1867:                         } else {
1868:                             $this->DebugMessage('Not using ImageMagick rotate because alpha background buggy before v6.3.7', __FILE__, __LINE__);
1869:                         }
1870:                     } else {
1871:                         $this->DebugMessage('Not using ImageMagick rotate because not supported', __FILE__, __LINE__);
1872:                     }
1873:                 }
1874: 
1875:                 $successfullyProcessedFilters = array();
1876:                 foreach ($this->fltr as $filterkey => $filtercommand) {
1877:                     @list($command, $parameter) = explode('|', $filtercommand, 2);
1878:                     switch ($command) {
1879:                         case 'brit':
1880:                             if ($this->ImageMagickSwitchAvailable('modulate')) {
1881:                                 $commandline .= ' -modulate '.phpthumb_functions::escapeshellarg_replacement((100 + intval($parameter)).',100,100');
1882:                                 $successfullyProcessedFilters[] = $filterkey;
1883:                             }
1884:                             break;
1885: 
1886:                         case 'cont':
1887:                             if ($this->ImageMagickSwitchAvailable('contrast')) {
1888:                                 $contDiv10 = round(intval($parameter) / 10);
1889:                                 if ($contDiv10 > 0) {
1890:                                     $contDiv10 = min($contDiv10, 100);
1891:                                     for ($i = 0; $i < $contDiv10; $i++) {
1892:                                         $commandline .= ' -contrast'; // increase contrast by 10%
1893:                                     }
1894:                                 } elseif ($contDiv10 < 0) {
1895:                                     $contDiv10 = max($contDiv10, -100);
1896:                                     for ($i = $contDiv10; $i < 0; $i++) {
1897:                                         $commandline .= ' +contrast'; // decrease contrast by 10%
1898:                                     }
1899:                                 } else {
1900:                                     // do nothing
1901:                                 }
1902:                                 $successfullyProcessedFilters[] = $filterkey;
1903:                             }
1904:                             break;
1905: 
1906:                         case 'ds':
1907:                             if ($this->ImageMagickSwitchAvailable(array('colorspace', 'modulate'))) {
1908:                                 if ($parameter == 100) {
1909:                                     $commandline .= ' -colorspace GRAY';
1910:                                     $commandline .= ' -modulate 100,0,100';
1911:                                 } else {
1912:                                     $commandline .= ' -modulate '.phpthumb_functions::escapeshellarg_replacement('100,'.(100 - intval($parameter)).',100');
1913:                                 }
1914:                                 $successfullyProcessedFilters[] = $filterkey;
1915:                             }
1916:                             break;
1917: 
1918:                         case 'sat':
1919:                             if ($this->ImageMagickSwitchAvailable(array('colorspace', 'modulate'))) {
1920:                                 if ($parameter == -100) {
1921:                                     $commandline .= ' -colorspace GRAY';
1922:                                     $commandline .= ' -modulate 100,0,100';
1923:                                 } else {
1924:                                     $commandline .= ' -modulate '.phpthumb_functions::escapeshellarg_replacement('100,'.(100 + intval($parameter)).',100');
1925:                                 }
1926:                                 $successfullyProcessedFilters[] = $filterkey;
1927:                             }
1928:                             break;
1929: 
1930:                         case 'gray':
1931:                             if ($this->ImageMagickSwitchAvailable(array('colorspace', 'modulate'))) {
1932:                                 $commandline .= ' -colorspace GRAY';
1933:                                 $commandline .= ' -modulate 100,0,100';
1934:                                 $successfullyProcessedFilters[] = $filterkey;
1935:                             }
1936:                             break;
1937: 
1938:                         case 'clr':
1939:                             if ($this->ImageMagickSwitchAvailable(array('fill', 'colorize'))) {
1940:                                 @list($amount, $color) = explode('|', $parameter);
1941:                                 $commandline .= ' -fill '.phpthumb_functions::escapeshellarg_replacement('#'.preg_replace('#[^0-9A-F]#i', '', $color));
1942:                                 $commandline .= ' -colorize '.phpthumb_functions::escapeshellarg_replacement(min(max(intval($amount), 0), 100));
1943:                             }
1944:                             break;
1945: 
1946:                         case 'sep':
1947:                             if ($this->ImageMagickSwitchAvailable('sepia-tone')) {
1948:                                 @list($amount, $color) = explode('|', $parameter);
1949:                                 $amount = ($amount ? $amount : 80);
1950:                                 if (!$color) {
1951:                                     $commandline .= ' -sepia-tone '.phpthumb_functions::escapeshellarg_replacement(min(max(intval($amount), 0), 100).'%');
1952:                                     $successfullyProcessedFilters[] = $filterkey;
1953:                                 }
1954:                             }
1955:                             break;
1956: 
1957:                         case 'gam':
1958:                             @list($amount) = explode('|', $parameter);
1959:                             $amount = min(max(floatval($amount), 0.001), 10);
1960:                             if (number_format($amount, 3) != '1.000') {
1961:                                 if ($this->ImageMagickSwitchAvailable('gamma')) {
1962:                                     $commandline .= ' -gamma '.phpthumb_functions::escapeshellarg_replacement($amount);
1963:                                     $successfullyProcessedFilters[] = $filterkey;
1964:                                 }
1965:                             }
1966:                             break;
1967: 
1968:                         case 'neg':
1969:                             if ($this->ImageMagickSwitchAvailable('negate')) {
1970:                                 $commandline .= ' -negate';
1971:                                 $successfullyProcessedFilters[] = $filterkey;
1972:                             }
1973:                             break;
1974: 
1975:                         case 'th':
1976:                             @list($amount) = explode('|', $parameter);
1977:                             if ($this->ImageMagickSwitchAvailable(array('threshold', 'dither', 'monochrome'))) {
1978:                                 $commandline .= ' -threshold '.phpthumb_functions::escapeshellarg_replacement(round(min(max(intval($amount), 0), 255) / 2.55).'%');
1979:                                 $commandline .= ' -dither';
1980:                                 $commandline .= ' -monochrome';
1981:                                 $successfullyProcessedFilters[] = $filterkey;
1982:                             }
1983:                             break;
1984: 
1985:                         case 'rcd':
1986:                             if ($this->ImageMagickSwitchAvailable(array('colors', 'dither'))) {
1987:                                 @list($colors, $dither) = explode('|', $parameter);
1988:                                 $colors = ($colors                ?  (int) $colors : 256);
1989:                                 $dither  = ((strlen($dither) > 0) ? (bool) $dither : true);
1990:                                 $commandline .= ' -colors '.phpthumb_functions::escapeshellarg_replacement(max($colors, 8)); // ImageMagick will otherwise fail with "cannot quantize to fewer than 8 colors"
1991:                                 $commandline .= ($dither ? ' -dither' : ' +dither');
1992:                                 $successfullyProcessedFilters[] = $filterkey;
1993:                             }
1994:                             break;
1995: 
1996:                         case 'flip':
1997:                             if ($this->ImageMagickSwitchAvailable(array('flip', 'flop'))) {
1998:                                 if (strpos(strtolower($parameter), 'x') !== false) {
1999:                                     $commandline .= ' -flop';
2000:                                 }
2001:                                 if (strpos(strtolower($parameter), 'y') !== false) {
2002:                                     $commandline .= ' -flip';
2003:                                 }
2004:                                 $successfullyProcessedFilters[] = $filterkey;
2005:                             }
2006:                             break;
2007: 
2008:                         case 'edge':
2009:                             if ($this->ImageMagickSwitchAvailable('edge')) {
2010:                                 $parameter = (!empty($parameter) ? $parameter : 2);
2011:                                 $commandline .= ' -edge '.phpthumb_functions::escapeshellarg_replacement(!empty($parameter) ? intval($parameter) : 1);
2012:                                 $successfullyProcessedFilters[] = $filterkey;
2013:                             }
2014:                             break;
2015: 
2016:                         case 'emb':
2017:                             if ($this->ImageMagickSwitchAvailable(array('emboss', 'negate'))) {
2018:                                 $parameter = (!empty($parameter) ? $parameter : 2);
2019:                                 $commandline .= ' -emboss '.phpthumb_functions::escapeshellarg_replacement(intval($parameter));
2020:                                 if ($parameter < 2) {
2021:                                     $commandline .= ' -negate'; // ImageMagick negates the image for some reason with '-emboss 1';
2022:                                 }
2023:                                 $successfullyProcessedFilters[] = $filterkey;
2024:                             }
2025:                             break;
2026: 
2027:                         case 'lvl':
2028:                             @list($band, $method, $threshold) = explode('|', $parameter);
2029:                             $band      = ($band ? preg_replace('#[^RGBA\\*]#', '', strtoupper($band))       : '*');
2030:                             $method    = ((strlen($method) > 0)    ? intval($method)                        :   2);
2031:                             $threshold = ((strlen($threshold) > 0) ? min(max(floatval($threshold), 0), 100) : 0.1);
2032: 
2033:                             $band = preg_replace('#[^RGBA\\*]#', '', strtoupper($band));
2034: 
2035:                             if (($method > 1) && !$this->ImageMagickSwitchAvailable(array('channel', 'contrast-stretch'))) {
2036:                                 // Because ImageMagick processing happens before PHP-GD filters, and because some
2037:                                 // clipping is involved in the "lvl" filter, if "lvl" happens before "wb" then the
2038:                                 // "wb" filter will have (almost) no effect. Therefore, if "wb" is enabled then
2039:                                 // force the "lvl" filter to be processed by GD, not ImageMagick.
2040:                                 foreach ($this->fltr as $fltr_key => $fltr_value) {
2041:                                     list($fltr_cmd) = explode('|', $fltr_value);
2042:                                     if ($fltr_cmd == 'wb') {
2043:                                         $this->DebugMessage('Setting "lvl" filter method to "0" (from "'.$method.'") because white-balance filter also enabled', __FILE__, __LINE__);
2044:                                         $method = 0;
2045:                                     }
2046:                                 }
2047:                             }
2048: 
2049:                             switch ($method) {
2050:                                 case 0: // internal RGB
2051:                                 case 1: // internal grayscale
2052:                                     break;
2053:                                 case 2: // ImageMagick "contrast-stretch"
2054:                                     if ($this->ImageMagickSwitchAvailable('contrast-stretch')) {
2055:                                         if ($band != '*') {
2056:                                             $commandline .= ' -channel '.phpthumb_functions::escapeshellarg_replacement(strtoupper($band));
2057:                                         }
2058:                                         $threshold = preg_replace('#[^0-9\\.]#', '', $threshold); // should be unneccesary, but just to be double-sure
2059:                                         //$commandline .= ' -contrast-stretch '.phpthumb_functions::escapeshellarg_replacement($threshold.'%');
2060:                                         $commandline .= ' -contrast-stretch \''.$threshold.'%\'';
2061:                                         if ($band != '*') {
2062:                                             $commandline .= ' +channel';
2063:                                         }
2064:                                         $successfullyProcessedFilters[] = $filterkey;
2065:                                     }
2066:                                     break;
2067:                                 case 3: // ImageMagick "normalize"
2068:                                     if ($this->ImageMagickSwitchAvailable('normalize')) {
2069:                                         if ($band != '*') {
2070:                                             $commandline .= ' -channel '.phpthumb_functions::escapeshellarg_replacement(strtoupper($band));
2071:                                         }
2072:                                         $commandline .= ' -normalize';
2073:                                         if ($band != '*') {
2074:                                             $commandline .= ' +channel';
2075:                                         }
2076:                                         $successfullyProcessedFilters[] = $filterkey;
2077:                                     }
2078:                                     break;
2079:                                 default:
2080:                                     $this->DebugMessage('unsupported method ('.$method.') for "lvl" filter', __FILE__, __LINE__);
2081:                                     break;
2082:                             }
2083:                             if (isset($this->fltr[$filterkey]) && ($method > 1)) {
2084:                                 $this->fltr[$filterkey] = $command.'|'.$band.'|0|'.$threshold;
2085:                                 $this->DebugMessage('filter "lvl" remapped from method "'.$method.'" to method "0" because ImageMagick support is missing', __FILE__, __LINE__);
2086:                             }
2087:                             break;
2088: 
2089:                         case 'wb':
2090:                             if ($this->ImageMagickSwitchAvailable(array('channel', 'contrast-stretch'))) {
2091:                                 @list($threshold) = explode('|', $parameter);
2092:                                 $threshold = (!empty($threshold) ? min(max(floatval($threshold), 0), 100) : 0.1);
2093:                                 $threshold = preg_replace('#[^0-9\\.]#', '', $threshold); // should be unneccesary, but just to be double-sure
2094:                                 //$commandline .= ' -channel R -contrast-stretch '.phpthumb_functions::escapeshellarg_replacement($threshold.'%'); // doesn't work on Windows because most versions of PHP do not properly
2095:                                 //$commandline .= ' -channel G -contrast-stretch '.phpthumb_functions::escapeshellarg_replacement($threshold.'%'); // escape special characters (such as %) and just replace them with spaces
2096:                                 //$commandline .= ' -channel B -contrast-stretch '.phpthumb_functions::escapeshellarg_replacement($threshold.'%'); // https://bugs.php.net/bug.php?id=43261
2097:                                 $commandline .= ' -channel R -contrast-stretch \''.$threshold.'%\'';
2098:                                 $commandline .= ' -channel G -contrast-stretch \''.$threshold.'%\'';
2099:                                 $commandline .= ' -channel B -contrast-stretch \''.$threshold.'%\'';
2100:                                 $commandline .= ' +channel';
2101:                                 $successfullyProcessedFilters[] = $filterkey;
2102:                             }
2103:                             break;
2104: 
2105:                         case 'blur':
2106:                             if ($this->ImageMagickSwitchAvailable('blur')) {
2107:                                 @list($radius) = explode('|', $parameter);
2108:                                 $radius = (!empty($radius) ? min(max(intval($radius), 0), 25) : 1);
2109:                                 $commandline .= ' -blur '.phpthumb_functions::escapeshellarg_replacement($radius);
2110:                                 $successfullyProcessedFilters[] = $filterkey;
2111:                             }
2112:                             break;
2113: 
2114:                         case 'gblr':
2115:                             @list($radius) = explode('|', $parameter);
2116:                             $radius = (!empty($radius) ? min(max(intval($radius), 0), 25) : 1);
2117:                             // "-gaussian" changed to "-gaussian-blur" sometime around 2009
2118:                             if ($this->ImageMagickSwitchAvailable('gaussian-blur')) {
2119:                                 $commandline .= ' -gaussian-blur '.phpthumb_functions::escapeshellarg_replacement($radius);
2120:                                 $successfullyProcessedFilters[] = $filterkey;
2121:                             } elseif ($this->ImageMagickSwitchAvailable('gaussian')) {
2122:                                 $commandline .= ' -gaussian '.phpthumb_functions::escapeshellarg_replacement($radius);
2123:                                 $successfullyProcessedFilters[] = $filterkey;
2124:                             }
2125:                             break;
2126: 
2127:                         case 'usm':
2128:                             if ($this->ImageMagickSwitchAvailable('unsharp')) {
2129:                                 @list($amount, $radius, $threshold) = explode('|', $parameter);
2130:                                 $amount    = ($amount            ? min(max(intval($radius), 0), 255) : 80);
2131:                                 $radius    = ($radius            ? min(max(intval($radius), 0), 10)  : 0.5);
2132:                                 $threshold = (strlen($threshold) ? min(max(intval($radius), 0), 50)  : 3);
2133:                                 $commandline .= ' -unsharp '.phpthumb_functions::escapeshellarg_replacement(number_format(($radius * 2) - 1, 2, '.', '').'x1+'.number_format($amount / 100, 2, '.', '').'+'.number_format($threshold / 100, 2, '.', ''));
2134:                                 $successfullyProcessedFilters[] = $filterkey;
2135:                             }
2136:                             break;
2137: 
2138:                         case 'bord':
2139:                             if ($this->ImageMagickSwitchAvailable(array('border', 'bordercolor', 'thumbnail', 'crop'))) {
2140:                                 if (!$this->zc) {
2141:                                     @list($width, $rX, $rY, $color) = explode('|', $parameter);
2142:                                     $width = intval($width);
2143:                                     $rX    = intval($rX);
2144:                                     $rY    = intval($rY);
2145:                                     if ($width && !$rX && !$rY) {
2146:                                         if (!phpthumb_functions::IsHexColor($color)) {
2147:                                             $color = ((!empty($this->bc) && phpthumb_functions::IsHexColor($this->bc)) ? $this->bc : '000000');
2148:                                         }
2149:                                         $commandline .= ' -border '.phpthumb_functions::escapeshellarg_replacement(intval($width));
2150:                                         $commandline .= ' -bordercolor '.phpthumb_functions::escapeshellarg_replacement('#'.$color);
2151: 
2152:                                         if (preg_match('# \\-crop "([0-9]+)x([0-9]+)\\+0\\+0" #', $commandline, $matches)) {
2153:                                             $commandline = str_replace(' -crop "'.$matches[1].'x'.$matches[2].'+0+0" ', ' -crop '.phpthumb_functions::escapeshellarg_replacement(($matches[1] - (2 * $width)).'x'.($matches[2] - (2 * $width)).'+0+0').' ', $commandline);
2154:                                         } elseif (preg_match('# \\-'.$IMresizeParameter.' "([0-9]+)x([0-9]+)" #', $commandline, $matches)) {
2155:                                             $commandline = str_replace(' -'.$IMresizeParameter.' "'.$matches[1].'x'.$matches[2].'" ', ' -'.$IMresizeParameter.' '.phpthumb_functions::escapeshellarg_replacement(($matches[1] - (2 * $width)).'x'.($matches[2] - (2 * $width))).' ', $commandline);
2156:                                         }
2157:                                         $successfullyProcessedFilters[] = $filterkey;
2158:                                     }
2159:                                 }
2160:                             }
2161:                             break;
2162: 
2163:                         case 'crop':
2164:                             break;
2165: 
2166:                         case 'sblr':
2167:                             break;
2168: 
2169:                         case 'mean':
2170:                             break;
2171: 
2172:                         case 'smth':
2173:                             break;
2174: 
2175:                         case 'bvl':
2176:                             break;
2177: 
2178:                         case 'wmi':
2179:                             break;
2180: 
2181:                         case 'wmt':
2182:                             break;
2183: 
2184:                         case 'over':
2185:                             break;
2186: 
2187:                         case 'hist':
2188:                             break;
2189: 
2190:                         case 'fram':
2191:                             break;
2192: 
2193:                         case 'drop':
2194:                             break;
2195: 
2196:                         case 'mask':
2197:                             break;
2198: 
2199:                         case 'elip':
2200:                             break;
2201: 
2202:                         case 'ric':
2203:                             break;
2204: 
2205:                         case 'stc':
2206:                             break;
2207: 
2208:                         case 'size':
2209:                             break;
2210: 
2211:                         default:
2212:                             $this->DebugMessage('Unknown $this->fltr['.$filterkey.'] ('.$filtercommand.') -- deleting filter command', __FILE__, __LINE__);
2213:                             $successfullyProcessedFilters[] = $filterkey;
2214:                             break;
2215:                     }
2216:                     if (!isset($this->fltr[$filterkey])) {
2217:                         $this->DebugMessage('Processed $this->fltr['.$filterkey.'] ('.$filtercommand.') with ImageMagick', __FILE__, __LINE__);
2218:                     } else {
2219:                         $this->DebugMessage('Skipping $this->fltr['.$filterkey.'] ('.$filtercommand.') with ImageMagick', __FILE__, __LINE__);
2220:                     }
2221:                 }
2222:                 $this->DebugMessage('Remaining $this->fltr after ImageMagick: ('.$this->phpThumbDebugVarDump($this->fltr).')', __FILE__, __LINE__);
2223:                 if (count($this->fltr) > 0) {
2224:                     $this->useRawIMoutput = false;
2225:                 }
2226: 
2227:                 if (preg_match('#jpe?g#i', $outputFormat) && $this->q) {
2228:                     if ($this->ImageMagickSwitchAvailable(array('quality', 'interlace'))) {
2229:                         $commandline .= ' -quality '.phpthumb_functions::escapeshellarg_replacement($this->thumbnailQuality);
2230:                         if ($this->config_output_interlace) {
2231:                             // causes weird things with animated GIF... leave for JPEG only
2232:                             $commandline .= ' -interlace line '; // Use Line or Plane to create an interlaced PNG or GIF or progressive JPEG image
2233:                         }
2234:                     }
2235:                 }
2236:                 $commandline .= ' '.phpthumb_functions::escapeshellarg_replacement(preg_replace('#[/\\\\]#', DIRECTORY_SEPARATOR, $this->sourceFilename).(($outputFormat == 'gif') ? '' : '['.intval($this->sfn).']')); // [0] means first frame of (GIF) animation, can be ignored
2237:                 $commandline .= ' '.$outputFormat.':'.phpthumb_functions::escapeshellarg_replacement($IMtempfilename);
2238:                 if (!$this->iswindows) {
2239:                     $commandline .= ' 2>&1';
2240:                 }
2241:                 $this->DebugMessage('ImageMagick called as ('.$commandline.')', __FILE__, __LINE__);
2242:                 $IMresult = phpthumb_functions::SafeExec($commandline);
2243:                 clearstatcache();
2244:                 if (!@file_exists($IMtempfilename) || !@filesize($IMtempfilename)) {
2245:                     $this->FatalError('ImageMagick failed with message ('.trim($IMresult).')');
2246:                     $this->DebugMessage('ImageMagick failed with message ('.trim($IMresult).')', __FILE__, __LINE__);
2247:                     if ($this->iswindows && !$IMresult) {
2248:                         $this->DebugMessage('Check to make sure that PHP has read+write permissions to "'.dirname($IMtempfilename).'"', __FILE__, __LINE__);
2249:                     }
2250: 
2251:                 } else {
2252: 
2253:                     foreach ($successfullyProcessedFilters as $dummy => $filterkey) {
2254:                         unset($this->fltr[$filterkey]);
2255:                     }
2256:                     $this->IMresizedData = file_get_contents($IMtempfilename);
2257:                     $getimagesize_imresized = @getimagesize($IMtempfilename);
2258:                     $this->DebugMessage('getimagesize('.$IMtempfilename.') returned [w='.$getimagesize_imresized[0].';h='.$getimagesize_imresized[1].';f='.$getimagesize_imresized[2].']', __FILE__, __LINE__);
2259:                     if (($this->config_max_source_pixels > 0) && (($getimagesize_imresized[0] * $getimagesize_imresized[1]) > $this->config_max_source_pixels)) {
2260:                         $this->DebugMessage('skipping ImageMagickThumbnailToGD::'.$ImageCreateFunction.'() because IM output is too large ('.$getimagesize_imresized[0].'x'.$getimagesize_imresized[0].' = '.($getimagesize_imresized[0] * $getimagesize_imresized[1]).' > '.$this->config_max_source_pixels.')', __FILE__, __LINE__);
2261:                     } elseif (function_exists(@$ImageCreateFunction) && ($this->gdimg_source = @$ImageCreateFunction($IMtempfilename))) {
2262:                         $this->source_width  = imagesx($this->gdimg_source);
2263:                         $this->source_height = imagesy($this->gdimg_source);
2264:                         $this->DebugMessage('ImageMagickThumbnailToGD::'.$ImageCreateFunction.'() succeeded, $this->gdimg_source is now ('.$this->source_width.'x'.$this->source_height.')', __FILE__, __LINE__);
2265:                         $this->DebugMessage('ImageMagickThumbnailToGD() returning $this->IMresizedData ('.strlen($this->IMresizedData).' bytes)', __FILE__, __LINE__);
2266:                     } else {
2267:                         $this->useRawIMoutput = true;
2268:                         $this->DebugMessage('$this->useRawIMoutput set to TRUE because '.@$ImageCreateFunction.'('.$IMtempfilename.') failed', __FILE__, __LINE__);
2269:                     }
2270:                     if (file_exists($IMtempfilename)) {
2271:                         $this->DebugMessage('deleting "'.$IMtempfilename.'"', __FILE__, __LINE__);
2272:                         @unlink($IMtempfilename);
2273:                     }
2274:                     return true;
2275: 
2276:                 }
2277:                 if (file_exists($IMtempfilename)) {
2278:                     $this->DebugMessage('deleting "'.$IMtempfilename.'"', __FILE__, __LINE__);
2279:                     @unlink($IMtempfilename);
2280:                 }
2281: 
2282:             } elseif ($this->issafemode) {
2283:                 $this->DebugMessage('ImageMagickThumbnailToGD() aborting because PHP safe_mode is enabled and phpThumb_tempnam() failed', __FILE__, __LINE__);
2284:                 $this->useRawIMoutput = false;
2285:             } else {
2286:                 if (file_exists($IMtempfilename)) {
2287:                     $this->DebugMessage('deleting "'.$IMtempfilename.'"', __FILE__, __LINE__);
2288:                     @unlink($IMtempfilename);
2289:                 }
2290:                 $this->DebugMessage('ImageMagickThumbnailToGD() aborting, phpThumb_tempnam() failed', __FILE__, __LINE__);
2291:             }
2292:         } else {
2293:             $this->DebugMessage('ImageMagickThumbnailToGD() aborting because ImageMagickCommandlineBase() failed', __FILE__, __LINE__);
2294:         }
2295:         $this->useRawIMoutput = false;
2296:         return false;
2297:     }
2298: 
2299: 
2300:     function Rotate() {
2301:         if ($this->ra || $this->ar) {
2302:             if (!function_exists('imagerotate')) {
2303:                 $this->DebugMessage('!function_exists(imagerotate)', __FILE__, __LINE__);
2304:                 return false;
2305:             }
2306:             if (!include_once(dirname(__FILE__).'/phpthumb.filters.php')) {
2307:                 $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.filters.php" which is required for applying filters ('.implode(';', $this->fltr).')', __FILE__, __LINE__);
2308:                 return false;
2309:             }
2310: 
2311:             $this->config_background_hexcolor = ($this->bg ? $this->bg : $this->config_background_hexcolor);
2312:             if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) {
2313:                 return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"');
2314:             }
2315: 
2316:             $rotate_angle = 0;
2317:             if ($this->ra) {
2318: 
2319:                 $rotate_angle = floatval($this->ra);
2320: 
2321:             } else {
2322: 
2323:                 if ($this->ar == 'x') {
2324:                     if (phpthumb_functions::version_compare_replacement(phpversion(), '4.2.0', '>=')) {
2325:                         if ($this->sourceFilename) {
2326:                             if (function_exists('exif_read_data')) {
2327:                                 if ($exif_data = @exif_read_data($this->sourceFilename, 'IFD0')) {
2328:                                     // http://sylvana.net/jpegcrop/exif_orientation.html
2329:                                     switch (@$exif_data['Orientation']) {
2330:                                         case 1:
2331:                                             $rotate_angle = 0;
2332:                                             break;
2333:                                         case 3:
2334:                                             $rotate_angle = 180;
2335:                                             break;
2336:                                         case 6:
2337:                                             $rotate_angle = 270;
2338:                                             break;
2339:                                         case 8:
2340:                                             $rotate_angle = 90;
2341:                                             break;
2342: 
2343:                                         default:
2344:                                             $this->DebugMessage('EXIF auto-rotate failed because unknown $exif_data[Orientation] "'.@$exif_data['Orientation'].'"', __FILE__, __LINE__);
2345:                                             return false;
2346:                                             break;
2347:                                     }
2348:                                     $this->DebugMessage('EXIF auto-rotate set to '.$rotate_angle.' degrees ($exif_data[Orientation] = "'.@$exif_data['Orientation'].'")', __FILE__, __LINE__);
2349:                                 } else {
2350:                                     $this->DebugMessage('failed: exif_read_data('.$this->sourceFilename.')', __FILE__, __LINE__);
2351:                                     return false;
2352:                                 }
2353:                             } else {
2354:                                 $this->DebugMessage('!function_exists(exif_read_data)', __FILE__, __LINE__);
2355:                                 return false;
2356:                             }
2357:                         } else {
2358:                             $this->DebugMessage('Cannot auto-rotate from EXIF data because $this->sourceFilename is empty', __FILE__, __LINE__);
2359:                             return false;
2360:                         }
2361:                     } else {
2362:                         $this->DebugMessage('Cannot auto-rotate from EXIF data because PHP is less than v4.2.0 ('.phpversion().')', __FILE__, __LINE__);
2363:                         return false;
2364:                     }
2365:                 } elseif (($this->ar == 'l') && ($this->source_height > $this->source_width)) {
2366:                     $rotate_angle = 270;
2367:                 } elseif (($this->ar == 'L') && ($this->source_height > $this->source_width)) {
2368:                     $rotate_angle = 90;
2369:                 } elseif (($this->ar == 'p') && ($this->source_width > $this->source_height)) {
2370:                     $rotate_angle = 90;
2371:                 } elseif (($this->ar == 'P') && ($this->source_width > $this->source_height)) {
2372:                     $rotate_angle = 270;
2373:                 }
2374: 
2375:             }
2376:             if ($rotate_angle % 90) {
2377:                 $this->is_alpha = true;
2378:             }
2379:             phpthumb_filters::ImprovedImageRotate($this->gdimg_source, $rotate_angle, $this->config_background_hexcolor, $this->bg, $this);
2380:             $this->source_width  = imagesx($this->gdimg_source);
2381:             $this->source_height = imagesy($this->gdimg_source);
2382:         }
2383:         return true;
2384:     }
2385: 
2386: 
2387:     function FixedAspectRatio() {
2388:         // optional fixed-dimension images (regardless of aspect ratio)
2389: 
2390:         if (!$this->far) {
2391:             // do nothing
2392:             return true;
2393:         }
2394: 
2395:         if (!$this->w || !$this->h) {
2396:             return false;
2397:         }
2398:         $this->thumbnail_width  = $this->w;
2399:         $this->thumbnail_height = $this->h;
2400:         $this->is_alpha = true;
2401:         if ($this->thumbnail_image_width >= $this->thumbnail_width) {
2402: 
2403:             $aspectratio = $this->thumbnail_image_height / $this->thumbnail_image_width;
2404:             if ($this->w) {
2405:                 $this->thumbnail_image_height = round($this->thumbnail_image_width * $aspectratio);
2406:                 $this->thumbnail_height = ($this->h ? $this->h : $this->thumbnail_image_height);
2407:             } elseif ($this->thumbnail_image_height < $this->thumbnail_height) {
2408:                 $this->thumbnail_image_height = $this->thumbnail_height;
2409:                 $this->thumbnail_image_width  = round($this->thumbnail_image_height / $aspectratio);
2410:             }
2411: 
2412:         } else {
2413: 
2414:             $aspectratio = $this->thumbnail_image_width / $this->thumbnail_image_height;
2415:             if ($this->h) {
2416:                 $this->thumbnail_image_width = round($this->thumbnail_image_height * $aspectratio);
2417:             } elseif ($this->thumbnail_image_width < $this->thumbnail_width) {
2418:                 $this->thumbnail_image_width = $this->thumbnail_width;
2419:                 $this->thumbnail_image_height  = round($this->thumbnail_image_width / $aspectratio);
2420:             }
2421: 
2422:         }
2423:         return true;
2424:     }
2425: 
2426: 
2427:     function OffsiteDomainIsAllowed($hostname, $allowed_domains) {
2428:         static $domain_is_allowed = array();
2429:         $hostname = strtolower($hostname);
2430:         if (!isset($domain_is_allowed[$hostname])) {
2431:             $domain_is_allowed[$hostname] = false;
2432:             foreach ($allowed_domains as $valid_domain) {
2433:                 $starpos = strpos($valid_domain, '*');
2434:                 if ($starpos !== false) {
2435:                     $valid_domain = substr($valid_domain, $starpos + 1);
2436:                     if (preg_match('#'.preg_quote($valid_domain).'$#', $hostname)) {
2437:                         $domain_is_allowed[$hostname] = true;
2438:                         break;
2439:                     }
2440:                 } else {
2441:                     if (strtolower($valid_domain) === $hostname) {
2442:                         $domain_is_allowed[$hostname] = true;
2443:                         break;
2444:                     }
2445:                 }
2446:             }
2447:         }
2448:         return $domain_is_allowed[$hostname];
2449:     }
2450: 
2451: 
2452:     function AntiOffsiteLinking() {
2453:         // Optional anti-offsite hijacking of the thumbnail script
2454:         $allow   = true;
2455:         if ($allow && $this->config_nooffsitelink_enabled && (@$_SERVER['HTTP_REFERER'] || $this->config_nooffsitelink_require_refer)) {
2456:             $this->DebugMessage('AntiOffsiteLinking() checking $_SERVER[HTTP_REFERER] "'.@$_SERVER['HTTP_REFERER'].'"', __FILE__, __LINE__);
2457:             foreach ($this->config_nooffsitelink_valid_domains as $key => $valid_domain) {
2458:                 // $_SERVER['HTTP_HOST'] contains the port number, so strip it out here to make default configuration work
2459:                 list($clean_domain) = explode(':', $valid_domain);
2460:                 $this->config_nooffsitelink_valid_domains[$key] = $clean_domain;
2461:             }
2462:             $parsed_url = phpthumb_functions::ParseURLbetter(@$_SERVER['HTTP_REFERER']);
2463:             if (!$this->OffsiteDomainIsAllowed(@$parsed_url['host'], $this->config_nooffsitelink_valid_domains)) {
2464:                 $allow   = false;
2465:                 //$this->DebugMessage('AntiOffsiteLinking() - "'.@$parsed_url['host'].'" is NOT in $this->config_nooffsitelink_valid_domains ('.implode(';', $this->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__);
2466:                 $this->ErrorImage('AntiOffsiteLinking() - "'.@$parsed_url['host'].'" is NOT in $this->config_nooffsitelink_valid_domains ('.implode(';', $this->config_nooffsitelink_valid_domains).')');
2467:             } else {
2468:                 $this->DebugMessage('AntiOffsiteLinking() - "'.@$parsed_url['host'].'" is in $this->config_nooffsitelink_valid_domains ('.implode(';', $this->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__);
2469:             }
2470:         }
2471: 
2472:         if ($allow && $this->config_nohotlink_enabled && preg_match('#^(f|ht)tps?\://#i', $this->src)) {
2473:             $parsed_url = phpthumb_functions::ParseURLbetter($this->src);
2474:             //if (!phpthumb_functions::CaseInsensitiveInArray(@$parsed_url['host'], $this->config_nohotlink_valid_domains)) {
2475:             if (!$this->OffsiteDomainIsAllowed(@$parsed_url['host'], $this->config_nohotlink_valid_domains)) {
2476:                 // This domain is not allowed
2477:                 $allow = false;
2478:                 $this->DebugMessage('AntiOffsiteLinking() - "'.$parsed_url['host'].'" is NOT in $this->config_nohotlink_valid_domains ('.implode(';', $this->config_nohotlink_valid_domains).')', __FILE__, __LINE__);
2479:             } else {
2480:                 $this->DebugMessage('AntiOffsiteLinking() - "'.$parsed_url['host'].'" is in $this->config_nohotlink_valid_domains ('.implode(';', $this->config_nohotlink_valid_domains).')', __FILE__, __LINE__);
2481:             }
2482:         }
2483: 
2484:         if ($allow) {
2485:             $this->DebugMessage('AntiOffsiteLinking() says this is allowed', __FILE__, __LINE__);
2486:             return true;
2487:         }
2488: 
2489:         if (!phpthumb_functions::IsHexColor($this->config_error_bgcolor)) {
2490:             return $this->ErrorImage('Invalid hex color string "'.$this->config_error_bgcolor.'" for $this->config_error_bgcolor');
2491:         }
2492:         if (!phpthumb_functions::IsHexColor($this->config_error_textcolor)) {
2493:             return $this->ErrorImage('Invalid hex color string "'.$this->config_error_textcolor.'" for $this->config_error_textcolor');
2494:         }
2495:         if ($this->config_nooffsitelink_erase_image) {
2496: 
2497:             return $this->ErrorImage($this->config_nooffsitelink_text_message, $this->thumbnail_width, $this->thumbnail_height);
2498: 
2499:         } else {
2500: 
2501:             $this->config_nooffsitelink_watermark_src = $this->ResolveFilenameToAbsolute($this->config_nooffsitelink_watermark_src);
2502:             if (is_file($this->config_nooffsitelink_watermark_src)) {
2503: 
2504:                 if (!include_once(dirname(__FILE__).'/phpthumb.filters.php')) {
2505:                     $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.filters.php" which is required for applying watermark', __FILE__, __LINE__);
2506:                     return false;
2507:                 }
2508:                 $watermark_img = $this->ImageCreateFromStringReplacement(file_get_contents($this->config_nooffsitelink_watermark_src));
2509:                 $phpthumbFilters = new phpthumb_filters();
2510:                 $phpthumbFilters->phpThumbObject = &$this;
2511:                 $opacity = 50;
2512:                 $margin  = 5;
2513:                 $phpthumbFilters->WatermarkOverlay($this->gdimg_output, $watermark_img, '*', $opacity, $margin);
2514:                 imagedestroy($watermark_img);
2515:                 unset($phpthumbFilters);
2516: 
2517:             } else {
2518: 
2519:                 $nohotlink_text_array = explode("\n", wordwrap($this->config_nooffsitelink_text_message, floor($this->thumbnail_width / imagefontwidth($this->config_error_fontsize)), "\n"));
2520:                 $nohotlink_text_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_error_textcolor);
2521: 
2522:                 $topoffset = round(($this->thumbnail_height - (count($nohotlink_text_array) * imagefontheight($this->config_error_fontsize))) / 2);
2523: 
2524:                 $rowcounter = 0;
2525:                 $this->DebugMessage('AntiOffsiteLinking() writing '.count($nohotlink_text_array).' lines of text "'.$this->config_nooffsitelink_text_message.'" (in #'.$this->config_error_textcolor.') on top of image', __FILE__, __LINE__);
2526:                 foreach ($nohotlink_text_array as $textline) {
2527:                     $leftoffset = max(0, round(($this->thumbnail_width - (strlen($textline) * imagefontwidth($this->config_error_fontsize))) / 2));
2528:                     imagestring($this->gdimg_output, $this->config_error_fontsize, $leftoffset, $topoffset + ($rowcounter++ * imagefontheight($this->config_error_fontsize)), $textline, $nohotlink_text_color);
2529:                 }
2530: 
2531:             }
2532: 
2533:         }
2534:         return true;
2535:     }
2536: 
2537: 
2538:     function AlphaChannelFlatten() {
2539:         if (!$this->is_alpha) {
2540:             // image doesn't have alpha transparency, no need to flatten
2541:             $this->DebugMessage('skipping AlphaChannelFlatten() because !$this->is_alpha', __FILE__, __LINE__);
2542:             return false;
2543:         }
2544:         switch ($this->thumbnailFormat) {
2545:             case 'png':
2546:             case 'ico':
2547:                 // image has alpha transparency, but output as PNG or ICO which can handle it
2548:                 $this->DebugMessage('skipping AlphaChannelFlatten() because ($this->thumbnailFormat == "'.$this->thumbnailFormat.'")', __FILE__, __LINE__);
2549:                 return false;
2550:                 break;
2551: 
2552:             case 'gif':
2553:                 // image has alpha transparency, but output as GIF which can handle only single-color transparency
2554:                 $CurrentImageColorTransparent = imagecolortransparent($this->gdimg_output);
2555:                 if ($CurrentImageColorTransparent == -1) {
2556:                     // no transparent color defined
2557: 
2558:                     if (phpthumb_functions::gd_version() < 2.0) {
2559:                         $this->DebugMessage('AlphaChannelFlatten() failed because GD version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
2560:                         return false;
2561:                     }
2562: 
2563:                     if ($img_alpha_mixdown_dither = @imagecreatetruecolor(imagesx($this->gdimg_output), imagesy($this->gdimg_output))) {
2564: 
2565:                         $dither_color = array();
2566:                         for ($i = 0; $i <= 255; $i++) {
2567:                             $dither_color[$i] = imagecolorallocate($img_alpha_mixdown_dither, $i, $i, $i);
2568:                         }
2569: 
2570:                         // scan through current truecolor image copy alpha channel to temp image as grayscale
2571:                         for ($x = 0; $x < $this->thumbnail_width; $x++) {
2572:                             for ($y = 0; $y < $this->thumbnail_height; $y++) {
2573:                                 $PixelColor = phpthumb_functions::GetPixelColor($this->gdimg_output, $x, $y);
2574:                                 imagesetpixel($img_alpha_mixdown_dither, $x, $y, $dither_color[($PixelColor['alpha'] * 2)]);
2575:                             }
2576:                         }
2577: 
2578:                         // dither alpha channel grayscale version down to 2 colors
2579:                         imagetruecolortopalette($img_alpha_mixdown_dither, true, 2);
2580: 
2581:                         // reduce color palette to 256-1 colors (leave one palette position for transparent color)
2582:                         imagetruecolortopalette($this->gdimg_output, true, 255);
2583: 
2584:                         // allocate a new color for transparent color index
2585:                         $TransparentColor = imagecolorallocate($this->gdimg_output, 1, 254, 253);
2586:                         imagecolortransparent($this->gdimg_output, $TransparentColor);
2587: 
2588:                         // scan through alpha channel image and note pixels with >50% transparency
2589:                         for ($x = 0; $x < $this->thumbnail_width; $x++) {
2590:                             for ($y = 0; $y < $this->thumbnail_height; $y++) {
2591:                                 $AlphaChannelPixel = phpthumb_functions::GetPixelColor($img_alpha_mixdown_dither, $x, $y);
2592:                                 if ($AlphaChannelPixel['red'] > 127) {
2593:                                     imagesetpixel($this->gdimg_output, $x, $y, $TransparentColor);
2594:                                 }
2595:                             }
2596:                         }
2597:                         imagedestroy($img_alpha_mixdown_dither);
2598: 
2599:                         $this->DebugMessage('AlphaChannelFlatten() set image to 255+1 colors with transparency for GIF output', __FILE__, __LINE__);
2600:                         return true;
2601: 
2602:                     } else {
2603:                         $this->DebugMessage('AlphaChannelFlatten() failed imagecreate('.imagesx($this->gdimg_output).', '.imagesy($this->gdimg_output).')', __FILE__, __LINE__);
2604:                         return false;
2605:                     }
2606: 
2607:                 } else {
2608:                     // a single transparent color already defined, leave as-is
2609:                     $this->DebugMessage('skipping AlphaChannelFlatten() because ($this->thumbnailFormat == "'.$this->thumbnailFormat.'") and imagecolortransparent() returned "'.$CurrentImageColorTransparent.'"', __FILE__, __LINE__);
2610:                     return true;
2611:                 }
2612:                 break;
2613:         }
2614:         $this->DebugMessage('continuing AlphaChannelFlatten() for output format "'.$this->thumbnailFormat.'"', __FILE__, __LINE__);
2615:         // image has alpha transparency, and is being output in a format that doesn't support it -- flatten
2616:         if ($gdimg_flatten_temp = phpthumb_functions::ImageCreateFunction($this->thumbnail_width, $this->thumbnail_height)) {
2617: 
2618:             $this->config_background_hexcolor = ($this->bg ? $this->bg : $this->config_background_hexcolor);
2619:             if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) {
2620:                 return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"');
2621:             }
2622:             $background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_background_hexcolor);
2623:             imagefilledrectangle($gdimg_flatten_temp, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $background_color);
2624:             imagecopy($gdimg_flatten_temp, $this->gdimg_output, 0, 0, 0, 0, $this->thumbnail_width, $this->thumbnail_height);
2625: 
2626:             imagealphablending($this->gdimg_output, true);
2627:             imagesavealpha($this->gdimg_output, false);
2628:             imagecolortransparent($this->gdimg_output, -1);
2629:             imagecopy($this->gdimg_output, $gdimg_flatten_temp, 0, 0, 0, 0, $this->thumbnail_width, $this->thumbnail_height);
2630: 
2631:             imagedestroy($gdimg_flatten_temp);
2632:             return true;
2633: 
2634:         } else {
2635:             $this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__);
2636:         }
2637:         return false;
2638:     }
2639: 
2640: 
2641:     function ApplyFilters() {
2642:         if ($this->fltr && is_array($this->fltr)) {
2643:             if (!include_once(dirname(__FILE__).'/phpthumb.filters.php')) {
2644:                 $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.filters.php" which is required for applying filters ('.implode(';', $this->fltr).')', __FILE__, __LINE__);
2645:                 return false;
2646:             }
2647:             $phpthumbFilters = new phpthumb_filters();
2648:             $phpthumbFilters->phpThumbObject = &$this;
2649:             foreach ($this->fltr as $filtercommand) {
2650:                 @list($command, $parameter) = explode('|', $filtercommand, 2);
2651:                 $this->DebugMessage('Attempting to process filter command "'.$command.'('.$parameter.')"', __FILE__, __LINE__);
2652:                 switch ($command) {
2653:                     case 'brit': // Brightness
2654:                         $phpthumbFilters->Brightness($this->gdimg_output, $parameter);
2655:                         break;
2656: 
2657:                     case 'cont': // Contrast
2658:                         $phpthumbFilters->Contrast($this->gdimg_output, $parameter);
2659:                         break;
2660: 
2661:                     case 'ds': // Desaturation
2662:                         $phpthumbFilters->Desaturate($this->gdimg_output, $parameter, '');
2663:                         break;
2664: 
2665:                     case 'sat': // Saturation
2666:                         $phpthumbFilters->Saturation($this->gdimg_output, $parameter, '');
2667:                         break;
2668: 
2669:                     case 'gray': // Grayscale
2670:                         $phpthumbFilters->Grayscale($this->gdimg_output);
2671:                         break;
2672: 
2673:                     case 'clr': // Colorize
2674:                         if (phpthumb_functions::gd_version() < 2) {
2675:                             $this->DebugMessage('Skipping Colorize() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
2676:                             break;
2677:                         }
2678:                         @list($amount, $color) = explode('|', $parameter, 2);
2679:                         $phpthumbFilters->Colorize($this->gdimg_output, $amount, $color);
2680:                         break;
2681: 
2682:                     case 'sep': // Sepia
2683:                         if (phpthumb_functions::gd_version() < 2) {
2684:                             $this->DebugMessage('Skipping Sepia() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
2685:                             break;
2686:                         }
2687:                         @list($amount, $color) = explode('|', $parameter, 2);
2688:                         $phpthumbFilters->Sepia($this->gdimg_output, $amount, $color);
2689:                         break;
2690: 
2691:                     case 'gam': // Gamma correction
2692:                         $phpthumbFilters->Gamma($this->gdimg_output, $parameter);
2693:                         break;
2694: 
2695:                     case 'neg': // Negative colors
2696:                         $phpthumbFilters->Negative($this->gdimg_output);
2697:                         break;
2698: 
2699:                     case 'th': // Threshold
2700:                         $phpthumbFilters->Threshold($this->gdimg_output, $parameter);
2701:                         break;
2702: 
2703:                     case 'rcd': // ReduceColorDepth
2704:                         if (phpthumb_functions::gd_version() < 2) {
2705:                             $this->DebugMessage('Skipping ReduceColorDepth() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
2706:                             break;
2707:                         }
2708:                         @list($colors, $dither) = explode('|', $parameter, 2);
2709:                         $colors = ($colors                ?  (int) $colors : 256);
2710:                         $dither  = ((strlen($dither) > 0) ? (bool) $dither : true);
2711:                         $phpthumbFilters->ReduceColorDepth($this->gdimg_output, $colors, $dither);
2712:                         break;
2713: 
2714:                     case 'flip': // Flip
2715:                         $phpthumbFilters->Flip($this->gdimg_output, (strpos(strtolower($parameter), 'x') !== false), (strpos(strtolower($parameter), 'y') !== false));
2716:                         break;
2717: 
2718:                     case 'edge': // EdgeDetect
2719:                         $phpthumbFilters->EdgeDetect($this->gdimg_output);
2720:                         break;
2721: 
2722:                     case 'emb': // Emboss
2723:                         $phpthumbFilters->Emboss($this->gdimg_output);
2724:                         break;
2725: 
2726:                     case 'bvl': // Bevel
2727:                         @list($width, $color1, $color2) = explode('|', $parameter, 3);
2728:                         $phpthumbFilters->Bevel($this->gdimg_output, $width, $color1, $color2);
2729:                         break;
2730: 
2731:                     case 'lvl': // autoLevels
2732:                         @list($band, $method, $threshold) = explode('|', $parameter, 3);
2733:                         $band      = ($band ? preg_replace('#[^RGBA\\*]#', '', strtoupper($band)) : '*');
2734:                         $method    = ((strlen($method) > 0)    ? intval($method)                  :   2);
2735:                         $threshold = ((strlen($threshold) > 0) ? floatval($threshold)             : 0.1);
2736: 
2737:                         $phpthumbFilters->HistogramStretch($this->gdimg_output, $band, $method, $threshold);
2738:                         break;
2739: 
2740:                     case 'wb': // WhiteBalance
2741:                         $phpthumbFilters->WhiteBalance($this->gdimg_output, $parameter);
2742:                         break;
2743: 
2744:                     case 'hist': // Histogram overlay
2745:                         if (phpthumb_functions::gd_version() < 2) {
2746:                             $this->DebugMessage('Skipping HistogramOverlay() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
2747:                             break;
2748:                         }
2749:                         @list($bands, $colors, $width, $height, $alignment, $opacity, $margin_x, $margin_y) = explode('|', $parameter, 8);
2750:                         $bands     = ($bands     ? $bands     :  '*');
2751:                         $colors    = ($colors    ? $colors    :   '');
2752:                         $width     = ($width     ? $width     : 0.25);
2753:                         $height    = ($height    ? $height    : 0.25);
2754:                         $alignment = ($alignment ? $alignment : 'BR');
2755:                         $opacity   = ($opacity   ? $opacity   :   50);
2756:                         $margin_x  = ($margin_x  ? $margin_x  :    5);
2757:                         // $margin_y -- it wasn't forgotten, let the value always pass unchanged
2758:                         $phpthumbFilters->HistogramOverlay($this->gdimg_output, $bands, $colors, $width, $height, $alignment, $opacity, $margin_x, $margin_y);
2759:                         break;
2760: 
2761:                     case 'fram': // Frame
2762:                         @list($frame_width, $edge_width, $color_frame, $color1, $color2) = explode('|', $parameter, 5);
2763:                         $phpthumbFilters->Frame($this->gdimg_output, $frame_width, $edge_width, $color_frame, $color1, $color2);
2764:                         break;
2765: 
2766:                     case 'drop': // DropShadow
2767:                         if (phpthumb_functions::gd_version() < 2) {
2768:                             $this->DebugMessage('Skipping DropShadow() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
2769:                             return false;
2770:                         }
2771:                         $this->is_alpha = true;
2772:                         @list($distance, $width, $color, $angle, $fade) = explode('|', $parameter, 5);
2773:                         $phpthumbFilters->DropShadow($this->gdimg_output, $distance, $width, $color, $angle, $fade);
2774:                         break;
2775: 
2776:                     case 'mask': // Mask cropping
2777:                         if (phpthumb_functions::gd_version() < 2) {
2778:                             $this->DebugMessage('Skipping Mask() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
2779:                             return false;
2780:                         }
2781:                         @list($mask_filename, $invert) = explode('|', $parameter, 2);
2782:                         $mask_filename = $this->ResolveFilenameToAbsolute($mask_filename);
2783:                         if (@is_readable($mask_filename) && ($fp_mask = @fopen($mask_filename, 'rb'))) {
2784:                             $MaskImageData = '';
2785:                             do {
2786:                                 $buffer = fread($fp_mask, 8192);
2787:                                 $MaskImageData .= $buffer;
2788:                             } while (strlen($buffer) > 0);
2789:                             fclose($fp_mask);
2790:                             if ($gdimg_mask = $this->ImageCreateFromStringReplacement($MaskImageData)) {
2791:                                 if ($invert && phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) {
2792:                                     imagefilter($gdimg_mask, IMG_FILTER_NEGATE);
2793:                                 }
2794:                                 $this->is_alpha = true;
2795:                                 $phpthumbFilters->ApplyMask($gdimg_mask, $this->gdimg_output);
2796:                                 imagedestroy($gdimg_mask);
2797:                             } else {
2798:                                 $this->DebugMessage('ImageCreateFromStringReplacement() failed for "'.$mask_filename.'"', __FILE__, __LINE__);
2799:                             }
2800:                         } else {
2801:                             $this->DebugMessage('Cannot open mask file "'.$mask_filename.'"', __FILE__, __LINE__);
2802:                         }
2803:                         break;
2804: 
2805:                     case 'elip': // Ellipse cropping
2806:                         if (phpthumb_functions::gd_version() < 2) {
2807:                             $this->DebugMessage('Skipping Ellipse() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
2808:                             return false;
2809:                         }
2810:                         $this->is_alpha = true;
2811:                         $phpthumbFilters->Ellipse($this->gdimg_output);
2812:                         break;
2813: 
2814:                     case 'ric': // RoundedImageCorners
2815:                         if (phpthumb_functions::gd_version() < 2) {
2816:                             $this->DebugMessage('Skipping RoundedImageCorners() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
2817:                             return false;
2818:                         }
2819:                         @list($radius_x, $radius_y) = explode('|', $parameter, 2);
2820:                         if (($radius_x < 1) || ($radius_y < 1)) {
2821:                             $this->DebugMessage('Skipping RoundedImageCorners('.$radius_x.', '.$radius_y.') because x/y radius is less than 1', __FILE__, __LINE__);
2822:                             break;
2823:                         }
2824:                         $this->is_alpha = true;
2825:                         $phpthumbFilters->RoundedImageCorners($this->gdimg_output, $radius_x, $radius_y);
2826:                         break;
2827: 
2828:                     case 'crop': // Crop
2829:                         @list($left, $right, $top, $bottom) = explode('|', $parameter, 4);
2830:                         $phpthumbFilters->Crop($this->gdimg_output, $left, $right, $top, $bottom);
2831:                         break;
2832: 
2833:                     case 'bord': // Border
2834:                         @list($border_width, $radius_x, $radius_y, $hexcolor_border) = explode('|', $parameter, 4);
2835:                         $this->is_alpha = true;
2836:                         $phpthumbFilters->ImageBorder($this->gdimg_output, $border_width, $radius_x, $radius_y, $hexcolor_border);
2837:                         break;
2838: 
2839:                     case 'over': // Overlay
2840:                         @list($filename, $underlay, $margin, $opacity) = explode('|', $parameter, 4);
2841:                         $underlay = (bool) ($underlay              ? $underlay : false);
2842:                         $margin   =        ((strlen($margin)  > 0) ? $margin   : ($underlay ? 0.1 : 0.0));
2843:                         $opacity  =        ((strlen($opacity) > 0) ? $opacity  : 100);
2844:                         if (($margin > 0) && ($margin < 1)) {
2845:                             $margin = min(0.499, $margin);
2846:                         } elseif (($margin > -1) && ($margin < 0)) {
2847:                             $margin = max(-0.499, $margin);
2848:                         }
2849: 
2850:                         $filename = $this->ResolveFilenameToAbsolute($filename);
2851:                         if (@is_readable($filename) && ($fp_watermark = @fopen($filename, 'rb'))) {
2852:                             $WatermarkImageData = '';
2853:                             do {
2854:                                 $buffer = fread($fp_watermark, 8192);
2855:                                 $WatermarkImageData .= $buffer;
2856:                             } while (strlen($buffer) > 0);
2857:                             fclose($fp_watermark);
2858:                             if ($img_watermark = $this->ImageCreateFromStringReplacement($WatermarkImageData)) {
2859:                                 if (($margin > 0) && ($margin < 1)) {
2860:                                     $resized_x = max(1, imagesx($this->gdimg_output) - round(2 * (imagesx($this->gdimg_output) * $margin)));
2861:                                     $resized_y = max(1, imagesy($this->gdimg_output) - round(2 * (imagesy($this->gdimg_output) * $margin)));
2862:                                 } else {
2863:                                     $resized_x = max(1, imagesx($this->gdimg_output) - round(2 * $margin));
2864:                                     $resized_y = max(1, imagesy($this->gdimg_output) - round(2 * $margin));
2865:                                 }
2866: 
2867:                                 if ($underlay) {
2868: 
2869:                                     if ($img_watermark_resized = phpthumb_functions::ImageCreateFunction(imagesx($this->gdimg_output), imagesy($this->gdimg_output))) {
2870:                                         imagealphablending($img_watermark_resized, false);
2871:                                         imagesavealpha($img_watermark_resized, true);
2872:                                         $this->ImageResizeFunction($img_watermark_resized, $img_watermark, 0, 0, 0, 0, imagesx($img_watermark_resized), imagesy($img_watermark_resized), imagesx($img_watermark), imagesy($img_watermark));
2873:                                         if ($img_source_resized = phpthumb_functions::ImageCreateFunction($resized_x, $resized_y)) {
2874:                                             imagealphablending($img_source_resized, false);
2875:                                             imagesavealpha($img_source_resized, true);
2876:                                             $this->ImageResizeFunction($img_source_resized, $this->gdimg_output, 0, 0, 0, 0, imagesx($img_source_resized), imagesy($img_source_resized), imagesx($this->gdimg_output), imagesy($this->gdimg_output));
2877:                                             $phpthumbFilters->WatermarkOverlay($img_watermark_resized, $img_source_resized, 'C', $opacity, $margin);
2878:                                             imagecopy($this->gdimg_output, $img_watermark_resized, 0, 0, 0, 0, imagesx($this->gdimg_output), imagesy($this->gdimg_output));
2879:                                         } else {
2880:                                             $this->DebugMessage('phpthumb_functions::ImageCreateFunction('.$resized_x.', '.$resized_y.')', __FILE__, __LINE__);
2881:                                         }
2882:                                         imagedestroy($img_watermark_resized);
2883:                                     } else {
2884:                                         $this->DebugMessage('phpthumb_functions::ImageCreateFunction('.imagesx($this->gdimg_output).', '.imagesy($this->gdimg_output).')', __FILE__, __LINE__);
2885:                                     }
2886: 
2887:                                 } else { // overlay
2888: 
2889:                                     if ($img_watermark_resized = phpthumb_functions::ImageCreateFunction($resized_x, $resized_y)) {
2890:                                         imagealphablending($img_watermark_resized, false);
2891:                                         imagesavealpha($img_watermark_resized, true);
2892:                                         $this->ImageResizeFunction($img_watermark_resized, $img_watermark, 0, 0, 0, 0, imagesx($img_watermark_resized), imagesy($img_watermark_resized), imagesx($img_watermark), imagesy($img_watermark));
2893:                                         $phpthumbFilters->WatermarkOverlay($this->gdimg_output, $img_watermark_resized, 'C', $opacity, $margin);
2894:                                         imagedestroy($img_watermark_resized);
2895:                                     } else {
2896:                                         $this->DebugMessage('phpthumb_functions::ImageCreateFunction('.$resized_x.', '.$resized_y.')', __FILE__, __LINE__);
2897:                                     }
2898: 
2899:                                 }
2900:                                 imagedestroy($img_watermark);
2901: 
2902:                             } else {
2903:                                 $this->DebugMessage('ImageCreateFromStringReplacement() failed for "'.$filename.'"', __FILE__, __LINE__);
2904:                             }
2905:                         } else {
2906:                             $this->DebugMessage('Cannot open overlay file "'.$filename.'"', __FILE__, __LINE__);
2907:                         }
2908:                         break;
2909: 
2910:                     case 'wmi': // WaterMarkImage
2911:                         @list($filename, $alignment, $opacity, $margin['x'], $margin['y'], $rotate_angle) = explode('|', $parameter, 6);
2912:                         // $margin can be pixel margin or percent margin if $alignment is text, or max width/height if $alignment is position like "50x75"
2913:                         $alignment    = ($alignment            ? $alignment            : 'BR');
2914:                         $opacity      = (strlen($opacity)      ? intval($opacity)      : 50);
2915:                         $rotate_angle = (strlen($rotate_angle) ? intval($rotate_angle) : 0);
2916:                         if (!preg_match('#^([0-9\\.\\-]*)x([0-9\\.\\-]*)$#i', $alignment, $matches)) {
2917:                             $margins = array('x', 'y');
2918:                             foreach ($margins as $xy) {
2919:                                 $margin[$xy] = (strlen($margin[$xy]) ? $margin[$xy] : 5);
2920:                                 if (($margin[$xy] > 0) && ($margin[$xy] < 1)) {
2921:                                     $margin[$xy] = min(0.499, $margin[$xy]);
2922:                                 } elseif (($margin[$xy] > -1) && ($margin[$xy] < 0)) {
2923:                                     $margin[$xy] = max(-0.499, $margin[$xy]);
2924:                                 }
2925:                             }
2926:                         }
2927: 
2928:                         $filename = $this->ResolveFilenameToAbsolute($filename);
2929:                         if (@is_readable($filename)) {
2930:                             if ($img_watermark = $this->ImageCreateFromFilename($filename)) {
2931:                                 if ($rotate_angle !== 0) {
2932:                                     $phpthumbFilters->ImprovedImageRotate($img_watermark, $rotate_angle, 'FFFFFF', null, $this);
2933:                                 }
2934:                                 if (preg_match('#^([0-9\\.\\-]*)x([0-9\\.\\-]*)$#i', $alignment, $matches)) {
2935:                                     $watermark_max_width  = intval($margin['x'] ? $margin['x'] : imagesx($img_watermark));
2936:                                     $watermark_max_height = intval($margin['y'] ? $margin['y'] : imagesy($img_watermark));
2937:                                     $scale = phpthumb_functions::ScaleToFitInBox(imagesx($img_watermark), imagesy($img_watermark), $watermark_max_width, $watermark_max_height, true, true);
2938:                                     $this->DebugMessage('Scaling watermark by a factor of '.number_format($scale, 4), __FILE__, __LINE__);
2939:                                     if (($scale > 1) || ($scale < 1)) {
2940:                                         if ($img_watermark2 = phpthumb_functions::ImageCreateFunction($scale * imagesx($img_watermark), $scale * imagesy($img_watermark))) {
2941:                                             imagealphablending($img_watermark2, false);
2942:                                             imagesavealpha($img_watermark2, true);
2943:                                             $this->ImageResizeFunction($img_watermark2, $img_watermark, 0, 0, 0, 0, imagesx($img_watermark2), imagesy($img_watermark2), imagesx($img_watermark), imagesy($img_watermark));
2944:                                             $img_watermark = $img_watermark2;
2945:                                         } else {
2946:                                             $this->DebugMessage('ImageCreateFunction('.($scale * imagesx($img_watermark)).', '.($scale * imagesx($img_watermark)).') failed', __FILE__, __LINE__);
2947:                                         }
2948:                                     }
2949:                                     $watermark_dest_x = round($matches[1] - (imagesx($img_watermark) / 2));
2950:                                     $watermark_dest_y = round($matches[2] - (imagesy($img_watermark) / 2));
2951:                                     $alignment = $watermark_dest_x.'x'.$watermark_dest_y;
2952:                                 }
2953:                                 $phpthumbFilters->WatermarkOverlay($this->gdimg_output, $img_watermark, $alignment, $opacity, $margin['x'], $margin['y']);
2954:                                 imagedestroy($img_watermark);
2955:                                 if (isset($img_watermark2) && is_resource($img_watermark2)) {
2956:                                     imagedestroy($img_watermark2);
2957:                                 }
2958:                             } else {
2959:                                 $this->DebugMessage('ImageCreateFromFilename() failed for "'.$filename.'"', __FILE__, __LINE__);
2960:                             }
2961:                         } else {
2962:                             $this->DebugMessage('!is_readable('.$filename.')', __FILE__, __LINE__);
2963:                         }
2964:                         break;
2965: 
2966:                     case 'wmt': // WaterMarkText
2967:                         @list($text, $size, $alignment, $hex_color, $ttffont, $opacity, $margin, $angle, $bg_color, $bg_opacity, $fillextend) = explode('|', $parameter, 11);
2968:                         $text       = ($text            ? $text       : '');
2969:                         $size       = ($size            ? $size       : 3);
2970:                         $alignment  = ($alignment       ? $alignment  : 'BR');
2971:                         $hex_color  = ($hex_color       ? $hex_color  : '000000');
2972:                         $ttffont    = ($ttffont         ? $ttffont    : '');
2973:                         $opacity    = (strlen($opacity) ? $opacity    : 50);
2974:                         $margin     = (strlen($margin)  ? $margin     : 5);
2975:                         $angle      = (strlen($angle)   ? $angle      : 0);
2976:                         $bg_color   = ($bg_color        ? $bg_color   : false);
2977:                         $bg_opacity = ($bg_opacity      ? $bg_opacity : 0);
2978:                         $fillextend = ($fillextend      ? $fillextend : '');
2979: 
2980:                         if (basename($ttffont) == $ttffont) {
2981:                             $ttffont = $this->realPathSafe($this->config_ttf_directory.DIRECTORY_SEPARATOR.$ttffont);
2982:                         } else {
2983:                             $ttffont = $this->ResolveFilenameToAbsolute($ttffont);
2984:                         }
2985:                         $phpthumbFilters->WatermarkText($this->gdimg_output, $text, $size, $alignment, $hex_color, $ttffont, $opacity, $margin, $angle, $bg_color, $bg_opacity, $fillextend);
2986:                         break;
2987: 
2988:                     case 'blur': // Blur
2989:                         @list($radius) = explode('|', $parameter, 1);
2990:                         $radius = ($radius ? $radius : 1);
2991:                         if (phpthumb_functions::gd_version() >= 2) {
2992:                             $phpthumbFilters->Blur($this->gdimg_output, $radius);
2993:                         } else {
2994:                             $this->DebugMessage('Skipping Blur() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
2995:                         }
2996:                         break;
2997: 
2998:                     case 'gblr': // Gaussian Blur
2999:                         $phpthumbFilters->BlurGaussian($this->gdimg_output);
3000:                         break;
3001: 
3002:                     case 'sblr': // Selective Blur
3003:                         $phpthumbFilters->BlurSelective($this->gdimg_output);
3004:                         break;
3005: 
3006:                     case 'mean': // MeanRemoval blur
3007:                         $phpthumbFilters->MeanRemoval($this->gdimg_output);
3008:                         break;
3009: 
3010:                     case 'smth': // Smooth blur
3011:                         $phpthumbFilters->Smooth($this->gdimg_output, $parameter);
3012:                         break;
3013: 
3014:                     case 'usm': // UnSharpMask sharpening
3015:                         @list($amount, $radius, $threshold) = explode('|', $parameter, 3);
3016:                         $amount    = ($amount            ? $amount    : 80);
3017:                         $radius    = ($radius            ? $radius    : 0.5);
3018:                         $threshold = (strlen($threshold) ? $threshold : 3);
3019:                         if (phpthumb_functions::gd_version() >= 2.0) {
3020:                             ob_start();
3021:                             if (!@include_once(dirname(__FILE__).'/phpthumb.unsharp.php')) {
3022:                                 $include_error = ob_get_contents();
3023:                                 if ($include_error) {
3024:                                     $this->DebugMessage('include_once("'.dirname(__FILE__).'/phpthumb.unsharp.php") generated message: "'.$include_error.'"', __FILE__, __LINE__);
3025:                                 }
3026:                                 $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.unsharp.php" which is required for unsharp masking', __FILE__, __LINE__);
3027:                                 ob_end_clean();
3028:                                 return false;
3029:                             }
3030:                             ob_end_clean();
3031:                             phpUnsharpMask::applyUnsharpMask($this->gdimg_output, $amount, $radius, $threshold);
3032:                         } else {
3033:                             $this->DebugMessage('Skipping unsharp mask because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
3034:                             return false;
3035:                         }
3036:                         break;
3037: 
3038:                     case 'size': // Resize
3039:                         @list($newwidth, $newheight, $stretch) = explode('|', $parameter);
3040:                         $newwidth  = (!$newwidth  ? imagesx($this->gdimg_output) : ((($newwidth  > 0) && ($newwidth  < 1)) ? round($newwidth  * imagesx($this->gdimg_output)) : round($newwidth)));
3041:                         $newheight = (!$newheight ? imagesy($this->gdimg_output) : ((($newheight > 0) && ($newheight < 1)) ? round($newheight * imagesy($this->gdimg_output)) : round($newheight)));
3042:                         $stretch   = ($stretch ? true : false);
3043:                         if ($stretch) {
3044:                             $scale_x = phpthumb_functions::ScaleToFitInBox(imagesx($this->gdimg_output), imagesx($this->gdimg_output), $newwidth,  $newwidth,  true, true);
3045:                             $scale_y = phpthumb_functions::ScaleToFitInBox(imagesy($this->gdimg_output), imagesy($this->gdimg_output), $newheight, $newheight, true, true);
3046:                         } else {
3047:                             $scale_x = phpthumb_functions::ScaleToFitInBox(imagesx($this->gdimg_output), imagesy($this->gdimg_output), $newwidth, $newheight, true, true);
3048:                             $scale_y = $scale_x;
3049:                         }
3050:                         $this->DebugMessage('Scaling watermark ('.($stretch ? 'with' : 'without').' stretch) by a factor of "'.number_format($scale_x, 4).' x '.number_format($scale_y, 4).'"', __FILE__, __LINE__);
3051:                         if (($scale_x > 1) || ($scale_x < 1) || ($scale_y > 1) || ($scale_y < 1)) {
3052:                             if ($img_temp = phpthumb_functions::ImageCreateFunction(imagesx($this->gdimg_output), imagesy($this->gdimg_output))) {
3053:                                 imagecopy($img_temp, $this->gdimg_output, 0, 0, 0, 0, imagesx($this->gdimg_output), imagesy($this->gdimg_output));
3054:                                 if ($this->gdimg_output = phpthumb_functions::ImageCreateFunction($scale_x * imagesx($img_temp), $scale_y * imagesy($img_temp))) {
3055:                                     imagealphablending($this->gdimg_output, false);
3056:                                     imagesavealpha($this->gdimg_output, true);
3057:                                     $this->ImageResizeFunction($this->gdimg_output, $img_temp, 0, 0, 0, 0, imagesx($this->gdimg_output), imagesy($this->gdimg_output), imagesx($img_temp), imagesy($img_temp));
3058:                                 } else {
3059:                                     $this->DebugMessage('ImageCreateFunction('.($scale_x * imagesx($img_temp)).', '.($scale_y * imagesy($img_temp)).') failed', __FILE__, __LINE__);
3060:                                 }
3061:                                 imagedestroy($img_temp);
3062:                             } else {
3063:                                 $this->DebugMessage('ImageCreateFunction('.imagesx($this->gdimg_output).', '.imagesy($this->gdimg_output).') failed', __FILE__, __LINE__);
3064:                             }
3065:                         }
3066:                         break;
3067: 
3068:                     case 'rot': // ROTate
3069:                         @list($angle, $bgcolor) = explode('|', $parameter, 2);
3070:                         $phpthumbFilters->ImprovedImageRotate($this->gdimg_output, $angle, $bgcolor, null, $this);
3071:                         break;
3072: 
3073:                     case 'stc': // Source Transparent Color
3074:                         @list($hexcolor, $min_limit, $max_limit) = explode('|', $parameter, 3);
3075:                         if (!phpthumb_functions::IsHexColor($hexcolor)) {
3076:                             $this->DebugMessage('Skipping SourceTransparentColor hex color is invalid ('.$hexcolor.')', __FILE__, __LINE__);
3077:                             return false;
3078:                         }
3079:                         $min_limit = (strlen($min_limit) ? $min_limit :  5);
3080:                         $max_limit = (strlen($max_limit) ? $max_limit : 10);
3081:                         if ($gdimg_mask = $phpthumbFilters->SourceTransparentColorMask($this->gdimg_output, $hexcolor, $min_limit, $max_limit)) {
3082:                             $this->is_alpha = true;
3083:                             $phpthumbFilters->ApplyMask($gdimg_mask, $this->gdimg_output);
3084:                             imagedestroy($gdimg_mask);
3085:                         } else {
3086:                             $this->DebugMessage('SourceTransparentColorMask() failed for "'.$hexcolor.','.$min_limit.','.$max_limit.'"', __FILE__, __LINE__);
3087:                         }
3088:                         break;
3089:                 }
3090:                 $this->DebugMessage('Finished processing filter command "'.$command.'('.$parameter.')"', __FILE__, __LINE__);
3091:             }
3092:         }
3093:         return true;
3094:     }
3095: 
3096: 
3097:     function MaxFileSize() {
3098:         if (phpthumb_functions::gd_version() < 2) {
3099:             $this->DebugMessage('Skipping MaxFileSize() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
3100:             return false;
3101:         }
3102:         if ($this->maxb > 0) {
3103:             switch ($this->thumbnailFormat) {
3104:                 case 'png':
3105:                 case 'gif':
3106:                     $imgRenderFunction = 'image'.$this->thumbnailFormat;
3107: 
3108:                     ob_start();
3109:                     $imgRenderFunction($this->gdimg_output);
3110:                     $imgdata = ob_get_contents();
3111:                     ob_end_clean();
3112: 
3113:                     if (strlen($imgdata) > $this->maxb) {
3114:                         for ($i = 8; $i >= 1; $i--) {
3115:                             $tempIMG = imagecreatetruecolor(imagesx($this->gdimg_output), imagesy($this->gdimg_output));
3116:                             imagecopy($tempIMG, $this->gdimg_output, 0, 0, 0, 0, imagesx($this->gdimg_output), imagesy($this->gdimg_output));
3117:                             imagetruecolortopalette($tempIMG, true, pow(2, $i));
3118:                             ob_start();
3119:                             $imgRenderFunction($tempIMG);
3120:                             $imgdata = ob_get_contents();
3121:                             ob_end_clean();
3122: 
3123:                             if (strlen($imgdata) <= $this->maxb) {
3124:                                 imagetruecolortopalette($this->gdimg_output, true, pow(2, $i));
3125:                                 break;
3126:                             }
3127:                         }
3128:                     }
3129:                     break;
3130: 
3131:                 case 'jpeg':
3132:                     ob_start();
3133:                     imagejpeg($this->gdimg_output);
3134:                     $imgdata = ob_get_contents();
3135:                     ob_end_clean();
3136: 
3137:                     if (strlen($imgdata) > $this->maxb) {
3138:                         for ($i = 3; $i < 20; $i++) {
3139:                             $q = round(100 * (1 - log10($i / 2)));
3140:                             ob_start();
3141:                             imagejpeg($this->gdimg_output, null, $q);
3142:                             $imgdata = ob_get_contents();
3143:                             ob_end_clean();
3144: 
3145:                             $this->thumbnailQuality = $q;
3146:                             if (strlen($imgdata) <= $this->maxb) {
3147:                                 break;
3148:                             }
3149:                         }
3150:                     }
3151:                     if (strlen($imgdata) > $this->maxb) {
3152:                         return false;
3153:                     }
3154:                     break;
3155: 
3156:                 default:
3157:                     return false;
3158:             }
3159:         }
3160:         return true;
3161:     }
3162: 
3163: 
3164:     function CalculateThumbnailDimensions() {
3165:         $this->DebugMessage('CalculateThumbnailDimensions() starting with [W,H,sx,sy,sw,sh] initially set to ['.$this->source_width.','.$this->source_height.','.$this->sx.','.$this->sy.','.$this->sw.','.$this->sh.']', __FILE__, __LINE__);
3166: //echo $this->source_width.'x'.$this->source_height.'<hr>';
3167:         $this->thumbnailCropX = ($this->sx ? (($this->sx >= 2) ? $this->sx : round($this->sx * $this->source_width))  : 0);
3168: //echo $this->thumbnailCropX.'<br>';
3169:         $this->thumbnailCropY = ($this->sy ? (($this->sy >= 2) ? $this->sy : round($this->sy * $this->source_height)) : 0);
3170: //echo $this->thumbnailCropY.'<br>';
3171:         $this->thumbnailCropW = ($this->sw ? (($this->sw >= 2) ? $this->sw : round($this->sw * $this->source_width))  : $this->source_width);
3172: //echo $this->thumbnailCropW.'<br>';
3173:         $this->thumbnailCropH = ($this->sh ? (($this->sh >= 2) ? $this->sh : round($this->sh * $this->source_height)) : $this->source_height);
3174: //echo $this->thumbnailCropH.'<hr>';
3175: 
3176:         // limit source area to original image area
3177:         $this->thumbnailCropW = max(1, min($this->thumbnailCropW, $this->source_width  - $this->thumbnailCropX));
3178:         $this->thumbnailCropH = max(1, min($this->thumbnailCropH, $this->source_height - $this->thumbnailCropY));
3179: 
3180:         $this->DebugMessage('CalculateThumbnailDimensions() starting with [x,y,w,h] initially set to ['.$this->thumbnailCropX.','.$this->thumbnailCropY.','.$this->thumbnailCropW.','.$this->thumbnailCropH.']', __FILE__, __LINE__);
3181: 
3182: 
3183:         if ($this->zc && $this->w && $this->h) {
3184:             // Zoom Crop
3185:             // retain proportional resizing we did above, but crop off larger dimension so smaller
3186:             // dimension fully fits available space
3187: 
3188:             $scaling_X = $this->source_width  / $this->w;
3189:             $scaling_Y = $this->source_height / $this->h;
3190:             if ($scaling_X > $scaling_Y) {
3191:                 // some of the width will need to be cropped
3192:                 $allowable_width = $this->source_width / $scaling_X * $scaling_Y;
3193:                 $this->thumbnailCropW = round($allowable_width);
3194:                 $this->thumbnailCropX = round(($this->source_width - $allowable_width) / 2);
3195: 
3196:             } elseif ($scaling_Y > $scaling_X) {
3197:                 // some of the height will need to be cropped
3198:                 $allowable_height = $this->source_height / $scaling_Y * $scaling_X;
3199:                 $this->thumbnailCropH = round($allowable_height);
3200:                 $this->thumbnailCropY = round(($this->source_height - $allowable_height) / 2);
3201: 
3202:             } else {
3203:                 // image fits perfectly, no cropping needed
3204:             }
3205:             $this->thumbnail_width  = $this->w;
3206:             $this->thumbnail_height = $this->h;
3207:             $this->thumbnail_image_width  = $this->thumbnail_width;
3208:             $this->thumbnail_image_height = $this->thumbnail_height;
3209: 
3210:         } elseif ($this->iar && $this->w && $this->h) {
3211: 
3212:             // Ignore Aspect Ratio
3213:             // stretch image to fit exactly 'w' x 'h'
3214:             $this->thumbnail_width  = $this->w;
3215:             $this->thumbnail_height = $this->h;
3216:             $this->thumbnail_image_width  = $this->thumbnail_width;
3217:             $this->thumbnail_image_height = $this->thumbnail_height;
3218: 
3219:         } else {
3220: 
3221:             $original_aspect_ratio = $this->thumbnailCropW / $this->thumbnailCropH;
3222:             if ($this->aoe) {
3223:                 if ($this->w && $this->h) {
3224:                     $maxwidth  = min($this->w, $this->h * $original_aspect_ratio);
3225:                     $maxheight = min($this->h, $this->w / $original_aspect_ratio);
3226:                 } elseif ($this->w) {
3227:                     $maxwidth  = $this->w;
3228:                     $maxheight = $this->w / $original_aspect_ratio;
3229:                 } elseif ($this->h) {
3230:                     $maxwidth  = $this->h * $original_aspect_ratio;
3231:                     $maxheight = $this->h;
3232:                 } else {
3233:                     $maxwidth  = $this->thumbnailCropW;
3234:                     $maxheight = $this->thumbnailCropH;
3235:                 }
3236:             } else {
3237:                 $maxwidth  = phpthumb_functions::nonempty_min($this->w, $this->thumbnailCropW, $this->config_output_maxwidth);
3238:                 $maxheight = phpthumb_functions::nonempty_min($this->h, $this->thumbnailCropH, $this->config_output_maxheight);
3239: //echo $maxwidth.'x'.$maxheight.'<br>';
3240:                 $maxwidth  = min($maxwidth, $maxheight * $original_aspect_ratio);
3241:                 $maxheight = min($maxheight, $maxwidth / $original_aspect_ratio);
3242: //echo $maxwidth.'x'.$maxheight.'<hr>';
3243:             }
3244: 
3245:             $this->thumbnail_image_width  = $maxwidth;
3246:             $this->thumbnail_image_height = $maxheight;
3247:             $this->thumbnail_width  = $maxwidth;
3248:             $this->thumbnail_height = $maxheight;
3249: 
3250:             $this->FixedAspectRatio();
3251:         }
3252: 
3253:         $this->thumbnail_width  = max(1, floor($this->thumbnail_width));
3254:         $this->thumbnail_height = max(1, floor($this->thumbnail_height));
3255:         return true;
3256:     }
3257: 
3258: 
3259:     function CreateGDoutput() {
3260:         $this->CalculateThumbnailDimensions();
3261: 
3262:         // create the GD image (either true-color or 256-color, depending on GD version)
3263:         $this->gdimg_output = phpthumb_functions::ImageCreateFunction($this->thumbnail_width, $this->thumbnail_height);
3264: 
3265:         // images that have transparency must have the background filled with the configured 'bg' color otherwise the transparent color will appear as black
3266:         imagesavealpha($this->gdimg_output, true);
3267:         if ($this->is_alpha && phpthumb_functions::gd_version() >= 2) {
3268: 
3269:             imagealphablending($this->gdimg_output, false);
3270:             $output_full_alpha = phpthumb_functions::ImageColorAllocateAlphaSafe($this->gdimg_output, 255, 255, 255, 127);
3271:             imagefilledrectangle($this->gdimg_output, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $output_full_alpha);
3272: 
3273:         } else {
3274: 
3275:             $current_transparent_color = imagecolortransparent($this->gdimg_source);
3276:             if ($this->bg || (@$current_transparent_color >= 0)) {
3277: 
3278:                 $this->config_background_hexcolor = ($this->bg ? $this->bg : $this->config_background_hexcolor);
3279:                 if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) {
3280:                     return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"');
3281:                 }
3282:                 $background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_background_hexcolor);
3283:                 imagefilledrectangle($this->gdimg_output, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $background_color);
3284: 
3285:             }
3286: 
3287:         }
3288:         $this->DebugMessage('CreateGDoutput() returning canvas "'.$this->thumbnail_width.'x'.$this->thumbnail_height.'"', __FILE__, __LINE__);
3289:         return true;
3290:     }
3291: 
3292:     function SetOrientationDependantWidthHeight() {
3293:         $this->DebugMessage('SetOrientationDependantWidthHeight() starting with "'.$this->source_width.'"x"'.$this->source_height.'"', __FILE__, __LINE__);
3294:         if ($this->source_height > $this->source_width) {
3295:             // portrait
3296:             $this->w = phpthumb_functions::OneOfThese($this->wp, $this->w, $this->ws, $this->wl);
3297:             $this->h = phpthumb_functions::OneOfThese($this->hp, $this->h, $this->hs, $this->hl);
3298:         } elseif ($this->source_height < $this->source_width) {
3299:             // landscape
3300:             $this->w = phpthumb_functions::OneOfThese($this->wl, $this->w, $this->ws, $this->wp);
3301:             $this->h = phpthumb_functions::OneOfThese($this->hl, $this->h, $this->hs, $this->hp);
3302:         } else {
3303:             // square
3304:             $this->w = phpthumb_functions::OneOfThese($this->ws, $this->w, $this->wl, $this->wp);
3305:             $this->h = phpthumb_functions::OneOfThese($this->hs, $this->h, $this->hl, $this->hp);
3306:         }
3307:         //$this->w = round($this->w ? $this->w : (($this->h && $this->source_height) ? $this->h * $this->source_width  / $this->source_height : $this->w));
3308:         //$this->h = round($this->h ? $this->h : (($this->w && $this->source_width)  ? $this->w * $this->source_height / $this->source_width  : $this->h));
3309:         $this->DebugMessage('SetOrientationDependantWidthHeight() setting w="'.intval($this->w).'", h="'.intval($this->h).'"', __FILE__, __LINE__);
3310:         return true;
3311:     }
3312: 
3313:     function ExtractEXIFgetImageSize() {
3314:         $this->DebugMessage('starting ExtractEXIFgetImageSize()', __FILE__, __LINE__);
3315: 
3316:         if (preg_match('#^http:#i', $this->src) && !$this->sourceFilename && $this->rawImageData) {
3317:             $this->SourceDataToTempFile();
3318:         }
3319:         if (is_null($this->getimagesizeinfo)) {
3320:             if ($this->sourceFilename) {
3321:                 $this->getimagesizeinfo = @getimagesize($this->sourceFilename);
3322:                 $this->source_width  = $this->getimagesizeinfo[0];
3323:                 $this->source_height = $this->getimagesizeinfo[1];
3324:                 $this->DebugMessage('getimagesize('.$this->sourceFilename.') says image is '.$this->source_width.'x'.$this->source_height, __FILE__, __LINE__);
3325:             } else {
3326:                 $this->DebugMessage('skipping getimagesize() because $this->sourceFilename is empty', __FILE__, __LINE__);
3327:             }
3328:         } else {
3329:             $this->DebugMessage('skipping getimagesize() because !is_null($this->getimagesizeinfo)', __FILE__, __LINE__);
3330:         }
3331: 
3332:         if (is_resource($this->gdimg_source)) {
3333: 
3334:             $this->source_width  = imagesx($this->gdimg_source);
3335:             $this->source_height = imagesy($this->gdimg_source);
3336: 
3337:             $this->SetOrientationDependantWidthHeight();
3338: 
3339:         } elseif ($this->rawImageData && !$this->sourceFilename) {
3340: 
3341:             if ($this->SourceImageIsTooLarge($this->source_width, $this->source_height)) {
3342:                 $this->DebugMessage('NOT bypassing EXIF and getimagesize sections because source image is too large for GD ('.$this->source_width.'x'.$this->source_width.'='.($this->source_width * $this->source_height * 5).'MB)', __FILE__, __LINE__);
3343:             } else {
3344:                 $this->DebugMessage('bypassing EXIF and getimagesize sections because $this->rawImageData is set, and $this->sourceFilename is not set, and source image is not too large for GD ('.$this->source_width.'x'.$this->source_width.'='.($this->source_width * $this->source_height * 5).'MB)', __FILE__, __LINE__);
3345:             }
3346: 
3347:         }
3348: 
3349:         if (is_null($this->getimagesizeinfo)) {
3350:             $this->getimagesizeinfo = @getimagesize($this->sourceFilename);
3351:         }
3352: 
3353:         if (!empty($this->getimagesizeinfo)) {
3354:             // great
3355:             $this->getimagesizeinfo['filesize'] = @filesize($this->sourceFilename);
3356:         } elseif (!$this->rawImageData) {
3357:             $this->DebugMessage('getimagesize("'.$this->sourceFilename.'") failed', __FILE__, __LINE__);
3358:         }
3359: 
3360:         if ($this->config_prefer_imagemagick) {
3361:             if ($this->ImageMagickThumbnailToGD()) {
3362:                 return true;
3363:             }
3364:             $this->DebugMessage('ImageMagickThumbnailToGD() failed', __FILE__, __LINE__);
3365:         }
3366: 
3367:         $this->source_width  = $this->getimagesizeinfo[0];
3368:         $this->source_height = $this->getimagesizeinfo[1];
3369: 
3370:         $this->SetOrientationDependantWidthHeight();
3371: 
3372:         if (phpthumb_functions::version_compare_replacement(phpversion(), '4.2.0', '>=') && function_exists('exif_read_data')) {
3373:             switch ($this->getimagesizeinfo[2]) {
3374:                 case IMAGETYPE_JPEG:
3375:                 case IMAGETYPE_TIFF_II:
3376:                 case IMAGETYPE_TIFF_MM:
3377:                     $this->exif_raw_data = @exif_read_data($this->sourceFilename, 0, true);
3378:                     break;
3379:             }
3380:         }
3381:         if (function_exists('exif_thumbnail') && ($this->getimagesizeinfo[2] == IMAGETYPE_JPEG)) {
3382:             // Extract EXIF info from JPEGs
3383: 
3384:             $this->exif_thumbnail_width  = '';
3385:             $this->exif_thumbnail_height = '';
3386:             $this->exif_thumbnail_type   = '';
3387: 
3388:             // The parameters width, height and imagetype are available since PHP v4.3.0
3389:             if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=')) {
3390: 
3391:                 $this->exif_thumbnail_data = @exif_thumbnail($this->sourceFilename, $this->exif_thumbnail_width, $this->exif_thumbnail_height, $this->exif_thumbnail_type);
3392: 
3393:             } else {
3394: 
3395:                 // older versions of exif_thumbnail output an error message but NOT return false on failure
3396:                 ob_start();
3397:                 $this->exif_thumbnail_data = exif_thumbnail($this->sourceFilename);
3398:                 $exit_thumbnail_error = ob_get_contents();
3399:                 ob_end_clean();
3400:                 if (!$exit_thumbnail_error && $this->exif_thumbnail_data) {
3401: 
3402:                     if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) {
3403:                         $this->exif_thumbnail_width  = imagesx($gdimg_exif_temp);
3404:                         $this->exif_thumbnail_height = imagesy($gdimg_exif_temp);
3405:                         $this->exif_thumbnail_type   = 2; // (2 == JPEG) before PHP v4.3.0 only JPEG format EXIF thumbnails are returned
3406:                         unset($gdimg_exif_temp);
3407:                     } else {
3408:                         return $this->ErrorImage('Failed - $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data) in '.__FILE__.' on line '.__LINE__);
3409:                     }
3410: 
3411:                 }
3412: 
3413:             }
3414: 
3415:         } elseif (!function_exists('exif_thumbnail')) {
3416: 
3417:             $this->DebugMessage('exif_thumbnail() does not exist, cannot extract EXIF thumbnail', __FILE__, __LINE__);
3418: 
3419:         }
3420: 
3421:         $this->DebugMessage('EXIF thumbnail extraction: (size='.strlen($this->exif_thumbnail_data).'; type="'.$this->exif_thumbnail_type.'"; '.intval($this->exif_thumbnail_width).'x'.intval($this->exif_thumbnail_height).')', __FILE__, __LINE__);
3422: 
3423:         // see if EXIF thumbnail can be used directly with no processing
3424:         if ($this->config_use_exif_thumbnail_for_speed && $this->exif_thumbnail_data) {
3425:             while (true) {
3426:                 if (!$this->xto) {
3427:                     $source_ar = $this->source_width / $this->source_height;
3428:                     $exif_ar = $this->exif_thumbnail_width / $this->exif_thumbnail_height;
3429:                     if (number_format($source_ar, 2) != number_format($exif_ar, 2)) {
3430:                         $this->DebugMessage('not using EXIF thumbnail because $source_ar != $exif_ar ('.$source_ar.' != '.$exif_ar.')', __FILE__, __LINE__);
3431:                         break;
3432:                     }
3433:                     if ($this->w && ($this->w != $this->exif_thumbnail_width)) {
3434:                         $this->DebugMessage('not using EXIF thumbnail because $this->w != $this->exif_thumbnail_width ('.$this->w.' != '.$this->exif_thumbnail_width.')', __FILE__, __LINE__);
3435:                         break;
3436:                     }
3437:                     if ($this->h && ($this->h != $this->exif_thumbnail_height)) {
3438:                         $this->DebugMessage('not using EXIF thumbnail because $this->h != $this->exif_thumbnail_height ('.$this->h.' != '.$this->exif_thumbnail_height.')', __FILE__, __LINE__);
3439:                         break;
3440:                     }
3441:                     $CannotBeSetParameters = array('sx', 'sy', 'sh', 'sw', 'far', 'bg', 'bc', 'fltr', 'phpThumbDebug');
3442:                     foreach ($CannotBeSetParameters as $parameter) {
3443:                         if ($this->$parameter) {
3444:                             break 2;
3445:                         }
3446:                     }
3447:                 }
3448: 
3449:                 $this->DebugMessage('setting $this->gdimg_source = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data)', __FILE__, __LINE__);
3450:                 $this->gdimg_source = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data);
3451:                 $this->source_width  = imagesx($this->gdimg_source);
3452:                 $this->source_height = imagesy($this->gdimg_source);
3453:                 return true;
3454:             }
3455:         }
3456: 
3457:         if (($this->config_max_source_pixels > 0) && (($this->source_width * $this->source_height) > $this->config_max_source_pixels)) {
3458: 
3459:             // Source image is larger than would fit in available PHP memory.
3460:             // If ImageMagick is installed, use it to generate the thumbnail.
3461:             // Else, if an EXIF thumbnail is available, use that as the source image.
3462:             // Otherwise, no choice but to fail with an error message
3463:             $this->DebugMessage('image is '.$this->source_width.'x'.$this->source_height.' and therefore contains more pixels ('.($this->source_width * $this->source_height).') than $this->config_max_source_pixels setting ('.$this->config_max_source_pixels.')', __FILE__, __LINE__);
3464:             if (!$this->config_prefer_imagemagick && $this->ImageMagickThumbnailToGD()) {
3465:                 // excellent, we have a thumbnailed source image
3466:                 return true;
3467:             }
3468: 
3469:         }
3470:         return true;
3471:     }
3472: 
3473: 
3474:     function SetCacheFilename() {
3475:         if (!is_null($this->cache_filename)) {
3476:             $this->DebugMessage('$this->cache_filename already set, skipping SetCacheFilename()', __FILE__, __LINE__);
3477:             return true;
3478:         }
3479:         if (is_null($this->config_cache_directory)) {
3480:             $this->setCacheDirectory();
3481:             if (!$this->config_cache_directory) {
3482:                 $this->DebugMessage('SetCacheFilename() failed because $this->config_cache_directory is empty', __FILE__, __LINE__);
3483:                 return false;
3484:             }
3485:         }
3486:         $this->setOutputFormat();
3487: 
3488:         if (!$this->sourceFilename && !$this->rawImageData && $this->src) {
3489:             $this->sourceFilename = $this->ResolveFilenameToAbsolute($this->src);
3490:         }
3491: 
3492:         if ($this->config_cache_default_only_suffix && $this->sourceFilename) {
3493:             // simplified cache filenames:
3494:             // only use default parameters in phpThumb.config.php
3495:             // substitute source filename into * in $this->config_cache_default_only_suffix
3496:             // (eg: '*_thumb' becomes 'picture_thumb.jpg')
3497:             if (strpos($this->config_cache_default_only_suffix, '*') === false) {
3498:                 $this->DebugMessage('aborting simplified caching filename because no * in "'.$this->config_cache_default_only_suffix.'"', __FILE__, __LINE__);
3499:             } else {
3500:                 preg_match('#(.+)(\\.[a-z0-9]+)?$#i', basename($this->sourceFilename), $matches);
3501:                 $this->cache_filename = $this->config_cache_directory.DIRECTORY_SEPARATOR.rawurlencode(str_replace('*', @$matches[1], $this->config_cache_default_only_suffix)).'.'.strtolower($this->thumbnailFormat);
3502:                 return true;
3503:             }
3504:         }
3505: 
3506:         $this->cache_filename = '';
3507:         if ($this->new) {
3508:             $broad_directory_name = strtolower(md5($this->new));
3509:             $this->cache_filename .= '_new'.$broad_directory_name;
3510:         } elseif ($this->md5s) {
3511:             // source image MD5 hash provided
3512:             $this->DebugMessage('SetCacheFilename() _raw set from $this->md5s = "'.$this->md5s.'"', __FILE__, __LINE__);
3513:             $broad_directory_name = $this->md5s;
3514:             $this->cache_filename .= '_raw'.$this->md5s;
3515:         } elseif (!$this->src && $this->rawImageData) {
3516:             $this->DebugMessage('SetCacheFilename() _raw set from md5($this->rawImageData) = "'.md5($this->rawImageData).'"', __FILE__, __LINE__);
3517:             $broad_directory_name = strtolower(md5($this->rawImageData));
3518:             $this->cache_filename .= '_raw'.$broad_directory_name;
3519:         } else {
3520:             $this->DebugMessage('SetCacheFilename() _src set from md5($this->sourceFilename) "'.$this->sourceFilename.'" = "'.md5($this->sourceFilename).'"', __FILE__, __LINE__);
3521:             $broad_directory_name = strtolower(md5($this->sourceFilename));
3522:             $this->cache_filename .= '_src'.$broad_directory_name;
3523:         }
3524:         if (!empty($_SERVER['HTTP_REFERER']) && $this->config_nooffsitelink_enabled) {
3525:             $parsed_url1 = @phpthumb_functions::ParseURLbetter(@$_SERVER['HTTP_REFERER']);
3526:             $parsed_url2 = @phpthumb_functions::ParseURLbetter('http://'.@$_SERVER['HTTP_HOST']);
3527:             if (@$parsed_url1['host'] && @$parsed_url2['host'] && ($parsed_url1['host'] != $parsed_url2['host'])) {
3528:                 // include "_offsite" only if nooffsitelink_enabled and if referrer doesn't match the domain of the current server
3529:                 $this->cache_filename .= '_offsite';
3530:             }
3531:         }
3532: 
3533:         $ParametersString = '';
3534:         if ($this->fltr && is_array($this->fltr)) {
3535:             $ParametersString .= '_fltr'.implode('_fltr', $this->fltr);
3536:         }
3537:         $FilenameParameters1 = array('ar', 'bg', 'bc', 'far', 'sx', 'sy', 'sw', 'sh', 'zc');
3538:         foreach ($FilenameParameters1 as $key) {
3539:             if ($this->$key) {
3540:                 $ParametersString .= '_'.$key.$this->$key;
3541:             }
3542:         }
3543:         $FilenameParameters2 = array('h', 'w', 'wl', 'wp', 'ws', 'hp', 'hs', 'xto', 'ra', 'iar', 'aoe', 'maxb', 'sfn', 'dpi');
3544:         foreach ($FilenameParameters2 as $key) {
3545:             if ($this->$key) {
3546:                 $ParametersString .= '_'.$key.intval($this->$key);
3547:             }
3548:         }
3549:         if ($this->thumbnailFormat == 'jpeg') {
3550:             // only JPEG output has variable quality option
3551:             $ParametersString .= '_q'.intval($this->thumbnailQuality);
3552:         }
3553:         $this->DebugMessage('SetCacheFilename() _par set from md5('.$ParametersString.')', __FILE__, __LINE__);
3554:         $this->cache_filename .= '_par'.strtolower(md5($ParametersString));
3555: 
3556:         if ($this->md5s) {
3557:             // source image MD5 hash provided
3558:             // do not source image modification date --
3559:             // cached image will be used even if file was modified or removed
3560:         } elseif (!$this->config_cache_source_filemtime_ignore_remote && preg_match('#^(f|ht)tps?\://#i', $this->src)) {
3561:             $this->cache_filename .= '_dat'.intval(phpthumb_functions::filedate_remote($this->src));
3562:         } elseif (!$this->config_cache_source_filemtime_ignore_local && $this->src && !$this->rawImageData) {
3563:             $this->cache_filename .= '_dat'.intval(@filemtime($this->sourceFilename));
3564:         }
3565: 
3566:         $this->cache_filename .= '.'.strtolower($this->thumbnailFormat);
3567:         $broad_directories = '';
3568:         for ($i = 0; $i < $this->config_cache_directory_depth; $i++) {
3569:             $broad_directories .= DIRECTORY_SEPARATOR.substr($broad_directory_name, 0, $i + 1);
3570:         }
3571: 
3572:         $this->cache_filename = $this->config_cache_directory.$broad_directories.DIRECTORY_SEPARATOR.$this->config_cache_prefix.rawurlencode($this->cache_filename);
3573:         return true;
3574:     }
3575: 
3576: 
3577:     function SourceImageIsTooLarge($width, $height) {
3578:         if (!$this->config_max_source_pixels) {
3579:             return false;
3580:         }
3581:         if ($this->php_memory_limit && function_exists('memory_get_usage')) {
3582:             $available_memory = $this->php_memory_limit - memory_get_usage();
3583:             return (bool) (($width * $height * 5) > $available_memory);
3584:         }
3585:         return (bool) (($width * $height) > $this->config_max_source_pixels);
3586:     }
3587: 
3588:     function ImageCreateFromFilename($filename) {
3589:         // try to create GD image source directly via GD, if possible,
3590:         // rather than buffering to memory and creating with imagecreatefromstring
3591:         $ImageCreateWasAttempted = false;
3592:         $gd_image = false;
3593: 
3594:         $this->DebugMessage('starting ImageCreateFromFilename('.$filename.')', __FILE__, __LINE__);
3595:         if ($filename && ($getimagesizeinfo = @getimagesize($filename))) {
3596:             if (!$this->SourceImageIsTooLarge($getimagesizeinfo[0], $getimagesizeinfo[1])) {
3597:                 $ImageCreateFromFunction = array(
3598:                     1  => 'imagecreatefromgif',
3599:                     2  => 'imagecreatefromjpeg',
3600:                     3  => 'imagecreatefrompng',
3601:                     15 => 'imagecreatefromwbmp',
3602:                 );
3603:                 $this->DebugMessage('ImageCreateFromFilename found ($getimagesizeinfo[2]=='.@$getimagesizeinfo[2].')', __FILE__, __LINE__);
3604:                 switch (@$getimagesizeinfo[2]) {
3605:                     case 1:  // GIF
3606:                     case 2:  // JPEG
3607:                     case 3:  // PNG
3608:                     case 15: // WBMP
3609:                         $ImageCreateFromFunctionName = $ImageCreateFromFunction[$getimagesizeinfo[2]];
3610:                         if (function_exists($ImageCreateFromFunctionName)) {
3611:                             $this->DebugMessage('Calling '.$ImageCreateFromFunctionName.'('.$filename.')', __FILE__, __LINE__);
3612:                             $ImageCreateWasAttempted = true;
3613:                             $gd_image = $ImageCreateFromFunctionName($filename);
3614:                         } else {
3615:                             $this->DebugMessage('NOT calling '.$ImageCreateFromFunctionName.'('.$filename.') because !function_exists('.$ImageCreateFromFunctionName.')', __FILE__, __LINE__);
3616:                         }
3617:                         break;
3618: 
3619:                     case 4:  // SWF
3620:                     case 5:  // PSD
3621:                     case 6:  // BMP
3622:                     case 7:  // TIFF (LE)
3623:                     case 8:  // TIFF (BE)
3624:                     case 9:  // JPC
3625:                     case 10: // JP2
3626:                     case 11: // JPX
3627:                     case 12: // JB2
3628:                     case 13: // SWC
3629:                     case 14: // IFF
3630:                     case 16: // XBM
3631:                         $this->DebugMessage('No built-in image creation function for image type "'.@$getimagesizeinfo[2].'" ($getimagesizeinfo[2])', __FILE__, __LINE__);
3632:                         break;
3633: 
3634:                     default:
3635:                         $this->DebugMessage('Unknown value for $getimagesizeinfo[2]: "'.@$getimagesizeinfo[2].'"', __FILE__, __LINE__);
3636:                         break;
3637:                 }
3638:             } else {
3639:                 $this->DebugMessage('image is '.$getimagesizeinfo[0].'x'.$getimagesizeinfo[1].' and therefore contains more pixels ('.($getimagesizeinfo[0] * $getimagesizeinfo[1]).') than $this->config_max_source_pixels setting ('.$this->config_max_source_pixels.')', __FILE__, __LINE__);
3640:                 return false;
3641:             }
3642:         } else {
3643:             $this->DebugMessage('empty $filename or getimagesize('.$filename.') failed', __FILE__, __LINE__);
3644:         }
3645: 
3646:         if (!$gd_image) {
3647:             // cannot create from filename, attempt to create source image with imagecreatefromstring, if possible
3648:             if ($ImageCreateWasAttempted) {
3649:                 $this->DebugMessage($ImageCreateFromFunctionName.'() was attempted but FAILED', __FILE__, __LINE__);
3650:             }
3651:             $this->DebugMessage('Populating $rawimagedata', __FILE__, __LINE__);
3652:             $rawimagedata = '';
3653:             if ($fp = @fopen($filename, 'rb')) {
3654:                 $filesize = filesize($filename);
3655:                 $blocksize = 8192;
3656:                 $blockreads = ceil($filesize / $blocksize);
3657:                 for ($i = 0; $i < $blockreads; $i++) {
3658:                     $rawimagedata .= fread($fp, $blocksize);
3659:                 }
3660:                 fclose($fp);
3661:             } else {
3662:                 $this->DebugMessage('cannot fopen('.$filename.')', __FILE__, __LINE__);
3663:             }
3664:             if ($rawimagedata) {
3665:                 $this->DebugMessage('attempting ImageCreateFromStringReplacement($rawimagedata ('.strlen($rawimagedata).' bytes), true)', __FILE__, __LINE__);
3666:                 $gd_image = $this->ImageCreateFromStringReplacement($rawimagedata, true);
3667:             }
3668:         }
3669:         return $gd_image;
3670:     }
3671: 
3672:     function SourceImageToGD() {
3673:         if (is_resource($this->gdimg_source)) {
3674:             $this->source_width  = imagesx($this->gdimg_source);
3675:             $this->source_height = imagesy($this->gdimg_source);
3676:             $this->DebugMessage('skipping SourceImageToGD() because $this->gdimg_source is already a resource ('.$this->source_width.'x'.$this->source_height.')', __FILE__, __LINE__);
3677:             return true;
3678:         }
3679:         $this->DebugMessage('starting SourceImageToGD()', __FILE__, __LINE__);
3680: 
3681:         if ($this->config_prefer_imagemagick) {
3682:             if (empty($this->sourceFilename) && !empty($this->rawImageData)) {
3683:                 $this->DebugMessage('Copying raw image data to temp file and trying again with ImageMagick', __FILE__, __LINE__);
3684:                 if ($tempnam = $this->phpThumb_tempnam()) {
3685:                     if (file_put_contents($tempnam, $this->rawImageData)) {
3686:                         $this->sourceFilename = $tempnam;
3687:                         if ($this->ImageMagickThumbnailToGD()) {
3688:                             // excellent, we have a thumbnailed source image
3689:                             $this->DebugMessage('ImageMagickThumbnailToGD() succeeded', __FILE__, __LINE__);
3690:                         } else {
3691:                             $this->DebugMessage('ImageMagickThumbnailToGD() failed', __FILE__, __LINE__);
3692:                         }
3693:                         @chmod($tempnam, $this->getParameter('config_file_create_mask'));
3694:                     } else {
3695:                         $this->DebugMessage('failed to put $this->rawImageData into temp file "'.$tempnam.'"', __FILE__, __LINE__);
3696:                     }
3697:                 } else {
3698:                     $this->DebugMessage('failed to generate temp file name', __FILE__, __LINE__);
3699:                 }
3700:             }
3701:         }
3702:         if (!$this->gdimg_source && $this->rawImageData) {
3703: 
3704:             if ($this->SourceImageIsTooLarge($this->source_width, $this->source_height)) {
3705:                 $memory_get_usage = (function_exists('memory_get_usage') ? memory_get_usage() : 0);
3706:                 return $this->ErrorImage('Source image is too large ('.$this->source_width.'x'.$this->source_height.' = '.number_format($this->source_width * $this->source_height / 1000000, 1).'Mpx, max='.number_format($this->config_max_source_pixels / 1000000, 1).'Mpx) for GD creation (either install ImageMagick or increase PHP memory_limit to at least '.ceil(($memory_get_usage + (5 * $this->source_width * $this->source_height)) / 1048576).'M).');
3707:             }
3708:             if ($this->md5s && ($this->md5s != md5($this->rawImageData))) {
3709:                 return $this->ErrorImage('$this->md5s != md5($this->rawImageData)'."\n".'"'.$this->md5s.'" != '."\n".'"'.md5($this->rawImageData).'"');
3710:             }
3711:             //if ($this->issafemode) {
3712:             //  return $this->ErrorImage('Cannot generate thumbnails from raw image data when PHP SAFE_MODE enabled');
3713:             //}
3714:             $this->gdimg_source = $this->ImageCreateFromStringReplacement($this->rawImageData);
3715:             if (!$this->gdimg_source) {
3716:                 if (substr($this->rawImageData, 0, 2) === 'BM') {
3717:                     $this->getimagesizeinfo[2] = 6; // BMP
3718:                 } elseif (substr($this->rawImageData, 0, 4) === 'II'."\x2A\x00") {
3719:                     $this->getimagesizeinfo[2] = 7; // TIFF (littlendian)
3720:                 } elseif (substr($this->rawImageData, 0, 4) === 'MM'."\x00\x2A") {
3721:                     $this->getimagesizeinfo[2] = 8; // TIFF (bigendian)
3722:                 }
3723:                 $this->DebugMessage('SourceImageToGD.ImageCreateFromStringReplacement() failed with unknown image type "'.substr($this->rawImageData, 0, 4).'" ('.phpthumb_functions::HexCharDisplay(substr($this->rawImageData, 0, 4)).')', __FILE__, __LINE__);
3724: //              return $this->ErrorImage('Unknown image type identified by "'.substr($this->rawImageData, 0, 4).'" ('.phpthumb_functions::HexCharDisplay(substr($this->rawImageData, 0, 4)).') in SourceImageToGD()['.__LINE__.']');
3725:             }
3726: 
3727:         } elseif (!$this->gdimg_source && $this->sourceFilename) {
3728: 
3729:             if ($this->md5s && ($this->md5s != phpthumb_functions::md5_file_safe($this->sourceFilename))) {
3730:                 return $this->ErrorImage('$this->md5s != md5(sourceFilename)'."\n".'"'.$this->md5s.'" != '."\n".'"'.phpthumb_functions::md5_file_safe($this->sourceFilename).'"');
3731:             }
3732:             switch (@$this->getimagesizeinfo[2]) {
3733:                 case 1:
3734:                 case 3:
3735:                     // GIF or PNG input file may have transparency
3736:                     $this->is_alpha = true;
3737:                     break;
3738:             }
3739:             if (!$this->SourceImageIsTooLarge($this->source_width, $this->source_height)) {
3740:                 $this->gdimg_source = $this->ImageCreateFromFilename($this->sourceFilename);
3741:             }
3742: 
3743:         }
3744: 
3745:         while (true) {
3746:             if ($this->gdimg_source) {
3747:                 $this->DebugMessage('Not using EXIF thumbnail data because $this->gdimg_source is already set', __FILE__, __LINE__);
3748:                 break;
3749:             }
3750:             if (!$this->exif_thumbnail_data) {
3751:                 $this->DebugMessage('Not using EXIF thumbnail data because $this->exif_thumbnail_data is empty', __FILE__, __LINE__);
3752:                 break;
3753:             }
3754:             if (ini_get('safe_mode')) {
3755:                 if (!$this->SourceImageIsTooLarge($this->source_width, $this->source_height)) {
3756:                     $this->DebugMessage('Using EXIF thumbnail data because source image too large and safe_mode enabled', __FILE__, __LINE__);
3757:                     $this->aoe = true;
3758:                 } else {
3759:                     break;
3760:                 }
3761:             } else {
3762:                 if (!$this->config_use_exif_thumbnail_for_speed) {
3763:                     $this->DebugMessage('Not using EXIF thumbnail data because $this->config_use_exif_thumbnail_for_speed is FALSE', __FILE__, __LINE__);
3764:                     break;
3765:                 }
3766:                 if (($this->thumbnailCropX != 0) || ($this->thumbnailCropY != 0)) {
3767:                     $this->DebugMessage('Not using EXIF thumbnail data because source cropping is enabled ('.$this->thumbnailCropX.','.$this->thumbnailCropY.')', __FILE__, __LINE__);
3768:                     break;
3769:                 }
3770:                 if (($this->w > $this->exif_thumbnail_width) || ($this->h > $this->exif_thumbnail_height)) {
3771:                     $this->DebugMessage('Not using EXIF thumbnail data because EXIF thumbnail is too small ('.$this->exif_thumbnail_width.'x'.$this->exif_thumbnail_height.' vs '.$this->w.'x'.$this->h.')', __FILE__, __LINE__);
3772:                     break;
3773:                 }
3774:                 $source_ar = $this->source_width / $this->source_height;
3775:                 $exif_ar   = $this->exif_thumbnail_width / $this->exif_thumbnail_height;
3776:                 if (number_format($source_ar, 2) != number_format($exif_ar, 2)) {
3777:                     $this->DebugMessage('not using EXIF thumbnail because $source_ar != $exif_ar ('.$source_ar.' != '.$exif_ar.')', __FILE__, __LINE__);
3778:                     break;
3779:                 }
3780:             }
3781: 
3782:             // EXIF thumbnail exists, and is equal to or larger than destination thumbnail, and will be use as source image
3783:             $this->DebugMessage('Trying to use EXIF thumbnail as source image', __FILE__, __LINE__);
3784: 
3785:             if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) {
3786: 
3787:                 $this->DebugMessage('Successfully using EXIF thumbnail as source image', __FILE__, __LINE__);
3788:                 $this->gdimg_source   = $gdimg_exif_temp;
3789:                 $this->source_width   = $this->exif_thumbnail_width;
3790:                 $this->source_height  = $this->exif_thumbnail_height;
3791:                 $this->thumbnailCropW = $this->source_width;
3792:                 $this->thumbnailCropH = $this->source_height;
3793:                 return true;
3794: 
3795:             } else {
3796:                 $this->DebugMessage('$this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false) failed', __FILE__, __LINE__);
3797:             }
3798: 
3799:             break;
3800:         }
3801: 
3802:         if (!$this->gdimg_source) {
3803:             $this->DebugMessage('$this->gdimg_source is still empty', __FILE__, __LINE__);
3804: 
3805:             $this->DebugMessage('ImageMagickThumbnailToGD() failed', __FILE__, __LINE__);
3806: 
3807:             $imageHeader = '';
3808:             $gd_info = gd_info();
3809:             $GDreadSupport = false;
3810:             switch (@$this->getimagesizeinfo[2]) {
3811:                 case 1:
3812:                     $imageHeader = 'Content-Type: image/gif';
3813:                     $GDreadSupport = (bool) @$gd_info['GIF Read Support'];
3814:                     break;
3815:                 case 2:
3816:                     $imageHeader = 'Content-Type: image/jpeg';
3817:                     $GDreadSupport = (bool) @$gd_info['JPEG Support'] || (bool) @$gd_info['JPG Support']; // changed for XOOPS
3818:                     break;
3819:                 case 3:
3820:                     $imageHeader = 'Content-Type: image/png';
3821:                     $GDreadSupport = (bool) @$gd_info['PNG Support'];
3822:                     break;
3823:             }
3824:             if ($imageHeader) {
3825:                 // cannot create image for whatever reason (maybe imagecreatefromjpeg et al are not available?)
3826:                 // and ImageMagick is not available either, no choice but to output original (not resized/modified) data and exit
3827:                 if ($this->config_error_die_on_source_failure) {
3828:                     $errormessages = array();
3829:                     $errormessages[] = 'All attempts to create GD image source failed.';
3830:                     if ($this->fatalerror) {
3831:                         $errormessages[] = $this->fatalerror;
3832:                     }
3833:                     if ($this->issafemode) {
3834:                         $errormessages[] = 'Safe Mode enabled, therefore ImageMagick is unavailable. (disable Safe Mode if possible)';
3835:                     } elseif (!$this->ImageMagickVersion()) {
3836:                         $errormessages[] = 'ImageMagick is not installed (it is highly recommended that you install it).';
3837:                     }
3838:                     if ($this->SourceImageIsTooLarge($this->getimagesizeinfo[0], $this->getimagesizeinfo[1])) {
3839:                         $memory_get_usage = (function_exists('memory_get_usage') ? memory_get_usage() : 0);
3840:                         $errormessages[] = 'Source image is too large ('.$this->getimagesizeinfo[0].'x'.$this->getimagesizeinfo[1].' = '.number_format($this->getimagesizeinfo[0] * $this->getimagesizeinfo[1] / 1000000, 1).'Mpx, max='.number_format($this->config_max_source_pixels / 1000000, 1).'Mpx) for GD creation (either install ImageMagick or increase PHP memory_limit to at least '.ceil(($memory_get_usage + (5 * $this->getimagesizeinfo[0] * $this->getimagesizeinfo[1])) / 1048576).'M).';
3841:                     } elseif (!$GDreadSupport) {
3842:                         $errormessages[] = 'GD does not have read support for "'.$imageHeader.'".';
3843:                     } else {
3844:                         $errormessages[] = 'Source image probably corrupt.';
3845:                     }
3846:                     $this->ErrorImage(implode("\n", $errormessages));
3847: 
3848:                 } else {
3849:                     $this->DebugMessage('All attempts to create GD image source failed ('.(ini_get('safe_mode') ? 'Safe Mode enabled, ImageMagick unavailable and source image probably too large for GD': ($GDreadSupport ? 'source image probably corrupt' : 'GD does not have read support for "'.$imageHeader.'"')).'), cannot generate thumbnail');
3850:                     //$this->DebugMessage('All attempts to create GD image source failed ('.($GDreadSupport ? 'source image probably corrupt' : 'GD does not have read support for "'.$imageHeader.'"').'), outputing raw image', __FILE__, __LINE__);
3851:                     //if (!$this->phpThumbDebug) {
3852:                     //  header($imageHeader);
3853:                     //  echo $this->rawImageData;
3854:                     //  exit;
3855:                     //}
3856:                     return false;
3857:                 }
3858:             }
3859: 
3860:             //switch (substr($this->rawImageData, 0, 2)) {
3861:             //  case 'BM':
3862:             switch (@$this->getimagesizeinfo[2]) {
3863:                 case 6:
3864:                     ob_start();
3865:                     if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) {
3866:                         ob_end_clean();
3867:                         return $this->ErrorImage('include_once('.dirname(__FILE__).'/phpthumb.bmp.php) failed');
3868:                     }
3869:                     ob_end_clean();
3870:                     if ($fp = @fopen($this->sourceFilename, 'rb')) {
3871:                         $this->rawImageData = '';
3872:                         while (!feof($fp)) {
3873:                             $this->rawImageData .= fread($fp, 32768);
3874:                         }
3875:                         fclose($fp);
3876:                     }
3877:                     $phpthumb_bmp = new phpthumb_bmp();
3878:                     $this->gdimg_source = $phpthumb_bmp->phpthumb_bmp2gd($this->rawImageData, (phpthumb_functions::gd_version() >= 2.0));
3879:                     unset($phpthumb_bmp);
3880:                     if ($this->gdimg_source) {
3881:                         $this->DebugMessage('$phpthumb_bmp->phpthumb_bmp2gd() succeeded', __FILE__, __LINE__);
3882:                     } else {
3883:                         return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on BMP source conversion' : 'phpthumb_bmp2gd() failed');
3884:                     }
3885:                     break;
3886:             //}
3887:             //switch (substr($this->rawImageData, 0, 4)) {
3888:             //  case 'II'."\x2A\x00":
3889:             //  case 'MM'."\x00\x2A":
3890:                 case 7:
3891:                 case 8:
3892:                     return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on TIFF source conversion' : 'ImageMagick is unavailable and phpThumb() does not support TIFF source images without it');
3893:                     break;
3894: 
3895:                 //case "\xD7\xCD\xC6\x9A":
3896:                 //  return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on WMF source conversion' : 'ImageMagick is unavailable and phpThumb() does not support WMF source images without it');
3897:                 //  break;
3898:             }
3899: 
3900:             if (!$this->gdimg_source) {
3901:                 if ($this->rawImageData) {
3902:                     $HeaderFourBytes = substr($this->rawImageData, 0, 4);
3903:                 } elseif ($this->sourceFilename) {
3904:                     if ($fp = @fopen($this->sourceFilename, 'rb')) {
3905:                         $HeaderFourBytes = fread($fp, 4);
3906:                         fclose($fp);
3907:                     } else {
3908:                         return $this->ErrorImage('failed to open "'.$this->sourceFilename.'" SourceImageToGD() ['.__LINE__.']');
3909:                     }
3910:                 } else {
3911:                     return $this->ErrorImage('Unable to create image, neither filename nor image data suppplied in SourceImageToGD() ['.__LINE__.']');
3912:                 }
3913:                 if (!$this->ImageMagickVersion() && !phpthumb_functions::gd_version()) {
3914:                     return $this->ErrorImage('Neither GD nor ImageMagick seem to be installed on this server. At least one (preferably GD), or better both, MUST be installed for phpThumb to work.');
3915:                 } elseif ($HeaderFourBytes == "\xD7\xCD\xC6\x9A") { // WMF
3916:                     return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on WMF source conversion' : 'ImageMagick is unavailable and phpThumb() does not support WMF source images without it');
3917:                 } elseif ($HeaderFourBytes == '%PDF') { // "%PDF"
3918:                     return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick and GhostScript are both required for PDF source images; GhostScript may not be properly configured' : 'ImageMagick and/or GhostScript are unavailable and phpThumb() does not support PDF source images without them');
3919:                 } elseif (substr($HeaderFourBytes, 0, 3) == "\xFF\xD8\xFF") { // JPEG
3920:                     return $this->ErrorImage('Image (JPEG) is too large for PHP-GD memory_limit, please install ImageMagick or increase php.ini memory_limit setting');
3921:                 } elseif ($HeaderFourBytes == '%PNG') { // "%PNG"
3922:                     return $this->ErrorImage('Image (PNG) is too large for PHP-GD memory_limit, please install ImageMagick or increase php.ini memory_limit setting');
3923:                 } elseif (substr($HeaderFourBytes, 0, 3) == 'GIF') { // GIF
3924:                     return $this->ErrorImage('Image (GIF) is too large for PHP-GD memory_limit, please install ImageMagick or increase php.ini memory_limit setting');
3925:                 }
3926:                 return $this->ErrorImage('Unknown image type identified by "'.$HeaderFourBytes.'" ('.phpthumb_functions::HexCharDisplay($HeaderFourBytes).') in SourceImageToGD() ['.__LINE__.']');
3927:             }
3928:         }
3929: 
3930:         if (!$this->gdimg_source) {
3931:             if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) {
3932:                 $this->DebugMessage('All other attempts failed, but successfully using EXIF thumbnail as source image', __FILE__, __LINE__);
3933:                 $this->gdimg_source = $gdimg_exif_temp;
3934:                 // override allow-enlarging setting if EXIF thumbnail is the only source available
3935:                 // otherwise thumbnails larger than the EXIF thumbnail will be created at EXIF size
3936:                 $this->aoe = true;
3937:                 return true;
3938:             }
3939:             return false;
3940:         }
3941: 
3942:         $this->source_width  = imagesx($this->gdimg_source);
3943:         $this->source_height = imagesy($this->gdimg_source);
3944:         return true;
3945:     }
3946: 
3947: 
3948:     function phpThumbDebugVarDump($var) {
3949:         if (is_null($var)) {
3950:             return 'NULL';
3951:         } elseif (is_bool($var)) {
3952:             return ($var ? 'TRUE' : 'FALSE');
3953:         } elseif (is_string($var)) {
3954:             return 'string('.strlen($var).')'.str_repeat(' ', max(0, 3 - strlen(strlen($var)))).' "'.$var.'"';
3955:         } elseif (is_int($var)) {
3956:             return 'integer     '.$var;
3957:         } elseif (is_float($var)) {
3958:             return 'float       '.$var;
3959:         } elseif (is_array($var)) {
3960:             ob_start();
3961:             var_dump($var);
3962:             $vardumpoutput = ob_get_contents();
3963:             ob_end_clean();
3964:             return strtr($vardumpoutput, "\n\r\t", '   ');
3965:         }
3966:         return gettype($var);
3967:     }
3968: 
3969:     function phpThumbDebug($level='') {
3970:         if ($level && ($this->phpThumbDebug !== $level)) {
3971:             return true;
3972:         }
3973:         if ($this->config_disable_debug) {
3974:             return $this->ErrorImage('phpThumbDebug disabled');
3975:         }
3976: 
3977:         $FunctionsExistance  = array('exif_thumbnail', 'gd_info', 'image_type_to_mime_type', 'getimagesize', 'imagecopyresampled', 'imagecopyresized', 'imagecreate', 'imagecreatefromstring', 'imagecreatetruecolor', 'imageistruecolor', 'imagerotate', 'imagetypes', 'version_compare', 'imagecreatefromgif', 'imagecreatefromjpeg', 'imagecreatefrompng', 'imagecreatefromwbmp', 'imagecreatefromxbm', 'imagecreatefromxpm', 'imagecreatefromstring', 'imagecreatefromgd', 'imagecreatefromgd2', 'imagecreatefromgd2part', 'imagejpeg', 'imagegif', 'imagepng', 'imagewbmp');
3978:         $ParameterNames      = array('src', 'new', 'w', 'h', 'f', 'q', 'sx', 'sy', 'sw', 'sh', 'far', 'bg', 'bc', 'file', 'goto', 'err', 'xto', 'ra', 'ar', 'aoe', 'iar', 'maxb');
3979:         $ConfigVariableNames = array('document_root', 'temp_directory', 'output_format', 'output_maxwidth', 'output_maxheight', 'error_message_image_default', 'error_bgcolor', 'error_textcolor', 'error_fontsize', 'error_die_on_error', 'error_silent_die_on_error', 'error_die_on_source_failure', 'nohotlink_enabled', 'nohotlink_valid_domains', 'nohotlink_erase_image', 'nohotlink_text_message', 'nooffsitelink_enabled', 'nooffsitelink_valid_domains', 'nooffsitelink_require_refer', 'nooffsitelink_erase_image', 'nooffsitelink_text_message', 'high_security_enabled', 'allow_src_above_docroot', 'allow_src_above_phpthumb', 'max_source_pixels', 'use_exif_thumbnail_for_speed', 'border_hexcolor', 'background_hexcolor', 'ttf_directory', 'disable_pathinfo_parsing', 'disable_imagecopyresampled');
3980:         $OtherVariableNames  = array('phpThumbDebug', 'thumbnailQuality', 'thumbnailFormat', 'gdimg_output', 'gdimg_source', 'sourceFilename', 'source_width', 'source_height', 'thumbnailCropX', 'thumbnailCropY', 'thumbnailCropW', 'thumbnailCropH', 'exif_thumbnail_width', 'exif_thumbnail_height', 'exif_thumbnail_type', 'thumbnail_width', 'thumbnail_height', 'thumbnail_image_width', 'thumbnail_image_height');
3981: 
3982:         $DebugOutput = array();
3983:         $DebugOutput[] = 'phpThumb() version          = '.$this->phpthumb_version;
3984:         $DebugOutput[] = 'phpversion()                = '.@phpversion();
3985:         $DebugOutput[] = 'PHP_OS                      = '.PHP_OS;
3986:         $DebugOutput[] = '$_SERVER[SERVER_SOFTWARE]   = '.@$_SERVER['SERVER_SOFTWARE'];
3987:         $DebugOutput[] = '__FILE__                    = '.__FILE__;
3988:         $DebugOutput[] = 'realpath(.)                 = '.@realpath('.');
3989:         $DebugOutput[] = '$_SERVER[PHP_SELF]          = '.@$_SERVER['PHP_SELF'];
3990:         $DebugOutput[] = '$_SERVER[HOST_NAME]         = '.@$_SERVER['HOST_NAME'];
3991:         $DebugOutput[] = '$_SERVER[HTTP_REFERER]      = '.@$_SERVER['HTTP_REFERER'];
3992:         $DebugOutput[] = '$_SERVER[QUERY_STRING]      = '.@$_SERVER['QUERY_STRING'];
3993:         $DebugOutput[] = '$_SERVER[PATH_INFO]         = '.@$_SERVER['PATH_INFO'];
3994:         $DebugOutput[] = '$_SERVER[DOCUMENT_ROOT]     = '.@$_SERVER['DOCUMENT_ROOT'];
3995:         $DebugOutput[] = 'getenv(DOCUMENT_ROOT)       = '.@getenv('DOCUMENT_ROOT');
3996:         $DebugOutput[] = '';
3997: 
3998:         $DebugOutput[] = 'get_magic_quotes_gpc()         = '.$this->phpThumbDebugVarDump(@get_magic_quotes_gpc());
3999:         $DebugOutput[] = 'get_magic_quotes_runtime()     = '.$this->phpThumbDebugVarDump(@get_magic_quotes_runtime());
4000:         $DebugOutput[] = 'error_reporting()              = '.$this->phpThumbDebugVarDump(error_reporting());
4001:         $DebugOutput[] = 'ini_get(error_reporting)       = '.$this->phpThumbDebugVarDump(@ini_get('error_reporting'));
4002:         $DebugOutput[] = 'ini_get(display_errors)        = '.$this->phpThumbDebugVarDump(@ini_get('display_errors'));
4003:         $DebugOutput[] = 'ini_get(allow_url_fopen)       = '.$this->phpThumbDebugVarDump(@ini_get('allow_url_fopen'));
4004:         $DebugOutput[] = 'ini_get(disable_functions)     = '.$this->phpThumbDebugVarDump(@ini_get('disable_functions'));
4005:         $DebugOutput[] = 'get_cfg_var(disable_functions) = '.$this->phpThumbDebugVarDump(@get_cfg_var('disable_functions'));
4006:         $DebugOutput[] = 'ini_get(safe_mode)             = '.$this->phpThumbDebugVarDump(@ini_get('safe_mode'));
4007:         $DebugOutput[] = 'ini_get(open_basedir)          = '.$this->phpThumbDebugVarDump(@ini_get('open_basedir'));
4008:         $DebugOutput[] = 'ini_get(max_execution_time)    = '.$this->phpThumbDebugVarDump(@ini_get('max_execution_time'));
4009:         $DebugOutput[] = 'ini_get(memory_limit)          = '.$this->phpThumbDebugVarDump(@ini_get('memory_limit'));
4010:         $DebugOutput[] = 'get_cfg_var(memory_limit)      = '.$this->phpThumbDebugVarDump(@get_cfg_var('memory_limit'));
4011:         $DebugOutput[] = 'memory_get_usage()             = '.(function_exists('memory_get_usage') ? $this->phpThumbDebugVarDump(@memory_get_usage()) : 'n/a');
4012:         $DebugOutput[] = '';
4013: 
4014:         $DebugOutput[] = '$this->config_prefer_imagemagick            = '.$this->phpThumbDebugVarDump($this->config_prefer_imagemagick);
4015:         $DebugOutput[] = '$this->config_imagemagick_path              = '.$this->phpThumbDebugVarDump($this->config_imagemagick_path);
4016:         $DebugOutput[] = '$this->ImageMagickWhichConvert()            = '.$this->ImageMagickWhichConvert();
4017:         $IMpathUsed = ($this->config_imagemagick_path ? $this->config_imagemagick_path : $this->ImageMagickWhichConvert());
4018:         $DebugOutput[] = '[actual ImageMagick path used]              = '.$this->phpThumbDebugVarDump($IMpathUsed);
4019:         $DebugOutput[] = 'file_exists([actual ImageMagick path used]) = '.$this->phpThumbDebugVarDump(@file_exists($IMpathUsed));
4020:         $DebugOutput[] = 'ImageMagickVersion(false)                   = '.$this->ImageMagickVersion(false);
4021:         $DebugOutput[] = 'ImageMagickVersion(true)                    = '.$this->ImageMagickVersion(true);
4022:         $DebugOutput[] = '';
4023: 
4024:         $DebugOutput[] = '$this->config_cache_directory               = '.$this->phpThumbDebugVarDump($this->config_cache_directory);
4025:         $DebugOutput[] = '$this->config_cache_directory_depth         = '.$this->phpThumbDebugVarDump($this->config_cache_directory_depth);
4026:         $DebugOutput[] = '$this->config_cache_disable_warning         = '.$this->phpThumbDebugVarDump($this->config_cache_disable_warning);
4027:         $DebugOutput[] = '$this->config_cache_maxage                  = '.$this->phpThumbDebugVarDump($this->config_cache_maxage);
4028:         $DebugOutput[] = '$this->config_cache_maxsize                 = '.$this->phpThumbDebugVarDump($this->config_cache_maxsize);
4029:         $DebugOutput[] = '$this->config_cache_maxfiles                = '.$this->phpThumbDebugVarDump($this->config_cache_maxfiles);
4030:         $DebugOutput[] = '$this->config_cache_force_passthru          = '.$this->phpThumbDebugVarDump($this->config_cache_force_passthru);
4031:         $DebugOutput[] = '$this->cache_filename                       = '.$this->phpThumbDebugVarDump($this->cache_filename);
4032:         $DebugOutput[] = 'is_readable($this->config_cache_directory)  = '.$this->phpThumbDebugVarDump(@is_readable($this->config_cache_directory));
4033:         $DebugOutput[] = 'is_writable($this->config_cache_directory)  = '.$this->phpThumbDebugVarDump(@is_writable($this->config_cache_directory));
4034:         $DebugOutput[] = 'is_readable($this->cache_filename)          = '.$this->phpThumbDebugVarDump(@is_readable($this->cache_filename));
4035:         $DebugOutput[] = 'is_writable($this->cache_filename)          = '.(@file_exists($this->cache_filename) ? $this->phpThumbDebugVarDump(@is_writable($this->cache_filename)) : 'n/a');
4036:         $DebugOutput[] = '';
4037: 
4038:         foreach ($ConfigVariableNames as $varname) {
4039:             $varname = 'config_'.$varname;
4040:             $value = $this->$varname;
4041:             $DebugOutput[] = '$this->'.str_pad($varname, 37, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value);
4042:         }
4043:         $DebugOutput[] = '';
4044:         foreach ($OtherVariableNames as $varname) {
4045:             $value = $this->$varname;
4046:             $DebugOutput[] = '$this->'.str_pad($varname, 27, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value);
4047:         }
4048:         $DebugOutput[] = 'strlen($this->rawImageData)        = '.strlen(@$this->rawImageData);
4049:         $DebugOutput[] = 'strlen($this->exif_thumbnail_data) = '.strlen(@$this->exif_thumbnail_data);
4050:         $DebugOutput[] = '';
4051: 
4052:         foreach ($ParameterNames as $varname) {
4053:             $value = $this->$varname;
4054:             $DebugOutput[] = '$this->'.str_pad($varname, 4, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value);
4055:         }
4056:         $DebugOutput[] = '';
4057: 
4058:         foreach ($FunctionsExistance as $functionname) {
4059:             $DebugOutput[] = 'builtin_function_exists('.$functionname.')'.str_repeat(' ', 23 - strlen($functionname)).' = '.$this->phpThumbDebugVarDump(phpthumb_functions::builtin_function_exists($functionname));
4060:         }
4061:         $DebugOutput[] = '';
4062: 
4063:         $gd_info = gd_info();
4064:         foreach ($gd_info as $key => $value) {
4065:             $DebugOutput[] = 'gd_info.'.str_pad($key, 34, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value);
4066:         }
4067:         $DebugOutput[] = '';
4068: 
4069:         $exif_info = phpthumb_functions::exif_info();
4070:         foreach ($exif_info as $key => $value) {
4071:             $DebugOutput[] = 'exif_info.'.str_pad($key, 26, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value);
4072:         }
4073:         $DebugOutput[] = '';
4074: 
4075:         if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray(dirname(@$_SERVER['PHP_SELF']))) {
4076:             foreach ($ApacheLookupURIarray as $key => $value) {
4077:                 $DebugOutput[] = 'ApacheLookupURIarray.'.str_pad($key, 15, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value);
4078:             }
4079:         } else {
4080:                 $DebugOutput[] = 'ApacheLookupURIarray() -- FAILED';
4081:         }
4082:         $DebugOutput[] = '';
4083: 
4084:         if (isset($_GET) && is_array($_GET)) {
4085:             foreach ($_GET as $key => $value) {
4086:                 $DebugOutput[] = '$_GET['.$key.']'.str_repeat(' ', 30 - strlen($key)).'= '.$this->phpThumbDebugVarDump($value);
4087:             }
4088:         }
4089:         if (isset($_POST) && is_array($_POST)) {
4090:             foreach ($_POST as $key => $value) {
4091:                 $DebugOutput[] = '$_POST['.$key.']'.str_repeat(' ', 29 - strlen($key)).'= '.$this->phpThumbDebugVarDump($value);
4092:             }
4093:         }
4094:         $DebugOutput[] = '';
4095: 
4096:         $DebugOutput[] = '$this->debugmessages:';
4097:         foreach ($this->debugmessages as $errorstring) {
4098:             $DebugOutput[] = '  * '.$errorstring;
4099:         }
4100:         $DebugOutput[] = '';
4101: 
4102:         $DebugOutput[] = '$this->debugtiming:';
4103:         foreach ($this->debugtiming as $timestamp => $timingstring) {
4104:             $DebugOutput[] = '  * '.$timestamp.' '.$timingstring;
4105:         }
4106:         $DebugOutput[] = '  * Total processing time: '.number_format(max(array_keys($this->debugtiming)) - min(array_keys($this->debugtiming)), 6);
4107: 
4108:         $this->f = (isset($_GET['f']) ? $_GET['f'] : $this->f); // debug modes 0-2 don't recognize text mode otherwise
4109:         return $this->ErrorImage(implode("\n", $DebugOutput), 700, 500, true);
4110:     }
4111: 
4112:     function FatalError($text) {
4113:         if (is_null($this->fatalerror)) {
4114:             $this->fatalerror = $text;
4115:         }
4116:         return true;
4117:     }
4118: 
4119:     function ErrorImage($text, $width=0, $height=0, $forcedisplay=false) {
4120:         $width  = ($width  ? $width  : $this->config_error_image_width);
4121:         $height = ($height ? $height : $this->config_error_image_height);
4122: 
4123:         $text = 'phpThumb() v'.$this->phpthumb_version."\n".'http://phpthumb.sourceforge.net'."\n\n".($this->config_disable_debug ? 'Error messages disabled.'."\n\n".'edit phpThumb.config.php and (temporarily) set'."\n".'$PHPTHUMB_CONFIG[\'disable_debug\'] = false;'."\n".'to view the details of this error' : $text);
4124: 
4125:         $this->FatalError($text);
4126:         $this->DebugMessage($text, __FILE__, __LINE__);
4127:         $this->purgeTempFiles();
4128:         if ($this->config_error_silent_die_on_error) {
4129:             exit;
4130:         }
4131:         if ($this->phpThumbDebug && !$forcedisplay) {
4132:             return false;
4133:         }
4134:         if (!$this->config_error_die_on_error && !$forcedisplay) {
4135:             return false;
4136:         }
4137:         if ($this->err || $this->config_error_message_image_default) {
4138:             // Show generic custom error image instead of error message
4139:             // for use on production sites where you don't want debug messages
4140:             if (($this->err == 'showerror') || $this->phpThumbDebug) {
4141:                 // fall through and actually show error message even if default error image is set
4142:             } else {
4143:                 header('Location: '.($this->err ? $this->err : $this->config_error_message_image_default));
4144:                 exit;
4145:             }
4146:         }
4147:         $this->setOutputFormat();
4148:         if (!$this->thumbnailFormat || !$this->config_disable_debug || (phpthumb_functions::gd_version() < 1)) {
4149:             $this->thumbnailFormat = 'text';
4150:         }
4151:         if (@$this->thumbnailFormat == 'text') {
4152:             // bypass all GD functions and output text error message
4153:             if (!headers_sent()) {
4154:                 header('Content-type: text/plain');
4155:                 echo $text;
4156:             } else {
4157:                 echo '<pre>'.htmlspecialchars($text).'</pre>';
4158:             }
4159:             exit;
4160:         }
4161: 
4162:         $FontWidth  = imagefontwidth($this->config_error_fontsize);
4163:         $FontHeight = imagefontheight($this->config_error_fontsize);
4164: 
4165:         $LinesOfText = explode("\n", @wordwrap($text, floor($width / $FontWidth), "\n", true));
4166:         $height = max($height, count($LinesOfText) * $FontHeight);
4167: 
4168:         $headers_file = '';
4169:         $headers_line = '';
4170:         if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=') && headers_sent($headers_file, $headers_line)) {
4171: 
4172:             echo "\n".'**Headers already sent in file "'.$headers_file.'" on line "'.$headers_line.'", dumping error message as text:**<br><pre>'."\n\n".$text."\n".'</pre>';
4173: 
4174:         } elseif (headers_sent()) {
4175: 
4176:             echo "\n".'**Headers already sent, dumping error message as text:**<br><pre>'."\n\n".$text."\n".'</pre>';
4177: 
4178:         } elseif ($gdimg_error = imagecreate($width, $height)) {
4179: 
4180:             $background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_error, $this->config_error_bgcolor,   true);
4181:             $text_color       = phpthumb_functions::ImageHexColorAllocate($gdimg_error, $this->config_error_textcolor, true);
4182:             imagefilledrectangle($gdimg_error, 0, 0, $width, $height, $background_color);
4183:             $lineYoffset = 0;
4184:             foreach ($LinesOfText as $line) {
4185:                 imagestring($gdimg_error, $this->config_error_fontsize, 2, $lineYoffset, $line, $text_color);
4186:                 $lineYoffset += $FontHeight;
4187:             }
4188:             if (function_exists('imagetypes')) {
4189:                 $imagetypes = imagetypes();
4190:                 if ($imagetypes & IMG_PNG) {
4191:                     header('Content-Type: image/png');
4192:                     imagepng($gdimg_error);
4193:                 } elseif ($imagetypes & IMG_GIF) {
4194:                     header('Content-Type: image/gif');
4195:                     imagegif($gdimg_error);
4196:                 } elseif ($imagetypes & IMG_JPG) {
4197:                     header('Content-Type: image/jpeg');
4198:                     imagejpeg($gdimg_error);
4199:                 } elseif ($imagetypes & IMG_WBMP) {
4200:                     header('Content-Type: image/vnd.wap.wbmp');
4201:                     imagewbmp($gdimg_error);
4202:                 }
4203:             }
4204:             imagedestroy($gdimg_error);
4205: 
4206:         }
4207:         if (!headers_sent()) {
4208:             echo "\n".'**Failed to send graphical error image, dumping error message as text:**<br>'."\n\n".$text;
4209:         }
4210:         exit;
4211:     }
4212: 
4213:     function ImageCreateFromStringReplacement(&$RawImageData, $DieOnErrors=false) {
4214:         // there are serious bugs in the non-bundled versions of GD which may cause
4215:         // PHP to segfault when calling imagecreatefromstring() - avoid if at all possible
4216:         // when not using a bundled version of GD2
4217:         if (!phpthumb_functions::gd_version()) {
4218:             if ($DieOnErrors) {
4219:                 if (!headers_sent()) {
4220:                     // base64-encoded error image in GIF format
4221:                     $ERROR_NOGD = 'R0lGODlhIAAgALMAAAAAABQUFCQkJDY2NkZGRldXV2ZmZnJycoaGhpSUlKWlpbe3t8XFxdXV1eTk5P7+/iwAAAAAIAAgAAAE/vDJSau9WILtTAACUinDNijZtAHfCojS4W5H+qxD8xibIDE9h0OwWaRWDIljJSkUJYsN4bihMB8th3IToAKs1VtYM75cyV8sZ8vygtOE5yMKmGbO4jRdICQCjHdlZzwzNW4qZSQmKDaNjhUMBX4BBAlmMywFSRWEmAI6b5gAlhNxokGhooAIK5o/pi9vEw4Lfj4OLTAUpj6IabMtCwlSFw0DCKBoFqwAB04AjI54PyZ+yY3TD0ss2YcVmN/gvpcu4TOyFivWqYJlbAHPpOntvxNAACcmGHjZzAZqzSzcq5fNjxFmAFw9iFRunD1epU6tsIPmFCAJnWYE0FURk7wJDA0MTKpEzoWAAskiAAA7';
4222:                     header('Content-Type: image/gif');
4223:                     echo base64_decode($ERROR_NOGD);
4224:                 } else {
4225:                     echo '*** ERROR: No PHP-GD support available ***';
4226:                 }
4227:                 exit;
4228:             } else {
4229:                 $this->DebugMessage('ImageCreateFromStringReplacement() failed: gd_version says "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
4230:                 return false;
4231:             }
4232:         }
4233:         if (phpthumb_functions::gd_is_bundled()) {
4234:             $this->DebugMessage('ImageCreateFromStringReplacement() calling built-in imagecreatefromstring()', __FILE__, __LINE__);
4235:             return @imagecreatefromstring($RawImageData);
4236:         }
4237:         if ($this->issafemode) {
4238:             $this->DebugMessage('ImageCreateFromStringReplacement() failed: cannot create temp file in SAFE_MODE', __FILE__, __LINE__);
4239:             return false;
4240:         }
4241: 
4242:         switch (substr($RawImageData, 0, 3)) {
4243:             case 'GIF':
4244:                 $ICFSreplacementFunctionName = 'imagecreatefromgif';
4245:                 break;
4246:             case "\xFF\xD8\xFF":
4247:                 $ICFSreplacementFunctionName = 'imagecreatefromjpeg';
4248:                 break;
4249:             case "\x89".'PN':
4250:                 $ICFSreplacementFunctionName = 'imagecreatefrompng';
4251:                 break;
4252:             default:
4253:                 $this->DebugMessage('ImageCreateFromStringReplacement() failed: unknown fileformat signature "'.phpthumb_functions::HexCharDisplay(substr($RawImageData, 0, 3)).'"', __FILE__, __LINE__);
4254:                 return false;
4255:                 break;
4256:         }
4257:         $ErrorMessage = '';
4258:         if ($tempnam = $this->phpThumb_tempnam()) {
4259:             if ($fp_tempnam = @fopen($tempnam, 'wb')) {
4260:                 fwrite($fp_tempnam, $RawImageData);
4261:                 fclose($fp_tempnam);
4262:                 @chmod($tempnam, $this->getParameter('config_file_create_mask'));
4263:                 if (($ICFSreplacementFunctionName == 'imagecreatefromgif') && !function_exists($ICFSreplacementFunctionName)) {
4264: 
4265:                     // Need to create from GIF file, but imagecreatefromgif does not exist
4266:                     ob_start();
4267:                     if (!@include_once(dirname(__FILE__).'/phpthumb.gif.php')) {
4268:                         $ErrorMessage = 'Failed to include required file "'.dirname(__FILE__).'/phpthumb.gif.php" in '.__FILE__.' on line '.__LINE__;
4269:                         $this->DebugMessage($ErrorMessage, __FILE__, __LINE__);
4270:                     }
4271:                     ob_end_clean();
4272:                     // gif_loadFileToGDimageResource() cannot read from raw data, write to file first
4273:                     if ($tempfilename = $this->phpThumb_tempnam()) {
4274:                         if ($fp_tempfile = @fopen($tempfilename, 'wb')) {
4275:                             fwrite($fp_tempfile, $RawImageData);
4276:                             fclose($fp_tempfile);
4277:                             $gdimg_source = gif_loadFileToGDimageResource($tempfilename);
4278:                             $this->DebugMessage('gif_loadFileToGDimageResource('.$tempfilename.') completed', __FILE__, __LINE__);
4279:                             $this->DebugMessage('deleting "'.$tempfilename.'"', __FILE__, __LINE__);
4280:                             unlink($tempfilename);
4281:                             return $gdimg_source;
4282:                         } else {
4283:                             $ErrorMessage = 'Failed to open tempfile in '.__FILE__.' on line '.__LINE__;
4284:                             $this->DebugMessage($ErrorMessage, __FILE__, __LINE__);
4285:                         }
4286:                     } else {
4287:                         $ErrorMessage = 'Failed to open generate tempfile name in '.__FILE__.' on line '.__LINE__;
4288:                         $this->DebugMessage($ErrorMessage, __FILE__, __LINE__);
4289:                     }
4290: 
4291:                 } elseif (function_exists($ICFSreplacementFunctionName) && ($gdimg_source = @$ICFSreplacementFunctionName($tempnam))) {
4292: 
4293:                     // great
4294:                     $this->DebugMessage($ICFSreplacementFunctionName.'('.$tempnam.') succeeded', __FILE__, __LINE__);
4295:                     $this->DebugMessage('deleting "'.$tempnam.'"', __FILE__, __LINE__);
4296:                     unlink($tempnam);
4297:                     return $gdimg_source;
4298: 
4299:                 } else {
4300: 
4301:                     // GD functions not available, or failed to create image
4302:                     $this->DebugMessage($ICFSreplacementFunctionName.'('.$tempnam.') '.(function_exists($ICFSreplacementFunctionName) ? 'failed' : 'does not exist'), __FILE__, __LINE__);
4303:                     if (isset($_GET['phpThumbDebug'])) {
4304:                         $this->phpThumbDebug();
4305:                     }
4306: 
4307:                 }
4308:             } else {
4309:                 $ErrorMessage = 'Failed to fopen('.$tempnam.', "wb") in '.__FILE__.' on line '.__LINE__."\n".'You may need to set $PHPTHUMB_CONFIG[temp_directory] in phpThumb.config.php';
4310:                 if ($this->issafemode) {
4311:                     $ErrorMessage = 'ImageCreateFromStringReplacement() failed in '.__FILE__.' on line '.__LINE__.': cannot create temp file in SAFE_MODE';
4312:                 }
4313:                 $this->DebugMessage($ErrorMessage, __FILE__, __LINE__);
4314:             }
4315:             $this->DebugMessage('deleting "'.$tempnam.'"', __FILE__, __LINE__);
4316:             @unlink($tempnam);
4317:         } else {
4318:             $ErrorMessage = 'Failed to generate phpThumb_tempnam() in '.__FILE__.' on line '.__LINE__."\n".'You may need to set $PHPTHUMB_CONFIG[temp_directory] in phpThumb.config.php';
4319:             if ($this->issafemode) {
4320:                 $ErrorMessage = 'ImageCreateFromStringReplacement() failed in '.__FILE__.' on line '.__LINE__.': cannot create temp file in SAFE_MODE';
4321:             }
4322:         }
4323:         if ($DieOnErrors && $ErrorMessage) {
4324:             return $this->ErrorImage($ErrorMessage);
4325:         }
4326:         return false;
4327:     }
4328: 
4329:     function ImageResizeFunction(&$dst_im, &$src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH) {
4330:         $this->DebugMessage('ImageResizeFunction($o, $s, '.$dstX.', '.$dstY.', '.$srcX.', '.$srcY.', '.$dstW.', '.$dstH.', '.$srcW.', '.$srcH.')', __FILE__, __LINE__);
4331:         if (($dstW == $srcW) && ($dstH == $srcH)) {
4332:             return imagecopy($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $srcW, $srcH);
4333:         }
4334:         if (phpthumb_functions::gd_version() >= 2.0) {
4335:             if ($this->config_disable_imagecopyresampled) {
4336:                 return phpthumb_functions::ImageCopyResampleBicubic($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH);
4337:             }
4338:             return imagecopyresampled($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH);
4339:         }
4340:         return imagecopyresized($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH);
4341:     }
4342: 
4343:     function InitializeTempDirSetting() {
4344:         $this->config_temp_directory = ($this->config_temp_directory ? $this->config_temp_directory : (function_exists('sys_get_temp_dir') ? sys_get_temp_dir() : '')); // sys_get_temp_dir added in PHP v5.2.1
4345:         $this->config_temp_directory = ($this->config_temp_directory ? $this->config_temp_directory : getenv('TMPDIR'));
4346:         $this->config_temp_directory = ($this->config_temp_directory ? $this->config_temp_directory : getenv('TMP'));
4347:         $this->config_temp_directory = ($this->config_temp_directory ? $this->config_temp_directory : ini_get('upload_tmp_dir'));
4348:         $this->config_temp_directory = $this->realPathSafe($this->config_temp_directory);
4349:         return true;
4350:     }
4351: 
4352:     function phpThumb_tempnam() {
4353:         $this->InitializeTempDirSetting();
4354:         $tempnam = $this->realPathSafe(tempnam($this->config_temp_directory, 'pThumb'));
4355:         $this->tempFilesToDelete[$tempnam] = $tempnam;
4356:         $this->DebugMessage('phpThumb_tempnam() returning "'.$tempnam.'"', __FILE__, __LINE__);
4357:         return $tempnam;
4358:     }
4359: 
4360:     function DebugMessage($message, $file='', $line='') {
4361:         $this->debugmessages[] = $message.($file ? ' in file "'.(basename($file) ? basename($file) : $file).'"' : '').($line ? ' on line '.$line : '');
4362:         return true;
4363:     }
4364: 
4365:     function DebugTimingMessage($message, $file='', $line='', $timestamp=0) {
4366:         if (!$timestamp) {
4367:             $timestamp = array_sum(explode(' ', microtime()));
4368:         }
4369:         $this->debugtiming[number_format($timestamp, 6, '.', '')] = ': '.$message.($file ? ' in file "'.(basename($file) ? basename($file) : $file).'"' : '').($line ? ' on line '.$line : '');
4370:         return true;
4371:     }
4372: 
4373: }
4374: 
API documentation generated by ApiGen