Subs-Sound.php 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. <?php
  2. /**
  3. * Handles sound processing. In order to make sure the visual
  4. * verification is still accessible for all users, a sound clip is being addded
  5. * that reads the letters that are being shown.
  6. *
  7. * Simple Machines Forum (SMF)
  8. *
  9. * @package SMF
  10. * @author Simple Machines http://www.simplemachines.org
  11. * @copyright 2012 Simple Machines
  12. * @license http://www.simplemachines.org/about/smf/license.php BSD
  13. *
  14. * @version 2.1 Alpha 1
  15. */
  16. if (!defined('SMF'))
  17. die('No direct access...');
  18. /**
  19. * Creates a wave file that spells the letters of $word.
  20. * Tries the user's language first, and defaults to english.
  21. * Used by VerificationCode() (Register.php).
  22. *
  23. * @param string $word
  24. * @return boolean false on failure
  25. */
  26. function createWaveFile($word)
  27. {
  28. global $settings, $user_info, $context;
  29. // Allow max 2 requests per 20 seconds.
  30. if (($ip = cache_get_data('wave_file/' . $user_info['ip'], 20)) > 2 || ($ip2 = cache_get_data('wave_file/' . $user_info['ip2'], 20)) > 2)
  31. die(header('HTTP/1.1 400 Bad Request'));
  32. cache_put_data('wave_file/' . $user_info['ip'], $ip ? $ip + 1 : 1, 20);
  33. cache_put_data('wave_file/' . $user_info['ip2'], $ip2 ? $ip2 + 1 : 1, 20);
  34. // Fixate randomization for this word.
  35. mt_srand(end(unpack('n', md5($word . session_id()))));
  36. // Try to see if there's a sound font in the user's language.
  37. if (file_exists($settings['default_theme_dir'] . '/fonts/sound/a.' . $user_info['language'] . '.wav'))
  38. $sound_language = $user_info['language'];
  39. // English should be there.
  40. elseif (file_exists($settings['default_theme_dir'] . '/fonts/sound/a.english.wav'))
  41. $sound_language = 'english';
  42. // Guess not...
  43. else
  44. return false;
  45. // File names are in lower case so lets make sure that we are only using a lower case string
  46. $word = strtolower($word);
  47. // Loop through all letters of the word $word.
  48. $sound_word = '';
  49. for ($i = 0; $i < strlen($word); $i++)
  50. {
  51. $sound_letter = implode('', file($settings['default_theme_dir'] . '/fonts/sound/' . $word{$i} . '.' . $sound_language . '.wav'));
  52. if (strpos($sound_letter, 'data') === false)
  53. return false;
  54. $sound_letter = substr($sound_letter, strpos($sound_letter, 'data') + 8);
  55. switch ($word{$i} === 's' ? 0 : mt_rand(0, 2))
  56. {
  57. case 0:
  58. for ($j = 0, $n = strlen($sound_letter); $j < $n; $j++)
  59. for ($k = 0, $m = round(mt_rand(15, 25) / 10); $k < $m; $k++)
  60. $sound_word .= $word{$i} === 's' ? $sound_letter{$j} : chr(mt_rand(max(ord($sound_letter{$j}) - 1, 0x00), min(ord($sound_letter{$j}) + 1, 0xFF)));
  61. break;
  62. case 1:
  63. for ($j = 0, $n = strlen($sound_letter) - 1; $j < $n; $j += 2)
  64. $sound_word .= (mt_rand(0, 3) == 0 ? '' : $sound_letter{$j}) . (mt_rand(0, 3) === 0 ? $sound_letter{$j + 1} : $sound_letter{$j}) . (mt_rand(0, 3) === 0 ? $sound_letter{$j} : $sound_letter{$j + 1}) . $sound_letter{$j + 1} . (mt_rand(0, 3) == 0 ? $sound_letter{$j + 1} : '');
  65. $sound_word .= str_repeat($sound_letter{$n}, 2);
  66. break;
  67. case 2:
  68. $shift = 0;
  69. for ($j = 0, $n = strlen($sound_letter); $j < $n; $j++)
  70. {
  71. if (mt_rand(0, 10) === 0)
  72. $shift += mt_rand(-3, 3);
  73. for ($k = 0, $m = round(mt_rand(15, 25) / 10); $k < $m; $k++)
  74. $sound_word .= chr(min(max(ord($sound_letter{$j}) + $shift, 0x00), 0xFF));
  75. }
  76. break;
  77. }
  78. $sound_word .= str_repeat(chr(0x80), mt_rand(10000, 10500));
  79. }
  80. $data_size = strlen($sound_word);
  81. $file_size = $data_size + 0x24;
  82. $sample_rate = 16000;
  83. // Disable compression.
  84. ob_end_clean();
  85. header('Content-Encoding: none');
  86. // Output the wav.
  87. header('Content-type: audio/x-wav');
  88. header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 525600 * 60) . ' GMT');
  89. header('Content-Length: ' . ($file_size + 0x08));
  90. echo pack('nnVnnnnnnnnVVnnnnV', 0x5249, 0x4646, $file_size, 0x5741, 0x5645, 0x666D, 0x7420, 0x1000, 0x0000, 0x0100, 0x0100, $sample_rate, $sample_rate, 0x0100, 0x0800, 0x6461, 0x7461, $data_size), $sound_word;
  91. // Noting more to add.
  92. die();
  93. }
  94. ?>