2742 * @return string A unique identifier assigned to the code. This hash should be passed to sessionManager::getCaptcha() to retrieve the code. |
2741 * @return string A unique identifier assigned to the code. This hash should be passed to sessionManager::getCaptcha() to retrieve the code. |
2743 */ |
2742 */ |
2744 |
2743 |
2745 function make_captcha($len = 7) |
2744 function make_captcha($len = 7) |
2746 { |
2745 { |
|
2746 global $db, $session, $paths, $template, $plugins; // Common objects |
2747 $code = $this->generate_captcha_code($len); |
2747 $code = $this->generate_captcha_code($len); |
2748 $hash = md5(microtime() . mt_rand()); |
2748 $hash = md5(microtime() . mt_rand()); |
2749 $this->sql('INSERT INTO '.table_prefix.'session_keys(session_key,salt,auth_level,source_ip,user_id) VALUES(\''.$hash.'\', \'\', -1, \''.ip2hex($_SERVER['REMOTE_ADDR']).'\', -2);'); |
2749 $session_data = $db->escape(serialize(array())); |
|
2750 |
|
2751 // sanity check |
|
2752 if ( !is_valid_ip(@$_SERVER['REMOTE_ADDR']) || !is_int($this->user_id) ) |
|
2753 return false; |
|
2754 |
|
2755 $this->sql('INSERT INTO '.table_prefix.'captcha(session_id, code, session_data, source_ip, user_id)' . " VALUES('$hash', '$code', '$session_data', '{$_SERVER['REMOTE_ADDR']}', {$this->user_id});"); |
2750 return $hash; |
2756 return $hash; |
2751 } |
2757 } |
2752 |
2758 |
2753 /** |
2759 /** |
2754 * Generates the actual confirmation code text. |
2760 * Generates a "pronouncable" or "human-friendly" word using various phonics rules |
2755 * @param int String length |
2761 * @param int Optional. The length of the word. |
2756 * @return string |
2762 * @return string |
2757 */ |
2763 */ |
2758 |
2764 |
2759 function generate_captcha_code($len = 7) |
2765 function generate_captcha_code($len = 7) |
2760 { |
2766 { |
2761 $chars = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9'); |
2767 // don't use k and x, they get mixed up a lot |
2762 $s = ''; |
2768 $consonants = 'bcdfghmnpqrsvwyz'; |
|
2769 $vowels = 'aeiou'; |
|
2770 $prev = 'vowel'; |
|
2771 $prev_l = ''; |
|
2772 $word = ''; |
|
2773 $allow_next_vowel = true; |
2763 for ( $i = 0; $i < $len; $i++ ) |
2774 for ( $i = 0; $i < $len; $i++ ) |
2764 { |
2775 { |
2765 $s .= $chars[mt_rand(0, count($chars)-1)]; |
2776 if ( $prev == 'vowel' ) |
2766 } |
2777 { |
2767 return $s; |
2778 $allow_next_vowel = false; |
|
2779 if ( $prev_l == 'o' && mt_rand(0, 3) == 3 && $allow_next_vowel ) |
|
2780 $word .= 'i'; |
|
2781 else if ( $prev_l == 'q' && mt_rand(0, 3) != 1 && $allow_next_vowel ) |
|
2782 $word .= 'u'; |
|
2783 else if ( $prev_l == 'o' && mt_rand(0, 3) == 2 && $allow_next_vowel ) |
|
2784 $word .= 'u'; |
|
2785 else if ( $prev_l == 'a' && mt_rand(0, 3) == 3 && $allow_next_vowel ) |
|
2786 $word .= 'i'; |
|
2787 else if ( $prev_l == 'a' && mt_rand(0, 10) == 7 && $allow_next_vowel ) |
|
2788 $word .= 'o'; |
|
2789 else if ( $prev_l == 'a' && mt_rand(0, 7) == 2 && $allow_next_vowel ) |
|
2790 $word .= 'u'; |
|
2791 else |
|
2792 { |
|
2793 $allow_next_vowel = true; |
|
2794 $word .= $consonants{mt_rand(0, (strlen($consonants)-1))}; |
|
2795 } |
|
2796 } |
|
2797 else if ( $prev == 'consonant' ) |
|
2798 { |
|
2799 if ( $prev_l == 'p' && mt_rand(0, 7) == 4 ) |
|
2800 $word .= 't'; |
|
2801 else if ( $prev_l == 'p' && mt_rand(0, 5) == 1 ) |
|
2802 $word .= 'h'; |
|
2803 else |
|
2804 $word .= $vowels{mt_rand(0, (strlen($vowels)-1))}; |
|
2805 } |
|
2806 $prev_l = substr($word, -1); |
|
2807 $l = ( mt_rand(0, 1) == 1 ) ? strtoupper($prev_l) : strtolower($prev_l); |
|
2808 $word = substr($word, 0, -1) . $l; |
|
2809 if ( strstr('aeiou', $prev_l) ) |
|
2810 $prev = 'vowel'; |
|
2811 else |
|
2812 $prev = 'consonant'; |
|
2813 } |
|
2814 return $word; |
2768 } |
2815 } |
2769 |
2816 |
2770 /** |
2817 /** |
2771 * For the given code ID, returns the correct CAPTCHA code, or false on failure |
2818 * For the given code ID, returns the correct CAPTCHA code, or false on failure |
2772 * @param string $hash The unique ID assigned to the code |
2819 * @param string $hash The unique ID assigned to the code |
2774 */ |
2821 */ |
2775 |
2822 |
2776 function get_captcha($hash) |
2823 function get_captcha($hash) |
2777 { |
2824 { |
2778 global $db, $session, $paths, $template, $plugins; // Common objects |
2825 global $db, $session, $paths, $template, $plugins; // Common objects |
2779 $s = $this->sql('SELECT salt FROM '.table_prefix.'session_keys WHERE session_key=\''.$db->escape($hash).'\' AND source_ip=\''.ip2hex($_SERVER['REMOTE_ADDR']).'\';'); |
2826 |
|
2827 if ( !preg_match('/^[a-f0-9]{32}([a-z0-9]{8})?$/', $hash) ) |
|
2828 { |
|
2829 return false; |
|
2830 } |
|
2831 |
|
2832 $q = $this->sql('SELECT code_id, code FROM ' . table_prefix . "captcha WHERE session_id = '$hash';"); |
2780 if ( $db->numrows() < 1 ) |
2833 if ( $db->numrows() < 1 ) |
2781 { |
|
2782 return false; |
2834 return false; |
2783 } |
2835 |
2784 $r = $db->fetchrow(); |
2836 list($code_id, $code) = $db->fetchrow_num(); |
2785 $db->free_result(); |
2837 $db->free_result(); |
2786 $this->sql('DELETE FROM ' . table_prefix . 'session_keys WHERE salt=\'' . $db->escape($r['salt']) . '\';'); |
2838 $this->sql('DELETE FROM ' . table_prefix . "captcha WHERE code_id = $code_id;"); |
2787 return $r['salt']; |
2839 return $code; |
2788 } |
2840 } |
2789 |
2841 |
2790 /** |
2842 /** |
2791 * (AS OF 1.0.2: Deprecated. Captcha codes are now killed on first fetch for security.) Deletes all CAPTCHA codes cached in the DB for this user. |
2843 * (AS OF 1.0.2: Deprecated. Captcha codes are now killed on first fetch for security.) Deletes all CAPTCHA codes cached in the DB for this user. |
2792 */ |
2844 */ |
2793 |
2845 |
2794 function kill_captcha() |
2846 function kill_captcha() |
2795 { |
2847 { |
2796 // $this->sql('DELETE FROM '.table_prefix.'session_keys WHERE user_id=-2 AND source_ip=\''.ip2hex($_SERVER['REMOTE_ADDR']).'\';'); |
|
2797 return true; |
2848 return true; |
2798 } |
2849 } |
2799 |
2850 |
2800 /** |
2851 /** |
2801 * Generates a random password. |
2852 * Generates a random password. |