1/* 2 * Password Management Servlets (PWM) 3 * http://www.pwm-project.org 4 * 5 * Copyright (c) 2006-2009 Novell, Inc. 6 * Copyright (c) 2009-2023 The PWM Project 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21"use strict"; 22 23var PWM_GLOBAL = PWM_GLOBAL || {}; 24var PWM_MAIN = PWM_MAIN || {}; 25var PWM_VAR = PWM_VAR || {}; 26var PWM_API = PWM_API || {}; 27 28PWM_API.formatDate = function(dateObj) { 29 return PWM_MAIN.TimestampHandler.formatDate(dateObj); 30}; 31 32PWM_MAIN.ajaxTimeout = 60 * 1000; 33 34PWM_MAIN.pageLoadHandler = function() { 35 PWM_GLOBAL['localeBundle'] = PWM_GLOBAL['localeBundle'] || []; 36 PWM_GLOBAL['url-context'] = PWM_MAIN.getObject('application-info').getAttribute('data-url-context'); 37 PWM_GLOBAL['pwmFormID'] = PWM_MAIN.getObject('application-info').getAttribute('data-pwmFormID'); 38 PWM_GLOBAL['clientEtag'] = PWM_MAIN.getObject('application-info').getAttribute('data-clientEtag'); 39 40 var finishInitCounter = 0; 41 var initFunctions = []; 42 43 var completeFunction = function () { 44 finishInitCounter++; 45 if ( finishInitCounter === initFunctions.length ) { 46 PWM_MAIN.initPage(); 47 } 48 }; 49 50 initFunctions.push(function () { 51 PWM_MAIN.loadClientData(completeFunction); 52 }); 53 if (typeof PWM_CONFIG !== 'undefined') { 54 PWM_GLOBAL['localeBundle'].push('Config'); 55 } 56 if (typeof PWM_SETTINGS !== 'undefined' && typeof PWM_CFGEDIT !== 'undefined') { 57 initFunctions.push(function () { 58 PWM_CFGEDIT.initConfigSettingsDefinition(completeFunction); 59 }); 60 } 61 if (typeof PWM_ADMIN !== 'undefined') { 62 PWM_GLOBAL['localeBundle'].push('Admin'); 63 64 initFunctions.push(function () { 65 PWM_ADMIN.initAdminPage(completeFunction); 66 }); 67 } 68 { 69 var seenBundles = []; 70 PWM_GLOBAL['localeBundle'].push('Display'); 71 PWM_MAIN.JSLibrary.forEachInArray(PWM_GLOBAL['localeBundle'], function (bundleName) { 72 if (!PWM_MAIN.JSLibrary.arrayContains(seenBundles, bundleName)) { 73 initFunctions.push(function () { 74 PWM_MAIN.loadLocaleBundle(bundleName, completeFunction); 75 }); 76 } 77 }); 78 } 79 80 PWM_MAIN.JSLibrary.forEachInArray(initFunctions,function(initFunction){ 81 initFunction(); 82 }); 83}; 84 85PWM_MAIN.loadClientData=function(completeFunction) { 86 PWM_GLOBAL['app-data-client-retry-count'] = PWM_GLOBAL['app-data-client-retry-count'] + 1; 87 var url = PWM_GLOBAL['url-context'] + "/public/api?processAction=clientData&etag=" + PWM_GLOBAL['clientEtag']; 88 url = PWM_MAIN.addParamToUrl(url,'pageUrl',window.location.href); 89 var loadFunction = function(data) { 90 PWM_MAIN.JSLibrary.forEachInObject(data['data']['PWM_GLOBAL'],function(key,value){ 91 PWM_GLOBAL[key] = value; 92 }) 93 PWM_MAIN.log('loaded client data'); 94 if (completeFunction) completeFunction(); 95 }; 96 var errorFunction = function(error) { 97 var errorMsg = 'unable to read app-data: ' + error;; 98 PWM_MAIN.log(errorMsg); 99 if (!PWM_VAR['initError']) PWM_VAR['initError'] = errorMsg; 100 if (completeFunction) completeFunction(); 101 }; 102 PWM_MAIN.ajaxRequest(url, loadFunction, {errorFunction:errorFunction,method:'GET',preventCache:false,addPwmFormID:false}); 103}; 104 105PWM_MAIN.loadLocaleBundle = function(bundleName, completeFunction) { 106 var clientConfigUrl = PWM_GLOBAL['url-context'] + "/public/api?processAction=strings&bundle=" + bundleName; 107 clientConfigUrl = PWM_MAIN.addParamToUrl(clientConfigUrl,'etag',PWM_GLOBAL['clientEtag']); 108 var loadFunction = function(data){ 109 if (data['error'] === true) { 110 console.error('unable to load locale bundle from ' + clientConfigUrl + ', error: ' + data['errorDetail']) 111 } else { 112 PWM_GLOBAL['localeStrings'] = PWM_GLOBAL['localeStrings'] || {}; 113 PWM_GLOBAL['localeStrings'][bundleName] = {}; 114 for (var settingKey in data['data']) { 115 PWM_GLOBAL['localeStrings'][bundleName][settingKey] = data['data'][settingKey]; 116 } 117 } 118 PWM_MAIN.log('loaded locale bundle data for ' + bundleName); 119 if (completeFunction) completeFunction(); 120 }; 121 var errorFunction = function(){ 122 var errorMsg = 'unable to load locale bundle from , please reload page (' + error + ')'; 123 PWM_MAIN.log(errorMsg); 124 if (!PWM_VAR['initError']) PWM_VAR['initError'] = errorMsg; 125 if (completeFunction) completeFunction(); 126 }; 127 PWM_MAIN.ajaxRequest(clientConfigUrl,loadFunction,{errorFunction:errorFunction,method:'GET',preventCache:false,addPwmFormID:false}); 128}; 129 130PWM_MAIN.initPage = function() { 131 PWM_MAIN.applyFormAttributes(); 132 PWM_MAIN.initDisplayTabPreferences(); 133 134 document.body.setAttribute( 'data-browserType', PWM_GLOBAL['browserType']); 135 136 PWM_MAIN.addEventHandler(document, "keypress", function (event) {
137 PWM_MAIN.checkForCapsLock(event); 138 }); 139 140 PWM_MAIN.doQuery('.pwm-link-print',function(element){ 141 PWM_MAIN.addEventHandler(element, "click", function(){ window.print(); }); 142 }); 143 144 if (PWM_MAIN.getObject('ldapProfile')) { 145 PWM_MAIN.addEventHandler('ldapProfile', 'click', function () { 146 PWM_MAIN.updateLoginContexts() 147 }); 148 } 149 150 PWM_MAIN.addEventHandler('icon-configModeHelp','click',function(){ 151 PWM_MAIN.showDialog({title:'Notice - Configuration Mode',text:PWM_MAIN.showString('Display_ConfigOpenInfo',{bundle:'Config'})}); 152 }); 153 154 if (PWM_GLOBAL['applicationMode'] === 'CONFIGURATION') { 155 var configModeNoticeSeen = PWM_MAIN.Preferences.readSessionStorage('configModeNoticeSeen'); 156 if (!configModeNoticeSeen) { 157 PWM_MAIN.Preferences.writeSessionStorage('configModeNoticeSeen',true); 158 PWM_MAIN.showDialog({title:'Notice - Configuration Mode',text:PWM_MAIN.showString('Display_ConfigOpenInfo',{bundle:'Config'})}); 159 } 160 } 161 162 if (PWM_GLOBAL['pageLeaveNotice'] > 0) { 163 PWM_MAIN.addEventHandler(document, "beforeunload", function(){ 164 var url = PWM_GLOBAL['url-command'] + "?processAction=pageLeaveNotice&pwmFormID=" + PWM_GLOBAL['pwmFormID']; 165 PWM_MAIN.ajaxRequest(url,function(){},{preventCache:true}); 166 }); 167 } 168 169 if (PWM_MAIN.getObject('message')) { 170 PWM_GLOBAL['message_originalStyle'] = PWM_MAIN.getObject('message').style; 171 PWM_MAIN.addEventHandler(window, "resize", function(){ PWM_MAIN.messageDivFloatHandler() }); 172 PWM_MAIN.addEventHandler(window, "scroll", function(){ PWM_MAIN.messageDivFloatHandler() }); 173 } 174 175 if (PWM_GLOBAL['enableIdleTimeout']) { 176 PWM_MAIN.IdleTimeoutHandler.initCountDownTimer(PWM_GLOBAL['MaxInactiveInterval']); 177 } 178 PWM_MAIN.initLocaleSelectorMenu('localeSelectionMenu'); 179 180 if (PWM_MAIN.getObject('LogoutButton')) { 181 PWM_MAIN.showTooltip({ 182 id: 'LogoutButton', 183 position: ['below', 'above'], 184 text: PWM_MAIN.showString("Long_Title_Logout"), 185 width: 500 186 }); 187 } 188 189 PWM_MAIN.JSLibrary.onPageLoad(function(){ 190 PWM_MAIN.JSLibrary.forEachInArray(PWM_GLOBAL['startupFunctions'],function(startupFunction){ 191 try { 192 startupFunction(); 193 } catch(e) { 194 console.error('error executing startup function: ' + e); 195 } 196 }) 197 }); 198 199 PWM_MAIN.TimestampHandler.initAllElements(); 200 201 ShowHidePasswordHandler.initAllForms(); 202 PWM_MAIN.log('initPage completed'); 203}; 204 205PWM_MAIN.initDisplayTabPreferences = function() { 206 var storageName = 'lastTabState-' + window.location.pathname + '-'; 207 var knownTabNames = []; 208 PWM_MAIN.doQuery('div.tab-container>input[type="radio"]',function(formElement) { 209 var name = formElement.name; 210 var id = formElement.id; 211 if (!PWM_MAIN.JSLibrary.arrayContains(knownTabNames,name)) { 212 knownTabNames.push(name); 213 } 214 PWM_MAIN.addEventHandler(formElement, 'click', function(){ 215 PWM_MAIN.Preferences.writeSessionStorage(storageName + name, id); 216 }); 217 218 }); 219 220 knownTabNames.forEach(function(name){ 221 var value = PWM_MAIN.Preferences.readSessionStorage(storageName + name); 222 if (value) { 223 var selector = "input[name='" + name + "'][type='radio'][id='" + value + "']"; 224 PWM_MAIN.doQuery(selector,function(formElement){ 225 formElement.checked = true; 226 }); 227 } 228 }); 229}; 230 231 232PWM_MAIN.applyFormAttributes = function() { 233 PWM_MAIN.doQuery('form',function(formElement) { 234 formElement.setAttribute('autocomplete', 'off'); 235 236 //ios/webkit 237 formElement.setAttribute('autocapitalize', 'none'); 238 formElement.setAttribute('autocorrect', 'off'); 239 }); 240 241 PWM_MAIN.doQuery('.pwm-form:not(.pwm-form-captcha)',function(formElement) { 242 PWM_MAIN.addEventHandler(formElement, "submit", function(event){ 243 PWM_MAIN.handleFormSubmit(formElement, event); 244 }); 245 }); 246 247 PWM_MAIN.doQuery('a:not([target])',function(linkElement) { 248 try { 249 if (linkElement.classList.contains('pwm-basic-link')) { 250 return; 251 } 252 } catch (e) { /* ignore for browsers that don't support classList */ } 253 var hrefValue = linkElement.getAttribute('href'); 254 if (hrefValue && hrefValue.charAt(0) !== '#') { 255 PWM_MAIN.addEventHandler(linkElement, "click", function (event) { 256 console.log('intercepted anchor click event'); 257 event.preventDefault(); 258 PWM_MAIN.showWaitDialog({loadFunction: function () { 259 PWM_MAIN.gotoUrl(hrefValue); 260 }}); 261 }); 262 linkElement.removeAttribute('href'); 263 } 264 }); 265 266 // handle html5 form attribute in JS in case browser (IE) doesn't support it. 267 if(PWM_MAIN.isIE()){ 268 PWM_MAIN.doQuery("button[type=submit][form]",function(element){ 269 PWM_MAIN.log('added IE event handler for submit button with form attribute ' + element.i
269d); 270 PWM_MAIN.addEventHandler(element,'click',function(e){ 271 e.preventDefault(); 272 PWM_MAIN.log('IE event handler intercepted submit for referenced form attribute ' + element.id); 273 var formID = element.getAttribute('form'); 274 PWM_MAIN.handleFormSubmit(PWM_MAIN.getObject(formID)); 275 }); 276 }); 277 } 278}; 279 280PWM_MAIN.isIE = function() { 281 var browserType = document.body.getAttribute('data-browserType'); 282 return browserType && "ie" === browserType.toLowerCase(); 283} 284 285PWM_MAIN.preloadAll = function(nextFunction) { 286 if (!PWM_MAIN.html5DialogSupport()) { 287 if (!PWM_MAIN.getObject('css-nihilo')) { 288 PWM_MAIN.log('adding nihilo to body class css'); 289 document.body.classList.add("nihilo"); 290 PWM_MAIN.addCssClass() 291 var link = document.createElement('link'); 292 link.rel = 'stylesheet'; 293 link.type = 'text/css'; 294 link.href = PWM_GLOBAL['url-context'] + '/public/resources/webjars/dijit/themes/nihilo/nihilo.css'; 295 link.id = 'css-nihilo' 296 document.getElementsByTagName('HEAD')[0].appendChild(link); 297 } 298 299 require(["dijit/Dialog"], function () { 300 if (nextFunction) { nextFunction(); } 301 }); 302 } else { 303 if (nextFunction) { nextFunction(); } 304 } 305}; 306 307PWM_MAIN.showString = function (key, options) { 308 options = options === undefined ? {} : options; 309 var bundle = ('bundle' in options) ? options['bundle'] : 'Display'; 310 PWM_GLOBAL['localeStrings'] = PWM_GLOBAL['localeStrings'] || {}; 311 if (!PWM_GLOBAL['localeStrings'][bundle]) { 312 return "UNDEFINED BUNDLE: " + bundle; 313 } 314 if (PWM_GLOBAL['localeStrings'][bundle][key]) { 315 var returnStr = PWM_GLOBAL['localeStrings'][bundle][key]; 316 for (var i = 0; i < 10; i++) { 317 if (options['value' + i]) { 318 returnStr = returnStr.replace('%' + i + '%',options['value' + i]); 319 } 320 } 321 return returnStr; 322 } else { 323 return "UNDEFINED STRING-" + key; 324 } 325}; 326 327PWM_MAIN.addEventHandler = function(nodeId,events,theFunction) { 328 var element = PWM_MAIN.getObject(nodeId); 329 if (element && events) { 330 var eventArray = Array.isArray(events) ? events : events.split(','); 331 PWM_MAIN.JSLibrary.forEachInArray(eventArray,function(event){ 332 if (element.addEventListener){ 333 element.addEventListener(event, theFunction, false); 334 } else if (element.attachEvent){ 335 element.attachEvent('on'+event, theFunction); 336 } 337 }); 338 } 339}; 340 341PWM_MAIN.addOneTimeEventHandler = function(nodeId,events,theFunctions) { 342 var oneTimeFunction = function() { 343 element.removeEventListener(events, oneTimeFunction); 344 theFunctions(); 345 } 346 PWM_MAIN.addEventHandler(nodeId,events,oneTimeFunction) 347}; 348 349 350PWM_MAIN.gotoUrl = function(url, options) { 351 options = options === undefined ? {} : options; 352 if (!('noContext' in options) && url.indexOf(PWM_GLOBAL['url-context']) !== 0) { 353 if (url.substring(0,1) === '/') { 354 url = PWM_GLOBAL['url-context'] + url; 355 } 356 } 357 358 if ('addFormID' in options) { 359 if (url.indexOf('pwmFormID') === -1) { 360 url = PWM_MAIN.addPwmFormIDtoURL(url); 361 } 362 } 363 364 var executeGoto = function() { 365 if (options['delay']) { 366 setTimeout(function () { 367 PWM_MAIN.log('redirecting to new url: ' + url); 368 window.location = url; 369 }, options['delay']); 370 } else { 371 PWM_MAIN.log('redirecting to new url: ' + url); 372 window.location = url; 373 } 374 }; 375 376 var hideDialog = options['hideDialog'] = true; 377 if (hideDialog) { 378 executeGoto(); 379 } else { 380 PWM_MAIN.showWaitDialog({loadFunction:function () { 381 executeGoto(); 382 }}); 383 } 384}; 385 386 387PWM_MAIN.handleLoginFormSubmit = function(form, event) { 388 PWM_MAIN.log('entering handleLoginFormSubmit'); 389 PWM_MAIN.cancelEvent(event); 390 391 PWM_MAIN.showWaitDialog({loadFunction: function () { 392 var options = {}; 393 options['content'] = PWM_MAIN.JSLibrary.formToValueMap(form); 394 delete options['content']['processAction']; 395 delete options['content']['pwmFormID']; 396 var url = 'login?processAction=restLogin'; 397 if (options['content']['skipCaptcha']) 398 { 399 PWM_MAIN.addParamToUrl( url, 'skipCaptcha', options['content']['skipCaptcha']); 400 } 401 var loadFunction = function(data) { 402 if (data['error'] === true) { 403 PWM_MAIN.getObject('password').value = ''; 404 PWM_MAIN.showErrorDialog(data,{ 405 okAction:function(){ 406 setTimeout(function(){ 407 PWM_MAIN.getObject('password').focus(); 408 },50); 409 } 410 }); 411 return; 412 } 413 PWM_MAIN.log('authentication success'); 414 var nextURL = data['data']['nextURL']; 415 if (nextURL) { 416 PWM_MAIN.gotoUrl(nextURL, {noContext: true}); 417 } 418 }; 419 PWM_MAIN.ajaxRequest(url,loadFunction,options); 420 if(typeof grecaptcha !== 'undefined'){ 421 try { 422 grecaptcha.reset(); // reset the 423 } catch (e) { 424 PWM_MAIN.log("error resetting the captcha: " + e) 425 } 426 } 427 }}); 428}; 429 430PWM_MAIN.log = function(text) { 431 console.log(text); 432}; 433 434 435PWM_MAIN.handleFormSubmit = function(form, event) { 436 PWM_MAIN.log('entering handleFormSubmit');
437 PWM_MAIN.cancelEvent(event); 438 439 PWM_GLOBAL['idle_suspendTimeout'] = true; 440 if ( form.elements ) { 441 var formElements = form.elements; 442 for (var i = 0; i < formElements.length; i++) { 443 formElements[i].readOnly = true; 444 if (formElements[i].type === 'button' || formElements[i].type === 'submit') { 445 formElements[i].disabled = true; 446 } 447 } 448 } 449 450 PWM_MAIN.showWaitDialog({loadFunction:function(){ 451 form.submit(); 452 }}); 453 return false; 454}; 455 456 457PWM_MAIN.checkForCapsLock = function(e) { 458 var capsLockWarningElement = PWM_MAIN.getObject('capslockwarning'); 459 if (capsLockWarningElement === null || capsLockWarningElement === undefined) { 460 return; 461 } 462 463 var capsLockKeyDetected = false; 464 { 465 var elementTarget = null; 466 if (e.target) { 467 elementTarget = e.target; 468 } else if (e.srcElement) { 469 elementTarget = e.srcElement; 470 } 471 if (elementTarget) { 472 if (elementTarget.nodeName === 'input' || elementTarget.nodeName === 'INPUT') { 473 var kc = e.keyCode ? e.keyCode : e.which; 474 var sk = e.shiftKey ? e.shiftKey : ((kc === 16)); 475 if (((kc >= 65 && kc <= 90) && !sk) || ((kc >= 97 && kc <= 122) && sk)) { 476 capsLockKeyDetected = true; 477 } 478 } 479 } 480 } 481 482 var displayDuration = 5 * 1000; 483 if (capsLockKeyDetected) { 484 PWM_MAIN.removeCssClass('capslockwarning','display-none'); 485 PWM_GLOBAL['lastCapsLockErrorTime'] = (new Date().getTime()); 486 setTimeout(function(){ 487 if ((new Date().getTime() - PWM_GLOBAL['lastCapsLockErrorTime'] > displayDuration)) { 488 PWM_MAIN.addCssClass('capslockwarning','display-none'); 489 } 490 },displayDuration + 500); 491 } else { 492 PWM_MAIN.addCssClass('capslockwarning','display-none'); 493 } 494}; 495 496PWM_MAIN.getObject = function(name) { 497 if (name === null || name === undefined) { 498 return null; 499 } 500 501 if (name.tagName) { // argument is already a dom element 502 return name; 503 } 504 505 if (name === document || name === window) { 506 return name; 507 } 508 509 var ns4 = document.layers; 510 var w3c = document.getElementById; 511 var ie4 = document.all; 512 513 if (ns4) { 514 return eval('document.' + name); 515 } 516 if (w3c) { 517 return document.getElementById(name); 518 } 519 if (ie4) { 520 return eval('document.all.' + name); 521 } 522 return false; 523}; 524 525PWM_MAIN.trimString = function(sInString) { 526 sInString = sInString.replace(/^\s+/g, ""); 527 // strip leading 528 return sInString.replace(/\s+$/g, ""); 529 // strip trailing 530}; 531 532PWM_MAIN.showDijitTooltip = function(options){ 533 options = options === undefined ? {} : options; 534 535 if (!options['id']) { 536 return; 537 } 538 539 var id = options['id'] instanceof Array ? options['id'] : [options['id']]; 540 var position = options['position'] instanceof Array ? options['position'] : null; 541 542 var dojoOptions = {}; 543 dojoOptions['connectId'] = id; 544 dojoOptions['id'] = id[0]; 545 dojoOptions['label'] = 'text' in options ? options['text'] : "missing text option"; 546 547 if (position) { 548 dojoOptions['position'] = position; 549 } 550 551 if (options['width']) { 552 dojoOptions['label'] = '<div style="max-width:' + options['width'] + 'px">' + dojoOptions['label'] + '</div>' 553 } 554 555 require(["dijit/Tooltip","dijit/registry"],function(Tooltip){ 556 PWM_MAIN.clearDijitWidget(id[0]); 557 new Tooltip(dojoOptions); 558 }); 559}; 560 561PWM_MAIN.showTooltip = function(options){ 562 options = options === undefined ? {} : options; 563 564 if (!options['id']) { 565 return; 566 } 567 568 var id = options['id'] instanceof Array ? options['id'] : [options['id']]; 569 570 var dojoOptions = {}; 571 dojoOptions['connectId'] = id; 572 dojoOptions['id'] = id[0]; 573 574 var label = 'text' in options ? options['text'] : "missing text option for id " + id; 575 576 var element = PWM_MAIN.getObject(id); 577 if (element) { 578 element.setAttribute('title',label); 579 } 580}; 581 582 583
584PWM_MAIN.clearDijitWidget = function (widgetName) { 585 require(["dojo","dijit/registry"],function(dojo, registry){ 586 587 var oldDijitNode = registry.byId(widgetName); 588 if (oldDijitNode) { 589 try { 590 oldDijitNode.destroyRecursive(); 591 } catch (error) { 592 PWM_MAIN.log('error destroying old widget: ' + error); 593 } 594 595 try { 596 oldDijitNode.destroy(); 597 } catch (error) { 598 PWM_MAIN.log('error destroying old widget: ' + error); 599 } 600 } 601 }); 602}; 603 604PWM_MAIN.showLocaleSelectionMenu = function(nextFunction, options) { 605 options = options === undefined ? {} : options; 606 var excludeLocales = 'excludeLocales' in options ? options['excludeLocales'] : []; 607 608 var localeData = PWM_GLOBAL['localeInfo']; 609 610 var bodyHtml = '<table class="noborder" style="width:auto;margin-right:auto;margin-left:auto;overflow-x:scroll">'; 611 PWM_MAIN.JSLibrary.forEachInObject(localeData, function (localeKey, loopDisplayName) { 612 if (!PWM_MAIN.JSLibrary.arrayContains(excludeLocales, localeKey)) { 613 var flagCode = PWM_GLOBAL['localeFlags'][localeKey]; 614 var flagUrl = PWM_GLOBAL['url-resources'] + '/webjars/famfamfam-flags/dist/png/' + flagCode + '.png'; 615 bodyHtml += '<tr style="cursor:pointer" id="locale-row-' + localeKey + '">'; 616 bodyHtml += '<td><img alt="Flag Image" src="' + flagUrl + '"/></td>'; 617 bodyHtml += '<td>' + loopDisplayName + '</td>'; 618 bodyHtml += '</tr>'; 619 } 620 }); 621 bodyHtml += '</table>'; 622 623 PWM_MAIN.showDialog({ 624 showClose: true, 625 showOk: false, 626 text: bodyHtml, 627 title: PWM_MAIN.showString('Title_LocaleSelect'), 628 loadFunction: function () { 629 PWM_MAIN.JSLibrary.forEachInObject(localeData, function (localeKey, loopDisplayName) { 630 PWM_MAIN.addEventHandler('locale-row-' + localeKey, 'click', function () { 631 PWM_MAIN.closeWaitDialog(); 632 nextFunction(localeKey); 633 }); 634 }); 635 } 636 }); 637}; 638 639PWM_MAIN.initLocaleSelectorMenu = function(attachNode) { 640 PWM_MAIN.addEventHandler(attachNode,'click',function(){ 641 PWM_MAIN.showLocaleSelectionMenu(function(localeKey){ 642 PWM_MAIN.showWaitDialog({loadFunction:function(){ 643 var url = PWM_GLOBAL['url-context'] + '/public/api?locale=' + localeKey; 644 PWM_MAIN.ajaxRequest(url, function(){ 645 try { 646 var newLocation = window.location; 647 var searchParams = new URLSearchParams(newLocation.search); 648 if ( searchParams.has('locale')) { 649 searchParams.set('locale', localeKey); 650 newLocation.search = searchParams.toString(); 651 window.location = newLocation; 652 return; 653 } 654 } catch (e) { 655 PWM_MAIN.log('error replacing locale parameter on existing url: ' + e); 656 } 657 658 window.location.reload(true); 659 }); 660 } 661 }); 662 }); 663 }); 664}; 665 666 667 668PWM_MAIN.showErrorDialog = function(error, options) { 669 options = options === undefined ? {} : options; 670 var forceReload = false; 671 var body = ''; 672 var logMsg = ''; 673 var titleMsg = PWM_MAIN.showString('Title_Error'); 674 if ('text' in options) { 675 body += options['text']; 676 body += '<br/><br/>'; 677 logMsg += options['text']; 678 } 679 if (error && error['error']) { 680 var code = error['errorCode']; 681 if (code === 5028 || code === 5034 || code === 5035) { 682 forceReload = true; 683 } 684 titleMsg += ' ' + error['errorCode']; 685 body += error['errorMessage']; 686 logMsg += error['errorCode'] + "," + error['errorMessage']; 687 if (error['errorDetail']) { 688 body += "<br/><br/><div class='errorDetail' style='max-height: 250px; overflow-y: auto'>" + error['errorDetail'] + '</div>'; 689 logMsg += ", detail: " + error['errorDetail']; 690 } 691 } else { 692 body += error; 693 logMsg += error; 694 } 695 696 if (forceReload) { 697 logMsg += 'due to error code type, reloading page.'; 698 } 699 700 PWM_MAIN.log('displaying error message: ' + logMsg); 701 options['title'] = titleMsg; 702 options['text'] = body; 703 var previousOkAction = 'okAction' in options ? options['okAction'] : function() {}; 704 options['okAction'] = function() { 705 if (forceReload) { // incorrect page sequence; 706 var newURL = window.location.pathname; 707 PWM_MAIN.gotoUrl(newURL); 708 PWM_MAIN.showWaitDialog(); 709 } else { 710 previousOkAction(); 711 } 712 }; 713 PWM_MAIN.showDialog(options); 714}; 715 716PWM_MAIN.showWaitDialog = function(options) {
717 PWM_MAIN.closeWaitDialog(); 718 719 options = options || {}; 720 options['title'] = options['title'] || ''; 721 722 var waitOverlayDiv = document.createElement('div'); 723 waitOverlayDiv.setAttribute('id','wait-overlay'); 724 document.body.appendChild(waitOverlayDiv); 725 726 var waitOverlayMessage = document.createElement('div'); 727 waitOverlayMessage.setAttribute('id','wait-overlay-message'); 728 waitOverlayMessage.innerHTML = '<span>' + options['title'] + '</span><div id="wait-overlay-inner"></div>'; 729 document.body.appendChild(waitOverlayMessage); 730 731 if ('loadFunction' in options) { 732 options.loadFunction(); 733 } 734}; 735 736PWM_MAIN.closeWaitDialog = function(idName) { 737 738 var html5Mode = PWM_MAIN.html5DialogSupport(); 739 if (html5Mode) { 740 if (PWM_MAIN.getObject('html5Dialog')) { 741 PWM_MAIN.getObject('html5Dialog').parentNode.removeChild(PWM_MAIN.getObject('html5Dialog')); 742 } 743 } else { 744 idName = idName === undefined ? 'dialogPopup' : idName; 745 PWM_MAIN.clearDijitWidget(idName); 746 } 747 748 PWM_MAIN.JSLibrary.removeElementFromDom('wait-overlay'); 749 PWM_MAIN.JSLibrary.removeElementFromDom('wait-overlay-message'); 750}; 751 752PWM_MAIN.html5DialogSupport = function() { 753 if (PWM_GLOBAL['client.js.enableHtml5Dialog']) { 754 var testdialog = document.createElement("dialog"); 755 testdialog.setAttribute("open", ""); 756 return (testdialog.open === true); 757 } 758 return false; 759}; 760 761PWM_MAIN.showDialog = function(options) { 762 PWM_MAIN.closeWaitDialog(); 763 var html5Dialog = PWM_MAIN.html5DialogSupport(); 764 765 options = options === undefined ? {} : options; 766 var title = options['title'] || 'DialogTitle'; 767 var text = 'text' in options ? options['text'] : 'DialogBody'; 768 var closeOnOk = 'closeOnOk' in options ? options['closeOnOk'] : true; 769 var showOk = 'showOk' in options ? options['showOk'] : true; 770 var showCancel = 'showCancel' in options ? options['showCancel'] : false; 771 var showClose = 'showClose' in options ? options['showClose'] : false; 772 var allowMove = 'allowMove' in options ? options['allowMove'] : false; 773 var idName = 'id' in options ? options['id'] : 'dialogPopup'; 774 var dialogClass = 'dialogClass' in options ? options['dialogClass'] : null; 775 var dojoStyle = 'dojoStyle' in options ? options['dojoStyle'] : null; 776 var okLabel = 'okLabel' in options ? options['okLabel'] : PWM_MAIN.showString('Button_OK'); 777 var buttonHtml = 'buttonHtml' in options ? options['buttonHtml'] : ''; 778 var href = 'href' in options ? options['href'] : null; 779 780 var okAction = function(){ 781 if (closeOnOk) { 782 PWM_MAIN.closeWaitDialog(idName); 783 } 784 if ('okAction' in options) { 785 options['okAction'](); 786 } else { 787 PWM_MAIN.log('dialog okAction is empty') 788 } 789 }; 790 var cancelAction = 'cancelAction' in options ? options['cancelAction'] : function(){ 791 PWM_MAIN.closeWaitDialog(idName); 792 PWM_MAIN.log('no-dialog-cancelaction') 793 }; 794 var loadFunction = 'loadFunction' in options ? options['loadFunction'] : function(){ 795 PWM_MAIN.log('no-dialog-loadfunction') 796 }; 797 798 PWM_VAR['dialog_loadFunction'] = loadFunction; 799 800 var bodyText = ''; 801 bodyText += text; 802 803 if (showOk || showCancel || buttonHtml.length > 0) { 804 bodyText += '<div class="buttonbar">'; 805 if (showOk) { 806 bodyText += '<button class="btn" id="dialog_ok_button">' 807 + '<span class="btn-icon pwm-icon pwm-icon-check-square-o"></span>' 808 + okLabel + '</button> '; 809 } 810 if (showCancel) { 811 bodyText += '<button class="btn" id="dialog_cancel_button">' 812 + '<span class="btn-icon pwm-icon pwm-icon-times"></span>' 813 + PWM_MAIN.showString('Button_Cancel') + '</button> '; 814 } 815 bodyText += buttonHtml; 816 bodyText += '</div>'; 817 } 818 819 var dialogClassText = 'dialogBody'; 820 if (dialogClass) { 821 dialogClassText += ' ' + dialogClass; 822 } 823 bodyText = '<div class="' + dialogClassText + '">
823' + bodyText + '</div>'; 824 825 if (html5Dialog) { 826 var doDialogDisplay = function(){ 827 PWM_MAIN.closeWaitDialog(); 828 var dialogElement = document.createElement("dialog"); 829 dialogElement.setAttribute("id", 'html5Dialog'); 830 var html5DialogHtml = '<div class="titleBar">' + title; 831 if (showClose) { 832 html5DialogHtml += '<div id="icon-closeDialog" class="closeIcon pwm-icon pwm-icon-times"></div>' 833 } 834 html5DialogHtml += '</div><div class="body">' + bodyText + '</div>'; 835 dialogElement.innerHTML = html5DialogHtml; 836 document.body.appendChild(dialogElement); 837 dialogElement.showModal(); 838 839 setTimeout(function () { 840 if (showOk) { 841 PWM_MAIN.addEventHandler('dialog_ok_button', 'click', function () { 842 okAction() 843 }); 844 } 845 if (showClose) { 846 PWM_MAIN.addEventHandler('icon-closeDialog', 'click', function () { 847 PWM_MAIN.closeWaitDialog(); 848 }); 849 } 850 851 if (showCancel) { 852 PWM_MAIN.addEventHandler('dialog_cancel_button', 'click', function () { 853 cancelAction() 854 }); 855 } 856 setTimeout(loadFunction, 100); 857 }, 100); 858 } 859 860 if (href) { 861 var hrefContentHandler = function( value ) { 862 bodyText = '<div class="' + dialogClassText + '">' + value + '</div>'; 863 doDialogDisplay(); 864 }; 865 PWM_MAIN.showWaitDialog({loadFunction:function(){ 866 PWM_MAIN.ajaxRequest(href,hrefContentHandler,{method:'GET',responseMimeType:'text/html',handleAs:'html'}); 867 }}); 868 } else { 869 doDialogDisplay(); 870 } 871 } else { 872 PWM_MAIN.preloadAll(); 873 require(["dojo", "dijit/Dialog"], function (dojo, Dialog) { 874 PWM_MAIN.clearDijitWidget(idName); 875 var theDialog = new Dialog({ 876 id: idName, 877 closable: showClose, 878 draggable: allowMove, 879 title: title, 880 style: dojoStyle, 881 content: bodyText, 882 href: href 883 }); 884 if (!showClose) { 885 dojo.style(theDialog.closeButtonNode, "display", "none"); 886 } 887 dojo.connect(theDialog, "onShow", null, function () { 888 if (showOk) { 889 PWM_MAIN.addEventHandler('dialog_ok_button', 'click', function () { 890 okAction() 891 }); 892 } 893 if (showCancel) { 894 PWM_MAIN.addEventHandler('dialog_cancel_button', 'click', function () { 895 cancelAction() 896 }); 897 } 898 setTimeout(loadFunction, 100); 899 }); 900 theDialog.show(); 901 }); 902 } 903}; 904 905PWM_MAIN.showEula = function(requireAgreement, agreeFunction) { 906 if (agreeFunction && PWM_GLOBAL['eulaAgreed']) { 907 agreeFunction(); 908 return; 909 } 910 911 var displayEula = function (data) { 912 PWM_GLOBAL['dialog_agreeAction'] = agreeFunction ? agreeFunction : function(){}; 913 914 var bodyText = '<div style="height: 400px; overflow: auto" class="eulaText">' + data + '</div>'; 915 916 var dialogOptions = {}; 917 dialogOptions['text'] = bodyText; 918 dialogOptions['title'] = 'End User License Agreement'; 919 920 if (requireAgreement) { 921 dialogOptions['showCancel'] = true; 922 dialogOptions['okLabel'] = PWM_MAIN.showString('Button_Agree'); 923 dialogOptions['okAction'] = function() { 924 PWM_GLOBAL['eulaAgreed']=true; 925 agreeFunction(); 926 }; 927 } 928 929 PWM_MAIN.showDialog(dialogOptions); 930 }; 931 932 var eulaLocation = PWM_GLOBAL['url-resources'] + '/text/eula.txt'; 933 934 var options = {}; 935 options['method'] = 'GET'; 936 options['handleAs'] = 'text'; 937 var loadFunction = function (data) { 938 displayEula(data); 939 }; 940 PWM_MAIN.ajaxRequest(eulaLocation, loadFunction, options); 941}; 942 943PWM_MAIN.showConfirmDialog = function(options) { 944 options = options === undefined ? {} : options; 945 options['showCancel'] = true; 946 options['title'] = 'title' in options ? options['title'] : PWM_MAIN.showString('Button_Confirm'); 947 options['text'] = 'text' in options ? options['text'] : PWM_MAIN.showString('Confirm'); 948 PWM_MAIN.showDialog(options); 949}; 950
951PWM_MAIN.clearError=function() { 952 PWM_GLOBAL['messageStatus'] = ''; 953 PWM_MAIN.doShow('messageStatus','\u00a0'); 954}; 955 956PWM_MAIN.showInfo=function(infoMsg) { 957 PWM_GLOBAL['messageStatus'] = 'message-info'; 958 PWM_MAIN.doShow('message-info',infoMsg); 959}; 960 961PWM_MAIN.showError=function(errorMsg) { 962 PWM_GLOBAL['messageStatus'] = 'message-error'; 963 PWM_MAIN.doShow('message-error',errorMsg); 964}; 965 966PWM_MAIN.showSuccess=function(successMsg) { 967 PWM_GLOBAL['messageStatus'] = 'message-success'; 968 PWM_MAIN.doShow('message-success',successMsg); 969}; 970 971PWM_MAIN.doShow = function(destClass, message, fromFloatHandler) { 972 var messageElement = PWM_MAIN.getObject("message"); 973 if (messageElement === null || messageElement.firstChild === null || messageElement.firstChild.nodeValue === null) { 974 return; 975 } 976 977 // clear existing status 978 PWM_MAIN.removeCssClass(messageElement,'message-info'); 979 PWM_MAIN.removeCssClass(messageElement,'message-error'); 980 PWM_MAIN.removeCssClass(messageElement,'message-success'); 981 982 if (destClass === '') { 983 PWM_MAIN.addCssClass(messageElement, "nodisplay") 984 return; 985 } else { 986 PWM_MAIN.removeCssClass(messageElement, "nodisplay") 987 } 988 989 messageElement.firstChild.nodeValue = message; 990 991 PWM_MAIN.addCssClass(messageElement,destClass); 992 993 if (!fromFloatHandler) { 994 PWM_MAIN.messageDivFloatHandler(); 995 } 996}; 997 998PWM_MAIN.createCSSClass = function(selector, style) { 999 // using information found at: http://www.quirksmode.org/dom/w3c_css.html 1000 // doesn't work in older versions of Opera (< 9) due to lack of styleSheets support 1001 if(!document.styleSheets) return; 1002 if(document.getElementsByTagName("head").length === 0) return; 1003 var styleSheet; 1004 var mediaType; 1005 if(document.styleSheets.length > 0) 1006 { 1007 for(var i = 0; i<document.styleSheets.length; i++) 1008 { 1009 if(document.styleSheets[i].disabled) continue; 1010 var media = document.styleSheets[i].media; 1011 mediaType = typeof media; 1012 // IE 1013 if(mediaType === "string") 1014 { 1015 if(media === "" || media.indexOf("screen") !== -1) 1016 { 1017 styleSheet = document.styleSheets[i]; 1018 } 1019 } 1020 else if(mediaType === "object") 1021 { 1022 try { 1023 if(media.mediaText === "" || media.mediaText.indexOf("screen") !== -1) 1024 { 1025 styleSheet = document.styleSheets[i]; 1026 } 1027 } catch (e) { /* noop */ } 1028 } 1029 // stylesheet found, so break out of loop 1030 if(typeof styleSheet !== "undefined") break; 1031 } 1032 } 1033 // if no style sheet is found 1034 if(typeof styleSheet === "undefined") 1035 { 1036 // create a new style sheet 1037 var styleSheetElement = document.createElement("style"); 1038 styleSheetElement.type = "text/css"; 1039 // add to <head> 1040 document.getElementsByTagName("head")[0].appendChild(styleSheetElement); 1041 // select it 1042 for(i = 0; i<document.styleSheets.length; i++) 1043 { 1044 if(document.styleSheets[i].disabled) continue; 1045 styleSheet = document.styleSheets[i]; 1046 } 1047 // read media type 1048 var media = styleSheet.media; 1049 mediaType = typeof media; 1050 } 1051 // IE 1052 if(mediaType === "string") 1053 { 1054 for(i = 0;i<styleSheet.rules.length;i++) 1055 { 1056 // if there is an existing rule set up, replace it 1057 try { 1058 if(styleSheet.cssRules[i].selectorText && styleSheet.rules[i].selectorText.toLowerCase() === selector.toLowerCase()) 1059 { 1060 styleSheet.rules[i].style.cssText = style; 1061 return; 1062 } 1063 } catch (e) { 1064 PWM_MAIN.log('error while checking existing rules during cssCreate:' + e); 1065 } 1066 } 1067 // or add a new rule 1068 styleSheet.addRule(selector,style); 1069 } 1070 else if(mediaType === "object") 1071 { 1072 for(i = 0;i<styleSheet.cssRules.length;i++) 1073 { 1074 // if there is an existing rule set up, replace it 1075 if(styleSheet.cssRules[i].selectorText && styleSheet.cssRules[i].selectorText.toLowerCase() === selector.toLowerCase()) 1076 { 1077 styleSheet.cssRules[i].style.cssText = style; 1078 return; 1079 } 1080 } 1081 // or insert new rule 1082 styleSheet.insertRule(selector + "{" + style + "}", styleSheet.cssRules.length); 1083 } 1084}; 1085 1086PWM_MAIN.flashDomElement = function(flashColor,elementName,durationMS) { 1087 var element = PWM_MAIN.getObject(elementName); 1088 if ( element ) { 1089 PWM_MAIN.addCssClass(element,'background-alert-flash'); 1090 setTimeout(function(){ 1091 // PWM_MAIN.removeCssClass(element, 'background-alert-flash'); 1092 },5000) 1093 } 1094 /* 1095 1096 if (!PWM_MAIN.getObject(elementName)) { 1097 PWM_MAIN.log('cant flash non-existing element id ' + elementName); 1098 return; 1099 } 1100 PWM_MAIN.log('will flash element id ' + elementName); 1101 require(["dojo","dojo/window","dojo/domReady!"],function(dojo) { 1102 var originalBGColor = PWM_MAIN.getRenderedStyle(elementName,'background-color'); 1103 PWM_MAIN.getObject(elementName).style.backgroundColor = flashColor; 1104 dojo.animateProperty({ 1105 node:elementName, 1106 duration: durationMS, 1107 properties: { backgroundColor: originalBGColor} 1108 }).play(); 1109 }); 1110 */ 1111}; 1112 1113PWM_MAIN.getRenderedStyle = function(el,styleProp) { 1114 var x = document.getElementById(el); 1115 if (x.currentStyle) { 1116 return x.currentStyle[styleProp]; 1117 } 1118 1119 if (window.getComputedStyle) { 1120 return document.defaultView.getComputedStyle(x,null).getPropertyValue(styleProp); 1121 } 1122 1123 return null; 1124}; 1125 1126PWM_MAIN.elementInViewport = function(el, includeWidth) { 1127 var top = el.offsetTop; 1128 var left = el.offsetLeft; 1129 var width = el.offsetWidth; 1130 var height = el.offsetHeight; 1131 1132 while(el.offsetParent) { 1133 el = el.offsetParent; 1134 top += el.offsetTop; 1135 left += el.offsetLeft; 1136 } 1137 1138 var pageY = (typeof(window.pageYOffset)=='number') ? window.pageYOffset : document.documentElement.scrollTop; 1139 var pageX = (typeof(window.pageXOffset)=='number') ? window.pageXOffset : document.documentElement.scrollLeft; 1140 1141 return includeWidth ? ( 1142 top >= pageY && (top + height) <= (pageY + window.innerHeight) && 1143 left >= pageX && 1144 (left + width) <= (pageX + window.innerWidth) 1145 ) : ( 1146 top >= pageY && (top + height) <= (pageY + window.innerHeight) 1147 ); 1148}; 1149 1150PWM_MAIN.messageDivFloatHandler = function() { 1151 var messageObj = PWM_MAIN.getObject('message'); 1152 var messageWrapperObj = PWM_MAIN.getObject('message_wrapper'); 1153 if (!messageObj || !messageWrapperObj) { 1154 return; 1155 } 1156 1157 if (PWM_MAIN.hasCssClass('message','nodisplay')) { 1158 return; 1159 } 1160 1161 var doFloatDisplay = !(PWM_MAIN.elementInViewport(messageWrapperObj,false) || PWM_GLOBAL['messageStatus'] === ''); 1162 1163 if (PWM_GLOBAL['message_scrollToggle'] !== doFloatDisplay) { 1164 PWM_GLOBAL['message_scrollToggle'] = doFloatDisplay; 1165 1166 if (doFloatDisplay) { 1167 PWM_MAIN.addCssClass(messageObj,'message-scrollFloat'); 1168 PWM_MAIN.doShow(PWM_GLOBAL['messageStatus'],messageObj.innerHTML,true); 1169 } else { 1170 PWM_MAIN.removeCssClass(messageObj,'message-scrollFloat'); 1171 PWM_MAIN.doShow(PWM_GLOBAL['messageStatus'],messageObj.innerHTML,true); 1172 } 1173 } 1174}; 1175
1176PWM_MAIN.pwmFormValidator = function(validationProps, reentrant) { 1177 var CONSOLE_DEBUG = false; 1178 1179 var serviceURL = validationProps['serviceURL']; 1180 var readDataFunction = validationProps['readDataFunction']; 1181 var processResultsFunction = validationProps['processResultsFunction']; 1182 var messageWorking = validationProps['messageWorking'] ? validationProps['messageWorking'] : PWM_MAIN.showString('Display_PleaseWait'); 1183 var typeWaitTimeMs = validationProps['typeWaitTimeMs'] ? validationProps['typeWaitTimeMs'] : PWM_GLOBAL['client.ajaxTypingWait']; 1184 var ajaxTimeout = validationProps['ajaxTimeout'] ? validationProps['ajaxTimeout'] : PWM_GLOBAL['client.ajaxTypingTimeout']; 1185 var showMessage = 'showMessage' in validationProps ? validationProps['showMessage'] : true; 1186 var completeFunction = 'completeFunction' in validationProps ? validationProps['completeFunction'] : function(){}; 1187 1188 1189 if (CONSOLE_DEBUG) PWM_MAIN.log("pwmFormValidator: beginning..."); 1190 1191 //init vars; 1192 if (!PWM_VAR['validationCache']) { 1193 PWM_VAR['validationCache'] = {}; 1194 } 1195 1196 // check if data is in cache, if it is just process it. 1197 var formData = readDataFunction(); 1198 var formKey = ""; 1199 for (var key in formData) {formKey += formData[key] + "-";} 1200 1201 { 1202 var cachedResult = PWM_VAR['validationCache'][formKey]; 1203 if (cachedResult) { 1204 processResultsFunction(cachedResult); 1205 if (CONSOLE_DEBUG) PWM_MAIN.log('pwmFormValidator: processed cached data, exiting'); 1206 completeFunction(cachedResult); 1207 return; 1208 } 1209 } 1210 1211 if (!reentrant) { 1212 PWM_VAR['validationLastType'] = new Date().getTime(); 1213 } 1214 1215 // check to see if user is still typing. if yes, then come back later. 1216 if (new Date().getTime() - PWM_VAR['validationLastType'] < typeWaitTimeMs) { 1217 if (showMessage) { 1218 PWM_MAIN.showInfo(PWM_MAIN.showString('Display_TypingWait')); 1219 } 1220 setTimeout(function(){PWM_MAIN.pwmFormValidator(validationProps, true)}, typeWaitTimeMs + 1); 1221 if (CONSOLE_DEBUG) PWM_MAIN.log('pwmFormValidator: sleeping while waiting for typing to finish, will retry...'); 1222 return; 1223 } 1224 if (CONSOLE_DEBUG) PWM_MAIN.log('pwmFormValidator: user no longer typing, continuing..'); 1225 1226 //check to see if a validation is already in progress, if it is then ignore keypress. 1227 if (PWM_VAR['validationInProgress'] === true) { 1228 setTimeout(function(){PWM_MAIN.pwmFormValidator(validationProps, true)}, typeWaitTimeMs + 1); 1229 if (CONSOLE_DEBUG) PWM_MAIN.log('pwmFormValidator: waiting for a previous validation to complete, exiting...'); 1230 return; 1231 } 1232 PWM_VAR['validationInProgress'] = true; 1233 1234 // show in-progress message if load takes too long. 1235 if (showMessage) { 1236 setTimeout(function () { 1237 if (PWM_VAR['validationInProgress'] === true) { 1238 PWM_MAIN.showInfo(messageWorking); 1239 } 1240 }, 5); 1241 } 1242 1243 var formDataString = JSON.stringify(formData) ; 1244 1245 if (CONSOLE_DEBUG) PWM_MAIN.log('FormValidator: sending form data to server... ' + formDataString); 1246 var loadFunction = function(data) { 1247 PWM_VAR['validationInProgress'] = false; 1248 delete PWM_VAR['validationLastType']; 1249 PWM_VAR['validationCache'][formKey] = data; 1250 if (CONSOLE_DEBUG) PWM_MAIN.log('pwmFormValidator: successful read, data added to cache'); 1251 PWM_MAIN.pwmFormValidator(validationProps, true); 1252 }; 1253 var options = {}; 1254 options['content'] = formData; 1255 options['ajaxTimeout'] = ajaxTimeout; 1256 options['errorFunction'] = function(error) { 1257 PWM_VAR['validationInProgress'] = false; 1258 if (showMessage) { 1259 PWM_MAIN.showInfo(PWM_MAIN.showString('Display_CommunicationError')); 1260 } 1261 if (CONSOLE_DEBUG) PWM_MAIN.log('pwmFormValidator: error connecting to service: ' + error); 1262 processResultsFunction(null); 1263 completeFunction(null); 1264 }; 1265 PWM_MAIN.ajaxRequest(serviceURL,loadFunction,options); 1266}; 1267 1268PWM_MAIN.preloadImages = function(imgArray){ 1269 var newimages=[]; 1270 var arr=(typeof imgArray!="object")? [imgArray] : imgArray; //force arr parameter to always be an array 1271 for (var i=0; i<arr.length; i++){ 1272 newimages[i]=new Image(); 1273 newimages[i].src=arr[i]; 1274 } 1275}; 1276 1277PWM_MAIN.JSLibrary = {}; 1278PWM_MAIN.JSLibrary.isEmpty = function(o) { 1279 return PWM_MAIN.JSLibrary.itemCount(o) < 1; 1280}; 1281 1282PWM_MAIN.JSLibrary.itemCount = function(o) { 1283 var i = 0; 1284 for (var key in o) if (o.hasOwnProperty(key)) i++; 1285 return i; 1286}; 1287 1288PWM_MAIN.JSLibrary.arrayContains = function(array,element) { 1289 if (!array) { 1290 return false;
1291 } 1292 1293 return array.indexOf(element) > -1; 1294}; 1295 1296PWM_MAIN.JSLibrary.getAttribute = function(element,attribute) { 1297 return PWM_MAIN.getObject(element).getAttribute(attribute); 1298}; 1299 1300PWM_MAIN.JSLibrary.setAttribute = function(element,attribute,value) { 1301 PWM_MAIN.getObject(element).setAttribute(attribute,value); 1302} 1303 1304PWM_MAIN.JSLibrary.removeFromArray = function(array,element) { 1305 for(var i = array.length - 1; i >= 0; i--) { 1306 if(array[i] === element) { 1307 array.splice(i, 1); 1308 } 1309 } 1310}; 1311 1312PWM_MAIN.JSLibrary.readValueOfSelectElement = function(nodeID) { 1313 var element = PWM_MAIN.getObject(nodeID); 1314 if (element && element.options && element.selectedIndex >= 0) { 1315 return element.options[element.selectedIndex].value; 1316 } 1317 return ""; 1318}; 1319 1320PWM_MAIN.JSLibrary.setValueOfSelectElement = function(nodeID, value) { 1321 var element = PWM_MAIN.getObject(nodeID); 1322 for(var i=0; i < element.options.length; i++) { 1323 if (element.options[i].value === value) { 1324 element.selectedIndex = i; 1325 break; 1326 } 1327 } 1328}; 1329 1330PWM_MAIN.JSLibrary.readValueOfRadioFormInput = function(name){ 1331 var value = ''; 1332 var query = "input[name='" + name + "'" 1333 PWM_MAIN.doQuery(query, function(element){ 1334 if( element.checked ) { 1335 value = element.value; 1336 } 1337 }); 1338 console.log('radioRead name=' + name + ' value=' + value); 1339 return value; 1340}; 1341 1342PWM_MAIN.JSLibrary.formToValueMap = function(formElement) { 1343 formElement = PWM_MAIN.getObject(formElement); 1344 var returnData = {}; 1345 if ( formElement.elements ) { 1346 var formElements = formElement.elements; 1347 for (var i = 0; i < formElements.length; i++) { 1348 var field = formElements[i]; 1349 if (field.disabled !== true) { 1350 var name = field.name; 1351 var value = field.value; 1352 if (field.tagName && field.tagName.toLowerCase() === 'input' && field.type === 'radio' ) { 1353 value = PWM_MAIN.JSLibrary.readValueOfRadioFormInput(name); 1354 } else if (field.tagName && field.tagName.toLowerCase() === 'select') { 1355 value = PWM_MAIN.JSLibrary.readValueOfSelectElement(field); 1356 } else if (field.type === "checkbox") { 1357 value = field.checked.toString(); 1358 } 1359 if ( name && value ) { 1360 returnData[name] = value; 1361 } 1362 } 1363 } 1364 } 1365 1366 return returnData; 1367}; 1368 1369PWM_MAIN.JSLibrary.forEachInArray = function(array,forEachFunction) { 1370 for (var i=0, l=array.length; i<l; i++) { 1371 forEachFunction(array[i]); 1372 } 1373} 1374 1375PWM_MAIN.JSLibrary.forEachInObject = function(object,forEachFunction) { 1376 for (var key in object) { 1377 if (object.hasOwnProperty(key)) { 1378 forEachFunction(key,object[key]); 1379 } 1380 } 1381} 1382 1383PWM_MAIN.JSLibrary.removeElementFromDom = function(elementID) { 1384 var element = PWM_MAIN.getObject(elementID); 1385 if (element) { 1386 element.parentNode.removeChild(element); 1387 } 1388}; 1389 1390PWM_MAIN.JSLibrary.onPageLoad = function(callback) { 1391 if (document.readyState === "complete") { 1392 callback(); 1393 } else { 1394 window.addEventListener("load",function(event) { 1395 callback(); 1396 }, false); 1397 } 1398}; 1399 1400PWM_MAIN.toggleFullscreen = function(iconObj,divName) { 1401 var obj = PWM_MAIN.getObject(divName); 1402 1403 var storedStyleName = 'fullscreen-style-' + divName; 1404 if (PWM_GLOBAL[storedStyleName]) { 1405 iconObj.className = "icon-fullscreen"; 1406 obj.style = PWM_GLOBAL[storedStyleName]; 1407 delete PWM_GLOBAL[storedStyleName]; 1408 } else { 1409 PWM_GLOBAL[storedStyleName] = obj.style; 1410 iconObj.className = "icon-resize-full"; 1411 obj.style.position = 'fixed'; 1412 obj.style.top = '0'; 1413 obj.style.left = '0'; 1414 obj.style.bottom = '0'; 1415 obj.style.right = '0'; 1416 obj.style.zIndex = '100'; 1417 obj.style.background = 'white'; 1418 } 1419 if (PWM_GLOBAL['displayGrid']) { 1420 PWM_GLOBAL['displayGrid'].resize(); 1421 } 1422}; 1423 1424PWM_MAIN.updateLoginContexts = function() { 1425 var ldapProfileElement = PWM_MAIN.getObject('ldapProfile'); 1426 var contextElement = PWM_MAIN.getObject('context'); 1427 if (contextElement && ldapProfileElement) { 1428 var selectedProfile = ldapProfileElement.options[ldapProfileElement.selectedIndex].value; 1429 var contextList = PWM_GLOBAL['ldapProfiles'][selectedProfile]; 1430 if (PWM_MAIN.JSLibrary.isEmpty(contextList)) { 1431 PWM_MAIN.addCssClass( 'contentSelectorWrapper', 'display-none' ); 1432 } else { 1433 contextElement.innerHTML = ''; 1434 PWM_MAIN.removeCssClass( 'contentSelectorWrapper', 'display-none' ); 1435 for (var iter in contextList) { 1436 (function (key) { 1437 var display = contextList[key]; 1438 var optionElement = document.createElement('option'); 1439 optionElement.setAttribute('value', key); 1440 optionElement.appendChild(document.createTextNode(display)); 1441 contextElement.appendChild(optionElement); 1442 }(iter)); 1443 } 1444 } 1445 } 1446}; 1447 1448//---------- show/hide password handler 1449
1450var ShowHidePasswordHandler = {}; 1451 1452ShowHidePasswordHandler.idSuffix = '-eye-icon'; 1453ShowHidePasswordHandler.state = {}; 1454ShowHidePasswordHandler.toggleRevertTimeout = 30 * 1000; //default value, overridden by settings. 1455ShowHidePasswordHandler.debugOutput = false; 1456 1457ShowHidePasswordHandler.initAllForms = function() { 1458 if (!PWM_GLOBAL['setting-showHidePasswordFields']) { 1459 return; 1460 } 1461 1462 PWM_MAIN.doQuery('.passwordfield',function(field){ 1463 if (field.id) { 1464 if (ShowHidePasswordHandler.debugOutput) PWM_MAIN.log('adding show/hide option on fieldID=' + field.id); 1465 ShowHidePasswordHandler.init(field.id); 1466 } 1467 }); 1468}; 1469 1470ShowHidePasswordHandler.init = function(nodeName) { 1471 if (!PWM_GLOBAL['setting-showHidePasswordFields']) { 1472 return; 1473 } 1474 1475 var node = PWM_MAIN.getObject(nodeName); 1476 if (!node) { 1477 return; 1478 } 1479 1480 ShowHidePasswordHandler.toggleRevertTimeout = PWM_GLOBAL['client.pwShowRevertTimeout'] || ShowHidePasswordHandler.toggleRevertTimeout; 1481 var eyeId = nodeName + ShowHidePasswordHandler.idSuffix; 1482 if (PWM_MAIN.getObject(eyeId)) { 1483 return; 1484 } 1485 1486 var defaultType = PWM_MAIN.JSLibrary.getAttribute(node, "type"); 1487 PWM_MAIN.JSLibrary.setAttribute(node, "data-originalType", defaultType); 1488 PWM_MAIN.JSLibrary.setAttribute(node, "data-managedByShowHidePasswordHandler","true"); 1489 1490 var divElement = document.createElement('div'); 1491 divElement.id = eyeId; 1492 divElement.onclick = function(){ShowHidePasswordHandler.toggle(nodeName)}; 1493 divElement.style.cursor = 'pointer'; 1494 divElement.style.visibility = 'hidden'; 1495 divElement.setAttribute('class','pwm-icon icon-showhidepassword'); 1496 node.parentNode.insertBefore(divElement, node.nextSibling); 1497 1498 ShowHidePasswordHandler.state[nodeName] = (defaultType === "password"); 1499 ShowHidePasswordHandler.setupTooltip(nodeName, false); 1500 ShowHidePasswordHandler.addInputEvents(nodeName); 1501}; 1502 1503ShowHidePasswordHandler.renderIcon = function(nodeName) { 1504 if (ShowHidePasswordHandler.debugOutput) PWM_MAIN.log("calling renderIcon on node " + nodeName); 1505 var node = PWM_MAIN.getObject(nodeName); 1506 var eyeId = nodeName + ShowHidePasswordHandler.idSuffix; 1507 var eyeNode = PWM_MAIN.getObject(eyeId); 1508 if (node && node.value && node.value.length > 0) { 1509 eyeNode.style.visibility = 'visible'; 1510 } else { 1511 eyeNode.style.visibility = 'hidden'; 1512 } 1513 eyeNode.className = eyeNode.className; //ie8 force-rendering hack 1514}; 1515 1516ShowHidePasswordHandler.toggle = function(nodeName) { 1517 if (ShowHidePasswordHandler.state[nodeName]) { 1518 ShowHidePasswordHandler.show(nodeName); 1519 } else { 1520 ShowHidePasswordHandler.hide(nodeName); 1521 } 1522}; 1523 1524ShowHidePasswordHandler.hide = function(nodeName) { 1525 ShowHidePasswordHandler.state[nodeName] = true; 1526 ShowHidePasswordHandler.changeInputTypeField(PWM_MAIN.getObject(nodeName),'password'); 1527 ShowHidePasswordHandler.setupTooltip(nodeName); 1528 ShowHidePasswordHandler.renderIcon(nodeName); 1529 var node = PWM_MAIN.getObject(nodeName); 1530 node.focus(); 1531}; 1532 1533ShowHidePasswordHandler.show = function(nodeName) { 1534 ShowHidePasswordHandler.state[nodeName] = false; 1535 ShowHidePasswordHandler.changeInputTypeField(PWM_MAIN.getObject(nodeName),'text'); 1536 ShowHidePasswordHandler.setupTooltip(nodeName); 1537 ShowHidePasswordHandler.renderIcon(nodeName); 1538 1539 var node = PWM_MAIN.getObject(nodeName); 1540 node.focus(); 1541 require(["dojo/dom-construct", "dojo/dom-attr"], function(domConstruct, attr) { 1542 var defaultType = attr.get(nodeName, "data-originalType"); 1543 if (defaultType === 'password') { 1544 setTimeout(function () { 1545 if (!ShowHidePasswordHandler.state[nodeName]) { 1546 ShowHidePasswordHandler.toggle(nodeName); 1547 } 1548 }, ShowHidePasswordHandler.toggleRevertTimeout); 1549 } 1550 }); 1551}; 1552 1553ShowHidePasswordHandler.addInputEvents = function(nodeName) { 1554 PWM_MAIN.addEventHandler(nodeName, "keyup, input", function(){ 1555 if (ShowHidePasswordHandler.debugOutput) PWM_MAIN.log("keypress event on node " + nodeName);
1556 ShowHidePasswordHandler.renderIcon(nodeName); 1557 ShowHidePasswordHandler.setupTooltip(nodeName); 1558 }); 1559 1560}; 1561 1562ShowHidePasswordHandler.changeInputTypeField = function(object, type) { 1563 require(["dojo","dojo/_base/lang", "dojo/dom", "dojo/dom-attr"], function(dojo, lang, dom, attr){ 1564 var newObject = null; 1565 if(dojo.isIE <= 8){ // IE doesn't support simply changing the type of object 1566 newObject = document.createElement(object.nodeName); 1567 newObject.type = type; 1568 if (object.size) newObject.size = object.size; 1569 if (object.value) newObject.value = object.value; 1570 if (object.name) newObject.name = object.name; 1571 if (object.id) newObject.id = object.id; 1572 if (object.className) newObject.className = object.className; 1573 if (object.disabled) newObject.disabled = object.disabled; 1574 if (object.readonly) newObject.readonly = object.readonly; 1575 if (object.data) newObject.data = object.data; 1576 } else { 1577 newObject = object; 1578 attr.set(newObject, "type", type); 1579 } 1580 1581 object.parentNode.replaceChild(newObject, object); 1582 ShowHidePasswordHandler.addInputEvents(object.id); 1583 return newObject; 1584 }); 1585}; 1586 1587ShowHidePasswordHandler.setupTooltip = function(nodeName) { 1588 if (ShowHidePasswordHandler.debugOutput) PWM_MAIN.log('begin setupTooltip'); 1589 var state = ShowHidePasswordHandler.state[nodeName]; 1590 var eyeNodeId = nodeName + ShowHidePasswordHandler.idSuffix; 1591 1592 if (state) { 1593 PWM_MAIN.showTooltip({id:eyeNodeId,text:PWM_MAIN.showString('Button_Show')}); 1594 PWM_MAIN.removeCssClass(eyeNodeId,"pwm-icon-eye-slash"); 1595 PWM_MAIN.addCssClass(eyeNodeId,"pwm-icon-eye"); 1596 if (ShowHidePasswordHandler.debugOutput) PWM_MAIN.log('set class to pwm-icon-eye'); 1597 } else { 1598 PWM_MAIN.showTooltip({id:eyeNodeId,text:PWM_MAIN.showString('Button_Hide')}); 1599 PWM_MAIN.removeCssClass(eyeNodeId,"pwm-icon-eye"); 1600 PWM_MAIN.addCssClass(eyeNodeId,"pwm-icon-eye-slash"); 1601 if (ShowHidePasswordHandler.debugOutput) PWM_MAIN.log('set class to pwm-icon-slash'); 1602 } 1603}; 1604 1605//---------- idle timeout handler 1606 1607PWM_MAIN.IdleTimeoutHandler = {}; 1608 1609PWM_MAIN.IdleTimeoutHandler.SETTING_LOOP_FREQUENCY = 1000; // milliseconds 1610PWM_MAIN.IdleTimeoutHandler.SETTING_WARN_SECONDS = 30; // seconds 1611PWM_MAIN.IdleTimeoutHandler.SETTING_POLL_SERVER_SECONDS = 10; // 1612PWM_MAIN.IdleTimeoutHandler.timeoutSeconds = 0; // idle timeout time permitted 1613PWM_MAIN.IdleTimeoutHandler.lastActivityTime = new Date(); // time at which we are "idled out" 1614PWM_MAIN.IdleTimeoutHandler.lastPingTime = new Date(); // date at which the last ping occured 1615PWM_MAIN.IdleTimeoutHandler.realWindowTitle = ""; 1616PWM_MAIN.IdleTimeoutHandler.warningDisplayed = false; 1617 1618PWM_MAIN.IdleTimeoutHandler.initCountDownTimer = function(secondsRemaining) { 1619 PWM_MAIN.IdleTimeoutHandler.timeoutSeconds = secondsRemaining; 1620 PWM_MAIN.IdleTimeoutHandler.lastPingTime = new Date(); 1621 PWM_MAIN.IdleTimeoutHandler.realWindowTitle = document.title; 1622 PWM_MAIN.IdleTimeoutHandler.resetIdleCounter(); 1623 setInterval(function(){PWM_MAIN.IdleTimeoutHandler.pollActivity()}, PWM_MAIN.IdleTimeoutHandler.SETTING_LOOP_FREQUENCY); //poll scrolling 1624 PWM_MAIN.addEventHandler(document, "click", function(){PWM_MAIN.IdleTimeoutHandler.resetIdleCounter()}); 1625 PWM_MAIN.addEventHandler(document, "keypress", function(){PWM_MAIN.IdleTimeoutHandler.resetIdleCounter()}); 1626 PWM_MAIN.addEventHandler(document, "scroll", function(){PWM_MAIN.IdleTimeoutHandler.resetIdleCounter()}); 1627}; 1628 1629PWM_MAIN.IdleTimeoutHandler.cancelCountDownTimer = function() { 1630 PWM_GLOBAL['idle_suspendTimeout'] = true; 1631}; 1632 1633PWM_MAIN.IdleTimeoutHandler.resetIdleCounter = function() { 1634 PWM_MAIN.IdleTimeoutHandler.lastActivityTime = new Date(); 1635 PWM_MAIN.IdleTimeoutHandler.closeIdleWarning(); 1636 PWM_MAIN.IdleTimeoutHandler.pollActivity(); 1637}; 1638 1639PWM_MAIN.IdleTimeoutHandler.pollActivity = function() { 1640 var secondsRemaining = PWM_MAIN.IdleTimeoutHandler.calcSecondsRemaining(); 1641 var idleDisplayString = PWM_MAIN.IdleTimeoutHandler.makeIdleDisplayString(secondsRemaining);
1642 var idleStatusFooter = PWM_MAIN.getObject("idle_status"); 1643 if (idleStatusFooter) { 1644 idleStatusFooter.firstChild.nodeValue = idleDisplayString; 1645 } 1646 1647 var warningDialogText = PWM_MAIN.getObject("IdleDialogWindowIdleText"); 1648 if (warningDialogText) { 1649 warningDialogText.firstChild.nodeValue = idleDisplayString; 1650 } 1651 1652 if (secondsRemaining < 0) { 1653 if (!PWM_GLOBAL['idle_suspendTimeout']) { 1654 PWM_GLOBAL['idle_suspendTimeout'] = true; 1655 var url = PWM_GLOBAL['url-logout'] + '?idle=true&url=' + encodeURIComponent(window.location.pathname); 1656 PWM_MAIN.gotoUrl(url); 1657 } else { 1658 try { PWM_MAIN.getObject('idle_wrapper').style.visibility = 'none'; } catch(e) { /* noop */ } 1659 } 1660 return; 1661 } 1662 1663 var pingAgoMs = (new Date()).getTime() - PWM_MAIN.IdleTimeoutHandler.lastPingTime.getTime(); 1664 if (pingAgoMs > (PWM_MAIN.IdleTimeoutHandler.timeoutSeconds - PWM_MAIN.IdleTimeoutHandler.SETTING_POLL_SERVER_SECONDS) * 1000) { 1665 PWM_MAIN.IdleTimeoutHandler.pingServer(); 1666 } 1667 1668 if (secondsRemaining < PWM_MAIN.IdleTimeoutHandler.SETTING_WARN_SECONDS) { 1669 if (!PWM_GLOBAL['idle_suspendTimeout']) { 1670 PWM_MAIN.IdleTimeoutHandler.showIdleWarning(); 1671 if (secondsRemaining % 2 === 0) { 1672 document.title = PWM_MAIN.IdleTimeoutHandler.realWindowTitle; 1673 } else { 1674 document.title = idleDisplayString; 1675 } 1676 } 1677 } 1678}; 1679 1680PWM_MAIN.IdleTimeoutHandler.pingServer = function() { 1681 PWM_MAIN.IdleTimeoutHandler.lastPingTime = new Date(); 1682 console.log("idle timeout ping at " + PWM_MAIN.IdleTimeoutHandler.lastPingTime.toISOString()); 1683 var pingURL = PWM_GLOBAL['url-command'] + "?processAction=idleUpdate&j=1"; 1684 PWM_MAIN.ajaxRequest(pingURL, function(){},{method:'POST',preventCache:true}); 1685}; 1686 1687PWM_MAIN.IdleTimeoutHandler.calcSecondsRemaining = function() { 1688 var timeoutTime = PWM_MAIN.IdleTimeoutHandler.lastActivityTime.getTime() + (PWM_MAIN.IdleTimeoutHandler.timeoutSeconds * 1000) 1689 var amount = timeoutTime - (new Date()).getTime(); 1690 amount = Math.floor(amount / 1000); 1691 return amount; 1692}; 1693 1694PWM_MAIN.IdleTimeoutHandler.makeIdleDisplayString = function(amount) { 1695 var output = PWM_MAIN.convertSecondsToDisplayTimeDuration(amount); 1696 output = PWM_MAIN.showString('Display_IdleTimeout') + " " + output; 1697 return output; 1698}; 1699 1700PWM_MAIN.IdleTimeoutHandler.showIdleWarning = function() { 1701 if (!PWM_MAIN.IdleTimeoutHandler.warningDisplayed) { 1702 PWM_MAIN.IdleTimeoutHandler.warningDisplayed = true; 1703 1704 var idleOverlayDiv = document.createElement('div'); 1705 idleOverlayDiv.setAttribute('id','idle-overlay'); 1706 document.body.appendChild(idleOverlayDiv); 1707 1708 var idleMsgDiv = document.createElement('div'); 1709 idleMsgDiv.setAttribute('id','idle-overlay-message'); 1710 idleMsgDiv.innerHTML = '<p>' + PWM_MAIN.showString('Display_IdleWarningMessage') + '</p><p><span id="IdleDialogWindowIdleText"> </span></p>'; 1711 document.body.appendChild(idleMsgDiv); 1712 1713 PWM_MAIN.addEventHandler('idle-overlay','click',function(){ 1714 idleOverlayDiv.parentNode.removeChild(idleOverlayDiv); 1715 idleMsgDiv.parentNode.removeChild(idleMsgDiv); 1716 }) 1717 } 1718}; 1719 1720PWM_MAIN.IdleTimeoutHandler.closeIdleWarning = function() { 1721 document.title = PWM_MAIN.IdleTimeoutHandler.realWindowTitle; 1722 PWM_MAIN.IdleTimeoutHandler.warningDisplayed = false; 1723}; 1724 1725PWM_MAIN.TimestampHandler = PWM_MAIN.TimestampHandler || {}; 1726PWM_MAIN.TimestampHandler.PreferencesKey = 'timestampLocalized'; 1727PWM_MAIN.TimestampHandler.ElementList = []; 1728 1729PWM_MAIN.TimestampHandler.initAllElements = function() { 1730 PWM_MAIN.doQuery(".timestamp",function(node){ 1731 PWM_MAIN.TimestampHandler.initElement(node); 1732 }); 1733}; 1734 1735PWM_MAIN.TimestampHandler.testIfStringIsTimestamp = function(input, trueFunction) { 1736 if (input && input.length > 0) { 1737 input = input.trim(); 1738 var timestamp = Date.parse(input); 1739 if (isNaN(timestamp) === false) { 1740 trueFunction(new Date(timestamp)); 1741 } 1742 } 1743}; 1744 1745PWM_MAIN.TimestampHandler.initElement = function(element) { 1746 if (!element) { 1747 return 1748 } 1749 1750 if (element.getAttribute('data-timestamp-init') === 'true') { 1751 return; 1752 } 1753 1754 require(["dojo"], function(dojo) { 1755 var innerText = dojo.attr(element, 'innerHTML'); 1756 innerText = innerText.trim(innerText); 1757 PWM_MAIN.TimestampHandler.testIfStringIsTimestamp(innerText, function () { 1758 element.setAttribute('data-timestamp-original', innerText); 1759 PWM_MAIN.addEventHandler(element, 'click', function(){ 1760 var LocalizedState = !PWM_MAIN.Preferences.readSessionStorage(PWM_MAIN.TimestampHandler.PreferencesKey,true); 1761 PWM_MAIN.Preferences.writeSessionStorage(PWM_MAIN.TimestampHandler.PreferencesKey, LocalizedState); 1762 PWM_MAIN.TimestampHandler.updateAllElements(); 1763 }); 1764 if (!dojo.hasClass(element,"timestamp")) { 1765 dojo.addClass(element,"timestamp"); 1766 } 1767 1768 element.setAttribute('data-timestamp-init', 'true'); 1769 PWM_MAIN.TimestampHandler.ElementList.push(element); 1770 PWM_MAIN.TimestampHandler.updateElement(element); 1771 }); 1772 }); 1773}; 1774 1775PWM_MAIN.TimestampHandler.updateAllElements = function() {
1776 PWM_MAIN.JSLibrary.forEachInArray(PWM_MAIN.TimestampHandler.ElementList,function(element){ 1777 if (document.body.contains(element)) { 1778 PWM_MAIN.TimestampHandler.updateElement(element); 1779 } else { 1780 PWM_MAIN.JSLibrary.removeFromArray(PWM_MAIN.TimestampHandler.ElementList,element); 1781 } 1782 }); 1783}; 1784 1785PWM_MAIN.TimestampHandler.updateElement = function(element) { 1786 require(["dojo"], function(dojo) { 1787 var localized = PWM_MAIN.Preferences.readSessionStorage(PWM_MAIN.TimestampHandler.PreferencesKey,true); 1788 if (localized) { 1789 var isoDateStr = element.getAttribute('data-timestamp-original'); 1790 var date = new Date(Date.parse(isoDateStr)); 1791 var localizedStr = PWM_MAIN.TimestampHandler.formatDate(date); 1792 1793 dojo.attr(element,'innerHTML',localizedStr); 1794 } else { 1795 dojo.attr(element,'innerHTML',element.getAttribute('data-timestamp-original')); 1796 } 1797 }) 1798}; 1799 1800PWM_MAIN.TimestampHandler.formatDate = function(dateObj) { 1801 var options = {timeZoneName:'short', year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric'}; 1802 var locale = PWM_GLOBAL['client.locale']; 1803 return dateObj.toLocaleString(locale, options); 1804}; 1805 1806PWM_MAIN.addPwmFormIDtoURL = function(url) { 1807 return PWM_MAIN.addParamToUrl(url,'pwmFormID',PWM_GLOBAL['pwmFormID']); 1808}; 1809 1810PWM_MAIN.addParamToUrl = function(url,paramName,paramValue) { 1811 if (!url || url.length < 1) { 1812 return url; 1813 } 1814 1815 if ( 1816 url.indexOf('?' + paramName + '=') > -1 1817 || url.indexOf('&' + paramName + '=') > -1) 1818 { 1819 console.warn('ignoring request to append duplicate param "' + paramName + '" to url ' + url); 1820 return url; 1821 } 1822 1823 var encodedName = encodeURIComponent(paramName); 1824 var encodedValue = encodeURIComponent(paramValue); 1825 1826 url += url.indexOf('?') > 0 ? '&' : '?'; 1827 url += encodedName + "=" + encodedValue; 1828 return url; 1829}; 1830 1831PWM_MAIN.ajaxRequest = function(url,loadFunction,options) { 1832 options = options === undefined ? {} : options; 1833 var content = 'content' in options ? options['content'] : null; 1834 var method = 'method' in options ? options['method'] : 'POST'; 1835 var responseMimeType = 'responseMimeType' in options ? options['responseMimeType'] : 'application/json'; 1836 var handleAs = 'handleAs' in options ? options['handleAs'] : 'json'; 1837 var errorFunction = 'errorFunction' in options ? options['errorFunction'] : function(error){ 1838 var status = error['response']['status']; 1839 if (status === 0 || status < 200 || status >= 300) { 1840 var msg = PWM_MAIN.showString("Display_ClientDisconnect") + " (" + status + ")"; 1841 PWM_MAIN.log(msg); 1842 PWM_MAIN.showErrorDialog(msg); 1843 } else { 1844 PWM_MAIN.showErrorDialog(error); 1845 } 1846 }; 1847 var hasContent = options['content'] !== null && options['content'] !== undefined; 1848 var preventCache = 'preventCache' in options ? options['preventCache'] : true; 1849 var addPwmFormID = 'addPwmFormID' in options ? options['addPwmFormID'] : true; 1850 var ajaxTimeout = options['ajaxTimeout'] ? options['ajaxTimeout'] : PWM_MAIN.ajaxTimeout; 1851 var requestHeaders = {}; 1852 requestHeaders['Accept'] = responseMimeType; 1853 if (hasContent) { 1854 requestHeaders['Content-Type'] = responseMimeType; 1855 } 1856 1857 if (addPwmFormID) { 1858 url = PWM_MAIN.addPwmFormIDtoURL(url); 1859 } 1860 if (preventCache) { 1861 url = PWM_MAIN.addParamToUrl(url, 'preventCache', (new Date).valueOf()); 1862 } 1863 1864 var xhr = new XMLHttpRequest(); 1865 xhr.onload = function() { 1866 if ( loadFunction === undefined ) { 1867 alert('missing load function, return results:' + xhr.response) 1868 } else { 1869 var response = xhr.response; 1870 // run parser for IE 1871 if ( typeof response === "string" && handleAs === "json") { 1872 response = JSON.parse( response ); 1873 } 1874 loadFunction(response); 1875 } 1876 }; 1877 xhr.onerror = errorFunction; 1878 xhr.ontimeout = errorFunction; 1879 xhr.open(method, url); 1880 xhr.responseType = handleAs; 1881 xhr.timeout = ajaxTimeout; 1882 1883 for (var headerKey in requestHeaders) { 1884 xhr.setRequestHeader( headerKey, requestHeaders[headerKey]); 1885 } 1886 1887 if ( hasContent ) { 1888 xhr.send( JSON.stringify( content ) ); 1889 } else { 1890 xhr.send(); 1891 } 1892}; 1893
1894PWM_MAIN.convertSecondsToDisplayTimeDuration = function(amount, fullLength) { 1895 if (amount < 1) { 1896 return ""; 1897 } 1898 1899 var output = ""; 1900 1901 var days = Math.floor(amount / 86400); 1902 1903 amount = amount % 86400; 1904 var hours = Math.floor(amount / 3600); 1905 1906 amount = amount % 3600; 1907 var mins = Math.floor(amount / 60); 1908 1909 amount = amount % 60; 1910 var secs = Math.floor(amount); 1911 1912 // write number of days 1913 var positions = 0; 1914 if (days !== 0) { 1915 output += days + " "; 1916 if (days !== 1) { 1917 output += PWM_MAIN.showString('Display_Days'); 1918 } else { 1919 output += PWM_MAIN.showString('Display_Day'); 1920 } 1921 positions++; 1922 } 1923 1924 // write number of hours 1925 if (days !== 0 || hours !== 0) { 1926 if (output.length > 0) { 1927 output += ", "; 1928 } 1929 1930 output += hours + " "; 1931 if (hours !== 1) { 1932 output += PWM_MAIN.showString('Display_Hours'); 1933 } else { 1934 output += PWM_MAIN.showString('Display_Hour'); 1935 } 1936 positions ++; 1937 } 1938 1939 // write number of minutes 1940 if (positions < 2 || fullLength) { 1941 if (days !== 0 || hours !== 0 || mins !== 0 || fullLength) { 1942 if (output.length > 0) { 1943 output += ", "; 1944 } 1945 output += mins + " "; 1946 if (mins !== 1) { 1947 output += PWM_MAIN.showString('Display_Minutes'); 1948 } else { 1949 output += PWM_MAIN.showString('Display_Minute'); 1950 } 1951 positions++; 1952 } 1953 } 1954 1955 // write number of seconds 1956 if (positions < 2 || fullLength) { 1957 if (mins < 4 || fullLength) { 1958 if (output.length > 0) { 1959 output += ", "; 1960 } 1961 1962 output += secs + " "; 1963 1964 if (secs !== 1) { 1965 output += PWM_MAIN.showString('Display_Seconds'); 1966 } else { 1967 output += PWM_MAIN.showString('Display_Second'); 1968 } 1969 } 1970 } 1971 1972 return output; 1973}; 1974 1975PWM_MAIN.setStyle = function(elementID, property, value) { 1976 1977 require(["dojo"],function(dojo) { 1978 if (dojo.isIE <= 8) { // IE8 and below cant handle the css associated with the locale select menu 1979 try { 1980 var element = PWM_MAIN.getObject(elementID); 1981 if (element) { 1982 element.style[property] = value; 1983 } 1984 } catch (e) { 1985 console.error('error while setting ie8 style, elementID=' + elementID + ", property=" + property + ", value=" + value + ", error: " + e); 1986 } 1987 } else { 1988 try { 1989 var element = PWM_MAIN.getObject(elementID); 1990 if (element) { 1991 element.style.setProperty(property, value, null); 1992 } 1993 } catch (e) { 1994 console.error('error while setting style, elementID=' + elementID + ", property=" + property + ", value=" + value + ", error: " + e); 1995 } 1996 } 1997 }); 1998}; 1999 2000PWM_MAIN.addCssClass = function(elementID, className) { 2001 var element = PWM_MAIN.getObject(elementID); 2002 if (element) { 2003 element.classList.add(className); 2004 } 2005}; 2006 2007PWM_MAIN.removeCssClass = function(elementID, className) { 2008 var element = PWM_MAIN.getObject(elementID); 2009 if (element) { 2010 element.classList.remove(className); 2011 } 2012}; 2013 2014PWM_MAIN.hasCssClass = function(elementID, className) { 2015 var element = PWM_MAIN.getObject(elementID); 2016 return element && element.classList.contains(className); 2017}; 2018 2019PWM_MAIN.newWindowOpen=function(windowUrl,windowName) { 2020 var windowParams = 'status=0,toolbar=0,location=0,menubar=0,scrollbars=1,resizable=1'; 2021 var viewLog = window.open(windowUrl,windowName,windowParams).focus(); 2022}; 2023 2024PWM_MAIN.cancelEvent = function(event) { 2025 if (event) { 2026 if (event.preventDefault) { 2027 event.preventDefault(); 2028 } else if (event.returnValue) { 2029 event.returnValue = false; 2030 } 2031 } 2032}; 2033 2034PWM_MAIN.submitPostAction = function(actionUrl,actionValue,additionalValues) { 2035 var fields = {}; 2036 fields['processAction'] = actionValue; 2037 fields['pwmFormID'] = PWM_GLOBAL['pwmFormID']; 2038 if (additionalValues) { 2039 var addValueFunction = function(key) { 2040 fields[key] = additionalValues[key]; 2041 }; 2042 for (var key in additionalValues) { 2043 addValueFunction(key); 2044 } 2045 } 2046 var makeFieldHtml = function() { 2047 var text = ''; 2048 var addField = function(key) { 2049 return '<input type="hidden" name="' + key + '" value="' + fields[key] + '"></input>'; 2050 }; 2051 for (var key in fields) { 2052 text += addField(key); 2053 } 2054 return text; 2055 }; 2056 var formElement = document.createElement('form'); 2057 formElement.setAttribute('id','form-jsSendAction'); 2058 formElement.setAttribute('action',actionUrl); 2059 formElement.setAttribute('method','post'); 2060 formElement.setAttribute('style','display:none'); 2061 formElement.innerHTML = makeFieldHtml(); 2062 document.body.appendChild(formElement); 2063 PWM_MAIN.handleFormSubmit(formElement); 2064}; 2065 2066PWM_MAIN.doQuery = function(queryString, resultFunction) { 2067 var results = document.querySelectorAll(queryString);
2068 PWM_MAIN.JSLibrary.forEachInArray(results,resultFunction); 2069}; 2070 2071PWM_MAIN.doIfQueryHasResults = function(queryString, trueFunction) { 2072 if (document.querySelector(queryString)) trueFunction(); 2073}; 2074 2075PWM_MAIN.stopEvent = function(e) { 2076 if (!e) var e = window.event; 2077 e.cancelBubble = true; 2078 if (e.stopPropagation) e.stopPropagation(); 2079}; 2080 2081PWM_MAIN.clearFocus = function() { 2082 document.activeElement.blur(); 2083}; 2084 2085PWM_MAIN.Preferences = {}; 2086PWM_MAIN.Preferences.StorageKeyName = 'preferences'; 2087PWM_MAIN.Preferences.Key_Timestamp = 'timestamp'; 2088PWM_MAIN.Preferences.Key_ExpireSeconds = 'expireSeconds'; 2089PWM_MAIN.Preferences.Key_Value = 'value'; 2090PWM_MAIN.Preferences.readLocalStorage = function(key,valueIfMissing) { 2091 if(typeof(Storage) !== "undefined") { 2092 try { 2093 var baseObjStr = localStorage.getItem(PWM_MAIN.Preferences.StorageKeyName); 2094 if (baseObjStr) { 2095 var baseJson = JSON.parse(baseObjStr); 2096 var wrappedValue = baseJson[key]; 2097 if (wrappedValue !== null) { 2098 var timestamp = new Date(Date.parse(wrappedValue[PWM_MAIN.Preferences.Key_Timestamp])); 2099 var expireSeconds = parseInt(wrappedValue[PWM_MAIN.Preferences.Key_ExpireSeconds]); 2100 var valueAgeSeconds = (new Date().getTime()) - timestamp.getTime(); 2101 if (valueAgeSeconds > (expireSeconds * 1000)) { 2102 delete baseJson[key]; 2103 localStorage.setItem(PWM_MAIN.Preferences.StorageKeyName,JSON.stringify(baseJson)); 2104 return valueIfMissing; 2105 } 2106 2107 return wrappedValue[PWM_MAIN.Preferences.Key_Value]; 2108 } 2109 } 2110 } catch (e) { 2111 PWM_MAIN.log("error reading locale storage preferences: " + e); 2112 } 2113 } else { 2114 PWM_MAIN.log("browser doesn't support local storage"); 2115 } 2116 return valueIfMissing; 2117}; 2118 2119PWM_MAIN.Preferences.writeLocalStorage = function(key, value, lifetimeSeconds) { 2120 if(typeof(Storage) !== "undefined") { 2121 try { 2122 var baseObjStr = localStorage.getItem(PWM_MAIN.Preferences.StorageKeyName); 2123 var baseJson = baseObjStr !== null ? JSON.parse(baseObjStr) : {}; 2124 var wrapperValue = {}; 2125 wrapperValue[PWM_MAIN.Preferences.Key_Timestamp] = new Date().toISOString(); 2126 wrapperValue[PWM_MAIN.Preferences.Key_ExpireSeconds] = lifetimeSeconds; 2127 wrapperValue[PWM_MAIN.Preferences.Key_Value] = value; 2128 baseJson[key] = wrapperValue; 2129 localStorage.setItem(PWM_MAIN.Preferences.StorageKeyName,JSON.stringify(baseJson)); 2130 } catch (e) { 2131 PWM_MAIN.log("error writing locale storage preferences: " + e); 2132 } 2133 } else { 2134 PWM_MAIN.log("browser doesn't support local storage"); 2135 } 2136}; 2137 2138PWM_MAIN.Preferences.readSessionStorage = function(key,valueIfMissing) { 2139 if(typeof(Storage) !== "undefined") { 2140 try { 2141 var baseObjStr = sessionStorage.getItem(PWM_MAIN.Preferences.StorageKeyName); 2142 if (baseObjStr !== null) { 2143 var baseJson = JSON.parse(baseObjStr); 2144 return key in baseJson ? baseJson[key] : valueIfMissing; 2145 } 2146 } catch (e) { 2147 PWM_MAIN.log("error reading session storage preferences: " + e); 2148 } 2149 } else { 2150 PWM_MAIN.log("browser doesn't support session storage"); 2151 } 2152 return valueIfMissing; 2153}; 2154 2155PWM_MAIN.Preferences.writeSessionStorage = function(key, value) { 2156 if(typeof(Storage) !== "undefined") { 2157 try { 2158 var baseObjStr = sessionStorage.getItem(PWM_MAIN.Preferences.StorageKeyName); 2159 var baseJson = baseObjStr !== null ? JSON.parse(baseObjStr) : {}; 2160 baseJson[key] = value; 2161 sessionStorage.setItem(PWM_MAIN.Preferences.StorageKeyName,JSON.stringify(baseJson)); 2162 } catch (e) { 2163 PWM_MAIN.log("error writing session storage preferences: " + e); 2164 } 2165 } else { 2166 PWM_MAIN.log("browser doesn't support session storage"); 2167 } 2168}; 2169
2170PWM_MAIN.copyObject = function(input) { 2171 return JSON.parse(JSON.stringify(input)); 2172}; 2173 2174PWM_MAIN.numberFormat = function (number) { 2175 try { 2176 return new Number(number).toLocaleString(); 2177 } catch (t) { 2178 PWM_MAIN.log('error localizing number value "' + number + '", error: ' + t); 2179 } 2180 2181 return number; 2182}; 2183 2184PWM_MAIN.pageLoadHandler(); 2185
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.