PageRenderTime 68ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/securimage.php

http://github.com/dapphp/securimage
PHP | 3801 lines | 2126 code | 414 blank | 1261 comment | 385 complexity | 10a63003b27d0c7d825e7dacd4df34e9 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. // error_reporting(E_ALL); ini_set('display_errors', 1); // uncomment this line for debugging
  3. /**
  4. * Project: Securimage: A PHP class dealing with CAPTCHA images, audio, and validation
  5. * File: securimage.php
  6. *
  7. * Copyright (c) 2018, Drew Phillips
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without modification,
  11. * are permitted provided that the following conditions are met:
  12. *
  13. * - Redistributions of source code must retain the above copyright notice,
  14. * this list of conditions and the following disclaimer.
  15. * - Redistributions in binary form must reproduce the above copyright notice,
  16. * this list of conditions and the following disclaimer in the documentation
  17. * and/or other materials provided with the distribution.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  20. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  23. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  24. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  25. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  26. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  27. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  28. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  29. * POSSIBILITY OF SUCH DAMAGE.
  30. *
  31. * Any modifications to the library should be indicated clearly in the source code
  32. * to inform users that the changes are not a part of the original software.
  33. *
  34. * @link https://www.phpcaptcha.org Securimage Homepage
  35. * @link https://www.phpcaptcha.org/latest.zip Download Latest Version
  36. * @link https://github.com/dapphp/securimage GitHub page
  37. * @link https://www.phpcaptcha.org/Securimage_Docs/ Online Documentation
  38. * @copyright 2018 Drew Phillips
  39. * @author Drew Phillips <drew@drew-phillips.com>
  40. * @version 3.6.8 (May 2020)
  41. * @package Securimage
  42. *
  43. */
  44. /**
  45. ChangeLog
  46. 3.6.8
  47. - Ability to fix open_basedir warning by setting Securimage::$lame_binary_path = ''; (#63)
  48. - Fix division by zero if captcha length is 1 (#88)
  49. - Add options to getCaptchaHtml input_required (#82) and js_url (#95)
  50. - PHP 7.3/7.4 compat fixes (#101)
  51. - Project status: https://github.com/dapphp/securimage/issues/99
  52. - Improve handling of multi-byte wordlists (#87)
  53. 3.6.7
  54. - Merge changes from 4.0.1-nextgen
  55. - Increase captcha difficulty
  56. - Add setting "use_text_angles". Enable to select a random angle and step value and draw each character at an angle in a step like fashion
  57. - Add setting "use_random_spaces". Enable to insert 1-3 spaces between a random group of letters some of the time
  58. - Add setting "use_random_baseline". Enable to draw letters at a random height instead of centered. Each character's baseline is a step up or down from the previous (not totally random)
  59. - Add setting "use_random_boxes". Enable to draw a bounding box around one or more characters at random
  60. - Improve performance of captcha generation when using distortion (perturbation) and noise (noise_level)
  61. - Enable image anti-aliasing
  62. - Make all text functions multibyte safe when using UTF-8 or other encodings for charsets and wordlists (using mbstring)
  63. 3.6.6
  64. - Not critical: Fix potential HTML injection in example form via HTTP_USER_AGENT (CVE-2017-14077)
  65. 3.6.5
  66. - Fix regex in replaceElements in securimage.js
  67. - Update examples
  68. - Exclude certain examples from Git autogenerated archives
  69. 3.6.4
  70. - Fix XSS vulnerability in example_form.ajax.php (Discovered by RedTeam. advisory rt-sa-2016-002)
  71. - Update example_form.ajax.php to use Securimage::getCaptchaHtml()
  72. 3.6.3
  73. - Add support for multibyte wordlist files
  74. - Fix code generation issues with UTF-8 charsets
  75. - Add parameter to getCaptchaHtml() method to control display components of captcha HTML
  76. - Fix database audio storage issue with multiple namespaces
  77. 3.6.2
  78. - Support HTTP range requests with audio playback (iOS requirement)
  79. - Add optional config.inc.php for storing global configuration settings
  80. 3.6.1
  81. - Fix copyElement bug in securimage.js for IE Flash fallback
  82. 3.6
  83. - Implement CAPTCHA audio using HTML5 <audio> with optional Flash fallback
  84. - Support MP3 audio using LAME MP3 Encoder (Internet Explorer 9+ does not support WAV format in <audio> tags)
  85. - Add getCaptchaHtml() options to support full framework integration (ruifil)
  86. 3.5.4
  87. - Fix email validation code in example form files
  88. - Fix backslashes in getCaptchaHtml for img attribute on Windows systems
  89. 3.5.3
  90. - Add options for audio button to getCaptchaHtml(), fix urlencoding of flash parameters that was breaking button
  91. 3.5.2
  92. - Add Securimage::getCaptchaHtml() for getting automatically generated captcha html code
  93. - Option for using SoX to add effects to captcha audio to make identification by neural networks more difficult
  94. - Add setNamespace() method
  95. - Add getTimeToSolve() method
  96. - Add session_status() check so session still starts if one had previously been opened and closed
  97. - Add .htaccess file to audio directory to deny access; update audio files
  98. - Option to skip checking of database tables during connection
  99. - Add composer.json to package, submit to packagist
  100. - Add font_ratio variable to determine size of font (github.com/wilkor)
  101. - Add hint if sqlite3 database is not writeable. Improve database error handling, add example database options to securimage_play.php
  102. - Fixed issue regarding database storage and math captcha breaking audio output (github.com/SoftwareAndOutsourcing)
  103. 3.5.1
  104. - Fix XSS vulnerability in example_form.php (discovered by Gjoko Krstic - <gjoko@zeroscience.mk>)
  105. 3.5
  106. - Release new version
  107. - MB string support for charlist
  108. - Modify audio file path to use language directories
  109. - Changed default captcha appearance
  110. 3.2RC4
  111. - Add MySQL, PostgreSQL, and SQLite3 support for database storage
  112. - Deprecate "use_sqlite_db" option and remove SQLite2/sqlite_* functions
  113. - Add new captcha type that displays 2 dictionary words on one image
  114. - Update examples
  115. 3.2RC3
  116. - Fix canSendHeaders() check which was breaking if a PHP startup error was issued
  117. 3.2RC2
  118. - Add error handler (https://github.com/dapphp/securimage/issues/15)
  119. - Fix flash examples to use the correct value name for audio parameter
  120. 3.2RC1
  121. - New audio captcha code. Faster, fully dynamic audio, full WAV support
  122. (Paul Voegler, Drew Phillips) <http://voegler.eu/pub/audio>
  123. - New Flash audio streaming button. User defined image and size supported
  124. - Additional options for customizing captcha (noise_level, send_headers,
  125. no_exit, no_session, display_value
  126. - Add captcha ID support. Uses sqlite and unique captcha IDs to track captchas,
  127. no session used
  128. - Add static methods for creating and validating captcha by ID
  129. - Automatic clearing of old codes from SQLite database
  130. 3.0.3Beta
  131. - Add improved mixing function to WavFile class (Paul Voegler)
  132. - Improve performance and security of captcha audio (Paul Voegler, Drew Phillips)
  133. - Add option to use random file as background noise in captcha audio
  134. - Add new securimage options for audio files
  135. 3.0.2Beta
  136. - Fix issue with session variables when upgrading from 2.0 - 3.0
  137. - Improve audio captcha, switch to use WavFile class, make mathematical captcha audio work
  138. 3.0.1
  139. - Bugfix: removed use of deprecated variable in addSignature method that would cause errors with display_errors on
  140. 3.0
  141. - Rewrite class using PHP5 OOP
  142. - Remove support for GD fonts, require FreeType
  143. - Remove support for multi-color codes
  144. - Add option to make codes case-sensitive
  145. - Add namespaces to support multiple captchas on a single page or page specific captchas
  146. - Add option to show simple math problems instead of codes
  147. - Remove support for mp3 files due to vulnerability in decoding mp3 audio files
  148. - Create new flash file to stream wav files instead of mp3
  149. - Changed to BSD license
  150. 2.0.2
  151. - Fix pathing to make integration into libraries easier (Nathan Phillip Brink ohnobinki@ohnopublishing.net)
  152. 2.0.1
  153. - Add support for browsers with cookies disabled (requires php5, sqlite) maps users to md5 hashed ip addresses and md5 hashed codes for security
  154. - Add fallback to gd fonts if ttf support is not enabled or font file not found (Mike Challis http://www.642weather.com/weather/scripts.php)
  155. - Check for previous definition of image type constants (Mike Challis)
  156. - Fix mime type settings for audio output
  157. - Fixed color allocation issues with multiple colors and background images, consolidate allocation to one function
  158. - Ability to let codes expire after a given length of time
  159. - Allow HTML color codes to be passed to Securimage_Color (suggested by Mike Challis)
  160. 2.0.0
  161. - Add mathematical distortion to characters (using code from HKCaptcha)
  162. - Improved session support
  163. - Added Securimage_Color class for easier color definitions
  164. - Add distortion to audio output to prevent binary comparison attack (proposed by Sven "SavageTiger" Hagemann [insecurity.nl])
  165. - Flash button to stream mp3 audio (Douglas Walsh www.douglaswalsh.net)
  166. - Audio output is mp3 format by default
  167. - Change font to AlteHaasGrotesk by yann le coroller
  168. - Some code cleanup
  169. 1.0.4 (unreleased)
  170. - Ability to output audible codes in mp3 format to stream from flash
  171. 1.0.3.1
  172. - Error reading from wordlist in some cases caused words to be cut off 1 letter short
  173. 1.0.3
  174. - Removed shadow_text from code which could cause an undefined property error due to removal from previous version
  175. 1.0.2
  176. - Audible CAPTCHA Code wav files
  177. - Create codes from a word list instead of random strings
  178. 1.0
  179. - Added the ability to use a selected character set, rather than a-z0-9 only.
  180. - Added the multi-color text option to use different colors for each letter.
  181. - Switched to automatic session handling instead of using files for code storage
  182. - Added GD Font support if ttf support is not available. Can use internal GD fonts or load new ones.
  183. - Added the ability to set line thickness
  184. - Added option for drawing arced lines over letters
  185. - Added ability to choose image type for output
  186. */
  187. /**
  188. * Securimage CAPTCHA Class.
  189. *
  190. * A class for creating and validating secure CAPTCHA images and audio.
  191. *
  192. * The class contains many options regarding appearance, security, storage of
  193. * captcha data and image/audio generation options.
  194. *
  195. * @package Securimage
  196. * @subpackage classes
  197. * @author Drew Phillips <drew@drew-phillips.com>
  198. *
  199. */
  200. class Securimage
  201. {
  202. // All of the public variables below are securimage options
  203. // They can be passed as an array to the Securimage constructor, set below,
  204. // or set from securimage_show.php and securimage_play.php
  205. /**
  206. * Constant for rendering captcha as a JPEG image
  207. * @var int
  208. */
  209. const SI_IMAGE_JPEG = 1;
  210. /**
  211. * Constant for rendering captcha as a PNG image (default)
  212. * @var int
  213. */
  214. const SI_IMAGE_PNG = 2;
  215. /**
  216. * Constant for rendering captcha as a GIF image
  217. * @var int
  218. */
  219. const SI_IMAGE_GIF = 3;
  220. /**
  221. * Constant for generating a normal alphanumeric captcha based on the
  222. * character set
  223. *
  224. * @see Securimage::$charset charset property
  225. * @var int
  226. */
  227. const SI_CAPTCHA_STRING = 0;
  228. /**
  229. * Constant for generating a captcha consisting of a simple math problem
  230. *
  231. * @var int
  232. */
  233. const SI_CAPTCHA_MATHEMATIC = 1;
  234. /**
  235. * Constant for generating a word based captcha using 2 words from a list
  236. *
  237. * @var int
  238. */
  239. const SI_CAPTCHA_WORDS = 2;
  240. /**
  241. * MySQL option identifier for database storage option
  242. *
  243. * @var string
  244. */
  245. const SI_DRIVER_MYSQL = 'mysql';
  246. /**
  247. * PostgreSQL option identifier for database storage option
  248. *
  249. * @var string
  250. */
  251. const SI_DRIVER_PGSQL = 'pgsql';
  252. /**
  253. * SQLite option identifier for database storage option
  254. *
  255. * @var string
  256. */
  257. const SI_DRIVER_SQLITE3 = 'sqlite';
  258. /**
  259. * getCaptchaHtml() display constant for HTML Captcha Image
  260. *
  261. * @var integer
  262. */
  263. const HTML_IMG = 1;
  264. /**
  265. * getCaptchaHtml() display constant for HTML5 Audio code
  266. *
  267. * @var integer
  268. */
  269. const HTML_AUDIO = 2;
  270. /**
  271. * getCaptchaHtml() display constant for Captcha Input text box
  272. *
  273. * @var integer
  274. */
  275. const HTML_INPUT = 4;
  276. /**
  277. * getCaptchaHtml() display constant for Captcha Text HTML label
  278. *
  279. * @var integer
  280. */
  281. const HTML_INPUT_LABEL = 8;
  282. /**
  283. * getCaptchaHtml() display constant for HTML Refresh button
  284. *
  285. * @var integer
  286. */
  287. const HTML_ICON_REFRESH = 16;
  288. /**
  289. * getCaptchaHtml() display constant for all HTML elements (default)
  290. *
  291. * @var integer
  292. */
  293. const HTML_ALL = 0xffffffff;
  294. /*%*********************************************************************%*/
  295. // Properties
  296. /**
  297. * The width of the captcha image
  298. * @var int
  299. */
  300. public $image_width = 215;
  301. /**
  302. * The height of the captcha image
  303. * @var int
  304. */
  305. public $image_height = 80;
  306. /**
  307. * Font size is calculated by image height and this ratio. Leave blank for
  308. * default ratio of 0.4.
  309. *
  310. * Valid range: 0.1 - 0.99.
  311. *
  312. * Depending on image_width, values > 0.6 are probably too large and
  313. * values < 0.3 are too small.
  314. *
  315. * @var float
  316. */
  317. public $font_ratio;
  318. /**
  319. * The type of the image, default = png
  320. *
  321. * @see Securimage::SI_IMAGE_PNG SI_IMAGE_PNG
  322. * @see Securimage::SI_IMAGE_JPEG SI_IMAGE_JPEG
  323. * @see Securimage::SI_IMAGE_GIF SI_IMAGE_GIF
  324. * @var int
  325. */
  326. public $image_type = self::SI_IMAGE_PNG;
  327. /**
  328. * The background color of the captcha
  329. * @var Securimage_Color|string
  330. */
  331. public $image_bg_color = '#ffffff';
  332. /**
  333. * The color of the captcha text
  334. * @var Securimage_Color|string
  335. */
  336. public $text_color = '#707070';
  337. /**
  338. * The color of the lines over the captcha
  339. * @var Securimage_Color|string
  340. */
  341. public $line_color = '#707070';
  342. /**
  343. * The color of the noise that is drawn
  344. * @var Securimage_Color|string
  345. */
  346. public $noise_color = '#707070';
  347. /**
  348. * How transparent to make the text.
  349. *
  350. * 0 = completely opaque, 100 = invisible
  351. *
  352. * @var int
  353. */
  354. public $text_transparency_percentage = 20;
  355. /**
  356. * Whether or not to draw the text transparently.
  357. *
  358. * true = use transparency, false = no transparency
  359. *
  360. * @var bool
  361. */
  362. public $use_transparent_text = true;
  363. /**
  364. * The length of the captcha code
  365. * @var int
  366. */
  367. public $code_length = 6;
  368. /**
  369. * Display random spaces in the captcha text on the image
  370. *
  371. * @var bool true to insert random spacing between groups of letters
  372. */
  373. public $use_random_spaces = false;
  374. /**
  375. * Draw each character at an angle with random starting angle and increase/decrease per character
  376. * @var bool true to use random angles, false to draw each character normally
  377. */
  378. public $use_text_angles = false;
  379. /**
  380. * Instead of centering text vertically in the image, the baseline of each character is
  381. * randomized in such a way that the next character is drawn slightly higher or lower than
  382. * the previous in a step-like fashion.
  383. *
  384. * @var bool true to use random baselines, false to center text in image
  385. */
  386. public $use_random_baseline = false;
  387. /**
  388. * Draw a bounding box around some characters at random. 20% of the time, random boxes
  389. * may be drawn around 0 or more characters on the image.
  390. *
  391. * @var bool true to randomly draw boxes around letters, false not to
  392. */
  393. public $use_random_boxes = false;
  394. /**
  395. * Whether the captcha should be case sensitive or not.
  396. *
  397. * Not recommended, use only for maximum protection.
  398. *
  399. * @var bool
  400. */
  401. public $case_sensitive = false;
  402. /**
  403. * The character set to use for generating the captcha code
  404. * @var string
  405. */
  406. public $charset = 'abcdefghijkmnopqrstuvwxzyABCDEFGHJKLMNPQRSTUVWXZY0123456789';
  407. /**
  408. * How long in seconds a captcha remains valid, after this time it will be
  409. * considered incorrect.
  410. *
  411. * @var int
  412. */
  413. public $expiry_time = 900;
  414. /**
  415. * The session name securimage should use.
  416. *
  417. * Only use if your application uses a custom session name (e.g. Joomla).
  418. * It is recommended to set this value here so it is used by all securimage
  419. * scripts (i.e. securimage_show.php)
  420. *
  421. * @var string
  422. */
  423. public $session_name = null;
  424. /**
  425. * true to use the wordlist file, false to generate random captcha codes
  426. * @var bool
  427. */
  428. public $use_wordlist = false;
  429. /**
  430. * The level of distortion.
  431. *
  432. * 0.75 = normal, 1.0 = very high distortion
  433. *
  434. * @var double
  435. */
  436. public $perturbation = 0.85;
  437. /**
  438. * How many lines to draw over the captcha code to increase security
  439. * @var int
  440. */
  441. public $num_lines = 5;
  442. /**
  443. * The level of noise (random dots) to place on the image, 0-10
  444. * @var int
  445. */
  446. public $noise_level = 2;
  447. /**
  448. * The signature text to draw on the bottom corner of the image
  449. * @var string
  450. */
  451. public $image_signature = '';
  452. /**
  453. * The color of the signature text
  454. * @var Securimage_Color|string
  455. */
  456. public $signature_color = '#707070';
  457. /**
  458. * The path to the ttf font file to use for the signature text.
  459. * Defaults to $ttf_file (AHGBold.ttf)
  460. *
  461. * @see Securimage::$ttf_file
  462. * @var string
  463. */
  464. public $signature_font;
  465. /**
  466. * No longer used.
  467. *
  468. * Use an SQLite database to store data (for users that do not support cookies)
  469. *
  470. * @var bool
  471. * @see Securimage::$database_driver database_driver property
  472. * @deprecated 3.2RC4
  473. */
  474. public $use_sqlite_db = false;
  475. /**
  476. * Use a database backend for code storage.
  477. * Provides a fallback to users with cookies disabled.
  478. * Required when using captcha IDs.
  479. *
  480. * @see Securimage::$database_driver
  481. * @var bool
  482. */
  483. public $use_database = false;
  484. /**
  485. * Whether or not to skip checking if Securimage tables exist when using a
  486. * database.
  487. *
  488. * Turn this to true once database functionality is working to improve
  489. * performance.
  490. *
  491. * @var bool true to not check if captcha_codes tables are set up, false
  492. * to check (and create if necessary)
  493. */
  494. public $skip_table_check = false;
  495. /**
  496. * Database driver to use for database support.
  497. * Allowable values: *mysql*, *pgsql*, *sqlite*.
  498. * Default: sqlite
  499. *
  500. * @var string
  501. */
  502. public $database_driver = self::SI_DRIVER_SQLITE3;
  503. /**
  504. * Database host to connect to when using mysql or postgres
  505. *
  506. * On Linux use "localhost" for Unix domain socket, otherwise uses TCP/IP
  507. *
  508. * Does not apply to SQLite
  509. *
  510. * @var string
  511. */
  512. public $database_host = 'localhost';
  513. /**
  514. * Database username for connection (mysql, postgres only)
  515. * Default is an empty string
  516. *
  517. * @var string
  518. */
  519. public $database_user = '';
  520. /**
  521. * Database password for connection (mysql, postgres only)
  522. * Default is empty string
  523. *
  524. * @var string
  525. */
  526. public $database_pass = '';
  527. /**
  528. * Name of the database to select (mysql, postgres only)
  529. *
  530. * @see Securimage::$database_file for SQLite
  531. * @var string
  532. */
  533. public $database_name = '';
  534. /**
  535. * Database table where captcha codes are stored
  536. *
  537. * Note: Securimage will attempt to create this table for you if it does
  538. * not exist. If the table cannot be created, an E_USER_WARNING is emitted
  539. *
  540. * @var string
  541. */
  542. public $database_table = 'captcha_codes';
  543. /**
  544. * Fully qualified path to the database file when using SQLite3.
  545. *
  546. * This value is only used when $database_driver == sqlite and does
  547. * not apply when no database is used, or when using MySQL or PostgreSQL.
  548. *
  549. * On *nix, file must have permissions of 0666.
  550. *
  551. * **Make sure the directory containing this file is NOT web accessible**
  552. *
  553. * @var string
  554. */
  555. public $database_file;
  556. /**
  557. * The type of captcha to create.
  558. *
  559. * Either alphanumeric based on *charset*, a simple math problem, or an
  560. * image consisting of 2 words from the word list.
  561. *
  562. * @see Securimage::SI_CAPTCHA_STRING SI_CAPTCHA_STRING
  563. * @see Securimage::SI_CAPTCHA_MATHEMATIC SI_CAPTCHA_MATHEMATIC
  564. * @see Securimage::SI_CAPTCHA_WORDS SI_CAPTCHA_WORDS
  565. * @see Securimage::$charset charset property
  566. * @see Securimage::$wordlist_file wordlist_file property
  567. * @var int
  568. */
  569. public $captcha_type = self::SI_CAPTCHA_STRING; // or self::SI_CAPTCHA_MATHEMATIC, or self::SI_CAPTCHA_WORDS;
  570. /**
  571. * The captcha namespace used for having multiple captchas on a page or
  572. * to separate captchas from differen forms on your site.
  573. * Example:
  574. *
  575. * <?php
  576. * // use <img src="securimage_show.php?namespace=contact_form">
  577. * // or manually in securimage_show.php
  578. * $img->setNamespace('contact_form');
  579. *
  580. * // in form validator
  581. * $img->setNamespace('contact_form');
  582. * if ($img->check($code) == true) {
  583. * echo "Valid!";
  584. * }
  585. *
  586. * @var string
  587. */
  588. public $namespace;
  589. /**
  590. * The TTF font file to use to draw the captcha code.
  591. *
  592. * Leave blank for default font AHGBold.ttf
  593. *
  594. * @var string
  595. */
  596. public $ttf_file;
  597. /**
  598. * The path to the wordlist file to use.
  599. *
  600. * Leave blank for default words/words.txt
  601. *
  602. * @var string
  603. */
  604. public $wordlist_file;
  605. /**
  606. * Character encoding of the wordlist file.
  607. * Requires PHP Multibyte String (mbstring) support.
  608. * Allows word list to contain characters other than US-ASCII (requires compatible TTF font).
  609. *
  610. * @var string The character encoding (e.g. UTF-8, UTF-7, EUC-JP, GB2312)
  611. * @see http://php.net/manual/en/mbstring.supported-encodings.php
  612. * @since 3.6.3
  613. */
  614. public $wordlist_file_encoding = null;
  615. /**
  616. * The directory to scan for background images, if set a random background
  617. * will be chosen from this folder
  618. *
  619. * @var string
  620. */
  621. public $background_directory;
  622. /**
  623. * No longer used
  624. *
  625. * The path to the SQLite database file to use
  626. *
  627. * @deprecated 3.2RC4
  628. * @see Securimage::$database_file database_file property
  629. * @var string
  630. */
  631. public $sqlite_database;
  632. /**
  633. * The path to the audio files to be used for audio captchas.
  634. *
  635. * Can also be set in securimage_play.php
  636. *
  637. * Example:
  638. *
  639. * $img->audio_path = '/home/yoursite/public_html/securimage/audio/en/';
  640. *
  641. * @var string
  642. */
  643. public $audio_path;
  644. /**
  645. * Use SoX (The Swiss Army knife of audio manipulation) for audio effects
  646. * and processing.
  647. *
  648. * Using SoX should make it more difficult for bots to solve audio captchas
  649. *
  650. * @see Securimage::$sox_binary_path sox_binary_path property
  651. * @var bool true to use SoX, false to use PHP
  652. */
  653. public $audio_use_sox = false;
  654. /**
  655. * The path to the SoX binary on your system
  656. *
  657. * @var string
  658. */
  659. public $sox_binary_path = '/usr/bin/sox';
  660. /**
  661. * The path to the lame (mp3 encoder) binary on your system
  662. * Static so that Securimage::getCaptchaHtml() has access to this value.
  663. *
  664. * @since 3.6
  665. * @var string
  666. */
  667. public static $lame_binary_path = '/usr/bin/lame';
  668. /**
  669. * The path to the directory containing audio files that will be selected
  670. * randomly and mixed with the captcha audio.
  671. *
  672. * @var string
  673. */
  674. public $audio_noise_path;
  675. /**
  676. * Whether or not to mix background noise files into captcha audio
  677. *
  678. * Mixing random background audio with noise can help improve security of
  679. * audio captcha.
  680. *
  681. * Default: securimage/audio/noise
  682. *
  683. * @since 3.0.3
  684. * @see Securimage::$audio_noise_path audio_noise_path property
  685. * @var bool true = mix, false = no
  686. */
  687. public $audio_use_noise;
  688. /**
  689. * The method and threshold (or gain factor) used to normalize the mixing
  690. * with background noise.
  691. *
  692. * See http://www.voegler.eu/pub/audio/ for more information.
  693. *
  694. * Default: 0.6
  695. *
  696. * Valid:
  697. * >= 1
  698. * Normalize by multiplying by the threshold (boost - positive gain).
  699. * A value of 1 in effect means no normalization (and results in clipping).
  700. *
  701. * <= -1
  702. * Normalize by dividing by the the absolute value of threshold (attenuate - negative gain).
  703. * A factor of 2 (-2) is about 6dB reduction in volume.
  704. *
  705. * [0, 1) (open inverval - not including 1)
  706. * The threshold above which amplitudes are comressed logarithmically.
  707. * e.g. 0.6 to leave amplitudes up to 60% "as is" and compressabove.
  708. *
  709. * (-1, 0) (open inverval - not including -1 and 0)
  710. * The threshold above which amplitudes are comressed linearly.
  711. * e.g. -0.6 to leave amplitudes up to 60% "as is" and compress above.
  712. *
  713. * @since 3.0.4
  714. * @var float
  715. */
  716. public $audio_mix_normalization = 0.8;
  717. /**
  718. * Whether or not to degrade audio by introducing random noise.
  719. *
  720. * Current research shows this may not increase the security of audible
  721. * captchas.
  722. *
  723. * Default: true
  724. *
  725. * @since 3.0.3
  726. * @var bool
  727. */
  728. public $degrade_audio;
  729. /**
  730. * Minimum delay to insert between captcha audio letters in milliseconds
  731. *
  732. * @since 3.0.3
  733. * @var float
  734. */
  735. public $audio_gap_min = 0;
  736. /**
  737. * Maximum delay to insert between captcha audio letters in milliseconds
  738. *
  739. * @since 3.0.3
  740. * @var float
  741. */
  742. public $audio_gap_max = 3000;
  743. /**
  744. * The file path for logging errors from audio (default __DIR__)
  745. *
  746. * @var string|null
  747. */
  748. public $log_path = null;
  749. /**
  750. * The name of the log file for logging audio errors
  751. *
  752. * @var string|null (defualt si_error.log)
  753. */
  754. public $log_file = null;
  755. /**
  756. * Captcha ID if using static captcha
  757. * @var string Unique captcha id
  758. */
  759. protected static $_captchaId = null;
  760. /**
  761. * The GD image resource of the captcha image
  762. *
  763. * @var resource
  764. */
  765. protected $im;
  766. /**
  767. * A temporary GD image resource of the captcha image for distortion
  768. *
  769. * @var resource
  770. */
  771. protected $tmpimg;
  772. /**
  773. * The background image GD resource
  774. * @var string
  775. */
  776. protected $bgimg;
  777. /**
  778. * Scale factor for magnification of distorted captcha image
  779. *
  780. * @var int
  781. */
  782. protected $iscale = 2;
  783. /**
  784. * Absolute path to securimage directory.
  785. *
  786. * This is calculated at runtime
  787. *
  788. * @var string
  789. */
  790. public $securimage_path = null;
  791. /**
  792. * The captcha challenge value.
  793. *
  794. * Either the case-sensitive/insensitive word captcha, or the solution to
  795. * the math captcha.
  796. *
  797. * @var string|bool Captcha challenge value
  798. */
  799. protected $code;
  800. /**
  801. * The display value of the captcha to draw on the image
  802. *
  803. * Either the word captcha or the math equation to present to the user
  804. *
  805. * @var string Captcha display value to draw on the image
  806. */
  807. protected $code_display;
  808. /**
  809. * Alternate text to draw as the captcha image text
  810. *
  811. * A value that can be passed to the constructor that can be used to
  812. * generate a captcha image with a given value.
  813. *
  814. * This value does not get stored in the session or database and is only
  815. * used when calling Securimage::show().
  816. *
  817. * If a display_value was passed to the constructor and the captcha image
  818. * is generated, the display_value will be used as the string to draw on
  819. * the captcha image.
  820. *
  821. * Used only if captcha codes are generated and managed by a 3rd party
  822. * app/library
  823. *
  824. * @var string Captcha code value to display on the image
  825. */
  826. public $display_value;
  827. /**
  828. * Captcha code supplied by user [set from Securimage::check()]
  829. *
  830. * @var string
  831. */
  832. protected $captcha_code;
  833. /**
  834. * Time (in seconds) that the captcha was solved in (correctly or incorrectly).
  835. *
  836. * This is from the time of code creation, to when validation was attempted.
  837. *
  838. * @var int
  839. */
  840. protected $_timeToSolve = 0;
  841. /**
  842. * Flag that can be specified telling securimage not to call exit after
  843. * generating a captcha image or audio file
  844. *
  845. * @var bool If true, script will not terminate; if false script will terminate (default)
  846. */
  847. protected $no_exit;
  848. /**
  849. * Flag indicating whether or not a PHP session should be started and used
  850. *
  851. * @var bool If true, no session will be started; if false, session will be started and used to store data (default)
  852. */
  853. protected $no_session;
  854. /**
  855. * Flag indicating whether or not HTTP headers will be sent when outputting
  856. * captcha image/audio
  857. *
  858. * @var bool If true (default) headers will be sent, if false, no headers are sent
  859. */
  860. protected $send_headers;
  861. /**
  862. * PDO connection when a database is used
  863. *
  864. * @var PDO|bool
  865. */
  866. protected $pdo_conn;
  867. /**
  868. * The GD color for the background color
  869. *
  870. * @var int
  871. */
  872. protected $gdbgcolor;
  873. /**
  874. * The GD color for the text color
  875. *
  876. * @var int
  877. */
  878. protected $gdtextcolor;
  879. /**
  880. * The GD color for the line color
  881. *
  882. * @var int
  883. */
  884. protected $gdlinecolor;
  885. /**
  886. * The GD color for the signature text color
  887. *
  888. * @var int
  889. */
  890. protected $gdsignaturecolor;
  891. /**
  892. * Create a new securimage object, pass options to set in the constructor.
  893. *
  894. * The object can then be used to display a captcha, play an audible captcha, or validate a submission.
  895. *
  896. * @param array $options Options to initialize the class. May be any class property.
  897. *
  898. * $options = array(
  899. * 'text_color' => new Securimage_Color('#013020'),
  900. * 'code_length' => 5,
  901. * 'num_lines' => 5,
  902. * 'noise_level' => 3,
  903. * 'font_file' => Securimage::getPath() . '/custom.ttf'
  904. * );
  905. *
  906. * $img = new Securimage($options);
  907. *
  908. */
  909. public function __construct($options = array())
  910. {
  911. $this->securimage_path = dirname(__FILE__);
  912. if (!is_array($options)) {
  913. trigger_error(
  914. '$options passed to Securimage::__construct() must be an array. ' .
  915. gettype($options) . ' given',
  916. E_USER_WARNING
  917. );
  918. $options = array();
  919. }
  920. if (function_exists('mb_internal_encoding')) {
  921. mb_internal_encoding('UTF-8');
  922. }
  923. // check for and load settings from custom config file
  924. $config_file = null;
  925. if (file_exists(dirname(__FILE__) . '/config.inc.php')) {
  926. $config_file = dirname(__FILE__) . '/config.inc.php';
  927. }
  928. if (isset($options['config_file']) && file_exists($options['config_file'])) {
  929. $config_file = $options['config_file'];
  930. }
  931. if ($config_file) {
  932. $settings = include $config_file;
  933. if (is_array($settings)) {
  934. $options = array_merge($settings, $options);
  935. }
  936. }
  937. if (is_array($options) && sizeof($options) > 0) {
  938. foreach($options as $prop => $val) {
  939. if ($prop == 'captchaId') {
  940. Securimage::$_captchaId = $val;
  941. $this->use_database = true;
  942. } else if ($prop == 'use_sqlite_db') {
  943. trigger_error("The use_sqlite_db option is deprecated, use 'use_database' instead", E_USER_NOTICE);
  944. } else {
  945. $this->$prop = $val;
  946. }
  947. }
  948. }
  949. $this->image_bg_color = $this->initColor($this->image_bg_color, '#ffffff');
  950. $this->text_color = $this->initColor($this->text_color, '#616161');
  951. $this->line_color = $this->initColor($this->line_color, '#616161');
  952. $this->noise_color = $this->initColor($this->noise_color, '#616161');
  953. $this->signature_color = $this->initColor($this->signature_color, '#616161');
  954. if (is_null($this->ttf_file)) {
  955. $this->ttf_file = $this->securimage_path . '/AHGBold.ttf';
  956. }
  957. $this->signature_font = $this->ttf_file;
  958. if (is_null($this->wordlist_file)) {
  959. $this->wordlist_file = $this->securimage_path . '/words/words.txt';
  960. }
  961. if (is_null($this->database_file)) {
  962. $this->database_file = $this->securimage_path . '/database/securimage.sq3';
  963. }
  964. if (is_null($this->audio_path)) {
  965. $this->audio_path = $this->securimage_path . '/audio/en/';
  966. }
  967. if (is_null($this->audio_noise_path)) {
  968. $this->audio_noise_path = $this->securimage_path . '/audio/noise/';
  969. }
  970. if (is_null($this->audio_use_noise)) {
  971. $this->audio_use_noise = true;
  972. }
  973. if (is_null($this->degrade_audio)) {
  974. $this->degrade_audio = true;
  975. }
  976. if (is_null($this->code_length) || (int)$this->code_length < 1) {
  977. $this->code_length = 6;
  978. }
  979. if (is_null($this->perturbation) || !is_numeric($this->perturbation)) {
  980. $this->perturbation = 0.75;
  981. }
  982. if (is_null($this->namespace) || !is_string($this->namespace)) {
  983. $this->namespace = 'default';
  984. }
  985. if (is_null($this->no_exit)) {
  986. $this->no_exit = false;
  987. }
  988. if (is_null($this->no_session)) {
  989. $this->no_session = false;
  990. }
  991. if (is_null($this->send_headers)) {
  992. $this->send_headers = true;
  993. }
  994. if (is_null($this->log_path)) {
  995. $this->log_path = __DIR__;
  996. }
  997. if (is_null($this->log_file)) {
  998. $this->log_file = 'securimage.error_log';
  999. }
  1000. if ($this->no_session != true) {
  1001. // Initialize session or attach to existing
  1002. if ( session_id() == '' || (function_exists('session_status') && PHP_SESSION_NONE == session_status()) ) { // no session has been started yet (or it was previousy closed), which is needed for validation
  1003. if (!is_null($this->session_name) && trim($this->session_name) != '') {
  1004. session_name(trim($this->session_name)); // set session name if provided
  1005. }
  1006. session_start();
  1007. }
  1008. }
  1009. }
  1010. /**
  1011. * Return the absolute path to the Securimage directory.
  1012. *
  1013. * @return string The path to the securimage base directory
  1014. */
  1015. public static function getPath()
  1016. {
  1017. return dirname(__FILE__);
  1018. }
  1019. /**
  1020. * Generate a new captcha ID or retrieve the current ID (if exists).
  1021. *
  1022. * @param bool $new If true, generates a new challenge and returns and ID. If false, the existing captcha ID is returned, or null if none exists.
  1023. * @param array $options Additional options to be passed to Securimage.
  1024. * $options must include database settings if they are not set directly in securimage.php
  1025. *
  1026. * @return null|string Returns null if no captcha id set and new was false, or the captcha ID
  1027. */
  1028. public static function getCaptchaId($new = true, array $options = array())
  1029. {
  1030. if (is_null($new) || (bool)$new == true) {
  1031. $id = sha1(uniqid($_SERVER['REMOTE_ADDR'], true));
  1032. $opts = array('no_session' => true,
  1033. 'use_database' => true);
  1034. if (sizeof($options) > 0) $opts = array_merge($options, $opts);
  1035. $si = new self($opts);
  1036. Securimage::$_captchaId = $id;
  1037. $si->createCode();
  1038. return $id;
  1039. } else {
  1040. return Securimage::$_captchaId;
  1041. }
  1042. }
  1043. /**
  1044. * Validate a captcha code input against a captcha ID
  1045. *
  1046. * @param string $id The captcha ID to check
  1047. * @param string $value The captcha value supplied by the user
  1048. * @param array $options Array of options to construct Securimage with.
  1049. * Options must include database options if they are not set in securimage.php
  1050. *
  1051. * @see Securimage::$database_driver
  1052. * @return bool true if the code was valid for the given captcha ID, false if not or if database failed to open
  1053. */
  1054. public static function checkByCaptchaId($id, $value, array $options = array())
  1055. {
  1056. $opts = array('captchaId' => $id,
  1057. 'no_session' => true,
  1058. 'use_database' => true);
  1059. if (sizeof($options) > 0) $opts = array_merge($options, $opts);
  1060. $si = new self($opts);
  1061. if ($si->openDatabase()) {
  1062. $code = $si->getCodeFromDatabase();
  1063. if (is_array($code)) {
  1064. $si->code = $code['code'];
  1065. $si->code_display = $code['code_disp'];
  1066. }
  1067. if ($si->check($value)) {
  1068. $si->clearCodeFromDatabase();
  1069. return true;
  1070. } else {
  1071. return false;
  1072. }
  1073. } else {
  1074. return false;
  1075. }
  1076. }
  1077. /**
  1078. * Generates a new challenge and serves a captcha image.
  1079. *
  1080. * Appropriate headers will be sent to the browser unless the *send_headers* option is false.
  1081. *
  1082. * @param string $background_image The absolute or relative path to the background image to use as the background of the captcha image.
  1083. *
  1084. * $img = new Securimage();
  1085. * $img->code_length = 6;
  1086. * $img->num_lines = 5;
  1087. * $img->noise_level = 5;
  1088. *
  1089. * $img->show(); // sends the image and appropriate headers to browser
  1090. * exit;
  1091. */
  1092. public function show($background_image = '')
  1093. {
  1094. set_error_handler(array(&$this, 'errorHandler'));
  1095. if($background_image != '' && is_readable($background_image)) {
  1096. $this->bgimg = $background_image;
  1097. }
  1098. $this->doImage();
  1099. }
  1100. /**
  1101. * Checks a given code against the correct value from the session and/or database.
  1102. *
  1103. * @param string $code The captcha code to check
  1104. *
  1105. * $code = $_POST['code'];
  1106. * $img = new Securimage();
  1107. * if ($img->check($code) == true) {
  1108. * $captcha_valid = true;
  1109. * } else {
  1110. * $captcha_valid = false;
  1111. * }
  1112. *
  1113. * @return bool true if the given code was correct, false if not.
  1114. */
  1115. public function check($code)
  1116. {
  1117. if (!is_string($code)) {
  1118. trigger_error("The \$code parameter passed to Securimage::check() must be a string, " . gettype($code) . " given", E_USER_NOTICE);
  1119. $code = '';
  1120. }
  1121. $this->code_entered = $code;
  1122. $this->validate();
  1123. return $this->correct_code;
  1124. }
  1125. /**
  1126. * Returns HTML code for displaying the captcha image, audio button, and form text input.
  1127. *
  1128. * Options can be specified to modify the output of the HTML. Accepted options:
  1129. *
  1130. * 'securimage_path':
  1131. * Optional: The URI to where securimage is installed (e.g. /securimage)
  1132. * 'show_image_url':
  1133. * Path to the securimage_show.php script (useful when integrating with a framework or moving outside the securimage directory)
  1134. * This will be passed as a urlencoded string to the <img> tag for outputting the captcha image
  1135. * 'audio_play_url':
  1136. * Same as show_image_url, except this indicates the URL of the audio playback script
  1137. * 'image_id':
  1138. * A string that sets the "id" attribute of the captcha image (default: captcha_image)
  1139. * 'image_alt_text':
  1140. * The alt text of the captcha image (default: CAPTCHA Image)
  1141. * 'show_audio_button':
  1142. * true/false Whether or not to show the audio button (default: true)
  1143. * 'disable_flash_fallback':)
  1144. * Allow only HTML5 audio and disable Flash fallback
  1145. * 'show_refresh_button':
  1146. * true/false Whether or not to show a button to refresh the image (default: true)
  1147. * 'audio_icon_url':
  1148. * URL to the image used for showing the HTML5 audio icon
  1149. * 'js_url':
  1150. * URL to the javascript file
  1151. * 'icon_size':
  1152. * Size (for both height & width) in pixels of the audio and refresh buttons
  1153. * 'show_text_input':
  1154. * true/false Whether or not to show the text input for the captcha (default: true)
  1155. * 'refresh_alt_text':
  1156. * Alt text for the refresh image (default: Refresh Image)
  1157. * 'refresh_title_text':
  1158. * Title text for the refresh image link (default: Refresh Image)
  1159. * 'input_id':
  1160. * A string that sets the "id" attribute of the captcha text input (default: captcha_code)
  1161. * 'input_name':
  1162. * A string that sets the "name" attribute of the captcha text input (default: same as input_id)
  1163. * 'input_text':
  1164. * A string that sets the text of the label for the captcha text input (default: Type the text:)
  1165. * 'input_attributes':
  1166. * An array of additional HTML tag attributes to pass to the text input tag (default: empty)
  1167. * 'image_attributes':
  1168. * An array of additional HTML tag attributes to pass to the captcha image tag (default: empty)
  1169. * 'error_html':
  1170. * Optional HTML markup to be shown above the text input field
  1171. * 'namespace':
  1172. * The optional captcha namespace to use for showing the image and playing back the audio. Namespaces are for using multiple captchas on the same page.
  1173. *
  1174. * @param array $options Array of options for modifying the HTML code.
  1175. * @param int $parts Securiage::HTML_* constant controlling what component of the captcha HTML to display
  1176. *
  1177. * @return string The generated HTML code for displaying the captcha
  1178. */
  1179. public static function getCaptchaHtml($options = array(), $parts = Securimage::HTML_ALL)
  1180. {
  1181. static $javascript_init = false;
  1182. if (!isset($options['securimage_path'])) {
  1183. $docroot = (isset($_SERVER['DOCUMENT_ROOT'])) ? $_SERVER['DOCUMENT_ROOT'] : substr($_SERVER['SCRIPT_FILENAME'], 0, -strlen($_SERVER['SCRIPT_NAME']));
  1184. $docroot = realpath($docroot);
  1185. $sipath = dirname(__FILE__);
  1186. $securimage_path = str_replace($docroot, '', $sipath);
  1187. } else {
  1188. $securimage_path = $options['securimage_path'];
  1189. }
  1190. $show_image_url = (isset($options['show_image_url'])) ? $options['show_image_url'] : null;
  1191. $image_id = (isset($options['image_id'])) ? $options['image_id'] : 'captcha_image';
  1192. $image_alt = (isset($options['image_alt_text'])) ? $options['image_alt_text'] : 'CAPTCHA Image';
  1193. $show_audio_btn = (isset($options['show_audio_button'])) ? (bool)$options['show_audio_button'] : true;
  1194. $disable_flash_fbk = (isset($options['disable_flash_fallback'])) ? (bool)$options['disable_flash_fallback'] : false;
  1195. $show_refresh_btn = (isset($options['show_refresh_button'])) ? (bool)$options['show_refresh_button'] : true;
  1196. $refresh_icon_url = (isset($options['refresh_icon_url'])) ? $options['refresh_icon_url'] : null;
  1197. $audio_but_bg_col = (isset($options['audio_button_bgcol'])) ? $options['audio_button_bgcol'] : '#ffffff';
  1198. $audio_icon_url = (isset($options['audio_icon_url'])) ? $options['audio_icon_url'] : null;
  1199. $loading_icon_url = (isset($options['loading_icon_url'])) ? $options['loading_icon_url'] : null;
  1200. $icon_size = (isset($options['icon_size'])) ? $options['icon_size'] : 32;
  1201. $audio_play_url = (isset($options['audio_play_url'])) ? $options['audio_play_url'] : null;
  1202. $audio_swf_url = (isset($options['audio_swf_url'])) ? $options['audio_swf_url'] : null;
  1203. $js_url = (isset($options['js_url'])) ? $options['js_url'] : null;
  1204. $show_input = (isset($options['show_text_input'])) ? (bool)$options['show_text_input'] : true;
  1205. $refresh_alt = (isset($options['refresh_alt_text'])) ? $options['refresh_alt_text'] : 'Refresh Image';
  1206. $refresh_title = (isset($options['refresh_title_text'])) ? $options['refresh_title_text'] : 'Refresh Image';
  1207. $input_text = (isset($options['input_text'])) ? $options['input_text'] : 'Type the text:';
  1208. $input_id = (isset($options['input_id'])) ? $options['input_id'] : 'captcha_code';
  1209. $input_name = (isset($options['input_name'])) ? $options['input_name'] : $input_id;
  1210. $input_required = (isset($options['input_required'])) ? (bool)$options['input_required'] : true;
  1211. $input_attrs = (isset($options['input_attributes'])) ? $options['input_attributes'] : array();
  1212. $image_attrs = (isset($options['image_attributes'])) ? $options['image_attributes'] : array();
  1213. $error_html = (isset($options['error_html'])) ? $options['error_html'] : null;
  1214. $namespace = (isset($options['namespace'])) ? $options['namespace'] : '';
  1215. $rand = md5(uniqid($_SERVER['REMOTE_PORT'], true));
  1216. $securimage_path = rtrim($securimage_path, '/\\');
  1217. $securimage_path = str_replace('\\', '/', $securimage_path);
  1218. $image_attr = '';
  1219. if (!is_array($image_attrs)) $image_attrs = array();
  1220. if (!isset($image_attrs['style'])) $image_attrs['style'] = 'float: left; padding-right: 5px';
  1221. $image_attrs['id'] = $image_id;
  1222. $show_path = $securimage_path . '/securimage_show.php?';
  1223. if ($show_image_url) {
  1224. if (parse_url($show_image_url, PHP_URL_QUERY)) {
  1225. $show_path = "{$show_image_url}&";
  1226. } else {
  1227. $show_path = "{$show_image_url}?";
  1228. }
  1229. }
  1230. if (!empty($namespace)) {
  1231. $show_path .= sprintf('namespace=%s&amp;', $namespace);
  1232. }
  1233. $image_attrs['src'] = $show_path . $rand;
  1234. $image_attrs['alt'] = $image_alt;
  1235. foreach($image_attrs as $name => $val) {
  1236. $image_attr .= sprintf('%s="%s" ', $name, htmlspecialchars($val));
  1237. }
  1238. $swf_path = $securimage_path . '/securimage_play.swf';
  1239. $play_path = $securimage_path . '/securimage_play.php?';
  1240. $icon_path = $securimage_path . '/images/audio_icon.png';
  1241. $load_path = $securimage_path . '/images/loading.png';
  1242. $js_path = $securimage_path . '/securimage.js';
  1243. if (!empty($audio_icon_url)) {
  1244. $icon_path = $audio_icon_url;
  1245. }
  1246. if (!empty($loading_icon_url)) {
  1247. $load_path = $loading_icon_url;
  1248. }
  1249. if (!empty($audio_play_url)) {
  1250. if (parse_url($audio_play_url, PHP_URL_QUERY)) {
  1251. $play_path = "{$audio_play_url}&";
  1252. } else {
  1253. $play_path = "{$audio_play_url}?";
  1254. }
  1255. }
  1256. if (!empty($namespace)) {
  1257. $play_path .= sprintf('namespace=%s&amp;', $namespace);
  1258. }
  1259. if (!empty($audio_swf_url)) {
  1260. $swf_path = $audio_swf_url;
  1261. }
  1262. if (!empty($js_url)) {
  1263. $js_path = $js_url;
  1264. }
  1265. $audio_obj = $image_id . '_audioObj';
  1266. $html = '';
  1267. if ( ($parts & Securimage::HTML_IMG) > 0) {
  1268. $html .= sprintf('<img %s/>', $image_attr);
  1269. }
  1270. if ( ($parts & Securimage::HTML_AUDIO) > 0 && $show_audio_btn) {
  1271. // html5 audio
  1272. $html .= sprintf('<div id="%s_audio_div">', $image_id) . "\n" .
  1273. sprintf('<audio id="%s_audio" preload="none" style="display: none">', $image_id) . "\n";
  1274. // check for existence and executability of LAME binary
  1275. // prefer mp3 over wav by sourcing it first, if available
  1276. if (!empty(Securimage::$lame_binary_path) && is_executable(Securimage::$lame_binary_path)) {
  1277. $html .= sprintf('<source id="%s_source_mp3" src="%sid=%s&amp;format=mp3" type="audio/mpeg">', $image_id, $play_path, uniqid()) . "\n";
  1278. }
  1279. // output wav source
  1280. $html .= sprintf('<source id="%s_source_wav" src="%sid=%s" type="audio/wav">', $image_id, $play_path, uniqid()) . "\n";
  1281. // flash audio button
  1282. if (!$disable_flash_fbk) {
  1283. $html .= sprintf('<object type="application/x-shockwave-flash" data="%s?bgcol=%s&amp;icon_file=%s&amp;audio_file=%s" height="%d" width="%d">',
  1284. htmlspecialchars($swf_path),
  1285. urlencode($audio_but_bg_col),
  1286. urlencode($icon_

Large files files are truncated, but you can click here to view the full file