Find this useful? Enter your email to receive occasional updates for securing PHP code.

Signing you up...

Thank you for signing up!

PHP Decode

<?php class SVGCaptcha { private static $instance = NULL; private $svg_data = '<?xml versi..

Decoded Output download

<?php class SVGCaptcha { private static $instance = NULL; private $svg_data = '<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" width="{{width}}" height="{{height}}" id="svgCaptcha" version="1.1" style="border:solid 2px #000"><g><path style="fill:none;stroke:#000000;stroke-width:2px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" d="{{pathdata}}" id="captcha" /></g></svg>'; private $alphabet; private $numchars = 0; private $width = 0; private $height = 0; private $difficulty; private $dsettings = array( 'glyph_offsetting' => array('apply' => True, 'h' => 1, 'v' => 0.5, 'mh' => 8), 'glyph_fragments' => array('apply' => False, 'r_num_frag' => NULL, 'frag_factor' => 2), 'transformations' => array('apply' => False, 'rotate' => False, 'skew' => False, 'scale' => False, 'shear' => False, 'translate' => False), 'approx_shapes' => array('apply' => False, 'p' => 3, 'r_al_num_lines' => NUll), 'change_degree' => array('apply' => False, 'p' => 5), 'split_curve' => array('apply' => False, 'p' => 5), 'shapeify' => array('apply' => False, 'r_num_shapes' => NULL, 'r_num_gp' => NULL) ); const DEBUG = FALSE; const VERBOSE = FALSE; const EASY = 1; const MEDIUM = 2; const HARD = 3; private $captcha_answer = ""; public static function getInstance($numchars, $width, $height, $difficulty = SVGCaptcha::MEDIUM) { if (!isset(self::$instance)) self::$instance = new SVGCaptcha($numchars, $width, $height, $difficulty); return self::$instance; } private function __construct($numchars, $width, $height, $difficulty) { $this->alphabet = array( 'y' => array( 'width' => 347, 'height' => 381, 'glyph_data' => array( 'cubic_splines' => array( array(new Point(178, 245), new Point(178, 245), new Point(148, 314), new Point(122, 339)), array(new Point(122, 339), new Point(109, 350), new Point(93, 361), new Point(76, 363)), array(new Point(76, 363), new Point(53, 366), new Point(6, 342), new Point(6, 342)), array(new Point(0, 359), new Point(0, 359), new Point(49, 381), new Point(73, 379)), array(new Point(0, 359), new Point(0, 359), new Point(49, 381), new Point(73, 379)), array(new Point(73, 379), new Point(93, 377), new Point(112, 365), new Point(128, 352)), array(new Point(128, 352), new Point(158, 325), new Point(175, 286), new Point(195, 250)), array(new Point(195, 250), new Point(235, 178), new Point(296, 16), new Point(296, 16)), array(new Point(195, 250), new Point(235, 178), new Point(296, 16), new Point(296, 16)) ), 'lines' => array( array(new Point(30, 19), new Point(65, 19)), array(new Point(65, 19), new Point(178, 245)), array(new Point(6, 342), new Point(0, 359)), array(new Point(296, 16), new Point(347, 16)), array(new Point(296, 16), new Point(347, 16)), array(new Point(347, 16), new Point(347, 0)), array(new Point(347, 0), new Point(239, 0)), array(new Point(239, 0), new Point(239, 16)), array(new Point(239, 0), new Point(239, 16)), array(new Point(239, 16), new Point(278, 16)), array(new Point(278, 16), new Point(189, 229)), array(new Point(189, 229), new Point(81, 19)), array(new Point(189, 229), new Point(81, 19)), array(new Point(81, 19), new Point(135, 18)), array(new Point(135, 18), new Point(135, 0)), array(new Point(135, 0), new Point(30, 0)), array(new Point(135, 0), new Point(30, 0)), array(new Point(30, 0), new Point(30, 19)) )) ), 'W' => array( 'width' => 520, 'height' => 390, 'glyph_data' => array( 'lines' => array( array(new Point(0, 0), new Point(130, 390)), array(new Point(130, 390), new Point(190, 390)), array(new Point(190, 390), new Point(270, 120)), array(new Point(270, 120), new Point(350, 390)), array(new Point(270, 120), new Point(350, 390)), array(new Point(350, 390), new Point(410, 390)), array(new Point(410, 390), new Point(520, 0)), array(new Point(520, 0), new Point(430, 10)), array(new Point(520, 0), new Point(430, 10)), array(new Point(430, 10), new Point(380, 290)), array(new Point(380, 290), new Point(300, 80)), array(new Point(300, 80), new Point(240, 80)), array(new Point(300, 80), new Point(240, 80)), array(new Point(240, 80), new Point(160, 290)), array(new Point(160, 290), new Point(90, 10)), array(new Point(90, 10), new Point(0, 0)), array(new Point(90, 10), new Point(0, 0)) )) ), 'G' => array( 'width' => 248, 'height' => 353, 'glyph_data' => array( 'cubic_splines' => array( array(new Point(248, 60), new Point(248, 60), new Point(211, 28), new Point(189, 17)), array(new Point(189, 17), new Point(169, 7), new Point(146, 0), new Point(124, 4)), array(new Point(124, 4), new Point(98, 8), new Point(74, 25), new Point(56, 45)), array(new Point(56, 45), new Point(33, 70), new Point(20, 103), new Point(12, 135)), array(new Point(56, 45), new Point(33, 70), new Point(20, 103), new Point(12, 135)), array(new Point(12, 135), new Point(3, 175), new Point(0, 218), new Point(12, 257)), array(new Point(12, 257), new Point(21, 287), new Point(39, 315), new Point(64, 333)), array(new Point(64, 333), new Point(83, 347), new Point(108, 352), new Point(132, 352)), array(new Point(64, 333), new Point(83, 347), new Point(108, 352), new Point(132, 352)), array(new Point(132, 352), new Point(167, 353), new Point(236, 344), new Point(236, 344)), array(new Point(207, 297), new Point(208, 326), new Point(181, 324), new Point(158, 321)), array(new Point(158, 321), new Point(130, 317), new Point(74, 301), new Point(58, 278)), array(new Point(158, 321), new Point(130, 317), new Point(74, 301), new Point(58, 278)), array(new Point(58, 278), new Point(38, 248), new Point(39, 208), new Point(43, 174)), array(new Point(43, 174), new Point(46, 136), new Point(56, 95), new Point(80, 65)), array(new Point(80, 65), new Point(96, 47), new Point(119, 34), new Point(144, 36)), array(new Point(80, 65), new Point(96, 47), new Point(119, 34), new Point(144, 36)), array(new Point(144, 36), new Point(177, 38), new Point(224, 84), new Point(224, 84)), array(new Point(224, 84), new Point(224, 84), new Point(218, 92), new Point(248, 60)) ), 'lines' => array( array(new Point(236, 344), new Point(238, 202)), array(new Point(238, 202), new Point(118, 200)), array(new Point(118, 200), new Point(116, 231)), array(new Point(116, 231), new Point(207, 231)), array(new Point(116, 231), new Point(207, 231)), array(new Point(207, 231), new Point(207, 297)), array(new Point(248, 60), new Point(248, 60)) )) ), 'e' => array( 'width' => 480, 'height' => 615, 'glyph_data' => array( 'cubic_splines' => array( array(new Point(46, 207), new Point(0, 331), new Point(3, 525), new Point(204, 570)), array(new Point(204, 570), new Point(404, 615), new Point(454, 423), new Point(460, 406)), array(new Point(389, 406), new Point(389, 406), new Point(354, 498), new Point(313, 515)), array(new Point(313, 515), new Point(252, 539), new Point(166, 522), new Point(121, 474)), array(new Point(313, 515), new Point(252, 539), new Point(166, 522), new Point(121, 474)), array(new Point(121, 474), new Point(82, 433), new Point(98, 306), new Point(98, 306)), array(new Point(461, 304), new Point(461, 304), new Point(480, 140), new Point(334, 70)), array(new Point(334, 70), new Point(188, 0), new Point(83, 108), new Point(46, 207)), array(new Point(334, 70), new Point(188, 0), new Point(83, 108), new Point(46, 207)), array(new Point(387, 257), new Point(387, 257), new Point(379, 114), new Point(251, 112)), array(new Point(251, 112), new Point(123, 109), new Point(97, 257), new Point(97, 257)) ), 'lines' => array( array(new Point(460, 406), new Point(389, 406)), array(new Point(98, 306), new Point(461, 304)), array(new Point(46, 207), new Point(46, 207)), array(new Point(97, 257), new Point(387, 257)), array(new Point(97, 257), new Point(387, 257)), array(new Point(97, 257), new Point(97, 257)) )) ), 'a' => array( 'width' => 351, 'height' => 634, 'glyph_data' => array( 'cubic_splines' => array( array(new Point(195, 0), new Point(163, 0), new Point(133, 9), new Point(107, 27)), array(new Point(107, 27), new Point(71, 53), new Point(60, 162), new Point(60, 162)), array(new Point(60, 162), new Point(73, 177), new Point(95, 212), new Point(95, 212)), array(new Point(95, 212), new Point(95, 212), new Point(104, 99), new Point(129, 72)), array(new Point(95, 212), new Point(95, 212), new Point(104, 99), new Point(129, 72)), array(new Point(129, 72), new Point(161, 31), new Point(207, 26), new Point(262, 74)), array(new Point(262, 74), new Point(300, 130), new Point(277, 185), new Point(245, 228)), array(new Point(245, 228), new Point(209, 277), new Point(151, 274), new Point(105, 287)), array(new Point(245, 228), new Point(209, 277), new Point(151, 274), new Point(105, 287)), array(new Point(105, 287), new Point(9, 326), new Point(0, 444), new Point(23, 521)), array(new Point(23, 521), new Point(32, 562), new Point(53, 590), new Point(90, 601)), array(new Point(90, 601), new Point(150, 618), new Point(193, 601), new Point(225, 563)), array(new Point(90, 601), new Point(150, 618), new Point(193, 601), new Point(225, 563)), array(new Point(225, 563), new Point(231, 590), new Point(232, 620), new Point(258, 626)), array(new Point(258, 626), new Point(298, 634), new Point(351, 628), new Point(312, 589)), array(new Point(312, 589), new Point(273, 551), new Point(283, 535), new Point(281, 510)), array(new Point(312, 589), new Point(273, 551), new Point(283, 535), new Point(281, 510)), array(new Point(335, 71), new Point(339, 43), new Point(291, 17), new Point(240, 5)), array(new Point(240, 5), new Point(224, 1), new Point(209, 0), new Point(195, 0)), array(new Point(252, 283), new Point(270, 367), new Point(251, 535), new Point(152, 571)), array(new Point(252, 283), new Point(270, 367), new Point(251, 535), new Point(152, 571)), array(new Point(152, 571), new Point(54, 608), new Point(35, 434), new Point(72, 384)), array(new Point(72, 384), new Point(124, 313), new Point(178, 279), new Point(252, 283)) ), 'lines' => array( array(new Point(281, 510), new Point(335, 71)), array(new Point(195, 0), new Point(195, 0)), array(new Point(252, 283), new Point(252, 283)) )) ), 'H' => array( 'width' => 420, 'height' => 550, 'glyph_data' => array( 'lines' => array( array(new Point(0, 0), new Point(0, 35)), array(new Point(0, 35), new Point(55, 35)), array(new Point(55, 35), new Point(55, 520)), array(new Point(55, 520), new Point(0, 520)), array(new Point(55, 520), new Point(0, 520)), array(new Point(0, 520), new Point(0, 550)), array(new Point(0, 550), new Point(150, 550)), array(new Point(150, 550), new Point(150, 520)), array(new Point(150, 550), new Point(150, 520)), array(new Point(150, 520), new Point(95, 520)), array(new Point(95, 520), new Point(95, 270)), array(new Point(95, 270), new Point(325, 270)), array(new Point(95, 270), new Point(325, 270)), array(new Point(325, 270), new Point(325, 520)), array(new Point(325, 520), new Point(265, 520)), array(new Point(265, 520), new Point(265, 550)), array(new Point(265, 520), new Point(265, 550)), array(new Point(265, 550), new Point(420, 550)), array(new Point(420, 550), new Point(420, 520)), array(new Point(420, 520), new Point(370, 520)), array(new Point(420, 520), new Point(370, 520)), array(new Point(370, 520), new Point(370, 35)), array(new Point(370, 35), new Point(420, 35)), array(new Point(420, 35), new Point(420, 0)), array(new Point(420, 35), new Point(420, 0)), array(new Point(420, 0), new Point(265, 0)), array(new Point(265, 0), new Point(265, 35)), array(new Point(265, 35), new Point(325, 35)), array(new Point(265, 35), new Point(325, 35)), array(new Point(325, 35), new Point(325, 230)), array(new Point(325, 230), new Point(95, 230)), array(new Point(95, 230), new Point(95, 35)), array(new Point(95, 230), new Point(95, 35)), array(new Point(95, 35), new Point(150, 35)), array(new Point(150, 35), new Point(150, 0)), array(new Point(150, 0), new Point(0, 0)), array(new Point(150, 0), new Point(0, 0)) )) ), 'k' => array( 'width' => 420, 'height' => 680, 'glyph_data' => array( 'lines' => array( array(new Point(0, 0), new Point(60, 0)), array(new Point(60, 0), new Point(60, 490)), array(new Point(60, 490), new Point(350, 280)), array(new Point(350, 280), new Point(420, 280)), array(new Point(350, 280), new Point(420, 280)), array(new Point(420, 280), new Point(210, 440)), array(new Point(210, 440), new Point(420, 680)), array(new Point(420, 680), new Point(350, 680)), array(new Point(420, 680), new Point(350, 680)), array(new Point(350, 680), new Point(170, 470)), array(new Point(170, 470), new Point(60, 550)), array(new Point(60, 550), new Point(60, 680)), array(new Point(60, 550), new Point(60, 680)), array(new Point(60, 680), new Point(0, 680)), array(new Point(0, 680), new Point(0, 0)) )) ), 'i' => array( 'width' => 122, 'height' => 687, 'glyph_data' => array( 'cubic_splines' => array( array(new Point(67, 1), new Point(48, 0), new Point(28, 14), new Point(17, 29)), array(new Point(17, 29), new Point(6, 45), new Point(0, 67), new Point(7, 85)), array(new Point(7, 85), new Point(14, 107), new Point(37, 128), new Point(60, 130)), array(new Point(60, 130), new Point(79, 131), new Point(99, 117), new Point(109, 100)), array(new Point(60, 130), new Point(79, 131), new Point(99, 117), new Point(109, 100)), array(new Point(109, 100), new Point(120, 82), new Point(122, 56), new Point(113, 37)), array(new Point(113, 37), new Point(105, 19), new Point(86, 3), new Point(67, 1)) ), 'lines' => array( array(new Point(23, 214), new Point(23, 687)), array(new Point(23, 687), new Point(96, 687)), array(new Point(96, 687), new Point(96, 214)), array(new Point(96, 214), new Point(23, 214)), array(new Point(96, 214), new Point(23, 214)), array(new Point(67, 1), new Point(67, 1)) )) ), 'f' => array( 'width' => 240, 'height' => 600, 'glyph_data' => array( 'cubic_splines' => array( array(new Point(240, 0), new Point(240, 0), new Point(167, 0), new Point(138, 11)), array(new Point(138, 11), new Point(106, 24), new Point(84, 48), new Point(70, 80)), array(new Point(70, 80), new Point(57, 108), new Point(60, 170), new Point(60, 170)), array(new Point(90, 170), new Point(90, 170), new Point(87, 116), new Point(97, 91)), array(new Point(90, 170), new Point(90, 170), new Point(87, 116), new Point(97, 91)), array(new Point(97, 91), new Point(106, 68), new Point(146, 48), new Point(170, 40)), array(new Point(170, 40), new Point(197, 31), new Point(240, 50), new Point(240, 50)) ), 'lines' => array( array(new Point(240, 50), new Point(240, 0)), array(new Point(60, 170), new Point(0, 170)), array(new Point(0, 170), new Point(0, 200)), array(new Point(0, 200), new Point(60, 200)), array(new Point(0, 200), new Point(60, 200)), array(new Point(60, 200), new Point(60, 570)), array(new Point(60, 570), new Point(0, 570)), array(new Point(0, 570), new Point(0, 600)), array(new Point(0, 570), new Point(0, 600)), array(new Point(0, 600), new Point(130, 600)), array(new Point(130, 600), new Point(150, 570)), array(new Point(150, 570), new Point(90, 570)), array(new Point(150, 570), new Point(90, 570)), array(new Point(90, 570), new Point(90, 200)), array(new Point(90, 200), new Point(150, 200)), array(new Point(150, 200), new Point(150, 170)), array(new Point(150, 200), new Point(150, 170)), array(new Point(150, 170), new Point(90, 170)), array(new Point(240, 50), new Point(240, 50)) )) ), 'b' => array( 'width' => 237, 'height' => 454, 'glyph_data' => array( 'cubic_splines' => array( array(new Point(43, 0), new Point(39, 13), new Point(38, 20), new Point(37, 26)), array(new Point(37, 26), new Point(0, 302), new Point(5, 438), new Point(5, 438)), array(new Point(5, 438), new Point(5, 438), new Point(142, 454), new Point(188, 414)), array(new Point(188, 414), new Point(222, 385), new Point(237, 329), new Point(224, 287)), array(new Point(188, 414), new Point(222, 385), new Point(237, 329), new Point(224, 287)), array(new Point(224, 287), new Point(213, 254), new Point(177, 221), new Point(141, 220)), array(new Point(141, 220), new Point(99, 220), new Point(40, 295), new Point(40, 295)), array(new Point(69, 305), new Point(69, 305), new Point(18, 373), new Point(38, 398)), array(new Point(69, 305), new Point(69, 305), new Point(18, 373), new Point(38, 398)), array(new Point(38, 398), new Point(64, 431), new Point(131, 416), new Point(161, 388)), array(new Point(161, 388), new Point(186, 366), new Point(189, 321), new Point(178, 289)), array(new Point(178, 289), new Point(172, 272), new Point(156, 253), new Point(138, 253)), array(new Point(178, 289), new Point(172, 272), new Point(156, 253), new Point(138, 253)), array(new Point(138, 253), new Point(109, 251), new Point(69, 305), new Point(69, 305)) ), 'lines' => array( array(new Point(40, 295), new Point(85, 4)), array(new Point(85, 4), new Point(43, 0)), array(new Point(69, 305), new Point(69, 305)) )) ), 'n' => array( 'width' => 420, 'height' => 380, 'glyph_data' => array( 'cubic_splines' => array( array(new Point(111, 50), new Point(111, 50), new Point(146, 38), new Point(206, 39)), array(new Point(206, 39), new Point(267, 41), new Point(287, 53), new Point(304, 67)), array(new Point(304, 67), new Point(318, 79), new Point(340, 110), new Point(340, 110)), array(new Point(370, 110), new Point(370, 110), new Point(361, 71), new Point(340, 50)), array(new Point(370, 110), new Point(370, 110), new Point(361, 71), new Point(340, 50)), array(new Point(340, 50), new Point(310, 20), new Point(288, 15), new Point(220, 10)), array(new Point(220, 10), new Point(151, 5), new Point(110, 20), new Point(110, 20)) ), 'lines' => array( array(new Point(30, 0), new Point(30, 30)), array(new Point(30, 30), new Point(80, 30)), array(new Point(80, 30), new Point(80, 350)), array(new Point(80, 350), new Point(30, 350)), array(new Point(80, 350), new Point(30, 350)), array(new Point(30, 350), new Point(0, 380)), array(new Point(0, 380), new Point(160, 380)), array(new Point(160, 380), new Point(160, 350)), array(new Point(160, 380), new Point(160, 350)), array(new Point(160, 350), new Point(110, 350)), array(new Point(110, 350), new Point(111, 50)), array(new Point(340, 110), new Point(340, 350)), array(new Point(340, 110), new Point(340, 350)), array(new Point(340, 350), new Point(290, 350)), array(new Point(290, 350), new Point(290, 380)), array(new Point(290, 380), new Point(420, 380)), array(new Point(290, 380), new Point(420, 380)), array(new Point(420, 380), new Point(370, 350)), array(new Point(370, 350), new Point(370, 110)), array(new Point(110, 20), new Point(110, 0)), array(new Point(110, 20), new Point(110, 0)), array(new Point(110, 0), new Point(30, 0)) )) ), 'S' => array( 'width' => 354, 'height' => 745, 'glyph_data' => array( 'cubic_splines' => array( array(new Point(287, 366), new Point(250, 289), new Point(141, 264), new Point(99, 189)), array(new Point(99, 189), new Point(88, 168), new Point(78, 141), new Point(85, 118)), array(new Point(85, 118), new Point(92, 96), new Point(116, 82), new Point(135, 71)), array(new Point(135, 71), new Point(157, 58), new Point(182, 50), new Point(207, 48)), array(new Point(135, 71), new Point(157, 58), new Point(182, 50), new Point(207, 48)), array(new Point(207, 48), new Point(244, 44), new Point(288, 42), new Point(319, 63)), array(new Point(319, 63), new Point(335, 73), new Point(348, 128), new Point(347, 110)), array(new Point(346, 44), new Point(345, 21), new Point(354, 16), new Point(293, 15)), array(new Point(346, 44), new Point(345, 21), new Point(354, 16), new Point(293, 15)), array(new Point(293, 15), new Point(293, 15), new Point(161, 0), new Point(88, 58)), array(new Point(88, 58), new Point(16, 116), new Point(27, 169), new Point(39, 196)), array(new Point(39, 196), new Point(74, 277), new Point(183, 304), new Point(233, 377)), array(new Point(39, 196), new Point(74, 277), new Point(183, 304), new Point(233, 377)), array(new Point(233, 377), new Point(248, 400), new Point(256, 427), new Point(262, 454)), array(new Point(262, 454), new Point(270, 493), new Point(272, 533), new Point(267, 572)), array(new Point(267, 572), new Point(261, 609), new Point(265, 640), new Point(228, 679)), array(new Point(267, 572), new Point(261, 609), new Point(265, 640), new Point(228, 679)), array(new Point(228, 679), new Point(182, 727), new Point(84, 731), new Point(28, 695)), array(new Point(28, 695), new Point(6, 681), new Point(0, 604), new Point(1, 623)), array(new Point(3, 691), new Point(6, 745), new Point(67, 742), new Point(94, 742)), array(new Point(3, 691), new Point(6, 745), new Point(67, 742), new Point(94, 742)), array(new Point(94, 742), new Point(124, 741), new Point(153, 741), new Point(182, 741)), array(new Point(182, 741), new Point(235, 740), new Point(287, 664), new Point(307, 605)), array(new Point(307, 605), new Point(333, 530), new Point(322, 438), new Point(287, 366)), array(new Point(307, 605), new Point(333, 530), new Point(322, 438), new Point(287, 366)) ), 'lines' => array( array(new Point(347, 110), new Point(346, 44)), array(new Point(1, 623), new Point(3, 691)), array(new Point(287, 366), new Point(287, 366)) )) ), 'X' => array( 'width' => 300, 'height' => 400, 'glyph_data' => array( 'lines' => array( array(new Point(10, 0), new Point(130, 200)), array(new Point(130, 200), new Point(0, 390)), array(new Point(0, 390), new Point(40, 390)), array(new Point(40, 390), new Point(150, 220)), array(new Point(40, 390), new Point(150, 220)), array(new Point(150, 220), new Point(260, 400)), array(new Point(260, 400), new Point(300, 400)), array(new Point(300, 400), new Point(170, 190)), array(new Point(300, 400), new Point(170, 190)), array(new Point(170, 190), new Point(296, 0)), array(new Point(296, 0), new Point(260, 0)), array(new Point(260, 0), new Point(150, 170)), array(new Point(260, 0), new Point(150, 170)), array(new Point(150, 170), new Point(50, 0)), array(new Point(50, 0), new Point(10, 0)) )) ), 'E' => array( 'width' => 370, 'height' => 680, 'glyph_data' => array( 'lines' => array( array(new Point(0, 0), new Point(0, 50)), array(new Point(0, 50), new Point(50, 50)), array(new Point(50, 50), new Point(50, 630)), array(new Point(50, 630), new Point(0, 630)), array(new Point(50, 630), new Point(0, 630)), array(new Point(0, 630), new Point(0, 680)), array(new Point(0, 680), new Point(370, 680)), array(new Point(370, 680), new Point(370, 550)), array(new Point(370, 680), new Point(370, 550)), array(new Point(370, 550), new Point(320, 550)), array(new Point(320, 550), new Point(320, 630)), array(new Point(320, 630), new Point(100, 630)), array(new Point(320, 630), new Point(100, 630)), array(new Point(100, 630), new Point(100, 360)), array(new Point(100, 360), new Point(280, 360)), array(new Point(280, 360), new Point(280, 310)), array(new Point(280, 360), new Point(280, 310)), array(new Point(280, 310), new Point(100, 310)), array(new Point(100, 310), new Point(100, 50)), array(new Point(100, 50), new Point(320, 50)), array(new Point(100, 50), new Point(320, 50)), array(new Point(320, 50), new Point(320, 130)), array(new Point(320, 130), new Point(370, 130)), array(new Point(370, 130), new Point(370, 0)), array(new Point(370, 130), new Point(370, 0)), array(new Point(370, 0), new Point(0, 0)) )) ), 'Q' => array( 'width' => 510, 'height' => 600, 'glyph_data' => array( 'cubic_splines' => array( array(new Point(70, 90), new Point(68, 202), new Point(71, 408), new Point(70, 440)) ), 'lines' => array( array(new Point(0, 450), new Point(70, 540)), array(new Point(70, 540), new Point(360, 540)), array(new Point(360, 540), new Point(410, 600)), array(new Point(410, 600), new Point(500, 600)), array(new Point(410, 600), new Point(500, 600)), array(new Point(500, 600), new Point(440, 530)), array(new Point(440, 530), new Point(510, 460)), array(new Point(510, 460), new Point(510, 70)), array(new Point(510, 460), new Point(510, 70)), array(new Point(510, 70), new Point(431, 2)), array(new Point(431, 2), new Point(70, 0)), array(new Point(70, 0), new Point(0, 70)), array(new Point(70, 0), new Point(0, 70)), array(new Point(0, 70), new Point(0, 450)), array(new Point(70, 440), new Point(110, 480)), array(new Point(110, 480), new Point(310, 480)), array(new Point(110, 480), new Point(310, 480)), array(new Point(310, 480), new Point(270, 420)), array(new Point(270, 420), new Point(360, 420)), array(new Point(360, 420), new Point(400, 480)), array(new Point(360, 420), new Point(400, 480)), array(new Point(400, 480), new Point(440, 430)), array(new Point(440, 430), new Point(440, 90)), array(new Point(440, 90), new Point(390, 50)), array(new Point(440, 90), new Point(390, 50)), array(new Point(390, 50), new Point(120, 50)), array(new Point(120, 50), new Point(70, 90)) )) ), ); $this->numchars = ($numchars > count($this->alphabet) ? count($this->alphabet) : $numchars); $this->width = $width; $this->height = $height; $this->difficulty = $difficulty; if ($this->difficulty == self::EASY) { $this->dsettings['glyph_fragments']['apply'] = True; $this->dsettings['glyph_fragments']['r_num_frag'] = range(2, 4); $this->dsettings["glyph_offseting"]["apply"] = True; $this->dsettings["glyph_offseting"]["h"] = 0.5; $this->dsettings["transformations"]["apply"] = True; $this->dsettings["transformations"]["rotate"] = True; $this->dsettings["shapeify"]["apply"] = False; $this->dsettings["shapeify"]["r_num_shapes"] = range(0, 4); $this->dsettings["shapeify"]["r_num_gp"] = range(2, 4); $this->dsettings["approx_shapes"]["apply"] = True; $this->dsettings["approx_shapes"]["p"] = 5; $this->dsettings["approx_shapes"]["r_al_num_lines"] = range(4, 20); $this->dsettings["change_degree"]["apply"] = True; $this->dsettings["change_degree"]["p"] = 5; $this->dsettings["split_curve"]["apply"] = True; } else if ($this->difficulty == self::MEDIUM) { $this->dsettings["transformations"]["apply"] = True; $this->dsettings["transformations"]["rotate"] = True; $this->dsettings["transformations"]["skew"] = True; $this->dsettings["transformations"]["scale"] = True; $this->dsettings["shapeify"]["apply"] = True; $this->dsettings["shapeify"]["r_num_shapes"] = range(4, 5); $this->dsettings["shapeify"]["r_num_gp"] = range(3, 4); $this->dsettings["approx_shapes"]["apply"] = True; $this->dsettings["approx_shapes"]["p"] = 3; $this->dsettings["approx_shapes"]["r_al_num_lines"] = range(4, 16); $this->dsettings["change_degree"]["apply"] = True; $this->dsettings["change_degree"]["p"] = 5; $this->dsettings["split_curve"]["apply"] = True; } else if ($this->difficulty == self::HARD) { $this->dsettings["transformations"]["apply"] = True; $this->dsettings["transformations"]["rotate"] = True; $this->dsettings["transformations"]["skew"] = True; $this->dsettings["transformations"]["scale"] = True; $this->dsettings["transformations"]["shear"] = True; $this->dsettings["transformations"]["translate"] = True; $this->dsettings["shapeify"]["apply"] = True; $this->dsettings["shapeify"]["r_num_shapes"] = range(3, 8); $this->dsettings["shapeify"]["r_num_gp"] = range(3, 5); $this->dsettings["approx_shapes"]["apply"] = True; $this->dsettings["approx_shapes"]["p"] = 2; $this->dsettings["approx_shapes"]["r_al_num_lines"] = range(6, 26); $this->dsettings["change_degree"]["apply"] = True; $this->dsettings["change_degree"]["p"] = 3; $this->dsettings["split_curve"]["apply"] = True; } else if (is_array($difficulty) && !empty($difficulty) && (!array_diff_key($difficulty, $this->dsettings))) { $this->dsettings = $difficulty; } } public function generate() { $selected_keys = array_secure_rand($this->alphabet, $this->numchars, False); foreach ($selected_keys as $key) { $selected[$key] = $this->alphabet[$key]; } foreach ($selected as $key => $value) { $packed[$key]["width"] = $selected[$key]["width"]; $packed[$key]["height"] = $selected[$key]["height"]; foreach ($value['glyph_data'] as $shapetype) { foreach ($shapetype as $shape) { $packed[$key]['glyph_data'][] = $shape; } } $this->captcha_answer[] = $key; } $this->_scale_by_largest_glyph($packed); if ($this->dsettings['transformations']['apply']) { $this->_apply_affine_transformations($packed); } if ($this->dsettings["glyph_offsetting"]["apply"]) { $this->_align_randomly($packed); } if ($this->dsettings['glyph_fragments']['apply']) { $packed = $this->_glyph_fragments($packed); } foreach ($packed as $char => $value) { foreach ($value["glyph_data"] as $shape) { $shapearray[] = $shape; } } shuffle($shapearray); if ($this->dsettings['shapeify']['apply']) { $shapearray = $this->_shapeify($shapearray); } if ($this->dsettings['change_degree']['apply']) { $this->_maybe_change_curvature_degree($shapearray); } if ($this->dsettings['split_curve']['apply']) { $shapearray = $this->_maybe_split_curve($shapearray); } if ($this->dsettings['approx_shapes']['apply']) { $shapearray = $this->_maybe_approximate_xor_make_curvaceous($shapearray); } shuffle($shapearray); $path_str = ""; $begin_path = True; foreach ($shapearray as $key => &$shape) { array_map(function($p) { $p->x = sprintf("%." . rand(3, 6) . "f", $p->x); $p->y = sprintf("%." . rand(4, 7) . "f", $p->y); }, $shape); if ($begin_path) { $path_str .= "M {$shape[0]->x} {$shape[0]->y}"; $begin_path = False; } $path_str .= $this->_shape2_cmd($shape, True, True); } $this->D("mtest"); return $this->_write_SVG($path_str); } private function _write_SVG($path_str) { $svg_output = $this->svg_data; $svg_output = str_replace("{{width}}", $this->width, $svg_output); $svg_output = str_replace("{{height}}", $this->height, $svg_output); $svg_output = str_replace("{{pathdata}}", $path_str, $svg_output); return array(implode($this->captcha_answer, ""), $svg_output); } private function _glyph_fragments($glyphs) { if (!empty($this->dsettings['glyph_fragments']['r_num_frag'])) { $ngf = max($this->dsettings['glyph_fragments']['r_num_frag']); $ngf = $ngf >= count($glyphs) ? count($glyphs) - 1 : $ngf; } else { $ngf = secure_rand(0, count($glyphs) - 1); } $chosen_keys = array_secure_rand($glyphs, $ngf, True); $glyph_fragments = array(); foreach ($chosen_keys as $key) { $ukey = uniqid($prefix = "gf__"); $shape_keys = array_secure_rand( $glyphs[$key]["glyph_data"], secure_rand(0, count($glyphs[$key]["glyph_data"]) / $this->dsettings['glyph_fragments']['frag_factor']) ); if (count($shape_keys) > 0 && !empty($shape_keys)) { $pos = (($rel = $glyphs[$key]["glyph_data"][$shape_keys[0]][0]->x) > $this->width / 2) ? false : true; $x_translate = ($pos) ? secure_rand(abs($rel), $this->width) : - secure_rand(0, abs($rel)); $y_translate = (microtime() & 1) ? -secure_rand(0, $this->width / 5) : secure_rand(0, $this->width / 5); $a = $this->_ra(0.6); foreach ($shape_keys as $skey) { $copy = array_copy($glyphs[$key]["glyph_data"][$skey]); $this->on_points($copy, array($this, "_translate"), array($x_translate, $y_translate)); $this->on_points($copy, array($this, "_rotate"), array($a)); $glyph_fragments[$ukey]["glyph_data"][] = $copy; } } } return array_merge($glyph_fragments, $glyphs); } private function _shapeify($shapearray) { $random_shapes = array(); $ns = secure_rand(min($this->dsettings["shapeify"]["r_num_shapes"]), max($this->dsettings["shapeify"]["r_num_shapes"])); foreach (range(0, $ns) as $i) { $random_shapes = array_merge($random_shapes, $this->_random_shape()); } return array_merge($shapearray, $random_shapes); } private function _random_shape() { $rshapes = array(); $min = new Point(0, 0); $max = new Point($this->width, $this->height); $previous = $startp = new Point(secure_rand($min->x, $max->x), secure_rand($min->y, $max->y)); $ngp = secure_rand(min($this->dsettings["shapeify"]["r_num_gp"]), max($this->dsettings["shapeify"]["r_num_gp"])); foreach (range(0, $ngp) as $j) { $rp = new Point(secure_rand($min->x, $max->x), secure_rand($min->y, $max->y)); if (($ngp - 4) <= $j) { $rp = new Point(secure_rand($min->x, $max->x), secure_rand($min->y, $max->y)); $axis = abs($startp->x - $rp->x) > abs($startp->y - $rp->y) ? 'x' : 'y'; if ($axis === 'x') { $rp->x += ($startp->x > $rp->x) ? abs($startp->x - $rp->x) / 4 : abs($startp->x - $rp->x) / -4; } else { $rp->y += ($startp->y > $rp->y) ? abs($startp->y - $rp->y) / 4 : abs($startp->y - $rp->y) / -4; } } if ($j == ($ngp - 1)) { $rshapes[] = array($previous, $startp); break; } else if (rand(0, 1) == 1) { $rshapes[] = array($previous, $rp); } else { $rshapes[] = array($previous, new Point($previous->x, $rp->y), $rp); } $previous = $rp; } return $rshapes; } private function _maybe_change_curvature_degree(&$shapearray) { foreach ($shapearray as &$shape) { $p = $this->dsettings["change_degree"]["p"]; $do_change = (bool) (secure_rand(0, $p) == $p); if ($do_change && count($shape) == 3) { self::V("changing curvature degree"); list($p1, $p2, $p3) = $shape; $shape = array( $p1, new Point(1 / 3 * $p1->x + 2 / 3 * $p2->x, 1 / 3 * $p1->y + 2 / 3 * $p2->y), new Point(1 / 3 * $p3->x + 2 / 3 * $p2->x, 1 / 3 * $p3->y + 2 / 3 * $p2->y), $p3 ); } } return True; } private function _maybe_split_curve($shapearray) { $newshapes = array(); foreach ($shapearray as $key => $shape) { $p = $this->dsettings["split_curve"]["p"]; $do_change = (bool) (secure_rand(0, $p) == $p); if ($do_change && count($shape) >= 3) { self::V("splitting curve"); $left = array(); $right = array(); $this->_split_curve($shape, $this->_rt(), $left, $right); $right = array_reverse($right); if (!empty($left) and !empty($right)) { self::D("adding left:" . count($left) . " and right:" . count($right)); unset($shapearray[$key]); $newshapes[] = $left; $newshapes[] = $right; } } } return array_merge($newshapes, $shapearray); } private function _maybe_approximate_xor_make_curvaceous($shapearray) { $dk = array(); $merge = array(); foreach ($shapearray as $key => $shape) { $p = $this->dsettings["approx_shapes"]["p"]; $do_change = (bool) (secure_rand(0, $p) == $p); if ($do_change) { if ((count($shape) == 3 || count($shape) == 4)) { self::V("approximating curve with lines"); $lines = $this->_approximate_bezier($shape); $dk[] = $key; $merge = array_merge($merge, $lines); } else if (count($shape) == 2) { self::V("approximating lines by curves"); $shapearray[$key] = $this->_approximate_line($shape); } } } return array_merge($merge, array_diff_key($shapearray, array_fill_keys($dk, 0))); } private function _shape2_cmd($shape, $absolute = True, $explicit_moveto = False) { if ($explicit_moveto) { $prefix = "M {$shape[0]->x} {$shape[0]->y} "; } else { $prefix = ""; } if (count($shape) == 2) { list($p1, $p2) = $shape; $cmd = "L {$p2->x} {$p2->y} "; } else if (count($shape) == 3) { list($p1, $p2, $p3) = $shape; $cmd = "Q {$p2->x} {$p2->y} {$p3->x} {$p3->y} "; } else if (count($shape) == 4) { list($p1, $p2, $p3, $p4) = $shape; $cmd = "C {$p2->x} {$p2->y} {$p3->x} {$p3->y} {$p4->x} {$p4->y} "; } if (!$cmd) return False; return $prefix . $cmd; } private function _scale_by_largest_glyph(&$glyphs) { $my = max(array_column($glyphs, "height")); $scale_factor = ($this->height / 1.5) / $my; $this->on_points( $glyphs, array($this, "_scale"), array($scale_factor) ); foreach ($glyphs as &$value) { $value["width"] *= $scale_factor; $value["height"] *= $scale_factor; } } private function _align_randomly(&$glyphs) { $accumulated_hoffset = 0; $lastxo = 0; $lastyo = 0; $cnt = 0; $overlapf_h = $this->dsettings["glyph_offsetting"]["h"]; $overlapf_v = $this->dsettings["glyph_offsetting"]["v"]; foreach ($glyphs as &$glyph) { $accumulated_hoffset += ($cnt == 0) ? $glyph['width'] / 3 : secure_rand($lastxo, ($glyph["width"] > $lastxo) ? $glyph["width"] : $lastxo); $h = round($glyph['height'] * $overlapf_v); $svo = $this->height / $this->dsettings["glyph_offsetting"]["mh"]; $yoffset = secure_rand(($svo > $h ? 0 : $svo), $h); $this->on_points( $glyph["glyph_data"], array($this, "_translate"), array($accumulated_hoffset, $yoffset) ); $lastxo = round($glyph['width'] * $overlapf_h); $lastyo = round($glyph['height'] * $overlapf_h); $cnt++; } $this->width = $accumulated_hoffset + $glyph["width"] + secure_rand($glyph["width"] * $overlapf_h, $glyph["width"]); } private function _apply_affine_transformations(&$glyphs) { foreach ($glyphs as &$glyph) { foreach ($this->_get_random_transformations() as $transformation) { $this->on_points($glyph["glyph_data"], $transformation[0], $transformation[1]); } } } private function _get_random_transformations() { $transformations = array(); if ($this->dsettings["transformations"]["rotate"]) { $transformations[] = array(array($this, "_rotate"), array($this->_ra())); } if ($this->dsettings["transformations"]["skew"]) { $transformations[] = array(array($this, "_skew"), array($this->_ra())); } if ($this->dsettings["transformations"]["scale"]) { $transformations[] = array(array($this, "_scale"), array($this->_rs())); } if ($this->dsettings["transformations"]["shear"]) { $transformations[] = array(array($this, "_shear"), array(1, 0)); } if ($this->dsettings["transformations"]["translate"]) { $transformations[] = array(array($this, "_translate"), array(0, 0)); } if (empty($transformations)) { return (array) Null; } $n = secure_rand(0, count($transformations) - 1); shuffle_assoc($transformations); for ($i = 0; $i < $n; $i++) { unset($transformations[$i]); } return $transformations; } private function on_points(&$data, $callback, $args) { if ($data instanceof Point) { if (is_callable($callback)) { call_user_func_array($callback, array_merge(array($data), $args)); } } if (is_array($data)) { foreach ($data as &$value) { $this->on_points($value, $callback, $args); } unset($value); } return; } private function _ra($ub=null) { $n = secure_rand(0, $ub != null ? $ub : 4) / 10; if (secure_rand(0, 1) == 1) $n *= -1; return $n; } private function _rs() { $z = secure_rand(8, 13) / 10; return $z; } private function _rt($inclusive = True) { if ($inclusive) { $z = secure_rand(0, 1000) / 1000; } else { $z = secure_rand(1, 999) / 1000; } return $z; } private function _rotate($p, $a) { $x = $p->x; $y = $p->y; $p->x = cos($a) * $x - sin($a) * $y; $p->y = sin($a) * $x + cos($a) * $y; } private function _skew($p, $a) { $x = $p->x; $y = $p->y; $p->x = $x + sin($a) * $y; } private function _scale($p, $s = 1) { $x = $p->x; $y = $p->y; $p->x = $x * $s; $p->y = $y * $s; } private function _shear($p, $mh = 1, $mv = 0) { if ($mh * $mv != 0) { throw new InvalidArgumentException(__FUNCTION__ . " _shear called with invalid arguments $p mh: $mh mv: $mv"); } $x = $p->x; $y = $p->y; $p->x = $x + $y * $mh; $p->y = $y + $x * $mv; } private function _translate($p, $dx, $dy) { $x = $p->x; $y = $p->y; $p->x = $x + $dx; $p->y = $y + $dy; } private function _approximate_line($line) { if (count($line) != 2 || !($line[0] instanceof Point) || !($line[1] instanceof Point)) { throw new InvalidArgumentException(__FUNCTION__ . ": Argument is not an array of two points"); } else if ($line[0]->_equals($line[1])) { } $make_cubic = (intval(time()) & 1) ? True : False; $d = sqrt(pow(abs($line[0]->x - $line[1]->x), 2) + pow(abs($line[0]->y - $line[1]->y), 2)); $md = $d / secure_rand(10, 50); $somewhere_near_the_line = function($line, $md) { $maxx = max($line[0]->x, $line[1]->x); $maxy = max($line[0]->y, $line[1]->y); $minx = min($line[0]->x, $line[1]->x); $miny = min($line[0]->y, $line[1]->y); if (($line[1]->x - $line[0]->x) == 0) { $line[1]->x += 1; } $m = ($line[1]->y - $line[0]->y) / ($line[1]->x - $line[0]->x); $d = ($line[1]->x * $line[0]->y - $line[0]->x * $line[1]->y) / ($line[1]->x - $line[0]->x); if ($maxx < 0 || $minx < 0) { $ma = max(abs($maxx), abs($minx)); $mi = min(abs($maxx), abs($minx)); $x = - secure_rand($mi, $ma); } else { $x = secure_rand($minx, $maxx); } $y = $m * $x + $d; return new Point($x + ((rand(0, 1) == 1) ? $md : -$md), $y + ((rand(0, 1) == 1) ? $md : -$md)); }; if ($make_cubic) { $p1 = $somewhere_near_the_line($line, $md); $p2 = $somewhere_near_the_line($line, $md); $curve = array($line[0], $p1, $p2, $line[1]); } else { $p1 = $somewhere_near_the_line($line, $md); $curve = array($line[0], $p1, $line[1]); } return $curve; } private function _approximate_bezier($curve, $nlines = False) { foreach ($curve as $point) { if (get_class($point) != "Point") throw new InvalidArgumentException("curve is not an array of points"); } if (!$nlines || !isset($nlines)) { $nlines = secure_rand(min($this->dsettings["approx_shapes"]["r_al_num_lines"]), max($this->dsettings["approx_shapes"]["r_al_num_lines"])); } $approx_func = nUlL; if (count($curve) == 3) { $approx_func = function($curve, $nlines) { list($p1, $p2, $p3) = $curve; $last = $p1; $lines = array(); for ($i = 0; $i <= $nlines; $i++) { $t = $i / $nlines; $t2 = $t * $t; $mt = 1 - $t; $mt2 = $mt * $mt; $x = $p1->x * $mt2 + $p2->x * 2 * $mt * $t + $p3->x * $t2; $y = $p1->y * $mt2 + $p2->y * 2 * $mt * $t + $p3->y * $t2; $lines[] = array($last, new Point($x, $y)); $last = new Point($x, $y); } return $lines; }; } else if (count($curve) == 4) { $approx_func = function($curve, $nlines) { list($p1, $p2, $p3, $p4) = $curve; $last = $p1; $lines = array(); for ($i = 0; $i <= $nlines; $i++) { $t = $i / $nlines; $t2 = $t * $t; $t3 = $t2 * $t; $mt = 1 - $t; $mt2 = $mt * $mt; $mt3 = $mt2 * $mt; $x = $p1->x * $mt3 + 3 * $p2->x * $mt2 * $t + 3 * $p3->x * $mt * $t2 + $p4->x * $t3; $y = $p1->y * $mt3 + 3 * $p2->y * $mt2 * $t + 3 * $p3->y * $mt * $t2 + $p4->y * $t3; $lines[] = array($last, new Point($x, $y)); $last = new Point($x, $y); } return $lines; }; } else { throw new InvalidArgumentException("Can only approx. 3/4th degree curves."); } return $approx_func($curve, $nlines); } private function _split_curve($curve, $t, &$left, &$right) { foreach ($curve as $point) { if (get_class($point) != "Point") throw new InvalidArgumentException("curve is not an array of points"); } if (count($curve) == 1) { $left[] = $curve[0]; $right[] = $curve[0]; } else { $newpoints = array(); for ($i = 0; $i < count($curve) - 1; $i++) { if ($i == 0) $left[] = $curve[$i]; if ($i == count($curve) - 2) $right[] = $curve[$i + 1]; $x = (1 - $t) * $curve[$i]->x + $t * $curve[$i + 1]->x; $y = (1 - $t) * $curve[$i]->y + $t * $curve[$i + 1]->y; $newpoints[] = new Point($x, $y); } $this->_split_curve($newpoints, $t, $left, $right); } } public static function D($msg) { if (self::DEBUG) { if (ini_get('display_errors') != 'On') { ini_set('display_errors', 'On'); } error_reporting(E_ALL); echo "Memory peak usage: " . memory_get_peak_usage() . " And usage now" . memory_get_usage() . " <br />"; echo '[Debug] - ' . $msg . '<br />'; } } public static function V($msg) { if (self::VERBOSE) { echo '[i] - ' . $msg . '<br />'; } } } class Point { public $x; public $y; public function __construct($x, $y) { $this->x = $x; $this->y = $y; } public function __toString() { return 'Point(x=' . $this->x . ', y=' . $this->y . ')'; } public function _equals($p) { if ($p instanceof Point) { return ($this->x == $p->x && $this->y == $p->y); } else { return False; } } } function secure_rand($start, $stop, &$secure = "True", $calls = 0) { if ($start < 0 || $stop < 0 || $stop < $start) { throw new InvalidArgumentException("Either stop<start or negative input parameters. Arguments: start=$start, stop=$stop"); } static $LUT; static $last_lu; $num_bytes = 1024; $range = abs($stop - $start); $format = ''; if ($range < 256) { $format = 'C'; } elseif ($range < 65536) { $format = 'S'; $num_bytes <<= 2; } elseif ($range >= 65536 && $range < 4294967296) { $format = 'L'; $num_bytes <<= 3; } if (is_array($LUT) && !empty($LUT) && $last_lu === $format) { foreach ($LUT as $key => $value) { if ($value >= $start && $value <= $stop) { $secure = True; unset($LUT[$key]); return $value; } } } $binary = openssl_random_pseudo_bytes($num_bytes, $crypto_strong); if ($crypto_strong == False) { throw new UnexpectedValueException("openssl_random_bytes cannot access secure PRNG"); } $data = unpack($format . '*', $binary); if ($data == False) { throw new ErrorException("unpack() failed."); } $LUT = $data; $last_lu = $format; foreach ($data as $value) { $value = intval($value, $base = 10); if ($value <= $range) { $secure = True; return ($start + $value); } } $calls++; if ($calls >= 50) { $secure = False; return rand($start, $stop); } else { return secure_rand($start, $stop, $secure, $calls); } } function array_secure_rand($input, $num_el = 1, $allow_duplicates = False) { if ($num_el > count($input)) { throw new InvalidArgumentException('Cannot choose more random keys from input that are in the array: input_size: ' . count($input) . ' and num_to_pick' . $num_el); } $keys = array_keys($input); $chosen_keys = array(); if ($allow_duplicates) { for ($i = 0; $i < $num_el; $i++) { $chosen_keys[] = $keys[secure_rand(0, count($input) - 1)]; } } else { $already_used = array(); for ($i = 0; $i < $num_el; $i++) { $key = pick_remaining($keys, $already_used); $chosen_keys[] = $key; $already_used[] = $key; } } return $chosen_keys; } function pick_remaining($key_pool, $already_picked) { $remaining = array_values(array_diff($key_pool, $already_picked)); return $remaining[secure_rand(0, count($remaining) - 1)]; } function shuffle_assoc(&$array) { $keys = array_keys($array); shuffle($keys); foreach ($keys as $key) { $new[$key] = $array[$key]; } $array = $new; return true; } function array_copy($arr) { $newArray = array(); foreach ($arr as $key => $value) { if (is_array($value)) $newArray[$key] = array_copy($value); elseif (is_object($value)) $newArray[$key] = clone $value; else $newArray[$key] = $value; } return $newArray; } if (!function_exists('array_column')) { function array_column($input = null, $columnKey = null, $indexKey = null) { $argc = func_num_args(); $params = func_get_args(); if ($argc < 2) { trigger_error("array_column() expects at least 2 parameters, {$argc} given", E_USER_WARNING); return null; } if (!is_array($params[0])) { trigger_error('array_column() expects parameter 1 to be array, ' . gettype($params[0]) . ' given', E_USER_WARNING); return null; } if (!is_int($params[1]) && !is_float($params[1]) && !is_string($params[1]) && $params[1] !== null && !(is_object($params[1]) && method_exists($params[1], '__toString')) ) { trigger_error('array_column(): The column key should be either a string or an integer', E_USER_WARNING); return false; } if (isset($params[2]) && !is_int($params[2]) && !is_float($params[2]) && !is_string($params[2]) && !(is_object($params[2]) && method_exists($params[2], '__toString')) ) { trigger_error('array_column(): The index key should be either a string or an integer', E_USER_WARNING); return false; } $paramsInput = $params[0]; $paramsColumnKey = ($params[1] !== null) ? (string) $params[1] : null; $paramsIndexKey = null; if (isset($params[2])) { if (is_float($params[2]) || is_int($params[2])) { $paramsIndexKey = (int) $params[2]; } else { $paramsIndexKey = (string) $params[2]; } } $resultArray = array(); foreach ($paramsInput as $row) { $key = $value = null; $keySet = $valueSet = false; if ($paramsIndexKey !== null && array_key_exists($paramsIndexKey, $row)) { $keySet = true; $key = (string) $row[$paramsIndexKey]; } if ($paramsColumnKey === null) { $valueSet = true; $value = $row; } elseif (is_array($row) && array_key_exists($paramsColumnKey, $row)) { $valueSet = true; $value = $row[$paramsColumnKey]; } if ($valueSet) { if ($keySet) { $resultArray[$key] = $value; } else { $resultArray[] = $value; } } } return $resultArray; } } 

Did this file decode correctly?

Original Code

<?php class SVGCaptcha { private static $instance = NULL; private $svg_data = '<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" width="{{width}}" height="{{height}}" id="svgCaptcha" version="1.1" style="border:solid 2px #000"><g><path style="fill:none;stroke:#000000;stroke-width:2px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" d="{{pathdata}}" id="captcha" /></g></svg>'; private $alphabet; private $numchars = 0; private $width = 0; private $height = 0; private $difficulty; private $dsettings = array( 'glyph_offsetting' => array('apply' => True, 'h' => 1, 'v' => 0.5, 'mh' => 8), 'glyph_fragments' => array('apply' => False, 'r_num_frag' => NULL, 'frag_factor' => 2), 'transformations' => array('apply' => False, 'rotate' => False, 'skew' => False, 'scale' => False, 'shear' => False, 'translate' => False), 'approx_shapes' => array('apply' => False, 'p' => 3, 'r_al_num_lines' => NUll), 'change_degree' => array('apply' => False, 'p' => 5), 'split_curve' => array('apply' => False, 'p' => 5), 'shapeify' => array('apply' => False, 'r_num_shapes' => NULL, 'r_num_gp' => NULL) ); const DEBUG = FALSE; const VERBOSE = FALSE; const EASY = 1; const MEDIUM = 2; const HARD = 3; private $captcha_answer = ""; public static function getInstance($numchars, $width, $height, $difficulty = SVGCaptcha::MEDIUM) { if (!isset(self::$instance)) self::$instance = new SVGCaptcha($numchars, $width, $height, $difficulty); return self::$instance; } private function __construct($numchars, $width, $height, $difficulty) { $this->alphabet = array( 'y' => array( 'width' => 347, 'height' => 381, 'glyph_data' => array( 'cubic_splines' => array( array(new Point(178, 245), new Point(178, 245), new Point(148, 314), new Point(122, 339)), array(new Point(122, 339), new Point(109, 350), new Point(93, 361), new Point(76, 363)), array(new Point(76, 363), new Point(53, 366), new Point(6, 342), new Point(6, 342)), array(new Point(0, 359), new Point(0, 359), new Point(49, 381), new Point(73, 379)), array(new Point(0, 359), new Point(0, 359), new Point(49, 381), new Point(73, 379)), array(new Point(73, 379), new Point(93, 377), new Point(112, 365), new Point(128, 352)), array(new Point(128, 352), new Point(158, 325), new Point(175, 286), new Point(195, 250)), array(new Point(195, 250), new Point(235, 178), new Point(296, 16), new Point(296, 16)), array(new Point(195, 250), new Point(235, 178), new Point(296, 16), new Point(296, 16)) ), 'lines' => array( array(new Point(30, 19), new Point(65, 19)), array(new Point(65, 19), new Point(178, 245)), array(new Point(6, 342), new Point(0, 359)), array(new Point(296, 16), new Point(347, 16)), array(new Point(296, 16), new Point(347, 16)), array(new Point(347, 16), new Point(347, 0)), array(new Point(347, 0), new Point(239, 0)), array(new Point(239, 0), new Point(239, 16)), array(new Point(239, 0), new Point(239, 16)), array(new Point(239, 16), new Point(278, 16)), array(new Point(278, 16), new Point(189, 229)), array(new Point(189, 229), new Point(81, 19)), array(new Point(189, 229), new Point(81, 19)), array(new Point(81, 19), new Point(135, 18)), array(new Point(135, 18), new Point(135, 0)), array(new Point(135, 0), new Point(30, 0)), array(new Point(135, 0), new Point(30, 0)), array(new Point(30, 0), new Point(30, 19)) )) ), 'W' => array( 'width' => 520, 'height' => 390, 'glyph_data' => array( 'lines' => array( array(new Point(0, 0), new Point(130, 390)), array(new Point(130, 390), new Point(190, 390)), array(new Point(190, 390), new Point(270, 120)), array(new Point(270, 120), new Point(350, 390)), array(new Point(270, 120), new Point(350, 390)), array(new Point(350, 390), new Point(410, 390)), array(new Point(410, 390), new Point(520, 0)), array(new Point(520, 0), new Point(430, 10)), array(new Point(520, 0), new Point(430, 10)), array(new Point(430, 10), new Point(380, 290)), array(new Point(380, 290), new Point(300, 80)), array(new Point(300, 80), new Point(240, 80)), array(new Point(300, 80), new Point(240, 80)), array(new Point(240, 80), new Point(160, 290)), array(new Point(160, 290), new Point(90, 10)), array(new Point(90, 10), new Point(0, 0)), array(new Point(90, 10), new Point(0, 0)) )) ), 'G' => array( 'width' => 248, 'height' => 353, 'glyph_data' => array( 'cubic_splines' => array( array(new Point(248, 60), new Point(248, 60), new Point(211, 28), new Point(189, 17)), array(new Point(189, 17), new Point(169, 7), new Point(146, 0), new Point(124, 4)), array(new Point(124, 4), new Point(98, 8), new Point(74, 25), new Point(56, 45)), array(new Point(56, 45), new Point(33, 70), new Point(20, 103), new Point(12, 135)), array(new Point(56, 45), new Point(33, 70), new Point(20, 103), new Point(12, 135)), array(new Point(12, 135), new Point(3, 175), new Point(0, 218), new Point(12, 257)), array(new Point(12, 257), new Point(21, 287), new Point(39, 315), new Point(64, 333)), array(new Point(64, 333), new Point(83, 347), new Point(108, 352), new Point(132, 352)), array(new Point(64, 333), new Point(83, 347), new Point(108, 352), new Point(132, 352)), array(new Point(132, 352), new Point(167, 353), new Point(236, 344), new Point(236, 344)), array(new Point(207, 297), new Point(208, 326), new Point(181, 324), new Point(158, 321)), array(new Point(158, 321), new Point(130, 317), new Point(74, 301), new Point(58, 278)), array(new Point(158, 321), new Point(130, 317), new Point(74, 301), new Point(58, 278)), array(new Point(58, 278), new Point(38, 248), new Point(39, 208), new Point(43, 174)), array(new Point(43, 174), new Point(46, 136), new Point(56, 95), new Point(80, 65)), array(new Point(80, 65), new Point(96, 47), new Point(119, 34), new Point(144, 36)), array(new Point(80, 65), new Point(96, 47), new Point(119, 34), new Point(144, 36)), array(new Point(144, 36), new Point(177, 38), new Point(224, 84), new Point(224, 84)), array(new Point(224, 84), new Point(224, 84), new Point(218, 92), new Point(248, 60)) ), 'lines' => array( array(new Point(236, 344), new Point(238, 202)), array(new Point(238, 202), new Point(118, 200)), array(new Point(118, 200), new Point(116, 231)), array(new Point(116, 231), new Point(207, 231)), array(new Point(116, 231), new Point(207, 231)), array(new Point(207, 231), new Point(207, 297)), array(new Point(248, 60), new Point(248, 60)) )) ), 'e' => array( 'width' => 480, 'height' => 615, 'glyph_data' => array( 'cubic_splines' => array( array(new Point(46, 207), new Point(0, 331), new Point(3, 525), new Point(204, 570)), array(new Point(204, 570), new Point(404, 615), new Point(454, 423), new Point(460, 406)), array(new Point(389, 406), new Point(389, 406), new Point(354, 498), new Point(313, 515)), array(new Point(313, 515), new Point(252, 539), new Point(166, 522), new Point(121, 474)), array(new Point(313, 515), new Point(252, 539), new Point(166, 522), new Point(121, 474)), array(new Point(121, 474), new Point(82, 433), new Point(98, 306), new Point(98, 306)), array(new Point(461, 304), new Point(461, 304), new Point(480, 140), new Point(334, 70)), array(new Point(334, 70), new Point(188, 0), new Point(83, 108), new Point(46, 207)), array(new Point(334, 70), new Point(188, 0), new Point(83, 108), new Point(46, 207)), array(new Point(387, 257), new Point(387, 257), new Point(379, 114), new Point(251, 112)), array(new Point(251, 112), new Point(123, 109), new Point(97, 257), new Point(97, 257)) ), 'lines' => array( array(new Point(460, 406), new Point(389, 406)), array(new Point(98, 306), new Point(461, 304)), array(new Point(46, 207), new Point(46, 207)), array(new Point(97, 257), new Point(387, 257)), array(new Point(97, 257), new Point(387, 257)), array(new Point(97, 257), new Point(97, 257)) )) ), 'a' => array( 'width' => 351, 'height' => 634, 'glyph_data' => array( 'cubic_splines' => array( array(new Point(195, 0), new Point(163, 0), new Point(133, 9), new Point(107, 27)), array(new Point(107, 27), new Point(71, 53), new Point(60, 162), new Point(60, 162)), array(new Point(60, 162), new Point(73, 177), new Point(95, 212), new Point(95, 212)), array(new Point(95, 212), new Point(95, 212), new Point(104, 99), new Point(129, 72)), array(new Point(95, 212), new Point(95, 212), new Point(104, 99), new Point(129, 72)), array(new Point(129, 72), new Point(161, 31), new Point(207, 26), new Point(262, 74)), array(new Point(262, 74), new Point(300, 130), new Point(277, 185), new Point(245, 228)), array(new Point(245, 228), new Point(209, 277), new Point(151, 274), new Point(105, 287)), array(new Point(245, 228), new Point(209, 277), new Point(151, 274), new Point(105, 287)), array(new Point(105, 287), new Point(9, 326), new Point(0, 444), new Point(23, 521)), array(new Point(23, 521), new Point(32, 562), new Point(53, 590), new Point(90, 601)), array(new Point(90, 601), new Point(150, 618), new Point(193, 601), new Point(225, 563)), array(new Point(90, 601), new Point(150, 618), new Point(193, 601), new Point(225, 563)), array(new Point(225, 563), new Point(231, 590), new Point(232, 620), new Point(258, 626)), array(new Point(258, 626), new Point(298, 634), new Point(351, 628), new Point(312, 589)), array(new Point(312, 589), new Point(273, 551), new Point(283, 535), new Point(281, 510)), array(new Point(312, 589), new Point(273, 551), new Point(283, 535), new Point(281, 510)), array(new Point(335, 71), new Point(339, 43), new Point(291, 17), new Point(240, 5)), array(new Point(240, 5), new Point(224, 1), new Point(209, 0), new Point(195, 0)), array(new Point(252, 283), new Point(270, 367), new Point(251, 535), new Point(152, 571)), array(new Point(252, 283), new Point(270, 367), new Point(251, 535), new Point(152, 571)), array(new Point(152, 571), new Point(54, 608), new Point(35, 434), new Point(72, 384)), array(new Point(72, 384), new Point(124, 313), new Point(178, 279), new Point(252, 283)) ), 'lines' => array( array(new Point(281, 510), new Point(335, 71)), array(new Point(195, 0), new Point(195, 0)), array(new Point(252, 283), new Point(252, 283)) )) ), 'H' => array( 'width' => 420, 'height' => 550, 'glyph_data' => array( 'lines' => array( array(new Point(0, 0), new Point(0, 35)), array(new Point(0, 35), new Point(55, 35)), array(new Point(55, 35), new Point(55, 520)), array(new Point(55, 520), new Point(0, 520)), array(new Point(55, 520), new Point(0, 520)), array(new Point(0, 520), new Point(0, 550)), array(new Point(0, 550), new Point(150, 550)), array(new Point(150, 550), new Point(150, 520)), array(new Point(150, 550), new Point(150, 520)), array(new Point(150, 520), new Point(95, 520)), array(new Point(95, 520), new Point(95, 270)), array(new Point(95, 270), new Point(325, 270)), array(new Point(95, 270), new Point(325, 270)), array(new Point(325, 270), new Point(325, 520)), array(new Point(325, 520), new Point(265, 520)), array(new Point(265, 520), new Point(265, 550)), array(new Point(265, 520), new Point(265, 550)), array(new Point(265, 550), new Point(420, 550)), array(new Point(420, 550), new Point(420, 520)), array(new Point(420, 520), new Point(370, 520)), array(new Point(420, 520), new Point(370, 520)), array(new Point(370, 520), new Point(370, 35)), array(new Point(370, 35), new Point(420, 35)), array(new Point(420, 35), new Point(420, 0)), array(new Point(420, 35), new Point(420, 0)), array(new Point(420, 0), new Point(265, 0)), array(new Point(265, 0), new Point(265, 35)), array(new Point(265, 35), new Point(325, 35)), array(new Point(265, 35), new Point(325, 35)), array(new Point(325, 35), new Point(325, 230)), array(new Point(325, 230), new Point(95, 230)), array(new Point(95, 230), new Point(95, 35)), array(new Point(95, 230), new Point(95, 35)), array(new Point(95, 35), new Point(150, 35)), array(new Point(150, 35), new Point(150, 0)), array(new Point(150, 0), new Point(0, 0)), array(new Point(150, 0), new Point(0, 0)) )) ), 'k' => array( 'width' => 420, 'height' => 680, 'glyph_data' => array( 'lines' => array( array(new Point(0, 0), new Point(60, 0)), array(new Point(60, 0), new Point(60, 490)), array(new Point(60, 490), new Point(350, 280)), array(new Point(350, 280), new Point(420, 280)), array(new Point(350, 280), new Point(420, 280)), array(new Point(420, 280), new Point(210, 440)), array(new Point(210, 440), new Point(420, 680)), array(new Point(420, 680), new Point(350, 680)), array(new Point(420, 680), new Point(350, 680)), array(new Point(350, 680), new Point(170, 470)), array(new Point(170, 470), new Point(60, 550)), array(new Point(60, 550), new Point(60, 680)), array(new Point(60, 550), new Point(60, 680)), array(new Point(60, 680), new Point(0, 680)), array(new Point(0, 680), new Point(0, 0)) )) ), 'i' => array( 'width' => 122, 'height' => 687, 'glyph_data' => array( 'cubic_splines' => array( array(new Point(67, 1), new Point(48, 0), new Point(28, 14), new Point(17, 29)), array(new Point(17, 29), new Point(6, 45), new Point(0, 67), new Point(7, 85)), array(new Point(7, 85), new Point(14, 107), new Point(37, 128), new Point(60, 130)), array(new Point(60, 130), new Point(79, 131), new Point(99, 117), new Point(109, 100)), array(new Point(60, 130), new Point(79, 131), new Point(99, 117), new Point(109, 100)), array(new Point(109, 100), new Point(120, 82), new Point(122, 56), new Point(113, 37)), array(new Point(113, 37), new Point(105, 19), new Point(86, 3), new Point(67, 1)) ), 'lines' => array( array(new Point(23, 214), new Point(23, 687)), array(new Point(23, 687), new Point(96, 687)), array(new Point(96, 687), new Point(96, 214)), array(new Point(96, 214), new Point(23, 214)), array(new Point(96, 214), new Point(23, 214)), array(new Point(67, 1), new Point(67, 1)) )) ), 'f' => array( 'width' => 240, 'height' => 600, 'glyph_data' => array( 'cubic_splines' => array( array(new Point(240, 0), new Point(240, 0), new Point(167, 0), new Point(138, 11)), array(new Point(138, 11), new Point(106, 24), new Point(84, 48), new Point(70, 80)), array(new Point(70, 80), new Point(57, 108), new Point(60, 170), new Point(60, 170)), array(new Point(90, 170), new Point(90, 170), new Point(87, 116), new Point(97, 91)), array(new Point(90, 170), new Point(90, 170), new Point(87, 116), new Point(97, 91)), array(new Point(97, 91), new Point(106, 68), new Point(146, 48), new Point(170, 40)), array(new Point(170, 40), new Point(197, 31), new Point(240, 50), new Point(240, 50)) ), 'lines' => array( array(new Point(240, 50), new Point(240, 0)), array(new Point(60, 170), new Point(0, 170)), array(new Point(0, 170), new Point(0, 200)), array(new Point(0, 200), new Point(60, 200)), array(new Point(0, 200), new Point(60, 200)), array(new Point(60, 200), new Point(60, 570)), array(new Point(60, 570), new Point(0, 570)), array(new Point(0, 570), new Point(0, 600)), array(new Point(0, 570), new Point(0, 600)), array(new Point(0, 600), new Point(130, 600)), array(new Point(130, 600), new Point(150, 570)), array(new Point(150, 570), new Point(90, 570)), array(new Point(150, 570), new Point(90, 570)), array(new Point(90, 570), new Point(90, 200)), array(new Point(90, 200), new Point(150, 200)), array(new Point(150, 200), new Point(150, 170)), array(new Point(150, 200), new Point(150, 170)), array(new Point(150, 170), new Point(90, 170)), array(new Point(240, 50), new Point(240, 50)) )) ), 'b' => array( 'width' => 237, 'height' => 454, 'glyph_data' => array( 'cubic_splines' => array( array(new Point(43, 0), new Point(39, 13), new Point(38, 20), new Point(37, 26)), array(new Point(37, 26), new Point(0, 302), new Point(5, 438), new Point(5, 438)), array(new Point(5, 438), new Point(5, 438), new Point(142, 454), new Point(188, 414)), array(new Point(188, 414), new Point(222, 385), new Point(237, 329), new Point(224, 287)), array(new Point(188, 414), new Point(222, 385), new Point(237, 329), new Point(224, 287)), array(new Point(224, 287), new Point(213, 254), new Point(177, 221), new Point(141, 220)), array(new Point(141, 220), new Point(99, 220), new Point(40, 295), new Point(40, 295)), array(new Point(69, 305), new Point(69, 305), new Point(18, 373), new Point(38, 398)), array(new Point(69, 305), new Point(69, 305), new Point(18, 373), new Point(38, 398)), array(new Point(38, 398), new Point(64, 431), new Point(131, 416), new Point(161, 388)), array(new Point(161, 388), new Point(186, 366), new Point(189, 321), new Point(178, 289)), array(new Point(178, 289), new Point(172, 272), new Point(156, 253), new Point(138, 253)), array(new Point(178, 289), new Point(172, 272), new Point(156, 253), new Point(138, 253)), array(new Point(138, 253), new Point(109, 251), new Point(69, 305), new Point(69, 305)) ), 'lines' => array( array(new Point(40, 295), new Point(85, 4)), array(new Point(85, 4), new Point(43, 0)), array(new Point(69, 305), new Point(69, 305)) )) ), 'n' => array( 'width' => 420, 'height' => 380, 'glyph_data' => array( 'cubic_splines' => array( array(new Point(111, 50), new Point(111, 50), new Point(146, 38), new Point(206, 39)), array(new Point(206, 39), new Point(267, 41), new Point(287, 53), new Point(304, 67)), array(new Point(304, 67), new Point(318, 79), new Point(340, 110), new Point(340, 110)), array(new Point(370, 110), new Point(370, 110), new Point(361, 71), new Point(340, 50)), array(new Point(370, 110), new Point(370, 110), new Point(361, 71), new Point(340, 50)), array(new Point(340, 50), new Point(310, 20), new Point(288, 15), new Point(220, 10)), array(new Point(220, 10), new Point(151, 5), new Point(110, 20), new Point(110, 20)) ), 'lines' => array( array(new Point(30, 0), new Point(30, 30)), array(new Point(30, 30), new Point(80, 30)), array(new Point(80, 30), new Point(80, 350)), array(new Point(80, 350), new Point(30, 350)), array(new Point(80, 350), new Point(30, 350)), array(new Point(30, 350), new Point(0, 380)), array(new Point(0, 380), new Point(160, 380)), array(new Point(160, 380), new Point(160, 350)), array(new Point(160, 380), new Point(160, 350)), array(new Point(160, 350), new Point(110, 350)), array(new Point(110, 350), new Point(111, 50)), array(new Point(340, 110), new Point(340, 350)), array(new Point(340, 110), new Point(340, 350)), array(new Point(340, 350), new Point(290, 350)), array(new Point(290, 350), new Point(290, 380)), array(new Point(290, 380), new Point(420, 380)), array(new Point(290, 380), new Point(420, 380)), array(new Point(420, 380), new Point(370, 350)), array(new Point(370, 350), new Point(370, 110)), array(new Point(110, 20), new Point(110, 0)), array(new Point(110, 20), new Point(110, 0)), array(new Point(110, 0), new Point(30, 0)) )) ), 'S' => array( 'width' => 354, 'height' => 745, 'glyph_data' => array( 'cubic_splines' => array( array(new Point(287, 366), new Point(250, 289), new Point(141, 264), new Point(99, 189)), array(new Point(99, 189), new Point(88, 168), new Point(78, 141), new Point(85, 118)), array(new Point(85, 118), new Point(92, 96), new Point(116, 82), new Point(135, 71)), array(new Point(135, 71), new Point(157, 58), new Point(182, 50), new Point(207, 48)), array(new Point(135, 71), new Point(157, 58), new Point(182, 50), new Point(207, 48)), array(new Point(207, 48), new Point(244, 44), new Point(288, 42), new Point(319, 63)), array(new Point(319, 63), new Point(335, 73), new Point(348, 128), new Point(347, 110)), array(new Point(346, 44), new Point(345, 21), new Point(354, 16), new Point(293, 15)), array(new Point(346, 44), new Point(345, 21), new Point(354, 16), new Point(293, 15)), array(new Point(293, 15), new Point(293, 15), new Point(161, 0), new Point(88, 58)), array(new Point(88, 58), new Point(16, 116), new Point(27, 169), new Point(39, 196)), array(new Point(39, 196), new Point(74, 277), new Point(183, 304), new Point(233, 377)), array(new Point(39, 196), new Point(74, 277), new Point(183, 304), new Point(233, 377)), array(new Point(233, 377), new Point(248, 400), new Point(256, 427), new Point(262, 454)), array(new Point(262, 454), new Point(270, 493), new Point(272, 533), new Point(267, 572)), array(new Point(267, 572), new Point(261, 609), new Point(265, 640), new Point(228, 679)), array(new Point(267, 572), new Point(261, 609), new Point(265, 640), new Point(228, 679)), array(new Point(228, 679), new Point(182, 727), new Point(84, 731), new Point(28, 695)), array(new Point(28, 695), new Point(6, 681), new Point(0, 604), new Point(1, 623)), array(new Point(3, 691), new Point(6, 745), new Point(67, 742), new Point(94, 742)), array(new Point(3, 691), new Point(6, 745), new Point(67, 742), new Point(94, 742)), array(new Point(94, 742), new Point(124, 741), new Point(153, 741), new Point(182, 741)), array(new Point(182, 741), new Point(235, 740), new Point(287, 664), new Point(307, 605)), array(new Point(307, 605), new Point(333, 530), new Point(322, 438), new Point(287, 366)), array(new Point(307, 605), new Point(333, 530), new Point(322, 438), new Point(287, 366)) ), 'lines' => array( array(new Point(347, 110), new Point(346, 44)), array(new Point(1, 623), new Point(3, 691)), array(new Point(287, 366), new Point(287, 366)) )) ), 'X' => array( 'width' => 300, 'height' => 400, 'glyph_data' => array( 'lines' => array( array(new Point(10, 0), new Point(130, 200)), array(new Point(130, 200), new Point(0, 390)), array(new Point(0, 390), new Point(40, 390)), array(new Point(40, 390), new Point(150, 220)), array(new Point(40, 390), new Point(150, 220)), array(new Point(150, 220), new Point(260, 400)), array(new Point(260, 400), new Point(300, 400)), array(new Point(300, 400), new Point(170, 190)), array(new Point(300, 400), new Point(170, 190)), array(new Point(170, 190), new Point(296, 0)), array(new Point(296, 0), new Point(260, 0)), array(new Point(260, 0), new Point(150, 170)), array(new Point(260, 0), new Point(150, 170)), array(new Point(150, 170), new Point(50, 0)), array(new Point(50, 0), new Point(10, 0)) )) ), 'E' => array( 'width' => 370, 'height' => 680, 'glyph_data' => array( 'lines' => array( array(new Point(0, 0), new Point(0, 50)), array(new Point(0, 50), new Point(50, 50)), array(new Point(50, 50), new Point(50, 630)), array(new Point(50, 630), new Point(0, 630)), array(new Point(50, 630), new Point(0, 630)), array(new Point(0, 630), new Point(0, 680)), array(new Point(0, 680), new Point(370, 680)), array(new Point(370, 680), new Point(370, 550)), array(new Point(370, 680), new Point(370, 550)), array(new Point(370, 550), new Point(320, 550)), array(new Point(320, 550), new Point(320, 630)), array(new Point(320, 630), new Point(100, 630)), array(new Point(320, 630), new Point(100, 630)), array(new Point(100, 630), new Point(100, 360)), array(new Point(100, 360), new Point(280, 360)), array(new Point(280, 360), new Point(280, 310)), array(new Point(280, 360), new Point(280, 310)), array(new Point(280, 310), new Point(100, 310)), array(new Point(100, 310), new Point(100, 50)), array(new Point(100, 50), new Point(320, 50)), array(new Point(100, 50), new Point(320, 50)), array(new Point(320, 50), new Point(320, 130)), array(new Point(320, 130), new Point(370, 130)), array(new Point(370, 130), new Point(370, 0)), array(new Point(370, 130), new Point(370, 0)), array(new Point(370, 0), new Point(0, 0)) )) ), 'Q' => array( 'width' => 510, 'height' => 600, 'glyph_data' => array( 'cubic_splines' => array( array(new Point(70, 90), new Point(68, 202), new Point(71, 408), new Point(70, 440)) ), 'lines' => array( array(new Point(0, 450), new Point(70, 540)), array(new Point(70, 540), new Point(360, 540)), array(new Point(360, 540), new Point(410, 600)), array(new Point(410, 600), new Point(500, 600)), array(new Point(410, 600), new Point(500, 600)), array(new Point(500, 600), new Point(440, 530)), array(new Point(440, 530), new Point(510, 460)), array(new Point(510, 460), new Point(510, 70)), array(new Point(510, 460), new Point(510, 70)), array(new Point(510, 70), new Point(431, 2)), array(new Point(431, 2), new Point(70, 0)), array(new Point(70, 0), new Point(0, 70)), array(new Point(70, 0), new Point(0, 70)), array(new Point(0, 70), new Point(0, 450)), array(new Point(70, 440), new Point(110, 480)), array(new Point(110, 480), new Point(310, 480)), array(new Point(110, 480), new Point(310, 480)), array(new Point(310, 480), new Point(270, 420)), array(new Point(270, 420), new Point(360, 420)), array(new Point(360, 420), new Point(400, 480)), array(new Point(360, 420), new Point(400, 480)), array(new Point(400, 480), new Point(440, 430)), array(new Point(440, 430), new Point(440, 90)), array(new Point(440, 90), new Point(390, 50)), array(new Point(440, 90), new Point(390, 50)), array(new Point(390, 50), new Point(120, 50)), array(new Point(120, 50), new Point(70, 90)) )) ), ); $this->numchars = ($numchars > count($this->alphabet) ? count($this->alphabet) : $numchars); $this->width = $width; $this->height = $height; $this->difficulty = $difficulty; if ($this->difficulty == self::EASY) { $this->dsettings['glyph_fragments']['apply'] = True; $this->dsettings['glyph_fragments']['r_num_frag'] = range(2, 4); $this->dsettings["glyph_offseting"]["apply"] = True; $this->dsettings["glyph_offseting"]["h"] = 0.5; $this->dsettings["transformations"]["apply"] = True; $this->dsettings["transformations"]["rotate"] = True; $this->dsettings["shapeify"]["apply"] = False; $this->dsettings["shapeify"]["r_num_shapes"] = range(0, 4); $this->dsettings["shapeify"]["r_num_gp"] = range(2, 4); $this->dsettings["approx_shapes"]["apply"] = True; $this->dsettings["approx_shapes"]["p"] = 5; $this->dsettings["approx_shapes"]["r_al_num_lines"] = range(4, 20); $this->dsettings["change_degree"]["apply"] = True; $this->dsettings["change_degree"]["p"] = 5; $this->dsettings["split_curve"]["apply"] = True; } else if ($this->difficulty == self::MEDIUM) { $this->dsettings["transformations"]["apply"] = True; $this->dsettings["transformations"]["rotate"] = True; $this->dsettings["transformations"]["skew"] = True; $this->dsettings["transformations"]["scale"] = True; $this->dsettings["shapeify"]["apply"] = True; $this->dsettings["shapeify"]["r_num_shapes"] = range(4, 5); $this->dsettings["shapeify"]["r_num_gp"] = range(3, 4); $this->dsettings["approx_shapes"]["apply"] = True; $this->dsettings["approx_shapes"]["p"] = 3; $this->dsettings["approx_shapes"]["r_al_num_lines"] = range(4, 16); $this->dsettings["change_degree"]["apply"] = True; $this->dsettings["change_degree"]["p"] = 5; $this->dsettings["split_curve"]["apply"] = True; } else if ($this->difficulty == self::HARD) { $this->dsettings["transformations"]["apply"] = True; $this->dsettings["transformations"]["rotate"] = True; $this->dsettings["transformations"]["skew"] = True; $this->dsettings["transformations"]["scale"] = True; $this->dsettings["transformations"]["shear"] = True; $this->dsettings["transformations"]["translate"] = True; $this->dsettings["shapeify"]["apply"] = True; $this->dsettings["shapeify"]["r_num_shapes"] = range(3, 8); $this->dsettings["shapeify"]["r_num_gp"] = range(3, 5); $this->dsettings["approx_shapes"]["apply"] = True; $this->dsettings["approx_shapes"]["p"] = 2; $this->dsettings["approx_shapes"]["r_al_num_lines"] = range(6, 26); $this->dsettings["change_degree"]["apply"] = True; $this->dsettings["change_degree"]["p"] = 3; $this->dsettings["split_curve"]["apply"] = True; } else if (is_array($difficulty) && !empty($difficulty) && (!array_diff_key($difficulty, $this->dsettings))) { $this->dsettings = $difficulty; } } public function generate() { $selected_keys = array_secure_rand($this->alphabet, $this->numchars, False); foreach ($selected_keys as $key) { $selected[$key] = $this->alphabet[$key]; } foreach ($selected as $key => $value) { $packed[$key]["width"] = $selected[$key]["width"]; $packed[$key]["height"] = $selected[$key]["height"]; foreach ($value['glyph_data'] as $shapetype) { foreach ($shapetype as $shape) { $packed[$key]['glyph_data'][] = $shape; } } $this->captcha_answer[] = $key; } $this->_scale_by_largest_glyph($packed); if ($this->dsettings['transformations']['apply']) { $this->_apply_affine_transformations($packed); } if ($this->dsettings["glyph_offsetting"]["apply"]) { $this->_align_randomly($packed); } if ($this->dsettings['glyph_fragments']['apply']) { $packed = $this->_glyph_fragments($packed); } foreach ($packed as $char => $value) { foreach ($value["glyph_data"] as $shape) { $shapearray[] = $shape; } } shuffle($shapearray); if ($this->dsettings['shapeify']['apply']) { $shapearray = $this->_shapeify($shapearray); } if ($this->dsettings['change_degree']['apply']) { $this->_maybe_change_curvature_degree($shapearray); } if ($this->dsettings['split_curve']['apply']) { $shapearray = $this->_maybe_split_curve($shapearray); } if ($this->dsettings['approx_shapes']['apply']) { $shapearray = $this->_maybe_approximate_xor_make_curvaceous($shapearray); } shuffle($shapearray); $path_str = ""; $begin_path = True; foreach ($shapearray as $key => &$shape) { array_map(function($p) { $p->x = sprintf("%." . rand(3, 6) . "f", $p->x); $p->y = sprintf("%." . rand(4, 7) . "f", $p->y); }, $shape); if ($begin_path) { $path_str .= "M {$shape[0]->x} {$shape[0]->y}"; $begin_path = False; } $path_str .= $this->_shape2_cmd($shape, True, True); } $this->D("mtest"); return $this->_write_SVG($path_str); } private function _write_SVG($path_str) { $svg_output = $this->svg_data; $svg_output = str_replace("{{width}}", $this->width, $svg_output); $svg_output = str_replace("{{height}}", $this->height, $svg_output); $svg_output = str_replace("{{pathdata}}", $path_str, $svg_output); return array(implode($this->captcha_answer, ""), $svg_output); } private function _glyph_fragments($glyphs) { if (!empty($this->dsettings['glyph_fragments']['r_num_frag'])) { $ngf = max($this->dsettings['glyph_fragments']['r_num_frag']); $ngf = $ngf >= count($glyphs) ? count($glyphs) - 1 : $ngf; } else { $ngf = secure_rand(0, count($glyphs) - 1); } $chosen_keys = array_secure_rand($glyphs, $ngf, True); $glyph_fragments = array(); foreach ($chosen_keys as $key) { $ukey = uniqid($prefix = "gf__"); $shape_keys = array_secure_rand( $glyphs[$key]["glyph_data"], secure_rand(0, count($glyphs[$key]["glyph_data"]) / $this->dsettings['glyph_fragments']['frag_factor']) ); if (count($shape_keys) > 0 && !empty($shape_keys)) { $pos = (($rel = $glyphs[$key]["glyph_data"][$shape_keys[0]][0]->x) > $this->width / 2) ? false : true; $x_translate = ($pos) ? secure_rand(abs($rel), $this->width) : - secure_rand(0, abs($rel)); $y_translate = (microtime() & 1) ? -secure_rand(0, $this->width / 5) : secure_rand(0, $this->width / 5); $a = $this->_ra(0.6); foreach ($shape_keys as $skey) { $copy = array_copy($glyphs[$key]["glyph_data"][$skey]); $this->on_points($copy, array($this, "_translate"), array($x_translate, $y_translate)); $this->on_points($copy, array($this, "_rotate"), array($a)); $glyph_fragments[$ukey]["glyph_data"][] = $copy; } } } return array_merge($glyph_fragments, $glyphs); } private function _shapeify($shapearray) { $random_shapes = array(); $ns = secure_rand(min($this->dsettings["shapeify"]["r_num_shapes"]), max($this->dsettings["shapeify"]["r_num_shapes"])); foreach (range(0, $ns) as $i) { $random_shapes = array_merge($random_shapes, $this->_random_shape()); } return array_merge($shapearray, $random_shapes); } private function _random_shape() { $rshapes = array(); $min = new Point(0, 0); $max = new Point($this->width, $this->height); $previous = $startp = new Point(secure_rand($min->x, $max->x), secure_rand($min->y, $max->y)); $ngp = secure_rand(min($this->dsettings["shapeify"]["r_num_gp"]), max($this->dsettings["shapeify"]["r_num_gp"])); foreach (range(0, $ngp) as $j) { $rp = new Point(secure_rand($min->x, $max->x), secure_rand($min->y, $max->y)); if (($ngp - 4) <= $j) { $rp = new Point(secure_rand($min->x, $max->x), secure_rand($min->y, $max->y)); $axis = abs($startp->x - $rp->x) > abs($startp->y - $rp->y) ? 'x' : 'y'; if ($axis === 'x') { $rp->x += ($startp->x > $rp->x) ? abs($startp->x - $rp->x) / 4 : abs($startp->x - $rp->x) / -4; } else { $rp->y += ($startp->y > $rp->y) ? abs($startp->y - $rp->y) / 4 : abs($startp->y - $rp->y) / -4; } } if ($j == ($ngp - 1)) { $rshapes[] = array($previous, $startp); break; } else if (rand(0, 1) == 1) { $rshapes[] = array($previous, $rp); } else { $rshapes[] = array($previous, new Point($previous->x, $rp->y), $rp); } $previous = $rp; } return $rshapes; } private function _maybe_change_curvature_degree(&$shapearray) { foreach ($shapearray as &$shape) { $p = $this->dsettings["change_degree"]["p"]; $do_change = (bool) (secure_rand(0, $p) == $p); if ($do_change && count($shape) == 3) { self::V("changing curvature degree"); list($p1, $p2, $p3) = $shape; $shape = array( $p1, new Point(1 / 3 * $p1->x + 2 / 3 * $p2->x, 1 / 3 * $p1->y + 2 / 3 * $p2->y), new Point(1 / 3 * $p3->x + 2 / 3 * $p2->x, 1 / 3 * $p3->y + 2 / 3 * $p2->y), $p3 ); } } return True; } private function _maybe_split_curve($shapearray) { $newshapes = array(); foreach ($shapearray as $key => $shape) { $p = $this->dsettings["split_curve"]["p"]; $do_change = (bool) (secure_rand(0, $p) == $p); if ($do_change && count($shape) >= 3) { self::V("splitting curve"); $left = array(); $right = array(); $this->_split_curve($shape, $this->_rt(), $left, $right); $right = array_reverse($right); if (!empty($left) and !empty($right)) { self::D("adding left:" . count($left) . " and right:" . count($right)); unset($shapearray[$key]); $newshapes[] = $left; $newshapes[] = $right; } } } return array_merge($newshapes, $shapearray); } private function _maybe_approximate_xor_make_curvaceous($shapearray) { $dk = array(); $merge = array(); foreach ($shapearray as $key => $shape) { $p = $this->dsettings["approx_shapes"]["p"]; $do_change = (bool) (secure_rand(0, $p) == $p); if ($do_change) { if ((count($shape) == 3 || count($shape) == 4)) { self::V("approximating curve with lines"); $lines = $this->_approximate_bezier($shape); $dk[] = $key; $merge = array_merge($merge, $lines); } else if (count($shape) == 2) { self::V("approximating lines by curves"); $shapearray[$key] = $this->_approximate_line($shape); } } } return array_merge($merge, array_diff_key($shapearray, array_fill_keys($dk, 0))); } private function _shape2_cmd($shape, $absolute = True, $explicit_moveto = False) { if ($explicit_moveto) { $prefix = "M {$shape[0]->x} {$shape[0]->y} "; } else { $prefix = ""; } if (count($shape) == 2) { list($p1, $p2) = $shape; $cmd = "L {$p2->x} {$p2->y} "; } else if (count($shape) == 3) { list($p1, $p2, $p3) = $shape; $cmd = "Q {$p2->x} {$p2->y} {$p3->x} {$p3->y} "; } else if (count($shape) == 4) { list($p1, $p2, $p3, $p4) = $shape; $cmd = "C {$p2->x} {$p2->y} {$p3->x} {$p3->y} {$p4->x} {$p4->y} "; } if (!$cmd) return False; return $prefix . $cmd; } private function _scale_by_largest_glyph(&$glyphs) { $my = max(array_column($glyphs, "height")); $scale_factor = ($this->height / 1.5) / $my; $this->on_points( $glyphs, array($this, "_scale"), array($scale_factor) ); foreach ($glyphs as &$value) { $value["width"] *= $scale_factor; $value["height"] *= $scale_factor; } } private function _align_randomly(&$glyphs) { $accumulated_hoffset = 0; $lastxo = 0; $lastyo = 0; $cnt = 0; $overlapf_h = $this->dsettings["glyph_offsetting"]["h"]; $overlapf_v = $this->dsettings["glyph_offsetting"]["v"]; foreach ($glyphs as &$glyph) { $accumulated_hoffset += ($cnt == 0) ? $glyph['width'] / 3 : secure_rand($lastxo, ($glyph["width"] > $lastxo) ? $glyph["width"] : $lastxo); $h = round($glyph['height'] * $overlapf_v); $svo = $this->height / $this->dsettings["glyph_offsetting"]["mh"]; $yoffset = secure_rand(($svo > $h ? 0 : $svo), $h); $this->on_points( $glyph["glyph_data"], array($this, "_translate"), array($accumulated_hoffset, $yoffset) ); $lastxo = round($glyph['width'] * $overlapf_h); $lastyo = round($glyph['height'] * $overlapf_h); $cnt++; } $this->width = $accumulated_hoffset + $glyph["width"] + secure_rand($glyph["width"] * $overlapf_h, $glyph["width"]); } private function _apply_affine_transformations(&$glyphs) { foreach ($glyphs as &$glyph) { foreach ($this->_get_random_transformations() as $transformation) { $this->on_points($glyph["glyph_data"], $transformation[0], $transformation[1]); } } } private function _get_random_transformations() { $transformations = array(); if ($this->dsettings["transformations"]["rotate"]) { $transformations[] = array(array($this, "_rotate"), array($this->_ra())); } if ($this->dsettings["transformations"]["skew"]) { $transformations[] = array(array($this, "_skew"), array($this->_ra())); } if ($this->dsettings["transformations"]["scale"]) { $transformations[] = array(array($this, "_scale"), array($this->_rs())); } if ($this->dsettings["transformations"]["shear"]) { $transformations[] = array(array($this, "_shear"), array(1, 0)); } if ($this->dsettings["transformations"]["translate"]) { $transformations[] = array(array($this, "_translate"), array(0, 0)); } if (empty($transformations)) { return (array) Null; } $n = secure_rand(0, count($transformations) - 1); shuffle_assoc($transformations); for ($i = 0; $i < $n; $i++) { unset($transformations[$i]); } return $transformations; } private function on_points(&$data, $callback, $args) { if ($data instanceof Point) { if (is_callable($callback)) { call_user_func_array($callback, array_merge(array($data), $args)); } } if (is_array($data)) { foreach ($data as &$value) { $this->on_points($value, $callback, $args); } unset($value); } return; } private function _ra($ub=null) { $n = secure_rand(0, $ub != null ? $ub : 4) / 10; if (secure_rand(0, 1) == 1) $n *= -1; return $n; } private function _rs() { $z = secure_rand(8, 13) / 10; return $z; } private function _rt($inclusive = True) { if ($inclusive) { $z = secure_rand(0, 1000) / 1000; } else { $z = secure_rand(1, 999) / 1000; } return $z; } private function _rotate($p, $a) { $x = $p->x; $y = $p->y; $p->x = cos($a) * $x - sin($a) * $y; $p->y = sin($a) * $x + cos($a) * $y; } private function _skew($p, $a) { $x = $p->x; $y = $p->y; $p->x = $x + sin($a) * $y; } private function _scale($p, $s = 1) { $x = $p->x; $y = $p->y; $p->x = $x * $s; $p->y = $y * $s; } private function _shear($p, $mh = 1, $mv = 0) { if ($mh * $mv != 0) { throw new InvalidArgumentException(__FUNCTION__ . " _shear called with invalid arguments $p mh: $mh mv: $mv"); } $x = $p->x; $y = $p->y; $p->x = $x + $y * $mh; $p->y = $y + $x * $mv; } private function _translate($p, $dx, $dy) { $x = $p->x; $y = $p->y; $p->x = $x + $dx; $p->y = $y + $dy; } private function _approximate_line($line) { if (count($line) != 2 || !($line[0] instanceof Point) || !($line[1] instanceof Point)) { throw new InvalidArgumentException(__FUNCTION__ . ": Argument is not an array of two points"); } else if ($line[0]->_equals($line[1])) { } $make_cubic = (intval(time()) & 1) ? True : False; $d = sqrt(pow(abs($line[0]->x - $line[1]->x), 2) + pow(abs($line[0]->y - $line[1]->y), 2)); $md = $d / secure_rand(10, 50); $somewhere_near_the_line = function($line, $md) { $maxx = max($line[0]->x, $line[1]->x); $maxy = max($line[0]->y, $line[1]->y); $minx = min($line[0]->x, $line[1]->x); $miny = min($line[0]->y, $line[1]->y); if (($line[1]->x - $line[0]->x) == 0) { $line[1]->x += 1; } $m = ($line[1]->y - $line[0]->y) / ($line[1]->x - $line[0]->x); $d = ($line[1]->x * $line[0]->y - $line[0]->x * $line[1]->y) / ($line[1]->x - $line[0]->x); if ($maxx < 0 || $minx < 0) { $ma = max(abs($maxx), abs($minx)); $mi = min(abs($maxx), abs($minx)); $x = - secure_rand($mi, $ma); } else { $x = secure_rand($minx, $maxx); } $y = $m * $x + $d; return new Point($x + ((rand(0, 1) == 1) ? $md : -$md), $y + ((rand(0, 1) == 1) ? $md : -$md)); }; if ($make_cubic) { $p1 = $somewhere_near_the_line($line, $md); $p2 = $somewhere_near_the_line($line, $md); $curve = array($line[0], $p1, $p2, $line[1]); } else { $p1 = $somewhere_near_the_line($line, $md); $curve = array($line[0], $p1, $line[1]); } return $curve; } private function _approximate_bezier($curve, $nlines = False) { foreach ($curve as $point) { if (get_class($point) != "Point") throw new InvalidArgumentException("curve is not an array of points"); } if (!$nlines || !isset($nlines)) { $nlines = secure_rand(min($this->dsettings["approx_shapes"]["r_al_num_lines"]), max($this->dsettings["approx_shapes"]["r_al_num_lines"])); } $approx_func = nUlL; if (count($curve) == 3) { $approx_func = function($curve, $nlines) { list($p1, $p2, $p3) = $curve; $last = $p1; $lines = array(); for ($i = 0; $i <= $nlines; $i++) { $t = $i / $nlines; $t2 = $t * $t; $mt = 1 - $t; $mt2 = $mt * $mt; $x = $p1->x * $mt2 + $p2->x * 2 * $mt * $t + $p3->x * $t2; $y = $p1->y * $mt2 + $p2->y * 2 * $mt * $t + $p3->y * $t2; $lines[] = array($last, new Point($x, $y)); $last = new Point($x, $y); } return $lines; }; } else if (count($curve) == 4) { $approx_func = function($curve, $nlines) { list($p1, $p2, $p3, $p4) = $curve; $last = $p1; $lines = array(); for ($i = 0; $i <= $nlines; $i++) { $t = $i / $nlines; $t2 = $t * $t; $t3 = $t2 * $t; $mt = 1 - $t; $mt2 = $mt * $mt; $mt3 = $mt2 * $mt; $x = $p1->x * $mt3 + 3 * $p2->x * $mt2 * $t + 3 * $p3->x * $mt * $t2 + $p4->x * $t3; $y = $p1->y * $mt3 + 3 * $p2->y * $mt2 * $t + 3 * $p3->y * $mt * $t2 + $p4->y * $t3; $lines[] = array($last, new Point($x, $y)); $last = new Point($x, $y); } return $lines; }; } else { throw new InvalidArgumentException("Can only approx. 3/4th degree curves."); } return $approx_func($curve, $nlines); } private function _split_curve($curve, $t, &$left, &$right) { foreach ($curve as $point) { if (get_class($point) != "Point") throw new InvalidArgumentException("curve is not an array of points"); } if (count($curve) == 1) { $left[] = $curve[0]; $right[] = $curve[0]; } else { $newpoints = array(); for ($i = 0; $i < count($curve) - 1; $i++) { if ($i == 0) $left[] = $curve[$i]; if ($i == count($curve) - 2) $right[] = $curve[$i + 1]; $x = (1 - $t) * $curve[$i]->x + $t * $curve[$i + 1]->x; $y = (1 - $t) * $curve[$i]->y + $t * $curve[$i + 1]->y; $newpoints[] = new Point($x, $y); } $this->_split_curve($newpoints, $t, $left, $right); } } public static function D($msg) { if (self::DEBUG) { if (ini_get('display_errors') != 'On') { ini_set('display_errors', 'On'); } error_reporting(E_ALL); echo "Memory peak usage: " . memory_get_peak_usage() . " And usage now" . memory_get_usage() . " <br />"; echo '[Debug] - ' . $msg . '<br />'; } } public static function V($msg) { if (self::VERBOSE) { echo '[i] - ' . $msg . '<br />'; } } } class Point { public $x; public $y; public function __construct($x, $y) { $this->x = $x; $this->y = $y; } public function __toString() { return 'Point(x=' . $this->x . ', y=' . $this->y . ')'; } public function _equals($p) { if ($p instanceof Point) { return ($this->x == $p->x && $this->y == $p->y); } else { return False; } } } function secure_rand($start, $stop, &$secure = "True", $calls = 0) { if ($start < 0 || $stop < 0 || $stop < $start) { throw new InvalidArgumentException("Either stop<start or negative input parameters. Arguments: start=$start, stop=$stop"); } static $LUT; static $last_lu; $num_bytes = 1024; $range = abs($stop - $start); $format = ''; if ($range < 256) { $format = 'C'; } elseif ($range < 65536) { $format = 'S'; $num_bytes <<= 2; } elseif ($range >= 65536 && $range < 4294967296) { $format = 'L'; $num_bytes <<= 3; } if (is_array($LUT) && !empty($LUT) && $last_lu === $format) { foreach ($LUT as $key => $value) { if ($value >= $start && $value <= $stop) { $secure = True; unset($LUT[$key]); return $value; } } } $binary = openssl_random_pseudo_bytes($num_bytes, $crypto_strong); if ($crypto_strong == False) { throw new UnexpectedValueException("openssl_random_bytes cannot access secure PRNG"); } $data = unpack($format . '*', $binary); if ($data == False) { throw new ErrorException("unpack() failed."); } $LUT = $data; $last_lu = $format; foreach ($data as $value) { $value = intval($value, $base = 10); if ($value <= $range) { $secure = True; return ($start + $value); } } $calls++; if ($calls >= 50) { $secure = False; return rand($start, $stop); } else { return secure_rand($start, $stop, $secure, $calls); } } function array_secure_rand($input, $num_el = 1, $allow_duplicates = False) { if ($num_el > count($input)) { throw new InvalidArgumentException('Cannot choose more random keys from input that are in the array: input_size: ' . count($input) . ' and num_to_pick' . $num_el); } $keys = array_keys($input); $chosen_keys = array(); if ($allow_duplicates) { for ($i = 0; $i < $num_el; $i++) { $chosen_keys[] = $keys[secure_rand(0, count($input) - 1)]; } } else { $already_used = array(); for ($i = 0; $i < $num_el; $i++) { $key = pick_remaining($keys, $already_used); $chosen_keys[] = $key; $already_used[] = $key; } } return $chosen_keys; } function pick_remaining($key_pool, $already_picked) { $remaining = array_values(array_diff($key_pool, $already_picked)); return $remaining[secure_rand(0, count($remaining) - 1)]; } function shuffle_assoc(&$array) { $keys = array_keys($array); shuffle($keys); foreach ($keys as $key) { $new[$key] = $array[$key]; } $array = $new; return true; } function array_copy($arr) { $newArray = array(); foreach ($arr as $key => $value) { if (is_array($value)) $newArray[$key] = array_copy($value); elseif (is_object($value)) $newArray[$key] = clone $value; else $newArray[$key] = $value; } return $newArray; } if (!function_exists('array_column')) { function array_column($input = null, $columnKey = null, $indexKey = null) { $argc = func_num_args(); $params = func_get_args(); if ($argc < 2) { trigger_error("array_column() expects at least 2 parameters, {$argc} given", E_USER_WARNING); return null; } if (!is_array($params[0])) { trigger_error('array_column() expects parameter 1 to be array, ' . gettype($params[0]) . ' given', E_USER_WARNING); return null; } if (!is_int($params[1]) && !is_float($params[1]) && !is_string($params[1]) && $params[1] !== null && !(is_object($params[1]) && method_exists($params[1], '__toString')) ) { trigger_error('array_column(): The column key should be either a string or an integer', E_USER_WARNING); return false; } if (isset($params[2]) && !is_int($params[2]) && !is_float($params[2]) && !is_string($params[2]) && !(is_object($params[2]) && method_exists($params[2], '__toString')) ) { trigger_error('array_column(): The index key should be either a string or an integer', E_USER_WARNING); return false; } $paramsInput = $params[0]; $paramsColumnKey = ($params[1] !== null) ? (string) $params[1] : null; $paramsIndexKey = null; if (isset($params[2])) { if (is_float($params[2]) || is_int($params[2])) { $paramsIndexKey = (int) $params[2]; } else { $paramsIndexKey = (string) $params[2]; } } $resultArray = array(); foreach ($paramsInput as $row) { $key = $value = null; $keySet = $valueSet = false; if ($paramsIndexKey !== null && array_key_exists($paramsIndexKey, $row)) { $keySet = true; $key = (string) $row[$paramsIndexKey]; } if ($paramsColumnKey === null) { $valueSet = true; $value = $row; } elseif (is_array($row) && array_key_exists($paramsColumnKey, $row)) { $valueSet = true; $value = $row[$paramsColumnKey]; } if ($valueSet) { if ($keySet) { $resultArray[$key] = $value; } else { $resultArray[] = $value; } } } return $resultArray; } }

Function Calls

None

Variables

None

Stats

MD5 d9f36ceaf5c81285c861c1ea421eb7a5
Eval Count 0
Decode Time 116 ms