1/*! 2 * Securimage CAPTCHA Audio Library 3 * https://www.phpcaptcha.org/ 4 * 5 * Copyright 2015 phpcaptcha.org 6 * Released under the BSD-3 license 7 * See https://github.com/dapphp/securimage/blob/master/README.md 8 */ 9 10var SecurimageAudio = function(options) { 11 this.html5Support = true; 12 this.flashFallback = false; 13 this.captchaId = null; 14 this.playing = false; 15 this.reload = false; 16 this.audioElement = null; 17 this.controlsElement = null; 18 this.playButton = null; 19 this.playButtonImage = null; 20 this.loadingImage = null; 21 22 if (options.audioElement) { 23 this.audioElement = document.getElementById(options.audioElement); 24 } 25 if (options.controlsElement) { 26 this.controlsElement = document.getElementById(options.controlsElement); 27 } 28 29 this.init(); 30} 31 32SecurimageAudio.prototype.init = function() { 33 var ua = navigator.userAgent.toLowerCase(); 34 var ieVer = (ua.indexOf('msie') != -1) ? parseInt(ua.split('msie')[1]) : false; 35 // ie 11+ detection 36 if (!ieVer && null != (ieVer = ua.match(/trident\/.*rv:(\d+\.\d+)/))) 37 ieVer = parseInt(ieVer[1]); 38 39 var objAu = this.audioElement.getElementsByTagName('object'); 40 if (objAu.length > 0) { 41 objAu = objAu[0]; 42 } else { 43 objAu = null; 44 } 45 46 if (ieVer) { 47 if (ieVer < 9) { 48 // no html5 audio support, hide player controls 49 this.controlsElement.style.display = 'none'; 50 this.html5Support = false; 51 return ; 52 } else if ('' == this.audioElement.canPlayType('audio/wav')) { 53 // check for mpeg <source> tag - if not found then fallback to flash 54 var sources = this.audioElement.getElementsByTagName('source'); 55 var mp3support = false; 56 var type; 57 58 if (objAu) { 59 this.flashFallback = true; 60 } 61 62 for (var i = 0; i < sources.length; ++i) { 63 type = sources[i].attributes["type"].value; 64 if (type.toLowerCase().indexOf('mpeg') >= 0 || type.toLowerCase().indexOf('mp3') >= 0) { 65 mp3support = true; 66 break; 67 } 68 } 69 70 if (false == mp3support) { 71 // browser supports <audio> but does not support WAV audio and no flash audio available 72 this.html5Support = false; 73 74 if (this.flashFallback) { 75 // ie9+? bug - flash object does not display when moved from within audio tag to other dom node 76 var newObjAu = document.createElement('object'); 77 var newParams = document.createElement('param'); 78 var oldParams = objAu.getElementsByTagName('param'); 79 this.copyElementAttributes(newObjAu, objAu); 80 if (oldParams.length > 0) { 81 this.copyElementAttributes(newParams, oldParams[0]); 82 newObjAu.appendChild(newParams); 83 } 84 objAu.parentNode.removeChild(objAu); 85 this.audioElement.parentNode.appendChild(newObjAu); 86 } 87 88 this.audioElement.parentNode.removeChild(this.audioElement); 89 this.controlsElement.parentNode.removeChild(this.controlsElement); 90 91 return ; 92 } 93 } 94 } 95 96 this.audioElement.addEventListener('playing', this.updateControls.bind(this), false); 97 this.audioElement.addEventListener('ended', this.audioStopped.bind(this), false); 98 99 // find the element used as the play button and register click event to play/stop audio 100 var children = this.controlsElement.getElementsByTagName('*'); 101 for (var i = 0; i < children.length; ++i) { 102 var el = children[i]; 103 if (undefined != el.className) { 104 if (el.className.indexOf('play_button') >= 0) { 105 this.playButton = el; 106 el.addEventListener('click', this.play.bind(this), false); 107 } else if (el.className.indexOf('play_image') >= 0) { 108 this.playButtonImage = el; 109 } else if (el.className.indexOf('loading_image') >= 0) { 110 this.loadingImage = el; 111 } 112 } 113 } 114 115 if (objAu) { 116 // remove flash object from DOM 117 objAu.parentNode.removeChild(objAu); 118 } 119} 120 121SecurimageAudio.prototype.play = function(evt) { 122 if (null != this.playButton) { 123 this.playButton.blur(); 124 } 125 126 if (this.reload) { 127 this.replaceElements(); 128 this.reload = false;
129 } 130 131 try { 132 if (!this.playing) { 133 if (this.playButtonImage != null) { 134 this.playButtonImage.style.display = 'none'; 135 } 136 if (this.loadingImage != null) { 137 this.loadingImage.style.display = ''; 138 } 139 //TODO: FIX, most likely browser doesn't support audio type 140 this.audioElement.onerror = this.audioError; 141 try { 142 this.audioElement.play(); 143 } catch(ex) { 144 alert('Audio error: ' + ex); 145 } 146 } else { 147 this.audioElement.pause(); 148 if (this.loadingImage != null) { 149 this.loadingImage.style.display = 'none'; 150 } 151 if (this.playButtonImage != null) { 152 this.playButtonImage.style.display = ''; 153 } 154 this.playing = false; 155 } 156 } catch (ex) { 157 alert('Audio error: ' + ex); 158 } 159 160 if (undefined !== evt) { 161 evt.preventDefault(); 162 } 163 return false; 164} 165 166SecurimageAudio.prototype.refresh = function(captchaId) { 167 if (!this.html5Support) { 168 return; 169 } 170 171 if (undefined !== captchaId) { 172 this.captchaId = captchaId; 173 } 174 175 this.playing = true; 176 this.reload = false; 177 this.play(); // stops audio if playing 178 this.reload = true; 179 180 return false; 181} 182 183SecurimageAudio.prototype.copyElementAttributes = function(newEl, el) { 184 for (var i = 0, atts = el.attributes, n = atts.length; i < n; ++i) { 185 newEl.setAttribute(atts[i].nodeName, atts[i].value); 186 } 187 188 return newEl; 189} 190 191SecurimageAudio.prototype.replaceElements = function() { 192 var parent = this.audioElement.parentNode; 193 parent.removeChild(this.audioElement); 194 195 var newAudioEl = document.createElement('audio'); 196 newAudioEl.setAttribute('style', 'display: none;'); 197 newAudioEl.setAttribute('preload', 'false'); 198 199 for (var c = 0; c < this.audioElement.children.length; ++c) { 200 if (this.audioElement.children[c].tagName.toLowerCase() != 'source') continue; 201 var sourceEl = document.createElement('source'); 202 this.copyElementAttributes(sourceEl, this.audioElement.children[c]); 203 var cid = (null !== this.captchaId) ? this.captchaId : (Math.random() + '').replace('0.', ''); 204 sourceEl.src = sourceEl.src.replace(/id=[a-zA-Z0-9]+/, 'id=' + cid); 205 newAudioEl.appendChild(sourceEl); 206 } 207 208 this.audioElement = null; 209 this.audioElement = newAudioEl; 210 parent.appendChild(this.audioElement); 211 212 this.audioElement.addEventListener('playing', this.updateControls.bind(this), false); 213 this.audioElement.addEventListener('ended', this.audioStopped.bind(this), false); 214} 215 216SecurimageAudio.prototype.updateControls = function() { 217 this.playing = true; 218 if (this.loadingImage != null) { 219 this.loadingImage.style.display = 'none'; 220 } 221 if (this.playButtonImage != null) { 222 this.playButtonImage.style.display = ''; 223 } 224} 225 226SecurimageAudio.prototype.audioStopped = function() { 227 this.playing = false; 228} 229 230SecurimageAudio.prototype.audioError = function(err) { 231 var msg = null; 232 switch(err.target.error.code) { 233 case err.target.error.MEDIA_ERR_ABORTED: 234 break; 235 case err.target.error.MEDIA_ERR_NETWORK: 236 msg = 'A network error caused the audio download to fail.'; 237 break; 238 case err.target.error.MEDIA_ERR_DECODE: 239 alert('An error occurred while decoding the audio'); 240 break; 241 case err.target.error.MEDIA_ERR_SRC_NOT_SUPPORTED: 242 alert('The audio format is not supported by your browser.'); 243 break; 244 default: 245 alert('An unknown error occurred trying to play the audio.'); 246 break; 247 } 248 if (msg) { 249 alert('Audio playback error: ' + msg); 250 } 251} 252 253/** Wordpress plugin specific code below */ 254 255function siwp_refresh(id, audioObj) { 256 var cid = siwp_genid(); 257 258 document.getElementById('input_siwp_captcha_id_' + id).value = cid; 259 document.getElementById('siwp_captcha_image_' + id).src = document.getElementById('siwp_captcha_image_' + id).src.replace(/\bid=[a-zA-Z0-9]{40}
259/, 'id=' + cid); 260 261 if (null !== audioObj) { 262 audioObj.refresh(cid); 263 } 264 265 // flash fallback refresh swf code 266 var obj = document.getElementById('siwp_obj_' + id); 267 if (null !== obj) { 268 obj.setAttribute('data', obj.getAttribute('data').replace(/[a-zA-Z0-9]{40}$/, cid)); 269 var par = document.getElementById('siwp_param'); 270 par.value = par.value.replace(/[a-zA-Z0-9]{40}$/, cid); 271 272 /* replace old flash w/ new one using new id */ 273 var newObj = obj.cloneNode(true); 274 obj.parentNode.insertBefore(newObj, obj); 275 obj.parentNode.removeChild(obj); 276 } 277 278 if (window.siwp_interval) { 279 clearInterval(window.siwp_interval); 280 siwpStartInterval(); 281 } 282} 283function siwp_genid() { 284 var cid = '', chars = 'abcdefghijklmnopqrstuvwxyz0123456789'; 285 for (var c = 0; c < 40; ++c) { cid += chars.charAt(Math.floor(Math.random() * chars.length)); } 286 return cid; 287} 288 289function siwpStartInterval() { 290 window.siwp_interval = setInterval(siwpRefreshInterval, 900000); // 15 minutes (900s) 291} 292 293function siwpRefreshInterval() { 294 var elems = document.querySelectorAll('.siwp_img'); 295 296 if (elems) { 297 for (var i = 0; i < elems.length; ++i) { 298 siwp_refresh(i, window['siwp_captcha_image_' + i + '_audioObj']); 299 } 300 } 301} 302 303function registerAudioObjects() { 304 //$audio_obj = new SecurimageAudio({ audioElement: '{$imgTagId}_audio', controlsElement: '{$imgTagId}_audio_controls' }); 305 306 var len = 0; 307 var elems = document.querySelectorAll('.siwp_audio'); 308 len = elems.length; 309 310 if (len) { 311 for (var i = 0; i < len; ++i) { 312 var varname = 'siwp_captcha_image_' + i + '_audioObj'; 313 314 window[varname] = new SecurimageAudio({ 315 audioElement: 'siwp_captcha_image_' + i + '_audio', 316 controlsElement: 'siwp_captcha_image_' + i + '_audio_controls' 317 }); 318 } 319 } 320 321 siwpStartInterval(); 322} 323 324if (window.addEventListener) { 325 window.addEventListener('load', registerAudioObjects, false); 326} else { 327 window.attachEvent('onload', registerAudioObjects); 328}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.