00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 if (!defined('SI_IMAGE_JPEG'))
00087 define('SI_IMAGE_JPEG', 1);
00088
00089
00090
00091 if (!defined('SI_IMAGE_PNG'))
00092 define('SI_IMAGE_PNG', 2);
00093
00094
00095
00096
00097 if (!defined('SI_IMAGE_GIF'))
00098 define('SI_IMAGE_GIF', 3);
00099
00100
00101
00102
00103
00104
00105
00106
00107 class Securimage {
00108
00109
00110
00111
00112
00113
00114 var $image_width;
00115
00116
00117
00118
00119
00120
00121 var $image_height;
00122
00123
00124
00125
00126
00127
00128
00129 var $image_type;
00130
00131
00132
00133
00134
00135
00136 var $code_length;
00137
00138
00139
00140
00141
00142
00143
00144
00145 var $charset;
00146
00147
00148
00149
00150
00151
00152 var $wordlist_file;
00153
00154
00155
00156
00157
00158
00159 var $use_wordlist = false;
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 var $gd_font_file;
00170
00171
00172
00173
00174
00175
00176
00177
00178 var $gd_font_size;
00179
00180
00181
00182
00183
00184
00185 var $use_gd_font;
00186
00187
00188
00189
00190
00191
00192
00193
00194 var $ttf_file;
00195
00196
00197
00198
00199
00200
00201
00202 var $perturbation;
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 var $text_angle_minimum;
00213
00214
00215
00216
00217
00218
00219
00220
00221 var $text_angle_maximum;
00222
00223
00224
00225
00226
00227
00228
00229
00230 var $text_x_start;
00231
00232
00233
00234
00235
00236
00237 var $image_bg_color;
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 var $background_directory = null;
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 var $text_color;
00259
00260
00261
00262
00263
00264
00265
00266 var $use_multi_text;
00267
00268
00269
00270
00271
00272
00273 var $multi_text_color;
00274
00275
00276
00277
00278
00279
00280
00281 var $use_transparent_text;
00282
00283
00284
00285
00286
00287
00288
00289
00290 var $text_transparency_percentage;
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 var $num_lines;
00302
00303
00304
00305
00306
00307
00308 var $line_color;
00309
00310
00311
00312
00313
00314
00315
00316 var $draw_lines_over_text;
00317
00318
00319
00320
00321
00322
00323
00324 var $image_signature;
00325
00326
00327
00328
00329
00330
00331
00332 var $signature_color;
00333
00334
00335
00336
00337
00338
00339
00340
00341 var $audio_path;
00342
00343
00344
00345
00346
00347
00348 var $audio_format;
00349
00350
00351
00352
00353
00354
00355
00356
00357 var $session_name = '';
00358
00359
00360
00361
00362
00363
00364
00365
00366 var $expiry_time;
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377 var $sqlite_database;
00378
00379
00380
00381
00382
00383 var $use_sqlite_db;
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395 var $im;
00396
00397
00398
00399
00400
00401
00402
00403 var $tmpimg;
00404
00405
00406
00407
00408
00409
00410
00411
00412 var $iscale;
00413
00414
00415
00416
00417
00418
00419
00420 var $bgimg;
00421
00422
00423
00424
00425
00426
00427
00428 var $code;
00429
00430
00431
00432
00433
00434
00435
00436 var $code_entered;
00437
00438
00439
00440
00441
00442
00443
00444 var $correct_code;
00445
00446
00447
00448
00449
00450
00451
00452 var $sqlite_handle;
00453
00454
00455
00456
00457
00458
00459
00460 var $gdlinecolor;
00461
00462
00463
00464
00465
00466
00467
00468 var $gdmulticolor;
00469
00470
00471
00472
00473
00474
00475
00476 var $gdtextcolor;
00477
00478
00479
00480
00481
00482
00483
00484 var $gdsignaturecolor;
00485
00486
00487
00488
00489
00490
00491
00492 var $gdbgcolor;
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506 function Securimage()
00507 {
00508
00509 if ( session_id() == '' ) {
00510 if (trim($this->session_name) != '') {
00511 session_name($this->session_name);
00512 }
00513 session_start();
00514 }
00515
00516
00517 $this->image_width = 230;
00518 $this->image_height = 80;
00519 $this->image_type = SI_IMAGE_PNG;
00520
00521 $this->code_length = 6;
00522 $this->charset = 'ABCDEFGHKLMNPRSTUVWYZabcdefghklmnprstuvwyz23456789';
00523 $this->wordlist_file = './words/words.txt';
00524 $this->use_wordlist = false;
00525
00526 $this->gd_font_file = 'gdfonts/automatic.gdf';
00527 $this->use_gd_font = false;
00528 $this->gd_font_size = 24;
00529 $this->text_x_start = 15;
00530
00531 $this->ttf_file = './AHGBold.ttf';
00532
00533 $this->perturbation = 0.75;
00534 $this->iscale = 5;
00535 $this->text_angle_minimum = 0;
00536 $this->text_angle_maximum = 0;
00537
00538 $this->image_bg_color = new Securimage_Color(0xff, 0xff, 0xff);
00539 $this->text_color = new Securimage_Color(0x3d, 0x3d, 0x3d);
00540 $this->multi_text_color = array(new Securimage_Color(0x0, 0x20, 0xCC),
00541 new Securimage_Color(0x0, 0x30, 0xEE),
00542 new Securimage_color(0x0, 0x40, 0xCC),
00543 new Securimage_Color(0x0, 0x50, 0xEE),
00544 new Securimage_Color(0x0, 0x60, 0xCC));
00545 $this->use_multi_text = false;
00546
00547 $this->use_transparent_text = false;
00548 $this->text_transparency_percentage = 30;
00549
00550 $this->num_lines = 10;
00551 $this->line_color = new Securimage_Color(0x3d, 0x3d, 0x3d);
00552 $this->draw_lines_over_text = true;
00553
00554 $this->image_signature = '';
00555 $this->signature_color = new Securimage_Color(0x20, 0x50, 0xCC);
00556 $this->signature_font = './AHGBold.ttf';
00557
00558 $this->audio_path = './audio/';
00559 $this->audio_format = 'mp3';
00560 $this->session_name = '';
00561 $this->expiry_time = 900;
00562
00563 $this->sqlite_database = 'database/securimage.sqlite';
00564 $this->use_sqlite_db = false;
00565
00566 $this->sqlite_handle = false;
00567 }
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582 function show($background_image = "")
00583 {
00584 if($background_image != "" && is_readable($background_image)) {
00585 $this->bgimg = $background_image;
00586 }
00587
00588 $this->doImage();
00589 }
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605 function check($code)
00606 {
00607 $this->code_entered = $code;
00608 $this->validate();
00609 return $this->correct_code;
00610 }
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623 function outputAudioFile()
00624 {
00625 if (strtolower($this->audio_format) == 'wav') {
00626 header('Content-type: audio/x-wav');
00627 $ext = 'wav';
00628 } else {
00629 header('Content-type: audio/mpeg');
00630 $ext = 'mp3';
00631 }
00632
00633 header("Content-Disposition: attachment; filename=\"securimage_audio.{$ext}\"");
00634 header('Cache-Control: no-store, no-cache, must-revalidate');
00635 header('Expires: Sun, 1 Jan 2000 12:00:00 GMT');
00636 header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . 'GMT');
00637
00638 $audio = $this->getAudibleCode($ext);
00639
00640 header('Content-Length: ' . strlen($audio));
00641
00642 echo $audio;
00643 exit;
00644 }
00645
00646
00647
00648
00649
00650
00651
00652 function doImage()
00653 {
00654 if ($this->use_gd_font == true) {
00655 $this->iscale = 1;
00656 }
00657 if($this->use_transparent_text == true || $this->bgimg != "") {
00658 $this->im = imagecreatetruecolor($this->image_width, $this->image_height);
00659 $this->tmpimg = imagecreatetruecolor($this->image_width * $this->iscale, $this->image_height * $this->iscale);
00660
00661 } else {
00662 $this->im = imagecreate($this->image_width, $this->image_height);
00663 $this->tmpimg = imagecreate($this->image_width * $this->iscale, $this->image_height * $this->iscale);
00664 }
00665
00666 $this->allocateColors();
00667 imagepalettecopy($this->tmpimg, $this->im);
00668
00669 $this->setBackground();
00670
00671 $this->createCode();
00672
00673 if (!$this->draw_lines_over_text && $this->num_lines > 0) $this->drawLines();
00674
00675 $this->drawWord();
00676 if ($this->use_gd_font == false && is_readable($this->ttf_file)) $this->distortedCopy();
00677
00678 if ($this->draw_lines_over_text && $this->num_lines > 0) $this->drawLines();
00679
00680 if (trim($this->image_signature) != '') $this->addSignature();
00681
00682 $this->output();
00683
00684 }
00685
00686
00687
00688
00689
00690
00691
00692 function allocateColors()
00693 {
00694
00695 $this->gdbgcolor = imagecolorallocate($this->im, $this->image_bg_color->r, $this->image_bg_color->g, $this->image_bg_color->b);
00696
00697 $alpha = intval($this->text_transparency_percentage / 100 * 127);
00698
00699 if ($this->use_transparent_text == true) {
00700 $this->gdtextcolor = imagecolorallocatealpha($this->im, $this->text_color->r, $this->text_color->g, $this->text_color->b, $alpha);
00701 $this->gdlinecolor = imagecolorallocatealpha($this->im, $this->line_color->r, $this->line_color->g, $this->line_color->b, $alpha);
00702 } else {
00703 $this->gdtextcolor = imagecolorallocate($this->im, $this->text_color->r, $this->text_color->g, $this->text_color->b);
00704 $this->gdlinecolor = imagecolorallocate($this->im, $this->line_color->r, $this->line_color->g, $this->line_color->b);
00705 }
00706
00707 $this->gdsignaturecolor = imagecolorallocate($this->im, $this->signature_color->r, $this->signature_color->g, $this->signature_color->b);
00708
00709 if ($this->use_multi_text == true) {
00710 $this->gdmulticolor = array();
00711
00712 foreach($this->multi_text_color as $color) {
00713 if ($this->use_transparent_text == true) {
00714 $this->gdmulticolor[] = imagecolorallocatealpha($this->im, $color->r, $color->g, $color->b, $alpha);
00715 } else {
00716 $this->gdmulticolor[] = imagecolorallocate($this->im, $color->r, $color->g, $color->b);
00717 }
00718 }
00719 }
00720 }
00721
00722
00723
00724
00725
00726
00727
00728 function setBackground()
00729 {
00730 imagefilledrectangle($this->im, 0, 0, $this->image_width * $this->iscale, $this->image_height * $this->iscale, $this->gdbgcolor);
00731 imagefilledrectangle($this->tmpimg, 0, 0, $this->image_width * $this->iscale, $this->image_height * $this->iscale, $this->gdbgcolor);
00732
00733 if ($this->bgimg == '') {
00734 if ($this->background_directory != null && is_dir($this->background_directory) && is_readable($this->background_directory)) {
00735 $img = $this->getBackgroundFromDirectory();
00736 if ($img != false) {
00737 $this->bgimg = $img;
00738 }
00739 }
00740 }
00741
00742 $dat = @getimagesize($this->bgimg);
00743 if($dat == false) {
00744 return;
00745 }
00746
00747 switch($dat[2]) {
00748 case 1: $newim = @imagecreatefromgif($this->bgimg); break;
00749 case 2: $newim = @imagecreatefromjpeg($this->bgimg); break;
00750 case 3: $newim = @imagecreatefrompng($this->bgimg); break;
00751 case 15: $newim = @imagecreatefromwbmp($this->bgimg); break;
00752 case 16: $newim = @imagecreatefromxbm($this->bgimg); break;
00753 default: return;
00754 }
00755
00756 if(!$newim) return;
00757
00758 imagecopyresized($this->im, $newim, 0, 0, 0, 0, $this->image_width, $this->image_height, imagesx($newim), imagesy($newim));
00759 }
00760
00761
00762
00763
00764
00765
00766
00767
00768 function getBackgroundFromDirectory()
00769 {
00770 $images = array();
00771
00772 if ($dh = opendir($this->background_directory)) {
00773 while (($file = readdir($dh)) !== false) {
00774 if (preg_match('/(jpg|gif|png)$/i', $file)) $images[] = $file;
00775 }
00776
00777 closedir($dh);
00778
00779 if (sizeof($images) > 0) {
00780 return rtrim($this->background_directory, '/') . '/' . $images[rand(0, sizeof($images)-1)];
00781 }
00782 }
00783
00784 return false;
00785 }
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795 function drawLines()
00796 {
00797 for ($line = 0; $line < $this->num_lines; ++$line) {
00798 $x = $this->image_width * (1 + $line) / ($this->num_lines + 1);
00799 $x += (0.5 - $this->frand()) * $this->image_width / $this->num_lines;
00800 $y = rand($this->image_height * 0.1, $this->image_height * 0.9);
00801
00802 $theta = ($this->frand()-0.5) * M_PI * 0.7;
00803 $w = $this->image_width;
00804 $len = rand($w * 0.4, $w * 0.7);
00805 $lwid = rand(0, 2);
00806
00807 $k = $this->frand() * 0.6 + 0.2;
00808 $k = $k * $k * 0.5;
00809 $phi = $this->frand() * 6.28;
00810 $step = 0.5;
00811 $dx = $step * cos($theta);
00812 $dy = $step * sin($theta);
00813 $n = $len / $step;
00814 $amp = 1.5 * $this->frand() / ($k + 5.0 / $len);
00815 $x0 = $x - 0.5 * $len * cos($theta);
00816 $y0 = $y - 0.5 * $len * sin($theta);
00817
00818 $ldx = round(-$dy * $lwid);
00819 $ldy = round($dx * $lwid);
00820
00821 for ($i = 0; $i < $n; ++$i) {
00822 $x = $x0 + $i * $dx + $amp * $dy * sin($k * $i * $step + $phi);
00823 $y = $y0 + $i * $dy - $amp * $dx * sin($k * $i * $step + $phi);
00824 imagefilledrectangle($this->im, $x, $y, $x + $lwid, $y + $lwid, $this->gdlinecolor);
00825 }
00826 }
00827 }
00828
00829
00830
00831
00832
00833
00834
00835 function drawWord()
00836 {
00837 $width2 = $this->image_width * $this->iscale;
00838 $height2 = $this->image_height * $this->iscale;
00839
00840 if ($this->use_gd_font == true || !is_readable($this->ttf_file)) {
00841 if (!is_int($this->gd_font_file)) {
00842 $font = @imageloadfont($this->gd_font_file);
00843 if ($font == false) {
00844 trigger_error("Failed to load GD Font file {$this->gd_font_file} ", E_USER_WARNING);
00845 return;
00846 }
00847 } else {
00848 $font = $this->gd_font_file;
00849 }
00850
00851 imagestring($this->im, $font, $this->text_x_start, ($this->image_height / 2) - ($this->gd_font_size / 2), $this->code, $this->gdtextcolor);
00852 } else {
00853 $font_size = $height2 * .35;
00854 $bb = imagettfbbox($font_size, 0, $this->ttf_file, $this->code);
00855 $tx = $bb[4] - $bb[0];
00856 $ty = $bb[5] - $bb[1];
00857 $x = floor($width2 / 2 - $tx / 2 - $bb[0]);
00858 $y = round($height2 / 2 - $ty / 2 - $bb[1]);
00859
00860 $strlen = strlen($this->code);
00861 if (!is_array($this->multi_text_color)) $this->use_multi_text = false;
00862
00863
00864 if ($this->use_multi_text == false && $this->text_angle_minimum == 0 && $this->text_angle_maximum == 0) {
00865 imagettftext($this->tmpimg, $font_size, 0, $x, $y, $this->gdtextcolor, $this->ttf_file, $this->code);
00866 } else {
00867 for($i = 0; $i < $strlen; ++$i) {
00868 $angle = rand($this->text_angle_minimum, $this->text_angle_maximum);
00869 $y = rand($y - 5, $y + 5);
00870 if ($this->use_multi_text == true) {
00871 $font_color = $this->gdmulticolor[rand(0, sizeof($this->gdmulticolor) - 1)];
00872 } else {
00873 $font_color = $this->gdtextcolor;
00874 }
00875
00876 $ch = $this->code{$i};
00877
00878 imagettftext($this->tmpimg, $font_size, $angle, $x, $y, $font_color, $this->ttf_file, $ch);
00879
00880
00881
00882
00883 if (strpos('abcdeghknopqsuvxyz', $ch) !== false) {
00884 $min_x = $font_size - ($this->iscale * 6);
00885 $max_x = $font_size - ($this->iscale * 6);
00886 } else if (strpos('ilI1', $ch) !== false) {
00887 $min_x = $font_size / 5;
00888 $max_x = $font_size / 3;
00889 } else if (strpos('fjrt', $ch) !== false) {
00890 $min_x = $font_size - ($this->iscale * 12);
00891 $max_x = $font_size - ($this->iscale * 12);
00892 } else if ($ch == 'wm') {
00893 $min_x = $font_size;
00894 $max_x = $font_size + ($this->iscale * 3);
00895 } else {
00896 $min_x = $font_size + ($this->iscale * 2);
00897 $max_x = $font_size + ($this->iscale * 5);
00898 }
00899
00900 $x += rand($min_x, $max_x);
00901 }
00902 }
00903 }
00904
00905
00906 }
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918 function distortedCopy()
00919 {
00920 $numpoles = 3;
00921
00922
00923 for ($i = 0; $i < $numpoles; ++$i) {
00924 $px[$i] = rand($this->image_width * 0.3, $this->image_width * 0.7);
00925 $py[$i] = rand($this->image_height * 0.3, $this->image_height * 0.7);
00926 $rad[$i] = rand($this->image_width * 0.4, $this->image_width * 0.7);
00927 $tmp = -$this->frand() * 0.15 - 0.15;
00928 $amp[$i] = $this->perturbation * $tmp;
00929 }
00930
00931 $bgCol = imagecolorat($this->tmpimg, 0, 0);
00932 $width2 = $this->iscale * $this->image_width;
00933 $height2 = $this->iscale * $this->image_height;
00934
00935 imagepalettecopy($this->im, $this->tmpimg);
00936
00937
00938 for ($ix = 0; $ix < $this->image_width; ++$ix) {
00939 for ($iy = 0; $iy < $this->image_height; ++$iy) {
00940 $x = $ix;
00941 $y = $iy;
00942
00943 for ($i = 0; $i < $numpoles; ++$i) {
00944 $dx = $ix - $px[$i];
00945 $dy = $iy - $py[$i];
00946 if ($dx == 0 && $dy == 0) continue;
00947
00948 $r = sqrt($dx * $dx + $dy * $dy);
00949 if ($r > $rad[$i]) continue;
00950
00951 $rscale = $amp[$i] * sin(3.14 * $r / $rad[$i]);
00952 $x += $dx * $rscale;
00953 $y += $dy * $rscale;
00954 }
00955
00956 $c = $bgCol;
00957 $x *= $this->iscale;
00958 $y *= $this->iscale;
00959
00960 if ($x >= 0 && $x < $width2 && $y >= 0 && $y < $height2) {
00961 $c = imagecolorat($this->tmpimg, $x, $y);
00962 }
00963
00964 if ($c != $bgCol) {
00965 imagesetpixel($this->im, $ix, $iy, $c);
00966 }
00967 }
00968 }
00969 }
00970
00971
00972
00973
00974
00975
00976
00977
00978 function createCode()
00979 {
00980 $this->code = false;
00981
00982 if ($this->use_wordlist && is_readable($this->wordlist_file)) {
00983 $this->code = $this->readCodeFromFile();
00984 }
00985
00986 if ($this->code == false) {
00987 $this->code = $this->generateCode($this->code_length);
00988 }
00989
00990 $this->saveData();
00991 }
00992
00993
00994
00995
00996
00997
00998
00999
01000 function generateCode($len)
01001 {
01002 $code = '';
01003
01004 for($i = 1, $cslen = strlen($this->charset); $i <= $len; ++$i) {
01005 $code .= $this->charset{rand(0, $cslen - 1)};
01006 }
01007 return $code;
01008 }
01009
01010
01011
01012
01013
01014
01015
01016
01017 function readCodeFromFile()
01018 {
01019 $fp = @fopen($this->wordlist_file, 'rb');
01020 if (!$fp) return false;
01021
01022 $fsize = filesize($this->wordlist_file);
01023 if ($fsize < 32) return false;
01024
01025 if ($fsize < 128) {
01026 $max = $fsize;
01027 } else {
01028 $max = 128;
01029 }
01030
01031 fseek($fp, rand(0, $fsize - $max), SEEK_SET);
01032 $data = fread($fp, 128);
01033 fclose($fp);
01034 $data = preg_replace("/\r?\n/", "\n", $data);
01035
01036 $start = strpos($data, "\n", rand(0, 100)) + 1;
01037 $end = strpos($data, "\n", $start);
01038
01039 return strtolower(substr($data, $start, $end - $start));
01040 }
01041
01042
01043
01044
01045
01046
01047
01048 function output()
01049 {
01050 header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
01051 header("Last-Modified: " . gmdate("D, d M Y H:i:s") . "GMT");
01052 header("Cache-Control: no-store, no-cache, must-revalidate");
01053 header("Cache-Control: post-check=0, pre-check=0", false);
01054 header("Pragma: no-cache");
01055
01056 switch($this->image_type)
01057 {
01058 case SI_IMAGE_JPEG:
01059 header("Content-Type: image/jpeg");
01060 imagejpeg($this->im, null, 90);
01061 break;
01062
01063 case SI_IMAGE_GIF:
01064 header("Content-Type: image/gif");
01065 imagegif($this->im);
01066 break;
01067
01068 default:
01069 header("Content-Type: image/png");
01070 imagepng($this->im);
01071 break;
01072 }
01073
01074 imagedestroy($this->im);
01075 exit;
01076 }
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086 function getAudibleCode($format = 'wav')
01087 {
01088 $letters = array();
01089 $code = $this->getCode();
01090
01091 if ($code == '') {
01092 $this->createCode();
01093 $code = $this->getCode();
01094 }
01095
01096 for($i = 0; $i < strlen($code); ++$i) {
01097 $letters[] = $code{$i};
01098 }
01099
01100 if ($format == 'mp3') {
01101 return $this->generateMP3($letters);
01102 } else {
01103 return $this->generateWAV($letters);
01104 }
01105 }
01106
01107
01108
01109
01110
01111
01112
01113 function setAudioPath($audio_directory)
01114 {
01115 if (is_dir($audio_directory) && is_readable($audio_directory)) {
01116 $this->audio_path = $audio_directory;
01117 return true;
01118 } else {
01119 return false;
01120 }
01121 }
01122
01123
01124
01125
01126
01127
01128
01129 function saveData()
01130 {
01131 $_SESSION['securimage_code_value'] = strtolower($this->code);
01132 $_SESSION['securimage_code_ctime'] = time();
01133
01134 $this->saveCodeToDatabase();
01135 }
01136
01137
01138
01139
01140
01141
01142
01143 function validate()
01144 {
01145
01146
01147 if (isset($_SESSION['securimage_code_value']) && trim($_SESSION['securimage_code_value']) != '') {
01148 if ($this->isCodeExpired($_SESSION['securimage_code_ctime']) == false) {
01149 $code = $_SESSION['securimage_code_value'];
01150 }
01151 } else if ($this->use_sqlite_db == true && function_exists('sqlite_open')) {
01152 $this->openDatabase();
01153 $code = $this->getCodeFromDatabase();
01154 } else {
01155
01156 $code = '';
01157 }
01158
01159 $code = trim(strtolower($code));
01160 $code_entered = trim(strtolower($this->code_entered));
01161 $this->correct_code = false;
01162
01163 if ($code != '') {
01164 if ($code == $code_entered) {
01165 $this->correct_code = true;
01166 $_SESSION['securimage_code_value'] = '';
01167 $_SESSION['securimage_code_ctime'] = '';
01168 $this->clearCodeFromDatabase();
01169 }
01170 }
01171 }
01172
01173
01174
01175
01176
01177
01178
01179 function getCode()
01180 {
01181 if (isset($_SESSION['securimage_code_value']) && !empty($_SESSION['securimage_code_value'])) {
01182 return strtolower($_SESSION['securimage_code_value']);
01183 } else {
01184 if ($this->sqlite_handle == false) $this->openDatabase();
01185
01186 return $this->getCodeFromDatabase();
01187 }
01188 }
01189
01190
01191
01192
01193
01194
01195
01196 function checkCode()
01197 {
01198 return $this->correct_code;
01199 }
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209 function generateWAV($letters)
01210 {
01211 $data_len = 0;
01212 $files = array();
01213 $out_data = '';
01214
01215 foreach ($letters as $letter) {
01216 $filename = $this->audio_path . strtoupper($letter) . '.wav';
01217
01218 $fp = fopen($filename, 'rb');
01219
01220 $file = array();
01221
01222 $data = fread($fp, filesize($filename));
01223
01224 $header = substr($data, 0, 36);
01225 $body = substr($data, 44);
01226
01227
01228 $data = unpack('NChunkID/VChunkSize/NFormat/NSubChunk1ID/VSubChunk1Size/vAudioFormat/vNumChannels/VSampleRate/VByteRate/vBlockAlign/vBitsPerSample', $header);
01229
01230 $file['sub_chunk1_id'] = $data['SubChunk1ID'];
01231 $file['bits_per_sample'] = $data['BitsPerSample'];
01232 $file['channels'] = $data['NumChannels'];
01233 $file['format'] = $data['AudioFormat'];
01234 $file['sample_rate'] = $data['SampleRate'];
01235 $file['size'] = $data['ChunkSize'] + 8;
01236 $file['data'] = $body;
01237
01238 if ( ($p = strpos($file['data'], 'LIST')) !== false) {
01239
01240 $info = substr($file['data'], $p + 4, 8);
01241 $data = unpack('Vlength/Vjunk', $info);
01242 $file['data'] = substr($file['data'], 0, $p);
01243 $file['size'] = $file['size'] - (strlen($file['data']) - $p);
01244 }
01245
01246 $files[] = $file;
01247 $data = null;
01248 $header = null;
01249 $body = null;
01250
01251 $data_len += strlen($file['data']);
01252
01253 fclose($fp);
01254 }
01255
01256 $out_data = '';
01257 for($i = 0; $i < sizeof($files); ++$i) {
01258 if ($i == 0) {
01259 $out_data .= pack('C4VC8', ord('R'), ord('I'), ord('F'), ord('F'), $data_len + 36, ord('W'), ord('A'), ord('V'), ord('E'), ord('f'), ord('m'), ord('t'), ord(' '));
01260
01261 $out_data .= pack('VvvVVvv',
01262 16,
01263 $files[$i]['format'],
01264 $files[$i]['channels'],
01265 $files[$i]['sample_rate'],
01266 $files[$i]['sample_rate'] * (($files[$i]['bits_per_sample'] * $files[$i]['channels']) / 8),
01267 ($files[$i]['bits_per_sample'] * $files[$i]['channels']) / 8,
01268 $files[$i]['bits_per_sample'] );
01269
01270 $out_data .= pack('C4', ord('d'), ord('a'), ord('t'), ord('a'));
01271
01272 $out_data .= pack('V', $data_len);
01273 }
01274
01275 $out_data .= $files[$i]['data'];
01276 }
01277
01278 $this->scrambleAudioData($out_data, 'wav');
01279 return $out_data;
01280 }
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290 function scrambleAudioData(&$data, $format)
01291 {
01292 if ($format == 'wav') {
01293 $start = strpos($data, 'data') + 4;
01294 if ($start === false) $start = 44;
01295 } else {
01296 $start = 4;
01297 }
01298
01299 $start += rand(1, 64);
01300 $datalen = strlen($data) - $start - 256;
01301
01302 for ($i = $start; $i < $datalen; $i += 64) {
01303 $ch = ord($data{$i});
01304 if ($ch < 9 || $ch > 119) continue;
01305
01306 $data{$i} = chr($ch + rand(-8, 8));
01307 }
01308 }
01309
01310
01311
01312
01313
01314
01315
01316
01317 function generateMP3($letters)
01318 {
01319 $data_len = 0;
01320 $files = array();
01321 $out_data = '';
01322
01323 foreach ($letters as $letter) {
01324 $filename = $this->audio_path . strtoupper($letter) . '.mp3';
01325
01326 $fp = fopen($filename, 'rb');
01327 $data = fread($fp, filesize($filename));
01328
01329 $this->scrambleAudioData($data, 'mp3');
01330 $out_data .= $data;
01331
01332 fclose($fp);
01333 }
01334
01335
01336 return $out_data;
01337 }
01338
01339
01340
01341
01342
01343
01344
01345 function frand()
01346 {
01347 return 0.0001*rand(0,9999);
01348 }
01349
01350
01351
01352
01353
01354
01355
01356
01357 function addSignature()
01358 {
01359 if ($this->use_gd_font) {
01360 imagestring($this->im, 5, $this->image_width - (strlen($this->image_signature) * 10), $this->image_height - 20, $this->image_signature, $this->gdsignaturecolor);
01361 } else {
01362
01363 $bbox = imagettfbbox(10, 0, $this->signature_font, $this->image_signature);
01364 $textlen = $bbox[2] - $bbox[0];
01365 $x = $this->image_width - $textlen - 5;
01366 $y = $this->image_height - 3;
01367
01368 imagettftext($this->im, 10, 0, $x, $y, $this->gdsignaturecolor, $this->signature_font, $this->image_signature);
01369 }
01370 }
01371
01372
01373
01374
01375
01376
01377
01378
01379 function getIPHash()
01380 {
01381 return strtolower(md5($_SERVER['REMOTE_ADDR']));
01382 }
01383
01384
01385
01386
01387
01388
01389
01390
01391 function openDatabase()
01392 {
01393 $this->sqlite_handle = false;
01394
01395 if ($this->use_sqlite_db && function_exists('sqlite_open')) {
01396 $this->sqlite_handle = sqlite_open($this->sqlite_database, 0666, $error);
01397
01398 if ($this->sqlite_handle !== false) {
01399 $res = sqlite_query($this->sqlite_handle, "PRAGMA table_info(codes)");
01400 if (sqlite_num_rows($res) == 0) {
01401 sqlite_query($this->sqlite_handle, "CREATE TABLE codes (iphash VARCHAR(32) PRIMARY KEY, code VARCHAR(32) NOT NULL, created INTEGER)");
01402 }
01403 }
01404
01405 return $this->sqlite_handle != false;
01406 }
01407
01408 return $this->sqlite_handle;
01409 }
01410
01411
01412
01413
01414
01415
01416
01417
01418 function saveCodeToDatabase()
01419 {
01420 $success = false;
01421
01422 $this->openDatabase();
01423
01424 if ($this->use_sqlite_db && $this->sqlite_handle !== false) {
01425 $ip = $this->getIPHash();
01426 $time = time();
01427 $code = $_SESSION['securimage_code_value'];
01428 $success = sqlite_query($this->sqlite_handle, "INSERT OR REPLACE INTO codes(iphash, code, created) VALUES('$ip', '$code', $time)");
01429 }
01430
01431 return $success !== false;
01432 }
01433
01434
01435
01436
01437
01438
01439
01440
01441 function getCodeFromDatabase()
01442 {
01443 $code = '';
01444
01445 if ($this->use_sqlite_db && $this->sqlite_handle !== false) {
01446 $ip = $this->getIPHash();
01447
01448 $res = sqlite_query($this->sqlite_handle, "SELECT * FROM codes WHERE iphash = '$ip'");
01449 if ($res && sqlite_num_rows($res) > 0) {
01450 $res = sqlite_fetch_array($res);
01451
01452 if ($this->isCodeExpired($res['created']) == false) {
01453 $code = $res['code'];
01454 }
01455 }
01456 }
01457
01458 return $code;
01459 }
01460
01461
01462
01463
01464
01465
01466
01467 function clearCodeFromDatabase()
01468 {
01469 if ($this->sqlite_handle !== false) {
01470 $ip = $this->getIPHash();
01471
01472 sqlite_query($this->sqlite_handle, "DELETE FROM codes WHERE iphash = '$ip'");
01473 }
01474 }
01475
01476
01477
01478
01479
01480
01481
01482 function purgeOldCodesFromDatabase()
01483 {
01484 if ($this->use_sqlite_db && $this->sqlite_handle !== false) {
01485 $now = time();
01486 $limit = (!is_numeric($this->expiry_time) || $this->expiry_time < 1) ? 86400 : $this->expiry_time;
01487
01488 sqlite_query($this->sqlite_handle, "DELETE FROM codes WHERE $now - created > $limit");
01489 }
01490 }
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500 function isCodeExpired($creation_time)
01501 {
01502 $expired = true;
01503
01504 if (!is_numeric($this->expiry_time) || $this->expiry_time < 1) {
01505 $expired = false;
01506 } else if (time() - $creation_time < $this->expiry_time) {
01507 $expired = false;
01508 }
01509
01510 return $expired;
01511 }
01512
01513 }
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524 class Securimage_Color {
01525
01526
01527
01528
01529
01530 var $r;
01531
01532
01533
01534
01535
01536 var $g;
01537
01538
01539
01540
01541
01542 var $b;
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554 function Securimage_Color($red, $green = null, $blue = null)
01555 {
01556 if ($green == null && $blue == null && preg_match('/^#[a-f0-9]{3,6}$/i', $red)) {
01557 $col = substr($red, 1);
01558 if (strlen($col) == 3) {
01559 $red = str_repeat(substr($col, 0, 1), 2);
01560 $green = str_repeat(substr($col, 1, 1), 2);
01561 $blue = str_repeat(substr($col, 2, 1), 2);
01562 } else {
01563 $red = substr($col, 0, 2);
01564 $green = substr($col, 2, 2);
01565 $blue = substr($col, 4, 2);
01566 }
01567
01568 $red = hexdec($red);
01569 $green = hexdec($green);
01570 $blue = hexdec($blue);
01571 } else {
01572 if ($red < 0) $red = 0;
01573 if ($red > 255) $red = 255;
01574 if ($green < 0) $green = 0;
01575 if ($green > 255) $green = 255;
01576 if ($blue < 0) $blue = 0;
01577 if ($blue > 255) $blue = 255;
01578 }
01579
01580 $this->r = $red;
01581 $this->g = $green;
01582 $this->b = $blue;
01583 }
01584 }