annotate forum/Sources/Subs-Graphics.php @ 76:e3e11437ecea website

Add forum code
author Chris Cannam
date Sun, 07 Jul 2013 11:25:48 +0200
parents
children
rev   line source
Chris@76 1 <?php
Chris@76 2
Chris@76 3 /**
Chris@76 4 * Simple Machines Forum (SMF)
Chris@76 5 *
Chris@76 6 * @package SMF
Chris@76 7 * @author Simple Machines http://www.simplemachines.org
Chris@76 8 * @copyright 2011 Simple Machines
Chris@76 9 * @license http://www.simplemachines.org/about/smf/license.php BSD
Chris@76 10 *
Chris@76 11 * @version 2.0
Chris@76 12 */
Chris@76 13
Chris@76 14 // TrueType fonts supplied by www.LarabieFonts.com
Chris@76 15
Chris@76 16 if (!defined('SMF'))
Chris@76 17 die('Hacking attempt...');
Chris@76 18
Chris@76 19 /* This whole file deals almost exclusively with handling avatars,
Chris@76 20 specifically uploaded ones. It uses, for gifs at least, Gif Util... for
Chris@76 21 more information on that, please see its website, shown above. The other
Chris@76 22 functions are as follows:
Chris@76 23
Chris@76 24 bool downloadAvatar(string url, int id_member, int max_width,
Chris@76 25 int max_height)
Chris@76 26 - downloads file from url and stores it locally for avatar use
Chris@76 27 by id_member.
Chris@76 28 - supports GIF, JPG, PNG, BMP and WBMP formats.
Chris@76 29 - detects if GD2 is available.
Chris@76 30 - if GIF support isn't present in GD, handles GIFs with gif_loadFile()
Chris@76 31 and gif_outputAsPng().
Chris@76 32 - uses resizeImageFile() to resize to max_width by max_height,
Chris@76 33 and saves the result to a file.
Chris@76 34 - updates the database info for the member's avatar.
Chris@76 35 - returns whether the download and resize was successful.
Chris@76 36
Chris@76 37 bool createThumbnail(string source, int max_width, int max_height)
Chris@76 38 - create a thumbnail of the given source.
Chris@76 39 - uses the resizeImageFile function to achieve the resize.
Chris@76 40 - returns whether the thumbnail creation was successful.
Chris@76 41
Chris@76 42 bool reencodeImage(string fileName, int preferred_format = 0)
Chris@76 43 - creates a copy of the file at the same location as fileName.
Chris@76 44 - the file would have the format preferred_format if possible,
Chris@76 45 otherwise the default format is jpeg.
Chris@76 46 - makes sure that all non-essential image contents are disposed.
Chris@76 47 - returns true on success, false on failure.
Chris@76 48
Chris@76 49 bool checkImageContents(string fileName, bool extensiveCheck = false)
Chris@76 50 - searches through the file to see if there's non-binary content.
Chris@76 51 - if extensiveCheck is true, searches for asp/php short tags as well.
Chris@76 52 - returns true on success, false on failure.
Chris@76 53
Chris@76 54 bool checkGD()
Chris@76 55 - sets a global $gd2 variable needed by some functions to determine
Chris@76 56 whetehr the GD2 library is present.
Chris@76 57 - returns whether or not GD1 is available.
Chris@76 58
Chris@76 59 void resizeImageFile(string source, string destination,
Chris@76 60 int max_width, int max_height, int preferred_format = 0)
Chris@76 61 - resizes an image from a remote location or a local file.
Chris@76 62 - puts the resized image at the destination location.
Chris@76 63 - the file would have the format preferred_format if possible,
Chris@76 64 otherwise the default format is jpeg.
Chris@76 65 - returns whether it succeeded.
Chris@76 66
Chris@76 67 void resizeImage(resource src_img, string destination_filename,
Chris@76 68 int src_width, int src_height, int max_width, int max_height,
Chris@76 69 int preferred_format)
Chris@76 70 - resizes src_img proportionally to fit within max_width and
Chris@76 71 max_height limits if it is too large.
Chris@76 72 - if GD2 is present, it'll use it to achieve better quality.
Chris@76 73 - saves the new image to destination_filename.
Chris@76 74 - saves as preferred_format if possible, default is jpeg.
Chris@76 75
Chris@76 76 void imagecopyresamplebicubic(resource dest_img, resource src_img,
Chris@76 77 int dest_x, int dest_y, int src_x, int src_y, int dest_w,
Chris@76 78 int dest_h, int src_w, int src_h)
Chris@76 79 - used when imagecopyresample() is not available.
Chris@76 80
Chris@76 81 resource gif_loadFile(string filename, int animation_index)
Chris@76 82 - loads a gif file with the Yamasoft GIF utility class.
Chris@76 83 - returns a new GD image.
Chris@76 84
Chris@76 85 bool gif_outputAsPng(resource gif, string destination_filename,
Chris@76 86 int bgColor = -1)
Chris@76 87 - writes a gif file to disk as a png file.
Chris@76 88 - returns whether it was successful or not.
Chris@76 89
Chris@76 90 bool imagecreatefrombmp(string filename)
Chris@76 91 - is set only if it doesn't already exist (for forwards compatiblity.)
Chris@76 92 - only supports uncompressed bitmaps.
Chris@76 93 - returns an image identifier representing the bitmap image obtained
Chris@76 94 from the given filename.
Chris@76 95
Chris@76 96 bool showCodeImage(string code)
Chris@76 97 - show an image containing the visual verification code for registration.
Chris@76 98 - requires the GD extension.
Chris@76 99 - uses a random font for each letter from default_theme_dir/fonts.
Chris@76 100 - outputs a gif or a png (depending on whether gif ix supported).
Chris@76 101 - returns false if something goes wrong.
Chris@76 102
Chris@76 103 bool showLetterImage(string letter)
Chris@76 104 - show a letter for the visual verification code.
Chris@76 105 - alternative function for showCodeImage() in case GD is missing.
Chris@76 106 - includes an image from a random sub directory of
Chris@76 107 default_theme_dir/fonts.
Chris@76 108 */
Chris@76 109
Chris@76 110 function downloadAvatar($url, $memID, $max_width, $max_height)
Chris@76 111 {
Chris@76 112 global $modSettings, $sourcedir, $smcFunc;
Chris@76 113
Chris@76 114 $ext = !empty($modSettings['avatar_download_png']) ? 'png' : 'jpeg';
Chris@76 115 $destName = 'avatar_' . $memID . '_' . time() . '.' . $ext;
Chris@76 116
Chris@76 117 // Just making sure there is a non-zero member.
Chris@76 118 if (empty($memID))
Chris@76 119 return false;
Chris@76 120
Chris@76 121 require_once($sourcedir . '/ManageAttachments.php');
Chris@76 122 removeAttachments(array('id_member' => $memID));
Chris@76 123
Chris@76 124 $id_folder = !empty($modSettings['currentAttachmentUploadDir']) ? $modSettings['currentAttachmentUploadDir'] : 1;
Chris@76 125 $avatar_hash = empty($modSettings['custom_avatar_enabled']) ? getAttachmentFilename($destName, false, null, true) : '';
Chris@76 126 $smcFunc['db_insert']('',
Chris@76 127 '{db_prefix}attachments',
Chris@76 128 array(
Chris@76 129 'id_member' => 'int', 'attachment_type' => 'int', 'filename' => 'string-255', 'file_hash' => 'string-255', 'fileext' => 'string-8', 'size' => 'int',
Chris@76 130 'id_folder' => 'int',
Chris@76 131 ),
Chris@76 132 array(
Chris@76 133 $memID, empty($modSettings['custom_avatar_enabled']) ? 0 : 1, $destName, $avatar_hash, $ext, 1,
Chris@76 134 $id_folder,
Chris@76 135 ),
Chris@76 136 array('id_attach')
Chris@76 137 );
Chris@76 138 $attachID = $smcFunc['db_insert_id']('{db_prefix}attachments', 'id_attach');
Chris@76 139 // Retain this globally in case the script wants it.
Chris@76 140 $modSettings['new_avatar_data'] = array(
Chris@76 141 'id' => $attachID,
Chris@76 142 'filename' => $destName,
Chris@76 143 'type' => empty($modSettings['custom_avatar_enabled']) ? 0 : 1,
Chris@76 144 );
Chris@76 145
Chris@76 146 $destName = (empty($modSettings['custom_avatar_enabled']) ? (is_array($modSettings['attachmentUploadDir']) ? $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']] : $modSettings['attachmentUploadDir']) : $modSettings['custom_avatar_dir']) . '/' . $destName . '.tmp';
Chris@76 147
Chris@76 148 // Resize it.
Chris@76 149 if (!empty($modSettings['avatar_download_png']))
Chris@76 150 $success = resizeImageFile($url, $destName, $max_width, $max_height, 3);
Chris@76 151 else
Chris@76 152 $success = resizeImageFile($url, $destName, $max_width, $max_height);
Chris@76 153
Chris@76 154 // Remove the .tmp extension.
Chris@76 155 $destName = substr($destName, 0, -4);
Chris@76 156
Chris@76 157 if ($success)
Chris@76 158 {
Chris@76 159 // Walk the right path.
Chris@76 160 if (!empty($modSettings['currentAttachmentUploadDir']))
Chris@76 161 {
Chris@76 162 if (!is_array($modSettings['attachmentUploadDir']))
Chris@76 163 $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']);
Chris@76 164 $path = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']];
Chris@76 165 }
Chris@76 166 else
Chris@76 167 $path = $modSettings['attachmentUploadDir'];
Chris@76 168
Chris@76 169 // Remove the .tmp extension from the attachment.
Chris@76 170 if (rename($destName . '.tmp', empty($avatar_hash) ? $destName : $path . '/' . $attachID . '_' . $avatar_hash))
Chris@76 171 {
Chris@76 172 $destName = empty($avatar_hash) ? $destName : $path . '/' . $attachID . '_' . $avatar_hash;
Chris@76 173 list ($width, $height) = getimagesize($destName);
Chris@76 174 $mime_type = 'image/' . $ext;
Chris@76 175
Chris@76 176 // Write filesize in the database.
Chris@76 177 $smcFunc['db_query']('', '
Chris@76 178 UPDATE {db_prefix}attachments
Chris@76 179 SET size = {int:filesize}, width = {int:width}, height = {int:height},
Chris@76 180 mime_type = {string:mime_type}
Chris@76 181 WHERE id_attach = {int:current_attachment}',
Chris@76 182 array(
Chris@76 183 'filesize' => filesize($destName),
Chris@76 184 'width' => (int) $width,
Chris@76 185 'height' => (int) $height,
Chris@76 186 'current_attachment' => $attachID,
Chris@76 187 'mime_type' => $mime_type,
Chris@76 188 )
Chris@76 189 );
Chris@76 190 return true;
Chris@76 191 }
Chris@76 192 else
Chris@76 193 return false;
Chris@76 194 }
Chris@76 195 else
Chris@76 196 {
Chris@76 197 $smcFunc['db_query']('', '
Chris@76 198 DELETE FROM {db_prefix}attachments
Chris@76 199 WHERE id_attach = {int:current_attachment}',
Chris@76 200 array(
Chris@76 201 'current_attachment' => $attachID,
Chris@76 202 )
Chris@76 203 );
Chris@76 204
Chris@76 205 @unlink($destName . '.tmp');
Chris@76 206 return false;
Chris@76 207 }
Chris@76 208 }
Chris@76 209
Chris@76 210 function createThumbnail($source, $max_width, $max_height)
Chris@76 211 {
Chris@76 212 global $modSettings;
Chris@76 213
Chris@76 214 $destName = $source . '_thumb.tmp';
Chris@76 215
Chris@76 216 // Do the actual resize.
Chris@76 217 if (!empty($modSettings['attachment_thumb_png']))
Chris@76 218 $success = resizeImageFile($source, $destName, $max_width, $max_height, 3);
Chris@76 219 else
Chris@76 220 $success = resizeImageFile($source, $destName, $max_width, $max_height);
Chris@76 221
Chris@76 222 // Okay, we're done with the temporary stuff.
Chris@76 223 $destName = substr($destName, 0, -4);
Chris@76 224
Chris@76 225 if ($success && @rename($destName . '.tmp', $destName))
Chris@76 226 return true;
Chris@76 227 else
Chris@76 228 {
Chris@76 229 @unlink($destName . '.tmp');
Chris@76 230 @touch($destName);
Chris@76 231 return false;
Chris@76 232 }
Chris@76 233 }
Chris@76 234
Chris@76 235 function reencodeImage($fileName, $preferred_format = 0)
Chris@76 236 {
Chris@76 237 // There is nothing we can do without GD, sorry!
Chris@76 238 if (!checkGD())
Chris@76 239 return false;
Chris@76 240
Chris@76 241 if (!resizeImageFile($fileName, $fileName . '.tmp', null, null, $preferred_format))
Chris@76 242 {
Chris@76 243 if (file_exists($fileName . '.tmp'))
Chris@76 244 unlink($fileName . '.tmp');
Chris@76 245
Chris@76 246 return false;
Chris@76 247 }
Chris@76 248
Chris@76 249 if (!unlink($fileName))
Chris@76 250 return false;
Chris@76 251
Chris@76 252 if (!rename($fileName . '.tmp', $fileName))
Chris@76 253 return false;
Chris@76 254
Chris@76 255 return true;
Chris@76 256 }
Chris@76 257
Chris@76 258 function checkImageContents($fileName, $extensiveCheck = false)
Chris@76 259 {
Chris@76 260 $fp = fopen($fileName, 'rb');
Chris@76 261 if (!$fp)
Chris@76 262 fatal_lang_error('attach_timeout');
Chris@76 263
Chris@76 264 $prev_chunk = '';
Chris@76 265 while (!feof($fp))
Chris@76 266 {
Chris@76 267 $cur_chunk = fread($fp, 8192);
Chris@76 268
Chris@76 269 // Though not exhaustive lists, better safe than sorry.
Chris@76 270 if (!empty($extensiveCheck))
Chris@76 271 {
Chris@76 272 // Paranoid check. Some like it that way.
Chris@76 273 if (preg_match('~(iframe|\\<\\?|\\<%|html|eval|body|script\W|[CF]WS[\x01-\x0C])~i', $prev_chunk . $cur_chunk) === 1)
Chris@76 274 {
Chris@76 275 fclose($fp);
Chris@76 276 return false;
Chris@76 277 }
Chris@76 278 }
Chris@76 279 else
Chris@76 280 {
Chris@76 281 // Check for potential infection
Chris@76 282 if (preg_match('~(iframe|html|eval|body|script\W|[CF]WS[\x01-\x0C])~i', $prev_chunk . $cur_chunk) === 1)
Chris@76 283 {
Chris@76 284 fclose($fp);
Chris@76 285 return false;
Chris@76 286 }
Chris@76 287 }
Chris@76 288 $prev_chunk = $cur_chunk;
Chris@76 289 }
Chris@76 290 fclose($fp);
Chris@76 291
Chris@76 292 return true;
Chris@76 293 }
Chris@76 294
Chris@76 295 function checkGD()
Chris@76 296 {
Chris@76 297 global $gd2;
Chris@76 298
Chris@76 299 // Check to see if GD is installed and what version.
Chris@76 300 if (($extensionFunctions = get_extension_funcs('gd')) === false)
Chris@76 301 return false;
Chris@76 302
Chris@76 303 // Also determine if GD2 is installed and store it in a global.
Chris@76 304 $gd2 = in_array('imagecreatetruecolor', $extensionFunctions) && function_exists('imagecreatetruecolor');
Chris@76 305
Chris@76 306 return true;
Chris@76 307 }
Chris@76 308
Chris@76 309 function resizeImageFile($source, $destination, $max_width, $max_height, $preferred_format = 0)
Chris@76 310 {
Chris@76 311 global $sourcedir;
Chris@76 312
Chris@76 313 // Nothing to do without GD
Chris@76 314 if (!checkGD())
Chris@76 315 return false;
Chris@76 316
Chris@76 317 static $default_formats = array(
Chris@76 318 '1' => 'gif',
Chris@76 319 '2' => 'jpeg',
Chris@76 320 '3' => 'png',
Chris@76 321 '6' => 'bmp',
Chris@76 322 '15' => 'wbmp'
Chris@76 323 );
Chris@76 324
Chris@76 325 require_once($sourcedir . '/Subs-Package.php');
Chris@76 326 @ini_set('memory_limit', '90M');
Chris@76 327
Chris@76 328 $success = false;
Chris@76 329
Chris@76 330 // Get the image file, we have to work with something after all
Chris@76 331 $fp_destination = fopen($destination, 'wb');
Chris@76 332 if ($fp_destination && substr($source, 0, 7) == 'http://')
Chris@76 333 {
Chris@76 334 $fileContents = fetch_web_data($source);
Chris@76 335
Chris@76 336 fwrite($fp_destination, $fileContents);
Chris@76 337 fclose($fp_destination);
Chris@76 338
Chris@76 339 $sizes = @getimagesize($destination);
Chris@76 340 }
Chris@76 341 elseif ($fp_destination)
Chris@76 342 {
Chris@76 343 $sizes = @getimagesize($source);
Chris@76 344
Chris@76 345 $fp_source = fopen($source, 'rb');
Chris@76 346 if ($fp_source !== false)
Chris@76 347 {
Chris@76 348 while (!feof($fp_source))
Chris@76 349 fwrite($fp_destination, fread($fp_source, 8192));
Chris@76 350 fclose($fp_source);
Chris@76 351 }
Chris@76 352 else
Chris@76 353 $sizes = array(-1, -1, -1);
Chris@76 354 fclose($fp_destination);
Chris@76 355 }
Chris@76 356 // We can't get to the file.
Chris@76 357 else
Chris@76 358 $sizes = array(-1, -1, -1);
Chris@76 359
Chris@76 360 // Gif? That might mean trouble if gif support is not available.
Chris@76 361 if ($sizes[2] == 1 && !function_exists('imagecreatefromgif') && function_exists('imagecreatefrompng'))
Chris@76 362 {
Chris@76 363 // Download it to the temporary file... use the special gif library... and save as png.
Chris@76 364 if ($img = @gif_loadFile($destination) && gif_outputAsPng($img, $destination))
Chris@76 365 $sizes[2] = 3;
Chris@76 366 }
Chris@76 367
Chris@76 368 // A known and supported format?
Chris@76 369 if (isset($default_formats[$sizes[2]]) && function_exists('imagecreatefrom' . $default_formats[$sizes[2]]))
Chris@76 370 {
Chris@76 371 $imagecreatefrom = 'imagecreatefrom' . $default_formats[$sizes[2]];
Chris@76 372 if ($src_img = @$imagecreatefrom($destination))
Chris@76 373 {
Chris@76 374 resizeImage($src_img, $destination, imagesx($src_img), imagesy($src_img), $max_width === null ? imagesx($src_img) : $max_width, $max_height === null ? imagesy($src_img) : $max_height, true, $preferred_format);
Chris@76 375 $success = true;
Chris@76 376 }
Chris@76 377 }
Chris@76 378
Chris@76 379 return $success;
Chris@76 380 }
Chris@76 381
Chris@76 382 function resizeImage($src_img, $destName, $src_width, $src_height, $max_width, $max_height, $force_resize = false, $preferred_format = 0)
Chris@76 383 {
Chris@76 384 global $gd2, $modSettings;
Chris@76 385
Chris@76 386 // Without GD, no image resizing at all.
Chris@76 387 if (!checkGD())
Chris@76 388 return false;
Chris@76 389
Chris@76 390 $success = false;
Chris@76 391
Chris@76 392 // Determine whether to resize to max width or to max height (depending on the limits.)
Chris@76 393 if (!empty($max_width) || !empty($max_height))
Chris@76 394 {
Chris@76 395 if (!empty($max_width) && (empty($max_height) || $src_height * $max_width / $src_width <= $max_height))
Chris@76 396 {
Chris@76 397 $dst_width = $max_width;
Chris@76 398 $dst_height = floor($src_height * $max_width / $src_width);
Chris@76 399 }
Chris@76 400 elseif (!empty($max_height))
Chris@76 401 {
Chris@76 402 $dst_width = floor($src_width * $max_height / $src_height);
Chris@76 403 $dst_height = $max_height;
Chris@76 404 }
Chris@76 405
Chris@76 406 // Don't bother resizing if it's already smaller...
Chris@76 407 if (!empty($dst_width) && !empty($dst_height) && ($dst_width < $src_width || $dst_height < $src_height || $force_resize))
Chris@76 408 {
Chris@76 409 // (make a true color image, because it just looks better for resizing.)
Chris@76 410 if ($gd2)
Chris@76 411 {
Chris@76 412 $dst_img = imagecreatetruecolor($dst_width, $dst_height);
Chris@76 413
Chris@76 414 // Deal nicely with a PNG - because we can.
Chris@76 415 if ((!empty($preferred_format)) && ($preferred_format == 3))
Chris@76 416 {
Chris@76 417 imagealphablending($dst_img, false);
Chris@76 418 if (function_exists('imagesavealpha'))
Chris@76 419 imagesavealpha($dst_img, true);
Chris@76 420 }
Chris@76 421 }
Chris@76 422 else
Chris@76 423 $dst_img = imagecreate($dst_width, $dst_height);
Chris@76 424
Chris@76 425 // Resize it!
Chris@76 426 if ($gd2)
Chris@76 427 imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $dst_width, $dst_height, $src_width, $src_height);
Chris@76 428 else
Chris@76 429 imagecopyresamplebicubic($dst_img, $src_img, 0, 0, 0, 0, $dst_width, $dst_height, $src_width, $src_height);
Chris@76 430 }
Chris@76 431 else
Chris@76 432 $dst_img = $src_img;
Chris@76 433 }
Chris@76 434 else
Chris@76 435 $dst_img = $src_img;
Chris@76 436
Chris@76 437 // Save the image as ...
Chris@76 438 if (!empty($preferred_format) && ($preferred_format == 3) && function_exists('imagepng'))
Chris@76 439 $success = imagepng($dst_img, $destName);
Chris@76 440 elseif (!empty($preferred_format) && ($preferred_format == 1) && function_exists('imagegif'))
Chris@76 441 $success = imagegif($dst_img, $destName);
Chris@76 442 elseif (function_exists('imagejpeg'))
Chris@76 443 $success = imagejpeg($dst_img, $destName);
Chris@76 444
Chris@76 445 // Free the memory.
Chris@76 446 imagedestroy($src_img);
Chris@76 447 if ($dst_img != $src_img)
Chris@76 448 imagedestroy($dst_img);
Chris@76 449
Chris@76 450 return $success;
Chris@76 451 }
Chris@76 452
Chris@76 453 function imagecopyresamplebicubic($dst_img, $src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h)
Chris@76 454 {
Chris@76 455 $palsize = imagecolorstotal($src_img);
Chris@76 456 for ($i = 0; $i < $palsize; $i++)
Chris@76 457 {
Chris@76 458 $colors = imagecolorsforindex($src_img, $i);
Chris@76 459 imagecolorallocate($dst_img, $colors['red'], $colors['green'], $colors['blue']);
Chris@76 460 }
Chris@76 461
Chris@76 462 $scaleX = ($src_w - 1) / $dst_w;
Chris@76 463 $scaleY = ($src_h - 1) / $dst_h;
Chris@76 464
Chris@76 465 $scaleX2 = (int) $scaleX / 2;
Chris@76 466 $scaleY2 = (int) $scaleY / 2;
Chris@76 467
Chris@76 468 for ($j = $src_y; $j < $dst_h; $j++)
Chris@76 469 {
Chris@76 470 $sY = (int) $j * $scaleY;
Chris@76 471 $y13 = $sY + $scaleY2;
Chris@76 472
Chris@76 473 for ($i = $src_x; $i < $dst_w; $i++)
Chris@76 474 {
Chris@76 475 $sX = (int) $i * $scaleX;
Chris@76 476 $x34 = $sX + $scaleX2;
Chris@76 477
Chris@76 478 $color1 = imagecolorsforindex($src_img, imagecolorat($src_img, $sX, $y13));
Chris@76 479 $color2 = imagecolorsforindex($src_img, imagecolorat($src_img, $sX, $sY));
Chris@76 480 $color3 = imagecolorsforindex($src_img, imagecolorat($src_img, $x34, $y13));
Chris@76 481 $color4 = imagecolorsforindex($src_img, imagecolorat($src_img, $x34, $sY));
Chris@76 482
Chris@76 483 $red = ($color1['red'] + $color2['red'] + $color3['red'] + $color4['red']) / 4;
Chris@76 484 $green = ($color1['green'] + $color2['green'] + $color3['green'] + $color4['green']) / 4;
Chris@76 485 $blue = ($color1['blue'] + $color2['blue'] + $color3['blue'] + $color4['blue']) / 4;
Chris@76 486
Chris@76 487 $color = imagecolorresolve($dst_img, $red, $green, $blue);
Chris@76 488 if ($color == -1)
Chris@76 489 {
Chris@76 490 if ($palsize++ < 256)
Chris@76 491 imagecolorallocate($dst_img, $red, $green, $blue);
Chris@76 492 $color = imagecolorclosest($dst_img, $red, $green, $blue);
Chris@76 493 }
Chris@76 494
Chris@76 495 imagesetpixel($dst_img, $i + $dst_x - $src_x, $j + $dst_y - $src_y, $color);
Chris@76 496 }
Chris@76 497 }
Chris@76 498 }
Chris@76 499
Chris@76 500 if (!function_exists('imagecreatefrombmp'))
Chris@76 501 {
Chris@76 502 function imagecreatefrombmp($filename)
Chris@76 503 {
Chris@76 504 global $gd2;
Chris@76 505
Chris@76 506 $fp = fopen($filename, 'rb');
Chris@76 507
Chris@76 508 $errors = error_reporting(0);
Chris@76 509
Chris@76 510 $header = unpack('vtype/Vsize/Vreserved/Voffset', fread($fp, 14));
Chris@76 511 $info = unpack('Vsize/Vwidth/Vheight/vplanes/vbits/Vcompression/Vimagesize/Vxres/Vyres/Vncolor/Vcolorimportant', fread($fp, 40));
Chris@76 512
Chris@76 513 if ($header['type'] != 0x4D42)
Chris@76 514 false;
Chris@76 515
Chris@76 516 if ($gd2)
Chris@76 517 $dst_img = imagecreatetruecolor($info['width'], $info['height']);
Chris@76 518 else
Chris@76 519 $dst_img = imagecreate($info['width'], $info['height']);
Chris@76 520
Chris@76 521 $palette_size = $header['offset'] - 54;
Chris@76 522 $info['ncolor'] = $palette_size / 4;
Chris@76 523
Chris@76 524 $palette = array();
Chris@76 525
Chris@76 526 $palettedata = fread($fp, $palette_size);
Chris@76 527 $n = 0;
Chris@76 528 for ($j = 0; $j < $palette_size; $j++)
Chris@76 529 {
Chris@76 530 $b = ord($palettedata{$j++});
Chris@76 531 $g = ord($palettedata{$j++});
Chris@76 532 $r = ord($palettedata{$j++});
Chris@76 533
Chris@76 534 $palette[$n++] = imagecolorallocate($dst_img, $r, $g, $b);
Chris@76 535 }
Chris@76 536
Chris@76 537 $scan_line_size = ($info['bits'] * $info['width'] + 7) >> 3;
Chris@76 538 $scan_line_align = $scan_line_size & 3 ? 4 - ($scan_line_size & 3) : 0;
Chris@76 539
Chris@76 540 for ($y = 0, $l = $info['height'] - 1; $y < $info['height']; $y++, $l--)
Chris@76 541 {
Chris@76 542 fseek($fp, $header['offset'] + ($scan_line_size + $scan_line_align) * $l);
Chris@76 543 $scan_line = fread($fp, $scan_line_size);
Chris@76 544
Chris@76 545 if (strlen($scan_line) < $scan_line_size)
Chris@76 546 continue;
Chris@76 547
Chris@76 548 if ($info['bits'] == 32)
Chris@76 549 {
Chris@76 550 $x = 0;
Chris@76 551 for ($j = 0; $j < $scan_line_size; $x++)
Chris@76 552 {
Chris@76 553 $b = ord($scan_line{$j++});
Chris@76 554 $g = ord($scan_line{$j++});
Chris@76 555 $r = ord($scan_line{$j++});
Chris@76 556 $j++;
Chris@76 557
Chris@76 558 $color = imagecolorexact($dst_img, $r, $g, $b);
Chris@76 559 if ($color == -1)
Chris@76 560 {
Chris@76 561 $color = imagecolorallocate($dst_img, $r, $g, $b);
Chris@76 562
Chris@76 563 // Gah! Out of colors? Stupid GD 1... try anyhow.
Chris@76 564 if ($color == -1)
Chris@76 565 $color = imagecolorclosest($dst_img, $r, $g, $b);
Chris@76 566 }
Chris@76 567
Chris@76 568 imagesetpixel($dst_img, $x, $y, $color);
Chris@76 569 }
Chris@76 570 }
Chris@76 571 elseif ($info['bits'] == 24)
Chris@76 572 {
Chris@76 573 $x = 0;
Chris@76 574 for ($j = 0; $j < $scan_line_size; $x++)
Chris@76 575 {
Chris@76 576 $b = ord($scan_line{$j++});
Chris@76 577 $g = ord($scan_line{$j++});
Chris@76 578 $r = ord($scan_line{$j++});
Chris@76 579
Chris@76 580 $color = imagecolorexact($dst_img, $r, $g, $b);
Chris@76 581 if ($color == -1)
Chris@76 582 {
Chris@76 583 $color = imagecolorallocate($dst_img, $r, $g, $b);
Chris@76 584
Chris@76 585 // Gah! Out of colors? Stupid GD 1... try anyhow.
Chris@76 586 if ($color == -1)
Chris@76 587 $color = imagecolorclosest($dst_img, $r, $g, $b);
Chris@76 588 }
Chris@76 589
Chris@76 590 imagesetpixel($dst_img, $x, $y, $color);
Chris@76 591 }
Chris@76 592 }
Chris@76 593 elseif ($info['bits'] == 16)
Chris@76 594 {
Chris@76 595 $x = 0;
Chris@76 596 for ($j = 0; $j < $scan_line_size; $x++)
Chris@76 597 {
Chris@76 598 $b1 = ord($scan_line{$j++});
Chris@76 599 $b2 = ord($scan_line{$j++});
Chris@76 600
Chris@76 601 $word = $b2 * 256 + $b1;
Chris@76 602
Chris@76 603 $b = (($word & 31) * 255) / 31;
Chris@76 604 $g = ((($word >> 5) & 31) * 255) / 31;
Chris@76 605 $r = ((($word >> 10) & 31) * 255) / 31;
Chris@76 606
Chris@76 607 // Scale the image colors up properly.
Chris@76 608 $color = imagecolorexact($dst_img, $r, $g, $b);
Chris@76 609 if ($color == -1)
Chris@76 610 {
Chris@76 611 $color = imagecolorallocate($dst_img, $r, $g, $b);
Chris@76 612
Chris@76 613 // Gah! Out of colors? Stupid GD 1... try anyhow.
Chris@76 614 if ($color == -1)
Chris@76 615 $color = imagecolorclosest($dst_img, $r, $g, $b);
Chris@76 616 }
Chris@76 617
Chris@76 618 imagesetpixel($dst_img, $x, $y, $color);
Chris@76 619 }
Chris@76 620 }
Chris@76 621 elseif ($info['bits'] == 8)
Chris@76 622 {
Chris@76 623 $x = 0;
Chris@76 624 for ($j = 0; $j < $scan_line_size; $x++)
Chris@76 625 imagesetpixel($dst_img, $x, $y, $palette[ord($scan_line{$j++})]);
Chris@76 626 }
Chris@76 627 elseif ($info['bits'] == 4)
Chris@76 628 {
Chris@76 629 $x = 0;
Chris@76 630 for ($j = 0; $j < $scan_line_size; $x++)
Chris@76 631 {
Chris@76 632 $byte = ord($scan_line{$j++});
Chris@76 633
Chris@76 634 imagesetpixel($dst_img, $x, $y, $palette[(int) ($byte / 16)]);
Chris@76 635 if (++$x < $info['width'])
Chris@76 636 imagesetpixel($dst_img, $x, $y, $palette[$byte & 15]);
Chris@76 637 }
Chris@76 638 }
Chris@76 639 else
Chris@76 640 {
Chris@76 641 // Sorry, I'm just not going to do monochrome :P.
Chris@76 642 }
Chris@76 643 }
Chris@76 644
Chris@76 645 fclose($fp);
Chris@76 646
Chris@76 647 error_reporting($errors);
Chris@76 648
Chris@76 649 return $dst_img;
Chris@76 650 }
Chris@76 651 }
Chris@76 652
Chris@76 653 function gif_loadFile($lpszFileName, $iIndex = 0)
Chris@76 654 {
Chris@76 655 // The classes needed are in this file.
Chris@76 656 loadClassFile('Class-Graphics.php');
Chris@76 657 $gif = new gif_file();
Chris@76 658
Chris@76 659 if (!$gif->loadFile($lpszFileName, $iIndex))
Chris@76 660 return false;
Chris@76 661
Chris@76 662 return $gif;
Chris@76 663 }
Chris@76 664
Chris@76 665 function gif_outputAsPng($gif, $lpszFileName, $background_color = -1)
Chris@76 666 {
Chris@76 667 if (!isset($gif) || @get_class($gif) != 'cgif' || !$gif->loaded || $lpszFileName == '')
Chris@76 668 return false;
Chris@76 669
Chris@76 670 $fd = $gif->get_png_data($background_color);
Chris@76 671 if (strlen($fd) <= 0)
Chris@76 672 return false;
Chris@76 673
Chris@76 674 if (!($fh = @fopen($lpszFileName, 'wb')))
Chris@76 675 return false;
Chris@76 676
Chris@76 677 @fwrite($fh, $fd, strlen($fd));
Chris@76 678 @fflush($fh);
Chris@76 679 @fclose($fh);
Chris@76 680
Chris@76 681 return true;
Chris@76 682 }
Chris@76 683
Chris@76 684 // Create the image for the visual verification code.
Chris@76 685 function showCodeImage($code)
Chris@76 686 {
Chris@76 687 global $settings, $user_info, $modSettings;
Chris@76 688
Chris@76 689 /*
Chris@76 690 Note: The higher the value of visual_verification_type the harder the verification is - from 0 as disabled through to 4 as "Very hard".
Chris@76 691 */
Chris@76 692
Chris@76 693 // What type are we going to be doing?
Chris@76 694 $imageType = $modSettings['visual_verification_type'];
Chris@76 695 // Special case to allow the admin center to show samples.
Chris@76 696 if ($user_info['is_admin'] && isset($_GET['type']))
Chris@76 697 $imageType = (int) $_GET['type'];
Chris@76 698
Chris@76 699 // Some quick references for what we do.
Chris@76 700 // Do we show no, low or high noise?
Chris@76 701 $noiseType = $imageType == 3 ? 'low' : ($imageType == 4 ? 'high' : ($imageType == 5 ? 'extreme' : 'none'));
Chris@76 702 // Can we have more than one font in use?
Chris@76 703 $varyFonts = $imageType > 3 ? true : false;
Chris@76 704 // Just a plain white background?
Chris@76 705 $simpleBGColor = $imageType < 3 ? true : false;
Chris@76 706 // Plain black foreground?
Chris@76 707 $simpleFGColor = $imageType == 0 ? true : false;
Chris@76 708 // High much to rotate each character.
Chris@76 709 $rotationType = $imageType == 1 ? 'none' : ($imageType > 3 ? 'low' : 'high');
Chris@76 710 // Do we show some characters inversed?
Chris@76 711 $showReverseChars = $imageType > 3 ? true : false;
Chris@76 712 // Special case for not showing any characters.
Chris@76 713 $disableChars = $imageType == 0 ? true : false;
Chris@76 714 // What do we do with the font colors. Are they one color, close to one color or random?
Chris@76 715 $fontColorType = $imageType == 1 ? 'plain' : ($imageType > 3 ? 'random' : 'cyclic');
Chris@76 716 // Are the fonts random sizes?
Chris@76 717 $fontSizeRandom = $imageType > 3 ? true : false;
Chris@76 718 // How much space between characters?
Chris@76 719 $fontHorSpace = $imageType > 3 ? 'high' : ($imageType == 1 ? 'medium' : 'minus');
Chris@76 720 // Where do characters sit on the image? (Fixed position or random/very random)
Chris@76 721 $fontVerPos = $imageType == 1 ? 'fixed' : ($imageType > 3 ? 'vrandom' : 'random');
Chris@76 722 // Make font semi-transparent?
Chris@76 723 $fontTrans = $imageType == 2 || $imageType == 3 ? true : false;
Chris@76 724 // Give the image a border?
Chris@76 725 $hasBorder = $simpleBGColor;
Chris@76 726
Chris@76 727 // Is this GD2? Needed for pixel size.
Chris@76 728 $testGD = get_extension_funcs('gd');
Chris@76 729 $gd2 = in_array('imagecreatetruecolor', $testGD) && function_exists('imagecreatetruecolor');
Chris@76 730 unset($testGD);
Chris@76 731
Chris@76 732 // The amount of pixels inbetween characters.
Chris@76 733 $character_spacing = 1;
Chris@76 734
Chris@76 735 // What color is the background - generally white unless we're on "hard".
Chris@76 736 if ($simpleBGColor)
Chris@76 737 $background_color = array(255, 255, 255);
Chris@76 738 else
Chris@76 739 $background_color = isset($settings['verification_background']) ? $settings['verification_background'] : array(236, 237, 243);
Chris@76 740
Chris@76 741 // The color of the characters shown (red, green, blue).
Chris@76 742 if ($simpleFGColor)
Chris@76 743 $foreground_color = array(0, 0, 0);
Chris@76 744 else
Chris@76 745 {
Chris@76 746 $foreground_color = array(64, 101, 136);
Chris@76 747
Chris@76 748 // Has the theme author requested a custom color?
Chris@76 749 if (isset($settings['verification_foreground']))
Chris@76 750 $foreground_color = $settings['verification_foreground'];
Chris@76 751 }
Chris@76 752
Chris@76 753 if (!is_dir($settings['default_theme_dir'] . '/fonts'))
Chris@76 754 return false;
Chris@76 755
Chris@76 756 // Get a list of the available fonts.
Chris@76 757 $font_dir = dir($settings['default_theme_dir'] . '/fonts');
Chris@76 758 $font_list = array();
Chris@76 759 $ttfont_list = array();
Chris@76 760 while ($entry = $font_dir->read())
Chris@76 761 {
Chris@76 762 if (preg_match('~^(.+)\.gdf$~', $entry, $matches) === 1)
Chris@76 763 $font_list[] = $entry;
Chris@76 764 elseif (preg_match('~^(.+)\.ttf$~', $entry, $matches) === 1)
Chris@76 765 $ttfont_list[] = $entry;
Chris@76 766 }
Chris@76 767
Chris@76 768 if (empty($font_list))
Chris@76 769 return false;
Chris@76 770
Chris@76 771 // For non-hard things don't even change fonts.
Chris@76 772 if (!$varyFonts)
Chris@76 773 {
Chris@76 774 $font_list = array($font_list[0]);
Chris@76 775 // Try use Screenge if we can - it looks good!
Chris@76 776 if (in_array('Screenge.ttf', $ttfont_list))
Chris@76 777 $ttfont_list = array('Screenge.ttf');
Chris@76 778 else
Chris@76 779 $ttfont_list = empty($ttfont_list) ? array() : array($ttfont_list[0]);
Chris@76 780
Chris@76 781 }
Chris@76 782
Chris@76 783 // Create a list of characters to be shown.
Chris@76 784 $characters = array();
Chris@76 785 $loaded_fonts = array();
Chris@76 786 for ($i = 0; $i < strlen($code); $i++)
Chris@76 787 {
Chris@76 788 $characters[$i] = array(
Chris@76 789 'id' => $code{$i},
Chris@76 790 'font' => array_rand($font_list),
Chris@76 791 );
Chris@76 792
Chris@76 793 $loaded_fonts[$characters[$i]['font']] = null;
Chris@76 794 }
Chris@76 795
Chris@76 796 // Load all fonts and determine the maximum font height.
Chris@76 797 foreach ($loaded_fonts as $font_index => $dummy)
Chris@76 798 $loaded_fonts[$font_index] = imageloadfont($settings['default_theme_dir'] . '/fonts/' . $font_list[$font_index]);
Chris@76 799
Chris@76 800 // Determine the dimensions of each character.
Chris@76 801 $total_width = $character_spacing * strlen($code) + 20;
Chris@76 802 $max_height = 0;
Chris@76 803 foreach ($characters as $char_index => $character)
Chris@76 804 {
Chris@76 805 $characters[$char_index]['width'] = imagefontwidth($loaded_fonts[$character['font']]);
Chris@76 806 $characters[$char_index]['height'] = imagefontheight($loaded_fonts[$character['font']]);
Chris@76 807
Chris@76 808 $max_height = max($characters[$char_index]['height'] + 5, $max_height);
Chris@76 809 $total_width += $characters[$char_index]['width'];
Chris@76 810 }
Chris@76 811
Chris@76 812 // Create an image.
Chris@76 813 $code_image = $gd2 ? imagecreatetruecolor($total_width, $max_height) : imagecreate($total_width, $max_height);
Chris@76 814
Chris@76 815 // Draw the background.
Chris@76 816 $bg_color = imagecolorallocate($code_image, $background_color[0], $background_color[1], $background_color[2]);
Chris@76 817 imagefilledrectangle($code_image, 0, 0, $total_width - 1, $max_height - 1, $bg_color);
Chris@76 818
Chris@76 819 // Randomize the foreground color a little.
Chris@76 820 for ($i = 0; $i < 3; $i++)
Chris@76 821 $foreground_color[$i] = mt_rand(max($foreground_color[$i] - 3, 0), min($foreground_color[$i] + 3, 255));
Chris@76 822 $fg_color = imagecolorallocate($code_image, $foreground_color[0], $foreground_color[1], $foreground_color[2]);
Chris@76 823
Chris@76 824 // Color for the dots.
Chris@76 825 for ($i = 0; $i < 3; $i++)
Chris@76 826 $dotbgcolor[$i] = $background_color[$i] < $foreground_color[$i] ? mt_rand(0, max($foreground_color[$i] - 20, 0)) : mt_rand(min($foreground_color[$i] + 20, 255), 255);
Chris@76 827 $randomness_color = imagecolorallocate($code_image, $dotbgcolor[0], $dotbgcolor[1], $dotbgcolor[2]);
Chris@76 828
Chris@76 829 // Some squares/rectanges for new extreme level
Chris@76 830 if ($noiseType == 'extreme')
Chris@76 831 {
Chris@76 832 for ($i = 0; $i < rand(1, 5); $i++)
Chris@76 833 {
Chris@76 834 $x1 = rand(0, $total_width / 4);
Chris@76 835 $x2 = $x1 + round(rand($total_width / 4, $total_width));
Chris@76 836 $y1 = rand(0, $max_height);
Chris@76 837 $y2 = $y1 + round(rand(0, $max_height / 3));
Chris@76 838 imagefilledrectangle($code_image, $x1, $y1, $x2, $y2, mt_rand(0, 1) ? $fg_color : $randomness_color);
Chris@76 839 }
Chris@76 840 }
Chris@76 841
Chris@76 842 // Fill in the characters.
Chris@76 843 if (!$disableChars)
Chris@76 844 {
Chris@76 845 $cur_x = 0;
Chris@76 846 foreach ($characters as $char_index => $character)
Chris@76 847 {
Chris@76 848 // Can we use true type fonts?
Chris@76 849 $can_do_ttf = function_exists('imagettftext');
Chris@76 850
Chris@76 851 // How much rotation will we give?
Chris@76 852 if ($rotationType == 'none')
Chris@76 853 $angle = 0;
Chris@76 854 else
Chris@76 855 $angle = mt_rand(-100, 100) / ($rotationType == 'high' ? 6 : 10);
Chris@76 856
Chris@76 857 // What color shall we do it?
Chris@76 858 if ($fontColorType == 'cyclic')
Chris@76 859 {
Chris@76 860 // Here we'll pick from a set of acceptance types.
Chris@76 861 $colors = array(
Chris@76 862 array(10, 120, 95),
Chris@76 863 array(46, 81, 29),
Chris@76 864 array(4, 22, 154),
Chris@76 865 array(131, 9, 130),
Chris@76 866 array(0, 0, 0),
Chris@76 867 array(143, 39, 31),
Chris@76 868 );
Chris@76 869 if (!isset($last_index))
Chris@76 870 $last_index = -1;
Chris@76 871 $new_index = $last_index;
Chris@76 872 while ($last_index == $new_index)
Chris@76 873 $new_index = mt_rand(0, count($colors) - 1);
Chris@76 874 $char_fg_color = $colors[$new_index];
Chris@76 875 $last_index = $new_index;
Chris@76 876 }
Chris@76 877 elseif ($fontColorType == 'random')
Chris@76 878 $char_fg_color = array(mt_rand(max($foreground_color[0] - 2, 0), $foreground_color[0]), mt_rand(max($foreground_color[1] - 2, 0), $foreground_color[1]), mt_rand(max($foreground_color[2] - 2, 0), $foreground_color[2]));
Chris@76 879 else
Chris@76 880 $char_fg_color = array($foreground_color[0], $foreground_color[1], $foreground_color[2]);
Chris@76 881
Chris@76 882 if (!empty($can_do_ttf))
Chris@76 883 {
Chris@76 884 // GD2 handles font size differently.
Chris@76 885 if ($fontSizeRandom)
Chris@76 886 $font_size = $gd2 ? mt_rand(17, 19) : mt_rand(18, 25);
Chris@76 887 else
Chris@76 888 $font_size = $gd2 ? 18 : 24;
Chris@76 889
Chris@76 890 // Work out the sizes - also fix the character width cause TTF not quite so wide!
Chris@76 891 $font_x = $fontHorSpace == 'minus' && $cur_x > 0 ? $cur_x - 3 : $cur_x + 5;
Chris@76 892 $font_y = $max_height - ($fontVerPos == 'vrandom' ? mt_rand(2, 8) : ($fontVerPos == 'random' ? mt_rand(3, 5) : 5));
Chris@76 893
Chris@76 894 // What font face?
Chris@76 895 if (!empty($ttfont_list))
Chris@76 896 $fontface = $settings['default_theme_dir'] . '/fonts/' . $ttfont_list[mt_rand(0, count($ttfont_list) - 1)];
Chris@76 897
Chris@76 898 // What color are we to do it in?
Chris@76 899 $is_reverse = $showReverseChars ? mt_rand(0, 1) : false;
Chris@76 900 $char_color = function_exists('imagecolorallocatealpha') && $fontTrans ? imagecolorallocatealpha($code_image, $char_fg_color[0], $char_fg_color[1], $char_fg_color[2], 50) : imagecolorallocate($code_image, $char_fg_color[0], $char_fg_color[1], $char_fg_color[2]);
Chris@76 901
Chris@76 902 $fontcord = @imagettftext($code_image, $font_size, $angle, $font_x, $font_y, $char_color, $fontface, $character['id']);
Chris@76 903 if (empty($fontcord))
Chris@76 904 $can_do_ttf = false;
Chris@76 905 elseif ($is_reverse)
Chris@76 906 {
Chris@76 907 imagefilledpolygon($code_image, $fontcord, 4, $fg_color);
Chris@76 908 // Put the character back!
Chris@76 909 imagettftext($code_image, $font_size, $angle, $font_x, $font_y, $randomness_color, $fontface, $character['id']);
Chris@76 910 }
Chris@76 911
Chris@76 912 if ($can_do_ttf)
Chris@76 913 $cur_x = max($fontcord[2], $fontcord[4]) + ($angle == 0 ? 0 : 3);
Chris@76 914 }
Chris@76 915
Chris@76 916 if (!$can_do_ttf)
Chris@76 917 {
Chris@76 918 // Rotating the characters a little...
Chris@76 919 if (function_exists('imagerotate'))
Chris@76 920 {
Chris@76 921 $char_image = $gd2 ? imagecreatetruecolor($character['width'], $character['height']) : imagecreate($character['width'], $character['height']);
Chris@76 922 $char_bgcolor = imagecolorallocate($char_image, $background_color[0], $background_color[1], $background_color[2]);
Chris@76 923 imagefilledrectangle($char_image, 0, 0, $character['width'] - 1, $character['height'] - 1, $char_bgcolor);
Chris@76 924 imagechar($char_image, $loaded_fonts[$character['font']], 0, 0, $character['id'], imagecolorallocate($char_image, $char_fg_color[0], $char_fg_color[1], $char_fg_color[2]));
Chris@76 925 $rotated_char = imagerotate($char_image, mt_rand(-100, 100) / 10, $char_bgcolor);
Chris@76 926 imagecopy($code_image, $rotated_char, $cur_x, 0, 0, 0, $character['width'], $character['height']);
Chris@76 927 imagedestroy($rotated_char);
Chris@76 928 imagedestroy($char_image);
Chris@76 929 }
Chris@76 930
Chris@76 931 // Sorry, no rotation available.
Chris@76 932 else
Chris@76 933 imagechar($code_image, $loaded_fonts[$character['font']], $cur_x, floor(($max_height - $character['height']) / 2), $character['id'], imagecolorallocate($code_image, $char_fg_color[0], $char_fg_color[1], $char_fg_color[2]));
Chris@76 934 $cur_x += $character['width'] + $character_spacing;
Chris@76 935 }
Chris@76 936 }
Chris@76 937 }
Chris@76 938 // If disabled just show a cross.
Chris@76 939 else
Chris@76 940 {
Chris@76 941 imageline($code_image, 0, 0, $total_width, $max_height, $fg_color);
Chris@76 942 imageline($code_image, 0, $max_height, $total_width, 0, $fg_color);
Chris@76 943 }
Chris@76 944
Chris@76 945 // Make the background color transparent on the hard image.
Chris@76 946 if (!$simpleBGColor)
Chris@76 947 imagecolortransparent($code_image, $bg_color);
Chris@76 948 if ($hasBorder)
Chris@76 949 imagerectangle($code_image, 0, 0, $total_width - 1, $max_height - 1, $fg_color);
Chris@76 950
Chris@76 951 // Add some noise to the background?
Chris@76 952 if ($noiseType != 'none')
Chris@76 953 {
Chris@76 954 for ($i = mt_rand(0, 2); $i < $max_height; $i += mt_rand(1, 2))
Chris@76 955 for ($j = mt_rand(0, 10); $j < $total_width; $j += mt_rand(1, 10))
Chris@76 956 imagesetpixel($code_image, $j, $i, mt_rand(0, 1) ? $fg_color : $randomness_color);
Chris@76 957
Chris@76 958 // Put in some lines too?
Chris@76 959 if ($noiseType != 'extreme')
Chris@76 960 {
Chris@76 961 $num_lines = $noiseType == 'high' ? mt_rand(3, 7) : mt_rand(2, 5);
Chris@76 962 for ($i = 0; $i < $num_lines; $i++)
Chris@76 963 {
Chris@76 964 if (mt_rand(0, 1))
Chris@76 965 {
Chris@76 966 $x1 = mt_rand(0, $total_width);
Chris@76 967 $x2 = mt_rand(0, $total_width);
Chris@76 968 $y1 = 0; $y2 = $max_height;
Chris@76 969 }
Chris@76 970 else
Chris@76 971 {
Chris@76 972 $y1 = mt_rand(0, $max_height);
Chris@76 973 $y2 = mt_rand(0, $max_height);
Chris@76 974 $x1 = 0; $x2 = $total_width;
Chris@76 975 }
Chris@76 976 imagesetthickness($code_image, mt_rand(1, 2));
Chris@76 977 imageline($code_image, $x1, $y1, $x2, $y2, mt_rand(0, 1) ? $fg_color : $randomness_color);
Chris@76 978 }
Chris@76 979 }
Chris@76 980 else
Chris@76 981 {
Chris@76 982 // Put in some ellipse
Chris@76 983 $num_ellipse = $noiseType == 'extreme' ? mt_rand(6, 12) : mt_rand(2, 6);
Chris@76 984 for ($i = 0; $i < $num_ellipse; $i++)
Chris@76 985 {
Chris@76 986 $x1 = round(rand(($total_width / 4) * -1, $total_width + ($total_width / 4)));
Chris@76 987 $x2 = round(rand($total_width / 2, 2 * $total_width));
Chris@76 988 $y1 = round(rand(($max_height / 4) * -1, $max_height + ($max_height / 4)));
Chris@76 989 $y2 = round(rand($max_height / 2, 2 * $max_height));
Chris@76 990 imageellipse($code_image, $x1, $y1, $x2, $y2, mt_rand(0, 1) ? $fg_color : $randomness_color);
Chris@76 991 }
Chris@76 992 }
Chris@76 993 }
Chris@76 994
Chris@76 995 // Show the image.
Chris@76 996 if (function_exists('imagegif'))
Chris@76 997 {
Chris@76 998 header('Content-type: image/gif');
Chris@76 999 imagegif($code_image);
Chris@76 1000 }
Chris@76 1001 else
Chris@76 1002 {
Chris@76 1003 header('Content-type: image/png');
Chris@76 1004 imagepng($code_image);
Chris@76 1005 }
Chris@76 1006
Chris@76 1007 // Bail out.
Chris@76 1008 imagedestroy($code_image);
Chris@76 1009 die();
Chris@76 1010 }
Chris@76 1011
Chris@76 1012 // Create a letter for the visual verification code.
Chris@76 1013 function showLetterImage($letter)
Chris@76 1014 {
Chris@76 1015 global $settings;
Chris@76 1016
Chris@76 1017 if (!is_dir($settings['default_theme_dir'] . '/fonts'))
Chris@76 1018 return false;
Chris@76 1019
Chris@76 1020 // Get a list of the available font directories.
Chris@76 1021 $font_dir = dir($settings['default_theme_dir'] . '/fonts');
Chris@76 1022 $font_list = array();
Chris@76 1023 while ($entry = $font_dir->read())
Chris@76 1024 if ($entry[0] !== '.' && is_dir($settings['default_theme_dir'] . '/fonts/' . $entry) && file_exists($settings['default_theme_dir'] . '/fonts/' . $entry . '.gdf'))
Chris@76 1025 $font_list[] = $entry;
Chris@76 1026
Chris@76 1027 if (empty($font_list))
Chris@76 1028 return false;
Chris@76 1029
Chris@76 1030 // Pick a random font.
Chris@76 1031 $random_font = $font_list[array_rand($font_list)];
Chris@76 1032
Chris@76 1033 // Check if the given letter exists.
Chris@76 1034 if (!file_exists($settings['default_theme_dir'] . '/fonts/' . $random_font . '/' . $letter . '.gif'))
Chris@76 1035 return false;
Chris@76 1036
Chris@76 1037 // Include it!
Chris@76 1038 header('Content-type: image/gif');
Chris@76 1039 include($settings['default_theme_dir'] . '/fonts/' . $random_font . '/' . $letter . '.gif');
Chris@76 1040
Chris@76 1041 // Nothing more to come.
Chris@76 1042 die();
Chris@76 1043 }
Chris@76 1044
Chris@76 1045 ?>