PageSourceSearch

https://rday11.com/resources/default/js/integration/tain-1_modestorion88.js

js rday11.com collected 2026-10-08 08:03:10 UTC 83,751 bytes, 2,611 lines download raw bytes

1iapiConf = {"casinoname":"modestorion88","loginServer":"login.modestorion88.com","imsLoginDomain":"modestorion88.com","clientSkin":"modestorion88","clientType":"casino","clientPlatform":"mobile","clientVersion":null,"systemId":"605","serviceType":"GamePlay","loginDomainRetryCount":"2","loginDomainRequestTimeout":"30","loginDomainRetryInterval":"1","fitToPlaySubmissionRequired":"0","onlypostrequestsforlogout":"1","fidoAuth":"0"};
2 function replaceImsDomain() {
3
4    if (!iapiConf || !iapiConf['imsLoginDomain']) {
5        return;
6    }
7
8    for (var key in iapiConf) {
9        var val = iapiConf[key];
10        if (typeof (val) === "string" && val.indexOf("http")>=0 && val.indexOf("$imsLoginDomain") > 0 ) {
11            val = val.replace("$imsLoginDomain", iapiConf['imsLoginDomain']);
12            iapiConf[key] = val;
13        }
14    }
15}
16
17replaceImsDomain();
18
19var iapiVersion = "_version_";
20
21var iapiERR_OK = 0;
22var iapiERR_NOK = -1;
23var iapiERR_BLOCKED = -2;
24
25var iapiCALLOUT_LOGIN = 'Login';
26var iapiCALLOUT_EMAILLOGIN = 'EmailLogin';
27var iapiCALLOUT_TEMPORARYTOKEN = 'GetTemporaryAuthenticationToken';
28var iapiCALLOUT_LOGINANDGETTEMPTOKEN = 'LoginAndGetTempToken';
29var iapiCALLOUT_EMAILLOGINANDGETTEMPTOKEN = 'EmailLoginAndGetTempToken';
30var iapiCALLOUT_SESSIONVALIDATION = 'ValidateLoginSession';
31var iapiCALLOUT_MESSAGES = 'GetWaitingMessages';
32var iapiCALLOUT_SUBMITDIALOG = 'SubmitDialog';
33var iapiCALLOUT_FORGOTPASSWORD = 'ForgotPassword';
34var iapiCALLOUT_STARTFORGOTEMAIL = 'StartForgotEamil';
35var iapiCALLOUT_COMPLETEFORGOTEMAIL = 'CompleteForgotEmail';
36var iapiCALLOUT_ONLINEFORGOTPASSWORD = 'OnlineForgotPassword';
37var iapiCALLOUT_GETLOGGEDINPLAYER = 'GetLoggedInPlayer';
38var iapiCALLOUT_KEEPALIVE = 'KeepAlive';
39var iapiCALLOUT_LOGOUT = 'Logout';
40var iapiCALLOUT_GETURLS = 'GetUrls';
41var iapiCALLOUT_RESENDLOGIN2FATOKEN = 'ResendLogin2FAToken';
42
43var iapiEVENT_TIMER = 10;
44
45var STOCK_AUTH_PHONE_NUMBER = "pinAuth888";
46
47var iapiUsername = null; // remember username
48var iapiPassword = null; // remember password, at least temporary
49var iapiEmail = null; // remember email
50var iapiAdminUsername = null;
51var iapiRealMode = 1; // real mode for login
52var iapiAuthenticationType = null; // remember authentication type
53var iapiDivname = 'iapidiv'; // div name
54var iapiIframename = 'iapiiframe'; // iframe name
55var iapiRealCookieIframe = 'iapirealcookieiframe'; // client cookie realmode iframe name
56var iapiFunCookieIframe = 'iapifuncookieiframe'; // client cookie funmode iframe name
57var iapiGetLoggedInPlayerRequestIdReal = 1234567890; // get logged in player request id is fixed, real
58var iapiGetLoggedInPlayerRequestIdFun = 9876543210; // get logged in player request id is fixed, fun
59var iapiClientParams = []; // defined by integration page
60var iapiWaitingMessagesId = 0; // to remember waiting messages requestId
61var iapiRememberMeLogin = null;
62
63var iapiCalloutFunctions = []; // defined by integration page
64var iapiRequestIds = []; // id's and callout types for requests
65
66var iapiLoginSuccess = false; // login success
67var iapiSessionValid = 0; // session valid (from login)
68
69var iapiNextLogin = null; // if login is in progress, then remember next login
70
71var iapiLoginModeDownload = false; // when download login is in progress
72var iapiLoginModeFlash = false; // when flash login is in progress
73var iapiFlashLoginClientType = null; // remember flash login client type
74var iapiFlashLoginGameType = null; // remember flash login game type
75
76var iapiMessagesSupported = false; // support receiving messages
77var iapiMessagesAnswered = false; // support sending messages to php scripts
78
79// enum, list of available authentication types
80var iapiLoginTypes = Object.freeze(
81    {
82        SESSION_TOKEN      : 'sessionToken',
83        CRYPTO_TOKEN       : 'cryptoToken',
84        EXTERNAL_TOKEN     : 'externalToken',
85        ADMIN_USERNAME     : 'adminUsername',
86        NICKNAME           : 'nickname',
87        EMAIL              : 'email',
88        TOKEN_CODE         : 'tokenCode',
89        PRINTED_TOKEN_CODE : 'printedTokenCode',
90        USERNAME_AND_PIN   : 'usernameAndPin',
91        TOKEN_CODE_AND_PASS: 'tokenCodeAndPass',
92        PASSWORD           : 'password'
93    });
94
95// public, login with username and password, and realMode (1/0) and language code in lowercase
96function iapiLogin(user, pass, realMode, language, rememberMeLogin)
97{
98    iapiLoginModeDownload = false;
99    iapiLoginModeFlash = false;
100    iapiAuthenticationType = iapiConf['authenticationType'];
101    iapiBaseLogin(user, pass, realMode, language, rememberMeLogin);
102    return iapiERR_OK;
103};
104function iapiEmailLogin(email, pass, realMode, language, rememberMeLogin)
105{
106    iapiLoginModeDownload = false;
107    iapiLoginModeFlash = false;
108    iapiAuthenticationType = iapiLoginTypes.EMAIL;
109
110    iapiBaseLogin(email, pass, realMode, language, rememberMeLogin);
111    return iapiERR_OK;
112};
113
114// public, login with external token, and realMode (1/0) and language code in lowercase
115function iapiLoginExternalToken(token, realMode, language, rememberMeLogin)
116{
117    iapiLoginModeDownload = false;
118    iapiLoginModeFlash = false;
119    iapiAuthenticationType = iapiLoginTypes.EXTERNAL_TOKEN;
120    iapiBaseLogin(null, token, realMode, language, rememberMeLogin);
121    return iapiERR_OK;
122}
123function iapiLoginUsernameExternalToken(user, token, realMode, language, rememberMeLogin)
124{
125    iapiLoginModeDownload = false;
126    iapiLoginModeFlash = false;
127    iapiAuthenticationType = iapiLoginTypes.EXTERNAL_TOKEN;
128    iapiBaseLogin(user, token, realMode, language, rememberMeLogin);
129    return iapiERR_OK;
130}
131
132// public, login with admin username, token, realMode (1/0), language code in lowercase and player username
133function iapiLoginAdminUsername(adminUser, token, realMode, language, user)
134{
135    iapiLoginModeDownload = false;
136    iapiLoginModeFlash = false;
137    iapiAuthenticationType = iapiLoginTypes.ADMIN_USERNAME;
138    iapiAdminUsername = adminUser;
139    iapiBaseLogin(user, token, realMode, language);
140    return iapiERR_OK;
141}
142
143// public, login with session token, and realMode (1/0) and language code in lowercase
144function iapiLoginSessionToken(token, realMode, language)
145{
146    iapiLoginModeDownload = false;
147    iapiLoginModeFlash = false;
148    iapiAuthenticationType = iapiLoginTypes.SESSION_TOKEN;
149    iapiBaseLogin(null, token, realMode, language);
150    return iapiERR_OK;
151}
152
153// public, login with crypto token and language code in lowercase
154function iapiLoginCryptoToken(cryptoToken, language)
155{
156    iapiLoginModeDownload = false;
157    iapiLoginModeFlash = false;
158    iapiAuthenticationType = iapiLoginTypes.CRYPTO_TOKEN;
159    iapiBaseLogin(null, cryptoToken, 1, language);
160    return iapiERR_OK;
161}
162
163// public, login with nickname, password, realMode (1/0) and language code in lowercase
164function iapiLoginNickname(nickname, pass, realMode, language)
165{
166    iapiLoginModeDownload = false;
167    iapiLoginModeFlash = false;
168    iapiAuthenticationType = iapiLoginTypes.NICKNAME;
169    iapiBaseLogin(nickname, pass, realMode, language);
170    return iapiERR_OK;
171};
172
173function iapiLoginIdTokenCodeAndPin(tokenCode, pin, language, rememberMeLogin)
174{
175    iapiLoginModeDownload = false;
176    iapiLoginModeFlash = false;
177    iapiAuthenticationType = iapiLoginTypes.TOKEN_CODE;
178    iapiBaseLogin(tokenCode, pin, 1, language, rememberMeLogin);
179    return iapiERR_OK;
180};
181
182function iapiLoginPrintedIdTokenCodeAndPin(printedTokenCode, pin, language, rememberMeLogin)
183{
184    iapiLoginModeDownload = false;
185    iapiLoginModeFlash = false;
186    iapiAuthenticationType = iapiLoginTypes.PRINTED_TOKEN_CODE;
187    iapiBaseLogin(printedTokenCode, pin, 1, language, rememberMeLogin);
188    return iapiERR_OK;
189};
190
191function iapiLoginUsernameAndPin(user, pin, language, rememberMeLogin)
192{
193    iapiLoginModeDownload = false;
194    iapiLoginModeFlash = false;
195    iapiAuthenticationType = iapiLoginTypes.USERNAME_AND_PIN;
196    iapiBaseLogin(user, pin, 1, language, rememberMeLogin);
197    return iapiERR_OK;
198};
199
200function iapiLoginIdTokenCodeAndPassword(tokenCode, pass, language)
201{
202    iapiLoginModeDownload = false;
203    iapiLoginModeFlash = false;
204    iapiAuthenticationType = iapiLoginTypes.TOKEN_CODE_AND_PASS;
205    iapiBaseLogin(tokenCode, pass, 1, language);
206    return iapiERR_OK;
207};
208
209// public, open client window, clientMode is one of ('real', 'fun', 'offline'),
210// windowName (optional), if window or iframe already exists the game is opened there, if no then new window is opened with this name
211// windowWidth and windowHeight can be given to override window size values from conf, use -1,-1 to open window in fullscreen
212function iapiLaunchClient(clientType, gameType, clientMode, windowName, windowWidth, windowHeight)
213{
214    // create url
215    var url = iapiConf['clientUrl_' + clientType];
216    if (url){
217        if (gameType) {
218            url = iapiAddUrlParams(url, 'game=' + gameType);
219        }
220
221        if (clientMode) {
222            url = iapiAddUrlParams(url, 'preferedmode=' + clientMode);
223        }
224
225        // set additional client params
226        if (iapiClientParams['clientParams_' + clientType])
227        {
228            url = iapiAddUrlParams(url, iapiClientParams['clientParams_' + clientType]);
229        }
230
231        if (url.indexOf('$domain')>=0 || url.indexOf('<domain>')>=0) {
232            var domain = getCurrentDomain();
233            url = url.replace("$domain", domain);
234            url = url.replace("<domain>", domain);
235        }
236
237        if (iapiLoginModeFlash)
238        {
239            document.location = url;
240            return;
241        }
242
243        // window sizes from conf, default 800x600
244        var sizeStr = 'width=800,height=600';
245        if (windowWidth != undefined && windowHeight != undefined)
246        {
247            if (windowWidth == -1 && windowHeight == -1)
248            {
249                sizeStr = '';
250                // for IE and safari set position
251                if (navigator.appName == 'Microsoft Internet Explorer'
252                    || (navigator.userAgent.indexOf('Safari') >= 0 && navigator.userAgent.indexOf('Chrome') < 0))
253                {
254                    sizeStr = 'left=0,top=0,';
255                };
256                var availWidth = screen.width;
257                var availHeight = screen.height;
258                if (screen.availWidth != undefined)
259                {
260                    availWidth = screen.availWidth;
261                    availHeight = screen.availHeight;
262                }
263                if (typeof (innerWidth) == 'number' && typeof (outerWidth) == 'number')
264                {
265                    availWidth -= (outerWidth - innerWidth);
266                    availHeight -= (outerWidth - innerWidth);
267                }
268
269                sizeStr += 'width=' + availWidth + ',height=' + availHeight;
270            }
271            else
272            {
273                sizeStr = 'width=' + windowWidth + ',height=' + windowHeight;
274            };
275        }
276        else if (iapiConf['windowSize_' + clientType])
277        {
278            var sizeIndex = iapiConf['windowSize_' + clientType][gameType];
279            if (sizeIndex == undefined)
280            {
281                sizeIndex = iapiConf['windowSize_' + clientType]['default'];
282            };
283            if (sizeIndex != undefined && iapiConf['windowSizes'][sizeIndex])
284            {
285                sizeStr = iapiConf['windowSizes'][sizeIndex];
286            };
287        };
288
289        if (windowName != null && windowName.length > 0)
290        {
291            var w = document.getElementById(windowName);
292            if (w)
293            {
294                w.src = url;
295                return iapiERR_OK;
296            };
297        }
298        else
299        {
300            windowName = '';
301        }
302
303        var par = 'toolbar=no,menubar=no,scrollbars=no,resizable=no';
304        if (iapiConf['windowParams_' + clientType])
305        {
306            par = iapiConf['windowParams_' + clientType];
307        };
308        windowParams = sizeStr + ',' + par;
309        var win = window.open(url, windowName, windowParams);
310        // if popup blocked window
311        if (win == null || win.closed)
312        {
313            return iapiERR_BLOCKED;
314        };
315
316        return iapiERR_OK;
317    }
318    return iapiERR_NOK;
319};
320
321// public, set additional parameters for client, params is parameters string in format "param1=value1&...&paramn=valuen"
322function iapiSetClientParams(clientType, params)
323{
324    iapiClientParams['clientParams_' + clientType] = params;
325};
326
327function NoSystemId(){}
328NoSystemId.prototype.toString = function empty(){return '';}
329var noSystemId = new NoSystemId();
330
331// public, request temporary token, realMode (1/0), system id (int) optional, serviceType (String) optional, inheritance (String) optional
332function iapiRequestTemporaryToken(realMode, systemId, serviceType, inheritance, label)
333{
334    var requestUrl = 'GetTemporaryAuthenticationToken.php?' + 'casinoname=' + iapiConf['casinoname'];
335
336    if (serviceType != undefined)
337    {
338        requestUrl += '&serviceType=' + serviceType;
339    }
340    else
341    {
342        requestUrl += '&serviceType=' + iapiConf['serviceType'];
343    };
344
345    if (0 === systemId || 0 === parseInt(systemId)){
346        systemId = undefined;
347    } else if (!systemId){//null/empty string come  here
348        systemId = iapiConf['systemId'];
349    } else if (!new String(systemId).toString()){
350        systemId = undefined;
351    }
352
353    if (systemId){
354        requestUrl += '&systemId=' + systemId;
355    };
356    if (inheritance) {
357        requestUrl += '&inheritance=' + inheritance;
358    }
359
360    if (realMode != undefined)
361    {
362        requestUrl += '&realMode=' + realMode;
363    };
364
365
366    if (label != undefined) {
367        requestUrl += '&label=' + label;
368    }
369
370
371    iapiMakeRedirectRequest(requestUrl, null, iapiCALLOUT_TEMPORARYTOKEN);
372
373    return iapiERR_OK;
374};
375
376// public, login and request temporary token, username, password, realMode (1/0), language, systemId (int) optional, serviceType (String) optional, rememberMeLogin (1/0) optional, inheritance (String) optional
377function iapiLoginAndGetTempToken(user, pass, realMode, language, systemId, serviceType, rememberMeLogin, inheritance)
378{
379    iapiClearRedirectRequests(iapiCALLOUT_LOGINANDGETTEMPTOKEN, realMode);
380
381    if (0 === systemId || 0===parseInt(systemId)){
382        systemId = undefined;
383    } else if (!systemId){//null/empty string come  here
384        systemId = iapiConf['systemId'];
385    } else if (!new String(systemId).toString()){
386        systemId = undefined;
387    }
388
389    if (!serviceType)
390    {
391        serviceType = iapiConf['serviceType'];
392    };
393
394    if (language)
395    {
396        iapiSetLanguageCode(language);
397    }
398
399    // login params
400    var requestUrl = 'LoginAndGetTempToken.php?' + 'casinoname=' + iapiConf['casinoname'] + '&realMode=' + realMode + '&serviceType=' + serviceType;
401
402    if (systemId)
403        requestUrl +='&systemId=' + systemId;
404
405    if (rememberMeLogin == 1)
406    {
407        requestUrl += '&rememberMeLogin=1';
408    }
409    if (inheritance)
410    {
411        requestUrl += '&inheritance=' + inheritance;
412    }
413    // login post data
414    var params = [];
415
416    if (iapiConf['challengeResponseToken']) {
417        params['challengeResponseToken'] = iapiConf['challengeResponseToken']
418        iapiConf['challengeResponseToken'] = ""
419    }
420
421    iapiAuthenticationType = iapiConf['authenticationType'];
422
423    if (iapiAuthenticationType == iapiLoginTypes.EXTERNAL_TOKEN)
424    {
425        if (user)
426        {
427            params['username'] = user;
428        }
429        params['externalToken'] = pass;
430        if (iapiConf['italyAamsSessionCode']) {
431            params['italyAamsSessionCode'] = iapiConf['italyAamsSessionCode'];
432        }
433        if (iapiConf['italyParticipationCode']) {
434            params['italyParticipationCode'] = iapiConf['italyParticipationCode'];
435        }
436        if (iapiConf['italyExternalGameTableSessionCode']) {
437            params['italyExternalGameTableSessionCode'] = iapiConf['italyExternalGameTableSessionCode'];
438        }
439    }
440    else if (iapiAuthenticationType == iapiLoginTypes.SESSION_TOKEN)
441    {
442        params['sessionToken'] = pass;
443    }
444    else if (iapiAuthenticationType == iapiLoginTypes.ADMIN_USERNAME)
445    {
446        if (user)
447        {
448            params['adminUsername'] = user;
449        }
450        params['externalToken'] = pass;
451    }
452    else if (iapiAuthenticationType == iapiLoginTypes.NICKNAME)
453    {
454        params['nickname'] = user;
455        params['password'] = pass;
456        params['systemId'] = systemId;
457    }
458    else if (iapiAuthenticationType == iapiLoginTypes.EMAIL)
459    {
460        if (user)
461        {
462            params['email'] = user;
463        }
464        params['password'] = pass;
465
466        if (iapiConf['iovationBlackbox']) {
467            params['iovationBlackbox'] = iapiConf['iovationBlackbox'];
468        }
469    }
470    else
471    {
472        params['username'] = user;
473        params['password'] = pass;
474
475        if (iapiConf['iovationBlackbox']) {
476            params['iovationBlackbox'] = iapiConf['iovationBlackbox'];
477        }
478        if (iapiConf['italyAamsSessionCode']) {
479            params['italyAamsSessionCode'] = iapiConf['italyAamsSessionCode'];
480        }
481        if (iapiConf['italyParticipationCode']) {
482            params['italyParticipationCode'] = iapiConf['italyParticipationCode'];
483        }
484        if (iapiConf['italyExternalGameTableSessionCode']) {
485            params['italyExternalGameTableSessionCode'] = iapiConf['italyExternalGameTableSessionCode'];
486        }
487    };
488
489    iapiAddClientHintsAndContinue(requestUrl, params, iapiCALLOUT_LOGINANDGETTEMPTOKEN);
490    return iapiERR_OK;
491};
492function iapiEmailLoginAndGetTempToken(email, pass, realMode, language, systemId, serviceType, rememberMeLogin, inheritance)
493{
494    iapiConf['authenticationType'] = iapiLoginTypes.EMAIL;
495    iapiLoginAndGetTempToken(email, pass, realMode, language, systemId, serviceType, rememberMeLogin, inheritance);
496    iapiConf['authenticationType'] = null;
497}
498
499// public, login with external token and request temporary token,
500// Parameters: username, externalToken, realMode (1/0), language, systemId (int) optional, serviceType (String) optional, rememberMeLogin (1/0) optional, inheritance (String) optional
501function iapiLoginExternalTokenAndGetTempToken(user, externalToken, realMode, language, systemId, serviceType, rememberMeLogin, inheritance)
502{
503    iapiConf['authenticationType'] = iapiLoginTypes.EXTERNAL_TOKEN;
504    iapiLoginAndGetTempToken(user, externalToken, realMode, language, systemId, serviceType, rememberMeLogin, inheritance)
505    iapiConf['authenticationType'] = null;
506};
507
508// public, make login and temptoken and call necessary htcmd, realMode (1/0), language code in lowercase
509function iapiDownloadLogin(user, pass, realMode, language)
510{
511    iapiAuthenticationType = null;
512    iapiLoginModeDownload = true;
513    iapiLoginModeFlash = false;
514    iapiBaseLogin(user, pass, realMode, language);
515    return iapiERR_OK;
516};
517function iapiDownloadEmailLogin(email, pass, realMode, language)
518{
519    iapiAuthenticationType = iapiLoginTypes.EMAIL;
520    iapiLoginModeDownload = true;
521    iapiLoginModeFlash = false;
522    iapiBaseLogin(email, pass, realMode, language);
523    return iapiERR_OK;
524};
525
526// public, make login and redirect to weblogin or client
527function iapiFlashLogin(user, pass, realMode, language, clientType, gameType)
528{
529    iapiAuthenticationType = null;
530    iapiLoginModeFlash = true;
531    iapiLoginModeDownload = false;
532    iapiFlashLoginClientType = clientType;
533    iapiFlashLoginGameType = gameType;
534    iapiBaseLogin(user, pass, realMode, language);
535    return iapiERR_OK;
536};
537function iapiFlashEmailLogin(email, pass, realMode, language, clientType, gameType)
538{
539    iapiAuthenticationType = iapiLoginTypes.EMAIL;
540    iapiLoginModeFlash = true;
541    iapiLoginModeDownload = false;
542    iapiFlashLoginClientType = clientType;
543    iapiFlashLoginGameType = gameType;
544    iapiBaseLogin(email, pass, realMode, language);
545    return iapiERR_OK;
546};
547
548// public, logout allSessions(0/1), realMode (1/0), behaviour(this, all, hierarchical), invalidateRememberMe (1/0), supportedFeatures (comma separated list)
549function iapiLogout(allSessions, realMode, behaviour, invalidateRememberMe, supportedFeatures, label)
550{
551    iapiUsername = null;
552    iapiPassword = null;
553    iapiEmail    = null;
554
555    iapiClearRedirectRequests(iapiCALLOUT_LOGIN, realMode);
556
557    // params for POST request
558    var params = [];
559
560    // write cookie for real and fun mode
561    if (realMode == 1)
562    {
563        iapiWriteClientCookie('loginSuccess=0&errorCode=0&expire=-1', 1);
564    }
565    else
566    {
567        iapiWriteClientCookie('loginSuccess=0&errorCode=0&expire=-1', 0);
568    };
569
570    if (behaviour == undefined)
571    {
572        if (allSessions == 1)
573        {
574            behaviour = 'all';
575        }
576        else
577        {
578            behaviour = 'this';
579        }
580    };
581
582    var requestUrl = 'Logout.php?' + 'allSessions=' + allSessions + '&casinoname=' + iapiConf['casinoname'] + '&behaviour=' + behaviour;
583    params['allSessions'] = allSessions;
584    params['casinoname'] = iapiConf['casinoname'];
585    params['behaviour'] = behaviour;
586
587    if (realMode != undefined)
588    {
589        requestUrl += '&realMode=' + realMode;
590        params['realMode'] = realMode;
591    };
592
593    if (invalidateRememberMe == 1)
594    {
595        requestUrl += '&invalidateRememberMe=1';
596        params['invalidateRememberMe'] = 1;
597    }
598
599    if (supportedFeatures != undefined)
600    {
601        requestUrl += '&supportedFeatures=' + encodeURIComponent(supportedFeatures);
602        params['supportedFeatures'] = supportedFeatures;
603    }
604
605    if (label != undefined) {
606        requestUrl += '&label=' + label;
607        params['label'] = label;
608    }
609
610    if (iapiConf['onlypostrequestsforlogout'])
611    {
612        // POST request
613        iapiMakeRedirectRequest(requestUrl, params, iapiCALLOUT_LOGOUT);
614    }
615    else
616    {
617        // GET request
618        iapiMakeRedirectRequest(requestUrl, null, iapiCALLOUT_LOGOUT);
619    }
620
621    return iapiERR_OK;
622};
623
624// public, callout functionality, example: iapiSetCallout(iapiCALLOUT_FORGOTPASSWORD, myCalloutForgotPasswordFunction);
625function iapiSetCallout(id, func)
626{
627    iapiCalloutFunctions[id] = func;
628    return iapiERR_OK;
629};
630
631// public, request waiting messages, messageTypes is comma separated string IN(login, bonus, alert, bonus:2, logout, before_logout), realMode (1/0)
632function iapiGetWaitingMessages(messageTypes, realMode)
633{
634    iapiClearRedirectRequests(iapiCALLOUT_MESSAGES, 0);
635    iapiClearRedirectRequests(iapiCALLOUT_MESSAGES, 1);
636
637    if (!messageTypes)
638    {
639        messageTypes = 'login,bonus,alert';
640    };
641
642    var requestUrl = 'GetWaitingMessages.php?' + 'messageTypes=' + messageTypes + '&casinoname=' + iapiConf['casinoname'] + '&realMode=' + realMode;
643
644    iapiMakeRedirectRequest(requestUrl, null, iapiCALLOUT_MESSAGES);
645
646    return iapiERR_OK;
647};
648
649// public, submit accept pending limits dialog, action in ['accept', 'cancel'], realMode (1/0)
650function iapiAcceptPendingLimits(action, realMode)
651{
652    var requestUrl = 'SubmitDialog.php?' + 'dialogType=' + 'AcceptPendingLimits' + '&casinoname=' + iapiConf['casinoname'];
653
654    if (realMode != undefined)
655    {
656        requestUrl += '&realMode=' + realMode;
657    };
658
659    var params = [];
660    params['action'] = action;
661
662    iapiMakeRedirectRequest(requestUrl, params, iapiCALLOUT_SUBMITDIALOG);
663
664    return iapiERR_OK;
665};
666
667// public, submit bonus confirmation dialog, bonusIdentifier is identifier from message, accept (1/0), realMode (1/0)
668function iapiBonusConfirmation(bonusIdentifier, accept, realMode)
669{
670    var requestUrl = 'SubmitDialog.php?' + 'dialogType=' + 'BonusConfirmation' + '&casinoname=' + iapiConf['casinoname'];
671
672    if (realMode != undefined)
673    {
674        requestUrl += '&realMode=' + realMode;
675    };
676
677    var params = [];
678    params['bonusIdentifier'] = bonusIdentifier;
679    if (accept)
680    {
681        params['accept'] = 1;
682    }
683    else
684    {
685        params['accept'] = 0;
686    };
687
688    iapiMakeRedirectRequest(requestUrl, params, iapiCALLOUT_SUBMITDIALOG);
689
690    return iapiERR_OK;
691};
692
693// public, accept terms and conditions, reference is tc version from login or validate login session response, accept (1/0), realMode (deprecated)
694function iapiValidateTCVersion(reference, accept, realMode) {
695    const requestUrl = 'ValidateLoginSession.php?' + 'validationType=' + 'TCVersion' + '&casinoname=' + iapiConf['casinoname'];
696
697    const params = [];
698    params['termVersionReference'] = reference;
699    if (accept)
700    {
701        params['accept'] = 1;
702    }
703    else
704    {
705        params['accept'] = 0;
706    }
707
708    iapiMakeRedirectRequest(requestUrl, params, iapiCALLOUT_SESSIONVALIDATION);
709
710    return iapiERR_OK;
711}
712
713function iapiValidateGeolocation(latitude, longitude, geoPacket, transactionId, error, geolocationType, metadata) {
714    const params = [];
715
716    params['latitude'] = latitude;
717    params['longitude'] = longitude;
718    params['geopacket'] = geoPacket;
719    params['transactionId'] = transactionId;
720    params['error'] = error;
721    params['geolocationType'] = geolocationType;
722    params['metadata'] = metadata;
723
724    for (let k in params) if (params[k] === null || params[k] === undefined) delete params[k]; //get rid of empty values
725
726    const requestUrl = 'ValidateLoginSession.php?' + 'validationType=Geolocation' + '&casinoname=' + iapiConf['casinoname'];
727
728    iapiMakeRedirectRequest(requestUrl, params, iapiCALLOUT_SESSIONVALIDATION);
729
730    return iapiERR_OK;
731}
732
733// public, validate password change, oldPassword, newPassword, changePassword (1/0) if 1 then player’s password is also physically changed, realMode (deprecated)
734function iapiValidatePasswordChange(oldPassword, newPassword, changePassword, realMode) {
735    const requestUrl = 'ValidateLoginSession.php?' + 'validationType=' + 'PasswordChange' + '&casinoname=' + iapiConf['casinoname'];
736
737    const params = [];
738    params['oldPassword'] = oldPassword;
739    params['newPassword'] = newPassword;
740    if (changePassword)
741    {
742        params['changePassword'] = 1;
743    }
744
745    iapiMakeRedirectRequest(requestUrl, params, iapiCALLOUT_SESSIONVALIDATION);
746
747    return iapiERR_OK;
748}
749
750// public, validate player confirmation token; parameter (string), realMode (deprecated)
751function iapiValidateConfirmationToken(parameter, realMode) {
752    const requestUrl = 'ValidateLoginSession.php?' + 'validationType=' + 'ConfirmationToken' + '&casinoname=' + iapiConf['casinoname'];
753
754    const params = [];
755    params['parameter'] = parameter;
756
757    iapiMakeRedirectRequest(requestUrl, params, iapiCALLOUT_SESSIONVALIDATION);
758
759    return iapiERR_OK;
760}
761
762// public, validate player birthdate token; birthdate (yyyy-MM-dd), realMode (deprecated)
763function iapiValidateBirthdateToken(birthdate, realMode) {
764    const requestUrl = 'ValidateLoginSession.php?' + 'validationType=' + 'Birthdate' + '&casinoname=' + iapiConf['casinoname'];
765
766    const params = [];
767    params['birthdate'] = birthdate;
768
769    iapiMakeRedirectRequest(requestUrl, params, iapiCALLOUT_SESSIONVALIDATION);
770
771    return iapiERR_OK;
772}
773
774// public, validate player activation code; activationCode (string), realMode (deprecated)
775function iapiValidateActivationCode(activationCode, realMode) {
776    const requestUrl = 'ValidateLoginSession.php?' + 'validationType=' + 'ActivationCode' + '&casinoname=' + iapiConf['casinoname'];
777
778    const params = [];
779    params['activationCode'] = activationCode;
780
781    iapiMakeRedirectRequest(requestUrl, params, iapiCALLOUT_SESSIONVALIDATION);
782
783    return iapiERR_OK;
784}
785
786function iapiValidatePinChange(oldPin, newPin) {
787    const requestUrl = 'ValidateLoginSession.php?' + 'validationType=' + 'PINChange' + '&casinoname=' + iapiConf['casinoname'];
788
789    const params = [];
790    params['oldPin'] = oldPin;
791    params['newPin'] = newPin;
792
793    iapiMakeRedirectRequest(requestUrl, params, iapiCALLOUT_SESSIONVALIDATION);
794}
795
796function iapiValidatePinToken(pin) {
797    const requestUrl = 'ValidateLoginSession.php?' + 'validationType=' + 'PINToken' + '&casinoname=' + iapiConf['casinoname'];
798
799    var params = [];
800    params['pin'] = pin;
801
802    iapiMakeRedirectRequest(requestUrl, params, iapiCALLOUT_SESSIONVALIDATION);
803}
804
805function iapiValidatePassword(password, loginName) {
806    const requestUrl = 'ValidateLoginSession.php?' + 'validationType=' + 'LoginNameAndPassword' + '&casinoname=' + iapiConf['casinoname'];
807    var params = [];
808    params['password'] = password;
809    params['loginName'] = loginName;
810
811    iapiMakeRedirectRequest(requestUrl, params, iapiCALLOUT_SESSIONVALIDATION);
812}
813
814function iapiValidateTwoFactorToken(token, trustDevice, deviceName) {
815    const requestUrl = 'ValidateLoginSession.php?' + 'validationType=' + 'TwoFactor' + '&casinoname=' + iapiConf['casinoname'];
816
817    const params = [];
818    params['2faToken'] = token;
819    params['trustDevice'] = trustDevice;
820    params['deviceName'] = deviceName;
821
822    iapiMakeRedirectRequest(requestUrl, params, iapiCALLOUT_SESSIONVALIDATION);
823}
824
825function iapiValidateFitToPlayToken(isFitToPlay) {
826    const requestUrl = 'ValidateLoginSession.php?' + 'validationType=' + 'FitToPlay' + '&casinoname=' + iapiConf['casinoname'];
827
828    const params = [];
829    params['fitToPlay'] = isFitToPlay;
830
831    iapiMakeRedirectRequest(requestUrl, params, iapiCALLOUT_SESSIONVALIDATION);
832}
833
834function iapiValidateMfaToken(mfaToken, transactionId) {
835    const requestUrl = 'ValidateLoginSession.php?' + 'validationType=' + 'MFA' + '&casinoname=' + iapiConf['casinoname'];
836
837    const params = [];
838    params['mfaToken'] = mfaToken;
839    params['transactionId'] = transactionId;
840
841    iapiMakeRedirectRequest(requestUrl, params, iapiCALLOUT_SESSIONVALIDATION);
842}
843
844function iapiGetPendingValidationData() {
845    const requestUrl = 'ValidateLoginSession.php?' + '&casinoname=' + iapiConf['casinoname'];
846
847    iapiMakeRedirectRequest(requestUrl, [], iapiCALLOUT_SESSIONVALIDATION);
848}
849
850// public, forgot password, username, email, birthDate in format "yyyy-mm-dd", realMode (1/0), verificationAnswer, passwordRecoveryDestinationLink, notificationChannels (comma-separated list)
851function iapiForgotPassword(username, email, birthDate, realMode, verificationAnswer, passwordRecoveryDestinationLink, notificationChannels)
852{
853    var requestUrl = 'ForgotPassword.php?' + 'casinoname=' + iapiConf['casinoname'] + '&realMode=' + realMode;
854
855    var params = [];
856    params['username'] = username;
857    params['email'] = email;
858    params['birthDate'] = birthDate;
859
860    if (verificationAnswer)
861    {
862        params['verificationAnswer'] = verificationAnswer;
863    }
864
865    if (passwordRecoveryDestinationLink)
866    {
867        params['passwordRecoveryDestinationLink'] = passwordRecoveryDestinationLink;
868    }
869
870    if (notificationChannels)
871    {
872        params['notificationChannels'] = notificationChannels;
873    }
874
875    if (iapiConf['challengeResponseToken']) {
876        params['challengeResponseToken'] = iapiConf['challengeResponseToken']
877        iapiConf['challengeResponseToken'] = ""
878    }
879
880    iapiMakeRedirectRequest(requestUrl, params, iapiCALLOUT_FORGOTPASSWORD);
881
882    return iapiERR_OK;
883};
884
885// public, start forgot email, cellphone, birthDate in format "yyyy-mm-dd", realMode (1/0)
886function iapiStartForgotEmail(cellphone, birthdate, realMode, lastName, personalId)
887{
888    var requestUrl = 'StartForgotEmail.php?' + 'casinoname=' + iapiConf['casinoname'] + '&realMode=' + realMode;
889
890    var params = [];
891    params['cellphone'] = cellphone;
892    params['birthdate'] = birthdate;
893    params['lastName'] = lastName;
894    params['personalId'] = personalId;
895
896    iapiMakeRedirectRequest(requestUrl, params, iapiCALLOUT_STARTFORGOTEMAIL);
897
898    return iapiERR_OK;
899};
900
901// public, complete forgot email, token, realMode (1/0), [pin]
902function iapiCompleteForgotEmail(token, realMode, pin)
903{
904    var requestUrl = 'CompleteForgotEmail.php?' + 'casinoname=' + iapiConf['casinoname'] + '&realMode=' + realMode;
905
906    var params = [];
907    params['token'] = token;
908
909    if (pin)
910    {
911        params['pin'] = pin;
912    }
913
914    iapiMakeRedirectRequest(requestUrl, params, iapiCALLOUT_COMPLETEFORGOTEMAIL);
915
916    return iapiERR_OK;
917};
918
919// public, online forgot password, username, email, birthDate in format "yyyy-mm-dd", realMode (1/0), verificationAnswer, newPassword, passwordRecoveryDestinationLink, notificationChannels(SMS,email)
920function iapiOnlineForgotPassword(username, email, birthDate, realMode, verificationAnswer, newPassword, passwordRecoveryDestinationLink, notificationChannels)
921{
922    var requestUrl = 'OnlineForgotPassword.php?' + 'casinoname=' + iapiConf['casinoname'] + '&realMode=' + realMode;
923
924    var params = [];
925    params['username'] = username;
926    if (email)
927    {
928        params['email'] = email;
929    }
930    if (birthDate)
931    {
932        params['birthDate'] = birthDate;
933    }
934    if (verificationAnswer)
935    {
936        params['verificationAnswer'] = verificationAnswer;
937    }
938    if (newPassword)
939    {
940        params['newPassword'] = newPassword;
941    }
942    if (passwordRecoveryDestinationLink)
943    {
944        params['passwordRecoveryDestinationLink'] = passwordRecoveryDestinationLink;
945    }
946    if (notificationChannels)
947    {
948        params['notificationChannels'] = notificationChannels;
949    }
950
951    iapiMakeRedirectRequest(requestUrl, params, iapiCALLOUT_ONLINEFORGOTPASSWORD);
952
953    return iapiERR_OK;
954};
955
956// public, get logged in player, realMode (1/0)
957function iapiGetLoggedInPlayer(realMode)
958{
959    var func = iapiCALLOUT_GETLOGGEDINPLAYER;
960    if (isStorageAvailable()){
961        iapiCalloutFunctions[func = "loggedInPlayerHandlerX"] = self.loggedInPlayerHandlerX;
962        let k = getSessionKey("loggedInPlayer-recent");
963        var recent = window.sessionStorage.getItem(k);
964        if (recent){
965            recent = JSON.parse(recent);
966            if (recent && Date.now() -  recent.time < (iapiConf['loggedInExpiry'] ? parseInt(iapiConf['loggedInExpiry']) : 260000)){//yes few min, default
967                if (recent.session == window.sessionStorage.getItem(getSessionKey("token")) ||
968                    recent.session == window.sessionStorage.getItem(getSessionKey("sessionRef"))
969                ){
970                    setTimeout(function(){iapiCalloutFunctions[iapiCALLOUT_GETLOGGEDINPLAYER](recent.resp)}, iapiEVENT_TIMER);//quick
971                    return iapiERR_OK;
972                }
973            }
974        }
975        window.sessionStorage.removeItem(k);
976    }
977    var requestUrl = 'GetLoggedInPlayer.php?' + 'casinoname=' + iapiConf['casinoname'] + '&realMode=' + realMode;
978    iapiMakeRedirectRequest(requestUrl, null, func);
979    return iapiERR_OK;
980};
981function getSessionKey(key)
982{
983    return "pas["+iapiConf['casinoname']+"][real][" + key + "]";
984}
985function loggedInPlayerHandlerX(e){
986    if (isStorageAvailable()) {
987        let k = getSessionKey("loggedInPlayer-recent");
988        if (e.username) {//no username present, don't hold it
989            var recent = {};
990            recent.resp = e;
991            recent.time = Date.now();
992            recent.session = window.sessionStorage.getItem(getSessionKey("token"));
993            if (!recent.session)
994                recent.session = window.sessionStorage.getItem(getSessionKey("sessionRef"));
995
996            let serialized = JSON.stringify(recent);
997            window.sessionStorage.setItem(k, serialized);
998        } else{
999            window.sessionStorage.removeItem(k);
1000        }
1001    }
1002
1003    if (iapiCalloutFunctions[iapiCALLOUT_GETLOGGEDINPLAYER])
1004        iapiCalloutFunctions[iapiCALLOUT_GETLOGGEDINPLAYER](e);
1005}
1006
1007// public, keep alive, realMode (1/0), milliseconds from last action
1008function iapiKeepAlive(realMode, millisFromLastAction)
1009{
1010    var requestUrl = 'KeepAlive.php?' + 'casinoname=' + iapiConf['casinoname'] + '&realMode=' + realMode;
1011
1012    if (millisFromLastAction)
1013    {
1014        requestUrl += '&millisFromLastAction=' + millisFromLastAction;
1015    }
1016
1017    iapiMakeRedirectRequest(requestUrl, null, iapiCALLOUT_KEEPALIVE);
1018
1019    return iapiERR_OK;
1020}
1021
1022// public, get urls, configured by url templates; urlTypeList (comma-separated list of strings)
1023function iapiGetUrls(urlTypeList)
1024{
1025    var requestUrl = 'GetUrls.php?' +  'casinoname=' + iapiConf['casinoname'] + '&realMode=1' + '&urlTypeList=' + urlTypeList;
1026
1027    iapiMakeRedirectRequest(requestUrl, null, iapiCALLOUT_GETURLS);
1028
1029    return iapiERR_OK;
1030}
1031
1032function iapiResendLogin2FAToken()
1033{
1034    const requestUrl = 'ResendLogin2FAToken?' + 'casinoname=' + iapiConf['casinoname'];
1035    const params = [];
1036
1037    if (iapiConf['challengeResponseToken']) {
1038        params['challengeResponseToken'] = iapiConf['challengeResponseToken']
1039        iapiConf['challengeResponseToken'] = ""
1040    }
1041
1042    iapiMakeRedirectRequest(requestUrl, params, iapiCALLOUT_RESENDLOGIN2FATOKEN);
1043
1044    return iapiERR_OK;
1045}
1046
1047// public, set authentication type, authType ("password" or "externalToken"), default is "password"
1048function iapiSetAuthenticationType(authType)
1049{
1050    iapiConf['authenticationType'] = authType;
1051};
1052
1053// public, set client skin used in login, overwrites client skin from conf
1054function iapiSetClientSkin(clientSkin)
1055{
1056    iapiConf['clientSkin'] = clientSkin;
1057};
1058
1059// public, set client type used in login, overwrites client type from conf
1060function iapiSetClientType(clientType)
1061{
1062    iapiConf['clientType'] = clientType;
1063};
1064
1065//public, set client URL used in login, overwrites client URL from conf
1066function iapiSetClientUrl(clientType, value)
1067{
1068    iapiConf['clientUrl_'+clientType] = value;
1069};
1070
1071// public, set client version used in login, overwrites client version from conf
1072function iapiSetClientVersion(clientVersion)
1073{
1074    iapiConf['clientVersion'] = clientVersion;
1075};
1076
1077// public, set client channel used in login, overwrites client channel from conf
1078function iapiSetClientChannel(clientChannel)
1079{
1080    iapiConf['clientChannel'] = clientChannel;
1081};
1082
1083// public, set game type used in login, overwrites game type from conf
1084function iapiSetGameType(gameType)
1085{
1086    iapiConf['gameType'] = gameType;
1087};
1088
1089// public, set game type prefix used in login, overwrites game type prefix from conf
1090function iapiSetGameTypePrefix(gameTypePrefix)
1091{
1092    iapiConf['gameTypePrefix'] = gameTypePrefix;
1093};
1094
1095// public, set launch alias used in login, overwrites launch alias from conf
1096function iapiSetLaunchAlias(launchAlias)
1097{
1098    iapiConf['launchAlias'] = launchAlias;
1099};
1100
1101// public, set client platform used in login, overwrites client platform from conf
1102function iapiSetClientPlatform(clientPlatform)
1103{
1104    iapiConf['clientPlatform'] = clientPlatform;
1105};
1106
1107// public, set system id, overwrites system id from conf
1108function iapiSetSystemId(systemId)
1109{
1110    iapiConf['systemId'] = systemId;
1111};
1112
1113// public, set service type, overwrites service type from conf
1114function iapiSetServiceType(serviceType)
1115{
1116    iapiConf['serviceType'] = serviceType;
1117};
1118
1119// public, set language code
1120function iapiSetLanguageCode(languageCode)
1121{
1122    iapiConf['languageCode'] = languageCode;
1123};
1124
1125// public, set call id
1126function iapiSetCallId(callId)
1127{
1128    iapiConf['callId'] = callId;
1129};
1130
1131// public, set delivery platform
1132function iapiSetDeliveryPlatform(deliveryPlatform)
1133{
1134    iapiConf['deliveryPlatform'] = deliveryPlatform;
1135};
1136
1137// public, set device browser
1138function iapiSetDeviceBrowser(deviceBrowser)
1139{
1140    iapiConf['deviceBrowser'] = deviceBrowser;
1141};
1142
1143// public, set general name of the operating system used.
1144function iapiSetOsName(osName)
1145{
1146    iapiConf['osName'] = osName;
1147};
1148
1149// public, set os version
1150function iapiSetOsVersion(osVersion)
1151{
1152    iapiConf['osVersion'] = osVersion;
1153};
1154
1155//public, set device ID
1156function iapiSetDeviceId(deviceId)
1157{
1158    iapiConf['deviceId'] = deviceId;
1159};
1160
1161//public, set device type
1162function iapiSetDeviceType(deviceType)
1163{
1164    iapiConf['deviceType'] = deviceType;
1165};
1166
1167//public, set device family
1168function iapiSetDeviceFamily(deviceFamily)
1169{
1170    iapiConf['deviceFamily'] = deviceFamily;
1171};
1172
1173//deprecated, use iapiSetDeviceId instead
1174//public, set soft serial
1175function iapiSetSoftSerial(softSerial)
1176{
1177    iapiConf['softSerial'] = softSerial;
1178};
1179
1180//public set Iovation blockbox string
1181function iapiSetIovationBlackbox(iovationBlackbox) {
1182    iapiConf['iovationBlackbox'] = iovationBlackbox;
1183}
1184
1185//public set italyAamsSessionCode string
1186function iapiSetItalyAamsSessionCode(italyAamsSessionCode) {
1187    iapiConf['italyAamsSessionCode'] = italyAamsSessionCode;
1188}
1189
1190//public set italyParticipationCode string
1191function iapiSetItalyParticipationCode(italyParticipationCode) {
1192    iapiConf['italyParticipationCode'] = italyParticipationCode;
1193}
1194
1195//public set italyExternalGameTableSessionCode string
1196function iapiSetItalyExternalGameTableSessionCode(italyExternalGameTableSessionCode) {
1197    iapiConf['italyExternalGameTableSessionCode'] = italyExternalGameTableSessionCode;
1198}
1199
1200function iapiSetCaptchaResponse(captcha) {
1201    iapiConf['challengeResponseToken'] = captcha;
1202}
1203
1204// public, enable to receive user error objects in callout function parameter
1205function iapiEnableUserErrors() {
1206    iapiConf['errorLevel'] = 1;
1207};
1208
1209function iapiGetGoogleLoginUri() {
1210    return getHttpProtocol() + '://' + iapiConf['loginServer'] + '/RedirectExternal/' + iapiConf['casinoname'] + '/Google';
1211}
1212
1213function iapiGetGoogleClientId() {
1214    return iapiConf["googleClientId"];
1215}
1216
1217// private, jsonp callback arrives here
1218function iapiCallbackWaitingMessages(messages)
1219{
1220    // check request id and type
1221    var request = iapiGetRequest(iapiWaitingMessagesId);
1222
1223    if (!request)
1224    {
1225        return;
1226    };
1227
1228    var error =
1229        {
1230            "errorCode" : 6,
1231            "errorText" : "Invalid response.",
1232            "playerMessage" : ""
1233        };
1234    if (messages)
1235    {
1236        if (messages.errorCode)
1237        {
1238            error =
1239                {
1240                    "errorCode" : messages.errorCode,
1241                    "errorText" : messages.errorText,
1242                    "playerMessage" : messages.playerMessage
1243                };
1244        }
1245        else
1246        {
1247            error = null;
1248        }
1249    }
1250    else
1251    {
1252        messages = error;
1253    }
1254
1255    var arr = request.request;
1256
1257    // if error 6 and not enough tries then retry
1258    if (error && error.errorCode == 6)
1259    {
1260        if (arr[3].length < iapiConf['loginDomainRetryCount'])
1261        {
1262            var requestId = (new Date().getTime()) + Math.round(Math.random() * 1000000);
1263            var failedTimer = setTimeout('iapiRequestFailed(' + requestId + ')', iapiConf['loginDomainRetryInterval'] * 1000);
1264            iapiRegisterRequestId(requestId, iapiCALLOUT_MESSAGES, failedTimer, arr[3], arr[4], arr[5]);
1265            return;
1266        }
1267    }
1268    // successful or error response
1269    if (iapiCalloutFunctions[iapiCALLOUT_MESSAGES])
1270    {
1271        setTimeout(function()
1272        {
1273            iapiCalloutFunctions[iapiCALLOUT_MESSAGES](messages);
1274        }, iapiEVENT_TIMER);
1275    };
1276};
1277
1278// private, login with this username and password, and realMode (1/0) and language code
1279function iapiBaseLogin(user, pass, realMode, language, rememberMeLogin)
1280{
1281    // if login is already in progress and this login is for different mode then put to waiting status
1282    if ((iapiHasRedirectRequest(iapiCALLOUT_LOGIN)) && iapiRealMode != realMode)
1283    {
1284        iapiNextLogin = [user, pass, realMode, language, rememberMeLogin];
1285        return iapiERR_OK;
1286    };
1287
1288    if (iapiAuthenticationType == iapiLoginTypes.EMAIL)
1289    {
1290        iapiEmail = user;
1291    }
1292    else
1293    {
1294        iapiUsername = user;
1295    }
1296    iapiPassword = pass;
1297
1298    if (realMode == 1)
1299    {
1300        iapiRealMode = 1;
1301    }
1302    else
1303    {
1304        iapiRealMode = 0;
1305    };
1306
1307    if (language)
1308    {
1309        iapiSetLanguageCode(language);
1310    }
1311
1312    iapiRememberMeLogin = rememberMeLogin;
1313
1314    // write to client cookie that login is being processed
1315    iapiLoginSuccess = false;
1316    iapiWriteClientCookie('loginInProgress=1', iapiRealMode);
1317
1318    // create divs/frames, post login
1319    iapiContinueLogin()
1320};
1321
1322// private, create frames/divs, open login url
1323function iapiContinueLogin()
1324{
1325    iapiClearRedirectRequests(iapiCALLOUT_LOGIN, 0);
1326    iapiClearRedirectRequests(iapiCALLOUT_LOGIN, 1);
1327
1328    var requestUrl = 'Login.php?' + 'casinoname=' + iapiConf['casinoname'];
1329
1330    if (iapiRealMode == 1)
1331    {
1332        requestUrl += '&realMode=1';
1333    }
1334    else
1335    {
1336        requestUrl += '&realMode=0';
1337    };
1338
1339    if (iapiRememberMeLogin == 1)
1340    {
1341        requestUrl += '&rememberMeLogin=1';
1342    }
1343
1344    var params = [];
1345
1346    if (iapiConf['challengeResponseToken']) {
1347        params['challengeResponseToken'] = iapiConf['challengeResponseToken']
1348        iapiConf['challengeResponseToken'] = ""
1349    }
1350
1351    if (iapiAuthenticationType == iapiLoginTypes.EXTERNAL_TOKEN)
1352    {
1353        if (iapiUsername)
1354        {
1355            params['username'] = iapiUsername;
1356        }
1357        params['externalToken'] = iapiPassword;
1358        if (iapiConf['italyAamsSessionCode']) {
1359            params['italyAamsSessionCode'] = iapiConf['italyAamsSessionCode'];
1360        }
1361        if (iapiConf['italyParticipationCode']) {
1362            params['italyParticipationCode'] = iapiConf['italyParticipationCode'];
1363        }
1364        if (iapiConf['italyExternalGameTableSessionCode']) {
1365            params['italyExternalGameTableSessionCode'] = iapiConf['italyExternalGameTableSessionCode'];
1366        }
1367    }
1368    else if (iapiAuthenticationType == iapiLoginTypes.EMAIL)
1369    {
1370        if (iapiEmail)
1371        {
1372            params['email'] = iapiEmail;
1373        }
1374        params['password'] = iapiPassword;
1375
1376        if (iapiConf['iovationBlackbox']) {
1377            params['iovationBlackbox'] = iapiConf['iovationBlackbox'];
1378        }
1379    }
1380    else if (iapiAuthenticationType == iapiLoginTypes.SESSION_TOKEN)
1381    {
1382        params['sessionToken'] = iapiPassword;
1383    }
1384    else if (iapiAuthenticationType == iapiLoginTypes.CRYPTO_TOKEN)
1385    {
1386        params['cryptoToken'] = iapiPassword;
1387    }
1388    else if (iapiAuthenticationType == iapiLoginTypes.ADMIN_USERNAME)
1389    {
1390        if (iapiAdminUsername)
1391        {
1392            params['adminUsername'] = iapiAdminUsername;
1393        }
1394        params['username'] = iapiUsername;
1395        params['externalToken'] = iapiPassword;
1396    }
1397    else if (iapiAuthenticationType == iapiLoginTypes.NICKNAME)
1398    {
1399        params['nickname'] = iapiUsername;
1400        params['password'] = iapiPassword;
1401        params['systemId'] = iapiConf['systemId'];
1402    }
1403    else if (iapiAuthenticationType == iapiLoginTypes.TOKEN_CODE)
1404    {
1405        params['tokenCode'] = iapiUsername;
1406        params['pin'] = iapiPassword;
1407        params['systemId'] = iapiConf['systemId'];
1408    }
1409    else if (iapiAuthenticationType == iapiLoginTypes.PRINTED_TOKEN_CODE)
1410    {
1411        params['printedTokenCode'] = iapiUsername;
1412        params['pin'] = iapiPassword;
1413        params['systemId'] = iapiConf['systemId'];
1414    }
1415    else if (iapiAuthenticationType == iapiLoginTypes.USERNAME_AND_PIN)
1416    {
1417        params['username'] = iapiUsername;
1418        params['phone'] = STOCK_AUTH_PHONE_NUMBER;
1419        params['pin'] = iapiPassword;
1420
1421        params['systemId'] = iapiConf['systemId'];
1422    }
1423    else if (iapiAuthenticationType == iapiLoginTypes.TOKEN_CODE_AND_PASS)
1424    {
1425        params['tokenCode'] = iapiUsername;
1426        params['password'] = iapiPassword;
1427        params['systemId'] = iapiConf['systemId'];
1428    }
1429    else
1430    {
1431        params['username'] = iapiUsername;
1432        params['password'] = iapiPassword;
1433
1434        if (iapiConf['iovationBlackbox']) {
1435            params['iovationBlackbox'] = iapiConf['iovationBlackbox'];
1436        }
1437        if (iapiConf['italyAamsSessionCode']) {
1438            params['italyAamsSessionCode'] = iapiConf['italyAamsSessionCode'];
1439        }
1440        if (iapiConf['italyParticipationCode']) {
1441            params['italyParticipationCode'] = iapiConf['italyParticipationCode'];
1442        }
1443        if (iapiConf['italyExternalGameTableSessionCode']) {
1444            params['italyExternalGameTableSessionCode'] = iapiConf['italyExternalGameTableSessionCode'];
1445        }
1446    };
1447
1448    iapiAddClientHintsAndContinue(requestUrl, params, iapiCALLOUT_LOGIN)
1449    return iapiERR_OK;
1450};
1451
1452// private, add client hints to params and continue login flow
1453function iapiAddClientHintsAndContinue(requestUrl, params, requestType) {
1454    if (!isDeviceAtlasEnabled()) {
1455        iapiMakeRedirectRequest(requestUrl, params, requestType);
1456        return;
1457    }
1458
1459    try {
1460        Promise.race([Promise.all([clientHints().clientHintHeaders, deviceAtlasLoaded]),
1461            new Promise(function (_, reject) {
1462                setTimeout(reject, 200) // shouldn't wait too long
1463            })]
1464        ).then(function (results) {
1465            const [clientHintsResult, deviceAtlasResult] = results;
1466
1467            if (clientHintsResult) {
1468                params['clientHints'] = JSON.stringify(clientHintsResult);
1469            }
1470
1471            if (deviceAtlasResult && typeof DeviceAtlas.getPropertiesAsString === 'function') {
1472                params['deviceAtlasProperties'] = DeviceAtlas.getPropertiesAsString();
1473            }
1474            iapiMakeRedirectRequest(requestUrl, params, requestType);
1475        }, function () { // timeout
1476            iapiMakeRedirectRequest(requestUrl, params, requestType);
1477        })
1478    } catch (e) { // couldn't create the promise
1479        iapiMakeRedirectRequest(requestUrl, params, requestType);
1480    }
1481}
1482
1483// private, Write client cookie
1484function iapiWriteClientCookie(params, realMode)
1485{
1486    // do not write client cookie in download login mode
1487    if (iapiLoginModeDownload)
1488    {
1489        return;
1490    }
1491    var tmpUrl = iapiConf['clientCookieUrl'];
1492    // if client cookie url doesn't exist then cookie is not needed
1493    if (!tmpUrl)
1494    {
1495        return;
1496    }
1497    if (tmpUrl.indexOf('://') < 0)
1498    {
1499        tmpUrl = location.protocol + '//' + tmpUrl;
1500    }
1501    var cookieUrl = tmpUrl + '?' + params + '&casinoname=' + iapiConf['casinoname'] + '&realMode=' + realMode;
1502
1503    var iframename = iapiRealCookieIframe;
1504    if (realMode == 0)
1505    {
1506        iframename = iapiFunCookieIframe;
1507    }
1508
1509    iapiCreateDiv(iapiDivname);
1510    iapiCreateIframe(iapiDivname, iframename, "weLoveBaking");
1511
1512    iapiGet(iframename, cookieUrl);
1513};
1514
1515// private, Create new div if div with given id doesn't exist
1516function iapiCreateDiv(id)
1517{
1518    if (document.getElementById(id))
1519    {
1520        return;
1521    };
1522    var newdiv = document.createElement('div');
1523    newdiv.setAttribute('id', id);
1524    newdiv.setAttribute('style', 'DISPLAY:none;');
1525
1526    document.body.appendChild(newdiv);
1527};
1528
1529function resolveFrameName(divName, frameName, type){
1530    let reusable = type == iapiCALLOUT_GETLOGGEDINPLAYER || type == "loggedInPlayerHandlerX";
1531    if (reusable){
1532        return divName+"-"+type;
1533    }
1534    return frameName;
1535}
1536
1537// private, create iframe
1538function iapiCreateIframe(divName, frameName, type)
1539{
1540    let c = document.getElementById(divName);
1541    let reusable = type == iapiCALLOUT_GETLOGGEDINPLAYER || type == "loggedInPlayerHandlerX";
1542    frameName = resolveFrameName(divName, frameName, type);
1543
1544    // if iframe exists then return only for getloggedinplayer
1545    if (document.getElementById(frameName))
1546    {
1547        if (reusable){
1548            return frameName;
1549        }
1550        c.removeChild(document.getElementById(frameName));
1551    }
1552
1553    var iframeelement;
1554    try
1555    {
1556        iframeelement = document.createElement("<iframe name='" + frameName + "'>");
1557    }
1558    catch (err)
1559    {
1560        iframeelement = document.createElement('iframe');
1561    };
1562
1563    if (reusable){
1564        iframeelement.dataset["reusable"] = type;
1565    }
1566    iframeelement.setAttribute('id', frameName);
1567    iframeelement.setAttribute('name', frameName);
1568    iframeelement.setAttribute('style', 'DISPLAY: none; LEFT: 0px; POSITION: absolute; TOP: 0px');
1569    iframeelement.setAttribute('width', '0px');
1570    iframeelement.setAttribute('height', '0px');
1571    iframeelement.setAttribute('border', '0px');
1572    iframeelement.setAttribute('frameborder', '0');
1573    c.appendChild(iframeelement);
1574
1575    return null;
1576};
1577
1578// private, post
1579function iapiPost(windowname, url, data)
1580{
1581    windowname = encodeHTML(windowname);
1582    url = encodeURL(url);
1583
1584    var str = "<html><head></head><body><form id='formid' target='" + windowname + "' method='POST' action='" + url + "'>";
1585    var prop;
1586    for (prop in data)
1587    {
1588        if (typeof (data[prop]) != 'function')
1589        {
1590            str += "<input type='hidden' name='" + prop + "' value='" + encodeHTML(data[prop]) + "'>";
1591        };
1592    };
1593
1594    str += "</form><script type='text/javascript'>setTimeout(function(){document.getElementById('formid').submit();},100);</script></body></html>";
1595
1596    iapiPostWindow(windowname, str);
1597};
1598
1599// private, write document into empty window
1600// this function is created and used for post
1601function iapiPostWindow(windowname, cont)
1602{
1603    var win = document.getElementById(windowname);
1604    if (win)
1605    {
1606        try
1607        {
1608            win.contentWindow.document.open();
1609            win.contentWindow.document.write(cont);
1610            win.contentWindow.document.close();
1611        }
1612        catch (e)
1613        {
1614            // write js to src, which changes document domain writes content
1615            var s = "<script>document.domain='" + document.domain + "';</script>" + cont;
1616            var u = "javascript:'<script>window.onload=function(){var ed=\\'" + escape(escape(s))
1617                + "\\';document.write(unescape(ed));document.close();};<\/script>'";
1618            win.src = u;
1619        };
1620    };
1621};
1622
1623// private
1624// requests are going through this functions
1625// url - requested php script name with parameters
1626// postParams - postParams
1627// requestType - request type, script name
1628// loginServers - loginServers already used, used to count retries and calculate next request server
1629function iapiMakeRedirectRequest(url, postParams, requestType, loginServers)
1630{
1631
1632    if (!loginServers)
1633    {
1634        loginServers = [];
1635    }
1636    else if (loginServers.length >= iapiConf['loginDomainRetryCount'] || loginServers.length >= 25)
1637    {
1638        // if already tried given number of times then do not try anymore
1639        return false;
1640    };
1641
1642    // availableServers contain all servers, multiple servers are supported now
1643    var availableServers = iapiConf['loginServer'].split('|');
1644    // remove already tested servers from availableServers, if some of the servers are not tested yet
1645    if (loginServers.length < availableServers.length)
1646    {
1647        var i;
1648        for (i in loginServers)
1649        {
1650            var s = loginServers[i];
1651            var j;
1652            for (j in availableServers)
1653            {
1654                // if server is tested, remove it
1655                if (availableServers[j] == s && typeof (availableServers[j]) === 'string')
1656                {
1657                    availableServers.splice(j, 1);
1658                    break;
1659                }
1660            }
1661        }
1662    }
1663
1664    url = iapiAppendContextParameters(url);
1665
1666
1667    // select random server from availableServers
1668    var loginServer = availableServers[Math.floor(Math.random() * availableServers.length)];
1669    loginServers.push(loginServer);
1670
1671    requestUrl = getHttpProtocol() + '://' + loginServer + '/' + url;
1672
1673    let requestId = Date.now() +"x"+ Math.round(Math.random() * 1000000);
1674    if (!isPostMessagesDisabled() || requestType != iapiCALLOUT_MESSAGES)
1675    {
1676        requestUrl += '&redirectUrl='
1677            + encodeURIComponent(location.protocol + '//' + location.hostname + (location.port ? ':' + location.port : '')
1678                + (iapiConf['redirectUrl'] ? iapiConf['redirectUrl'] : '/') + '#requestId=' + requestId);
1679    }
1680    else
1681    {
1682        requestUrl += '&cacheBreaker=' + (new Date().getTime());
1683    };
1684
1685    if (iapiConf['errorLevel'] == 1)
1686    {
1687        requestUrl += '&errorLevel=1';
1688    }
1689
1690    var failedTimer = setTimeout(
1691        function(){iapiRequestFailed(requestId);},
1692        iapiConf['loginDomainRequestTimeout'] * 1000);
1693
1694    // remember also request url and post parameters and tried login servers and retry count.
1695    // then it's possible to make retry to next server on fail
1696    iapiRegisterRequestId(requestId, requestType, failedTimer, loginServers, url, postParams);
1697
1698    if (self.pasLogin && self.pasLogin.removeCallbackFromPostParams) {
1699        postParams = self.pasLogin.removeCallbackFromPostParams(postParams);
1700    }
1701
1702    if (isPostMessagesDisabled() && requestType == iapiCALLOUT_MESSAGES)
1703    {
1704        iapiWaitingMessagesId = requestId;
1705        iapiJsonp(requestUrl, 'iapiCallbackWaitingMessages');
1706    }
1707    else {
1708        iapiCreateDiv(iapiDivname);
1709
1710        var iframeName = resolveFrameName(iapiDivname, iapiIframename + '_' + requestId, requestType);
1711        var frameAlreadyExists= iapiCreateIframe(iapiDivname, iframeName, requestType);
1712        if (frameAlreadyExists)
1713            iframeName = frameAlreadyExists;
1714
1715        var frame = document.getElementById(iframeName);
1716        frame.dataset.requestId = requestId;
1717
1718        if (!iapiMessagesSupported){
1719            initMessageListener();
1720        };
1721
1722        if (isPostMessagesDisabled()) {
1723            if (iapiMessagesSupported)
1724            {
1725                requestUrl += '&messagesSupported=1';
1726                // if iframe existed before and is loaded, then send message to that iframe
1727                // currently only used for GetLoggedInPlayer
1728                if (frameAlreadyExists && iapiMessagesAnswered)
1729                {
1730                    // send message to iframe
1731                    if (frame.contentWindow.postMessage)
1732                    {
1733                        frame.contentWindow.postMessage(requestType, getHttpProtocol() + "://" + loginServer);
1734                        return true;
1735                    };
1736                };
1737            };
1738        }
1739        else {
1740
1741
1742            if (iapiMessagesSupported) {
1743                requestUrl += '&messagesSupported=1';
1744                // if iframe existed before and is loaded, then send message to that iframe
1745                // currently only used for GetLoggedInPlayer
1746
1747                if (Array.isArray(postParams) && postParams.length == 0 && Object.keys(postParams).length > 0 && isHashPropertyUsed()){ //stringify does not appreciate arrays used as objects
1748                    var p = postParams;
1749                    var types =["object", "string", "number", "boolean"];
1750                    postParams = {};
1751                    for (var x in p){
1752                        var v = p[x];
1753                        if (types.indexOf(typeof v)>=0){
1754                            postParams[x] = v;
1755                        }
1756                    }
1757                }
1758
1759                var message = {
1760                    "requestType": requestType,
1761                    "postParams": postParams,
1762                    "url": requestUrl,
1763                    "casino": iapiConf['casinoname'],
1764                    "requestId": requestId,
1765                    "loginServer": getHttpProtocol() + "://" + loginServer
1766                };
1767
1768                if (!frameAlreadyExists) {
1769                    let s = getHttpProtocol() + "://" + loginServer + '/pasSetupPage.php?casino=' + iapiConf['casinoname'];
1770                    if (isHashPropertyUsed()){
1771                        s = s + "#" + encodeURIComponent(JSON.stringify(message));
1772                    }
1773                    frame.contentWindow.location.replace(s);
1774                    if (!isHashPropertyUsed()) {
1775                        frame.addEventListener("load", function (e) {
1776                            frame.contentWindow.postMessage(message, getHttpProtocol() + "://" + loginServer);
1777                        });
1778                    }
1779                } else{
1780                    frame.contentWindow.postMessage(message, getHttpProtocol() + "://" + loginServer);//do it now
1781                }
1782                return;
1783
1784            }
1785        }
1786
1787        if (postParams)
1788        {
1789            iapiPost(iframeName, requestUrl, postParams);
1790        }
1791        else
1792        {
1793            iapiGet(iframeName, requestUrl);
1794        };
1795    };
1796    return true;
1797};
1798
1799function isHashPropertyUsed() {
1800    return iapiConf['useHashProperty'] != 0;
1801}
1802
1803var storageAvailableResolved = 0;
1804function isStorageAvailable () {
1805    if (storageAvailableResolved)
1806        return storageAvailableResolved > 0;
1807
1808    try {
1809        var test = 'test';
1810        window.sessionStorage.setItem(test, test);
1811        window.sessionStorage.removeItem(test);
1812        checkCookieBuster();
1813
1814        return (storageAvailableResolved=1) > 0;
1815    }catch(e) {
1816    }
1817    return (storageAvailableResolved=-1) > 0;
1818}
1819
1820function checkCookieBuster(){
1821    try{
1822        if (storageAvailableResolved < 0 || !window.sessionStorage)
1823            return;
1824
1825        var buster = cookieBusterValue();
1826        if (buster && buster != window.sessionStorage.getItem('pasCookieBuster')){//got a buster that differs from a recorded one, clear it all
1827            clearSessionStorage(window.sessionStorage);
1828            window.sessionStorage.setItem('pasCookieBuster', buster);
1829        }
1830    }catch(any){
1831        storageAvailableResolved=-1;
1832    }
1833}
1834
1835function clearSessionStorage(s){
1836    let sessionKeys = Object.keys(s);
1837    for (var k in sessionKeys){
1838        if (sessionKeys[k].startsWith("pas["))
1839            s.removeItem(sessionKeys[k]);
1840    }
1841}
1842
1843function cookieBusterValue(){
1844    let cookies = document.cookie.split(';');
1845    for (var v in cookies){
1846        if (cookies[v].trim().startsWith("pasCookieBuster=")){
1847            return cookies[v].split('=')[1];
1848        }
1849    }
1850    return '';
1851}
1852function isPostMessagesDisabled() {
1853    return iapiConf['postMessagesDisabled'] == 1;
1854}
1855
1856//private
1857function iapiAppendContextParameters(url)
1858{
1859    iapiConf = iapiConf || [];
1860
1861    if (iapiLoginModeDownload)
1862    {
1863        iapiConf['clientPlatform'] = 'download';
1864    }
1865    else if (!iapiConf['clientPlatform'])
1866    {
1867        iapiConf['clientPlatform'] = 'flash';
1868    }
1869
1870    var contextFields = [
1871        'clientType', 'clientPlatform', 'clientVersion', 'clientSkin', 'clientChannel', 'callId',
1872        'gameType', 'gameTypePrefix', 'softSerial', 'deviceId', 'deliveryPlatform',
1873        'deviceType', 'osName', 'osVersion', 'deviceBrowser', 'languageCode', 'deviceFamily', 'launchAlias' ];
1874
1875    for (var i=0; i < contextFields.length; i++)
1876    {
1877        var fieldName = contextFields[i];
1878
1879        if (iapiConf[fieldName])
1880        {
1881            url = iapiAddUrlParams(url, fieldName+'='+iapiConf[fieldName]);
1882        }
1883    }
1884
1885    return url;
1886}
1887
1888// private jsonp request
1889// all the jsonp magic is here, we create an script element and we set the url and callback function.
1890function iapiJsonp(url, callback)
1891{
1892    var scriptElement = document.createElement('SCRIPT');
1893    scriptElement.type = 'text/javascript';
1894    // i add to the url the call back function
1895    scriptElement.src = encodeURL(url) + '&jsoncallback=' + callback + '&responseType=json';
1896    document.getElementsByTagName('HEAD')[0].appendChild(scriptElement);
1897};
1898
1899// private, write document into empty window
1900// this function is created and used for get
1901function iapiGet(windowname, url)
1902{
1903    var win = document.getElementById(windowname);
1904    if (win)
1905    {
1906        win.src = encodeURL(url);
1907    };
1908};
1909
1910// private, add url params (paramStr is 'key=value')
1911function iapiAddUrlParams(url, paramStr)
1912{
1913    if (url.indexOf('?') > 0)
1914    {
1915        url += '&';
1916    }
1917    else
1918    {
1919        url += '?';
1920    };
1921    return url + paramStr;
1922};
1923
1924// private, login failed actions
1925function iapiLoginFailedActions(response)
1926{
1927    iapiPassword = null; // set password to null
1928    iapiLoginSuccess = false;
1929    iapiSessionValid = 0;
1930    var errorCode = response.errorCode;
1931
1932    iapiWriteClientCookie('loginSuccess=0&errorCode=' + errorCode, iapiRealMode);
1933    if (iapiCalloutFunctions['login'])
1934    { // if login callout is defined, old
1935        setTimeout(function()
1936        {
1937            iapiCalloutFunctions['login'](0, 0, errorCode, iapiRealMode);
1938        }, iapiEVENT_TIMER);
1939    }
1940    if (iapiCalloutFunctions[iapiCALLOUT_LOGIN])
1941    { // if login callout is defined, new
1942        setTimeout(function()
1943        {
1944            iapiCalloutFunctions[iapiCALLOUT_LOGIN](response);
1945        }, iapiEVENT_TIMER);
1946    };
1947    if (iapiLoginModeDownload)
1948    {
1949        // send login failed htcmd
1950        iapiDownloadHtcmd(0, 0, errorCode, '');
1951    };
1952    iapiCheckNextLogin();
1953}
1954
1955// private, called from timer
1956function iapiTokenFailedActions(response)
1957{
1958    if (iapiCalloutFunctions['temporarytoken'])
1959    { // if temporarytoken callout is defined, old
1960        setTimeout(function()
1961        {
1962            iapiCalloutFunctions['temporarytoken'](0, null);
1963        }, iapiEVENT_TIMER);
1964    }
1965    if (iapiCalloutFunctions[iapiCALLOUT_TEMPORARYTOKEN])
1966    { // if temporarytoken callout is defined, new
1967        setTimeout(function()
1968        {
1969            iapiCalloutFunctions[iapiCALLOUT_TEMPORARYTOKEN](response);
1970        }, iapiEVENT_TIMER);
1971    };
1972    if (iapiLoginModeDownload)
1973    {
1974        // send htcmd temptoken failed
1975        iapiDownloadHtcmd(1, iapiSessionValid, 0, '');
1976    };
1977};
1978
1979// private, check if there is next login and execute it
1980function iapiCheckNextLogin()
1981{
1982    if (iapiNextLogin != null)
1983    {
1984        var user = iapiNextLogin[0];
1985        var pass = iapiNextLogin[1];
1986        var realMode = iapiNextLogin[2];
1987        var language = iapiNextLogin[3];
1988        var rememberMeLogin = iapiNextLogin[4];
1989        iapiNextLogin = null;
1990        setTimeout(function()
1991        {
1992            iapiLogin(user, pass, realMode, language, rememberMeLogin);
1993        }, iapiEVENT_TIMER);
1994    };
1995};
1996
1997// private, send download htcmd
1998function iapiDownloadHtcmd(loginSuccess, sessionValid, errorCode, tempToken)
1999{
2000    if (loginSuccess && tempToken)
2001    {
2002        var htcmd = 'htcmd:login?';
2003        htcmd = htcmd + 'username=' + encodeURIComponent(iapiUsername);
2004        htcmd = htcmd + '&password=' + encodeURIComponent(tempToken);
2005        htcmd = htcmd + '&realmode=' + iapiRealMode;
2006        htcmd = htcmd + '&type=' + 3;
2007
2008        document.location = htcmd;
2009    };
2010};
2011
2012// private
2013function iapiRedirectCallback(requestId, redirectResponse) {
2014    const request = iapiGetRequest(requestId);
2015
2016    if (!request) {
2017        return;
2018    }
2019
2020    if (redirectResponse && redirectResponse.sessionRef && isStorageAvailable()){
2021        window.sessionStorage.setItem(getSessionKey("sessionRef"), redirectResponse.sessionRef);
2022    }
2023
2024    var error =
2025        {
2026            "errorCode" : 6,
2027            "errorText" : "Invalid response.",
2028            "playerMessage" : ""
2029        };
2030    if (redirectResponse) {
2031        if (redirectResponse.errorCode) {
2032            error =
2033                {
2034                    "errorCode" : redirectResponse.errorCode,
2035                    "errorText" : redirectResponse.errorText,
2036                    "playerMessage" : redirectResponse.playerMessage
2037                };
2038        }
2039        else {
2040            error = null;
2041        }
2042    }
2043    else {
2044        redirectResponse = error;
2045    }
2046
2047    var arr = request.request;
2048    var calloutName = arr[1];
2049
2050    // if error 6 and not enough tries then retry
2051    if (error && error.errorCode == 6) {
2052        if (arr[3].length < iapiConf['loginDomainRetryCount']) {
2053            const retryRequestId = (new Date().getTime()) + Math.round(Math.random() * 1000000);
2054            const failedTimer = setTimeout('iapiRequestFailed(' + retryRequestId + ')', iapiConf['loginDomainRetryInterval'] * 1000);
2055            iapiRegisterRequestId(retryRequestId, calloutName, failedTimer, arr[3], arr[4], arr[5]);
2056            return;
2057        }
2058    }
2059
2060    if (self.pasLogin && self.pasLogin.handleResponse && self.pasLogin.handleResponse(request, redirectResponse)) //consumed, bail out
2061        return;
2062
2063    if (calloutName == iapiCALLOUT_LOGIN)
2064    {
2065        // success
2066        if (error == null)
2067        {
2068            iapiPassword = null; // set password to null
2069            iapiLoginSuccess = true;
2070
2071            // session validation data
2072            iapiSessionValid = 1;
2073            var validationData = redirectResponse.sessionValidationData;
2074            if (validationData)
2075            {
2076                for(let key in Object.keys(validationData)) {
2077                    if(validationData[key] !== 'SessionValidationByGeolocationData') {
2078                        iapiSessionValid = 0;
2079                        break;
2080                    }
2081                }
2082
2083            };
2084
2085            var str = 'loginSuccess=1&sessionValid=' + iapiSessionValid + '&loginDomain=' + iapiConf['loginServer'];
2086            iapiWriteClientCookie(str, iapiRealMode);
2087            if (iapiCalloutFunctions['login'])
2088            { // if login callout is defined
2089                setTimeout(function()
2090                {
2091                    iapiCalloutFunctions['login'](1, iapiSessionValid, 0, iapiRealMode);
2092                }, iapiEVENT_TIMER);
2093            };
2094            if (iapiCalloutFunctions[iapiCALLOUT_LOGIN])
2095            { // if login callout is defined
2096                setTimeout(function()
2097                {
2098                    iapiCalloutFunctions[iapiCALLOUT_LOGIN](redirectResponse);
2099                }, iapiEVENT_TIMER);
2100            };
2101            // if download mode login
2102            if (iapiLoginModeDownload)
2103            {
2104                // session is valid, request temptoken
2105                if (iapiSessionValid)
2106                {
2107                    iapiRequestTemporaryToken(iapiRealMode);
2108                }
2109                else
2110                {
2111                    // session is not valid, send htcmd
2112                    iapiDownloadHtcmd(1, 0, 0, '');
2113                };
2114            }
2115            else if (iapiLoginModeFlash)
2116            {
2117                // session is valid, redirect to flash client
2118                if (iapiSessionValid)
2119                {
2120                    var clientMode = 'real';
2121                    if (!iapiRealMode)
2122                    {
2123                        clientMode = 'fun';
2124                    }
2125                    iapiLaunchClient(iapiFlashLoginClientType, iapiFlashLoginGameType, clientMode);
2126                }
2127            };
2128            iapiCheckNextLogin();
2129        }
2130        else
2131        { // login failed
2132            iapiLoginFailedActions(redirectResponse); // login failed totally
2133        };
2134    }
2135    // temptoken
2136    else if (calloutName == iapiCALLOUT_TEMPORARYTOKEN)
2137    {
2138        // success
2139        if (error == null && redirectResponse.sessionToken && redirectResponse.sessionToken.sessionToken)
2140        {
2141            if (iapiCalloutFunctions['temporarytoken'])
2142            { // if temptoken callout is defined
2143                setTimeout(function()
2144                {
2145                    iapiCalloutFunctions['temporarytoken'](1, redirectResponse.sessionToken.sessionToken);
2146                }, iapiEVENT_TIMER);
2147            };
2148            if (iapiCalloutFunctions[iapiCALLOUT_TEMPORARYTOKEN])
2149            {
2150                setTimeout(function()
2151                {
2152                    iapiCalloutFunctions[iapiCALLOUT_TEMPORARYTOKEN](redirectResponse);
2153                }, iapiEVENT_TIMER);
2154            };
2155            // if download login and temptoken is success then send htcmd
2156            if (iapiLoginModeDownload)
2157            {
2158                iapiDownloadHtcmd(1, 1, 0, redirectResponse.sessionToken.sessionToken);
2159            };
2160        }
2161        else
2162        {
2163            iapiTokenFailedActions(redirectResponse);
2164        };
2165    }
2166    // handle other callouts
2167    else if (iapiCalloutFunctions[calloutName])
2168    {
2169        setTimeout(function()
2170        {
2171            iapiCalloutFunctions[calloutName](redirectResponse);
2172        }, iapiEVENT_TIMER);
2173    };
2174};
2175
2176// private, request failed
2177// called by timer
2178function iapiRequestFailed(requestId)
2179{
2180    // check request id and type
2181    var request = iapiGetRequest(requestId);
2182
2183    if (!request)
2184    {
2185        return;
2186    };
2187
2188
2189    var arr = request.request;
2190    var calloutName = arr[1];
2191
2192    if (iapiMakeRedirectRequest(arr[4], arr[5], calloutName, arr[3]))
2193    {
2194        return;
2195    }
2196
2197    var error =
2198        {
2199            "errorCode" : 6,
2200            "errorText" : "Request timed out.",
2201            "playerMessage" : ""
2202        };
2203
2204    if (self.pasLogin && self.pasLogin.handleResponse && self.pasLogin.handleResponse(request, error)) //consumed, bail out
2205        return;
2206
2207    if (calloutName == iapiCALLOUT_LOGIN)
2208    {
2209        if (iapiCalloutFunctions[iapiCALLOUT_LOGIN])
2210        {
2211            iapiLoginFailedActions(error);
2212        };
2213    }
2214    else if (calloutName == iapiCALLOUT_TEMPORARYTOKEN)
2215    {
2216        if (iapiCalloutFunctions[iapiCALLOUT_TEMPORARYTOKEN])
2217        {
2218            iapiTokenFailedActions(error);
2219        };
2220    }
2221    else if (iapiCalloutFunctions[calloutName])
2222    {
2223        // handle other callouts
2224        setTimeout(function()
2225        {
2226            iapiCalloutFunctions[calloutName](error);
2227        }, iapiEVENT_TIMER);
2228    };
2229};
2230
2231// private, register request id, remember it and check when response arrives
2232function iapiRegisterRequestId(requestId, callout, failedTimer, requestDomains, requestUrl, postParams)
2233{
2234    var request = {request: [requestId, callout, failedTimer, requestDomains, requestUrl, postParams]};
2235    iapiRequestIds.push(request);
2236
2237    if (self.pasLogin && self.pasLogin.registerCallback && postParams && postParams.iapiCallback) {
2238        self.pasLogin.registerCallback(request, postParams.iapiCallback)
2239    }
2240};
2241
2242// private, get callout (requestType) from requestId
2243function iapiGetRequest(requestId)
2244{
2245    var i;
2246    for (i in iapiRequestIds)
2247    {
2248        var request = iapiRequestIds[i];
2249        var arr = request.request;
2250        if (arr[0] == requestId)
2251        {
2252            iapiRequestIds.splice(i, 1);
2253            if (arr[2])
2254            {
2255                clearTimeout(arr[2]);
2256            }
2257            var win = document.getElementById(iapiIframename + '_' + requestId);
2258            if (win && !win.dataset["reusable"])
2259            {
2260                document.getElementById(iapiDivname).removeChild(win);
2261            };
2262            return request;
2263        };
2264    };
2265    return null;
2266};
2267
2268// private, clear request by type
2269function iapiClearRedirectRequests(requestType, realMode)
2270{
2271    var i = 0;
2272    while (i < iapiRequestIds.length)
2273    {
2274        var arr = iapiRequestIds[i].request;
2275        if (arr[1] == requestType)
2276        {
2277            // real mode in url
2278            var rm = 0;
2279            if (arr[4].indexOf('realMode=1') > 0)
2280            {
2281                rm = 1;
2282            }
2283            // if given real mode is same as in request
2284            if (rm == realMode)
2285            {
2286                iapiRequestIds.splice(i, 1);
2287                if (arr[2])
2288                {
2289                    clearTimeout(arr[2]);
2290                }
2291                var win = document.getElementById(iapiIframename + '_' + arr[0]);
2292                if (win)
2293                {
2294                    document.getElementById(iapiDivname).removeChild(win);
2295                };
2296                continue;
2297            }
2298        };
2299        i++;
2300    };
2301};
2302
2303// private, check request by type
2304function iapiHasRedirectRequest(requestType)
2305{
2306    var i = 0;
2307    while (i < iapiRequestIds.length)
2308    {
2309        var arr = iapiRequestIds[i].request
2310        if (arr[1] == requestType)
2311        {
2312            return true;
2313        };
2314        i++;
2315    };
2316    return false;
2317};
2318
2319// private, initialize message listener if messages are supported
2320function initMessageListener() {
2321    window.addEventListener('message', iapiOnMessage, false);
2322    iapiMessagesSupported = true;
2323}
2324
2325// private, called from message event
2326function iapiOnMessage(e) {
2327    if (!e.origin) return; // avoid custom events
2328
2329    const availableServers = iapiConf['loginServer'].split('|');
2330    const domain = e.origin.replace(getHttpProtocol() + "://", "");
2331    const index = availableServers.indexOf(domain);
2332    if (e.origin !== getHttpProtocol() + "://" + availableServers[index]) {
2333        return;  // not from us
2334    }
2335
2336    if (!e.data || typeof e.data !== 'string') {
2337        return; // not from pasSetupPage
2338    }
2339
2340    const params = new URLSearchParams(e.data)
2341
2342    let redirectResponse;
2343    let requestId;
2344    try {
2345        redirectResponse = JSON.parse(params.get("redirectResponse"))
2346    } catch (any) {
2347    }
2348
2349    if (redirectResponse) {
2350        requestId = redirectResponse.requestId
2351    }
2352
2353    if (!requestId) { // legacy fallback
2354        let c = document.getElementById(iapiDivname);
2355        if (c) {
2356            for (let i = 0; i < c.childNodes.length && i < 1000; i++) {
2357                if (c.childNodes[i].contentWindow == e.source) {
2358                    let r = c.childNodes[i].dataset['requestId'];
2359                    if (r) {
2360                        requestId = r;
2361                        break;
2362                    }
2363
2364                    const arr = c.childNodes[i].id.split('_');
2365                    if (arr.length > 1) {
2366                        requestId = arr[1];
2367                    }
2368                    break;
2369                }
2370            }
2371        }
2372    }
2373
2374    iapiMessagesAnswered = true;
2375    iapiRedirectCallback(requestId, redirectResponse);
2376}
2377
2378
2379//private
2380function iapiGetCookie(cname)
2381{
2382    var name = cname + "=";
2383    var ca = document.cookie.split(';');
2384    for (var i = 0; i < ca.length; i++)
2385    {
2386        var c = ca[i];
2387        while (c.charAt(0) == ' ')
2388            c = c.substring(1);
2389        if (c.indexOf(name) == 0)
2390            return c.substring(name.length, c.length);
2391    }
2392    return "";
2393}
2394
2395function encodeHTML(str)
2396{
2397    var e = document.createElement('div');
2398    var text = document.createTextNode(str);
2399    e.appendChild(text);
2400    return e.innerHTML.replace(/\'/g, '&#39;');
2401}
2402
2403function encodeURL(str)
2404{
2405    str = JSON.stringify(str);
2406    str = str.substring(1, str.length - 1);
2407    str = removeHex(str);
2408
2409    if (str.match(/^http/gi))
2410        return str.replace(/</g, '%3C').replace(/>/g, '%3E').replace(/\"/g, '%22').replace(/\'/g, '%27');
2411    else
2412        return '';
2413}
2414
2415function removeHex(str)
2416{
2417    return str.replace(/&#(\d+);/g, '').replace(/&#x([A-Za-z0-9]+);/g, '');
2418}
2419
2420// Production steps of ECMA-262, Edition 5, 15.4.4.14
2421// Reference: http://es5.github.io/#x15.4.4.14
2422// Support for IE8
2423if (!Array.prototype.indexOf)
2424{
2425    Array.prototype.indexOf = function(searchElement, fromIndex)
2426    {
2427        var k;
2428
2429        // 1. Let O be the result of calling ToObject passing
2430        // the this value as the argument.
2431        if (this == null)
2432        {
2433            throw new TypeError('"this" is null or not defined');
2434        }
2435
2436        var O = Object(this);
2437
2438        // 2. Let lenValue be the result of calling the Get
2439        // internal method of O with the argument "length".
2440        // 3. Let len be ToUint32(lenValue).
2441        var len = O.length >>> 0;
2442
2443        // 4. If len is 0, return -1.
2444        if (len === 0)
2445        {
2446            return -1;
2447        }
2448
2449        // 5. If argument fromIndex was passed let n be
2450        // ToInteger(fromIndex); else let n be 0.
2451        var n = +fromIndex || 0;
2452
2453        if (Math.abs(n) === Infinity)
2454        {
2455            n = 0;
2456        }
2457
2458        // 6. If n >= len, return -1.
2459        if (n >= len)
2460        {
2461            return -1;
2462        }
2463
2464        // 7. If n >= 0, then Let k be n.
2465        // 8. Else, n<0, Let k be len - abs(n).
2466        // If k is less than 0, then let k be 0.
2467        k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
2468
2469        // 9. Repeat, while k < len
2470        while (k < len)
2471        {
2472            // a. Let Pk be ToString(k).
2473            // This is implicit for LHS operands of the in operator
2474            // b. Let kPresent be the result of calling the
2475            // HasProperty internal method of O with argument Pk.
2476            // This step can be combined with c
2477            // c. If kPresent is true, then
2478            // i. Let elementK be the result of calling the Get
2479            // internal method of O with the argument ToString(k).
2480            // ii. Let same be the result of applying the
2481            // Strict Equality Comparison Algorithm to
2482            // searchElement and elementK.
2483            // iii. If same is true, return k.
2484            if (k in O && O[k] === searchElement)
2485            {
2486                return k;
2487            }
2488            k++;
2489        }
2490        return -1;
2491    };
2492}
2493
2494function getCurrentDomain(){
2495    if (self.$currentDomain)
2496        return self.$currentDomain;
2497
2498    return self.$currentDomain = (function(){
2499        var i=0,domain=document.domain,p=domain.split('.'),s='_gd'+(new Date()).getTime();
2500        while(i<(p.length-1) && document.cookie.indexOf(s+'='+s)==-1){
2501            domain = p.slice(-1-(++i)).join('.');
2502            document.cookie = s+"="+s+";domain="+domain+";";
2503        }
2504        document.cookie = s+"=;expires=Thu, 01 Jan 1970 00:00:01 GMT;domain="+domain+";";
2505        return domain;
2506    })();
2507}
2508
2509if (typeof iapiJsLoaded !== 'undefined') {
2510    iapiJsLoaded();
2511}
2512
2513function isSecureAttr()  {
2514    return iapiConf['setSecureAttr'] == "false" ? false : true;
2515}
2516
2517function getHttpProtocol() {
2518    return isSecureAttr() ? "https" : "http";
2519}
2520
2521function isDeviceAtlasEnabled() {
2522    return !iapiConf["disableDeviceAtlasIntegration"]
2523}
2524
2525var DeviceAtlas = {
2526    cacheType: "none",
2527    waitMilliSecondsToBulkSendProperties: 1000
2528}
2529
2530function shouldRunDeviceAtlas() {
2531    return navigator.userAgent.toLowerCase().search(/iphone|ipad/) !== -1
2532}
2533
2534function loadDeviceAtlasIfEnabled() {
2535    if (isDeviceAtlasEnabled() && shouldRunDeviceAtlas()) {
2536        return loadJsWrapperScript("dacs.js?v=2.7.3").catch(function(){/*ignored*/})
2537    }
2538    return Promise.resolve(false)
2539}
2540
2541var deviceAtlasLoaded = loadDeviceAtlasIfEnabled()
2542
2543function loadJsWrapperScript(scriptName) {
2544    return new Promise(function(resolve){
2545        const scriptElement = document.createElement("script");
2546        scriptElement.src = getHttpProtocol() + '://' + iapiConf["loginServer"] + '/jswrapper/' + scriptName;
2547        scriptElement.type = 'text/javascript'
2548        scriptElement.defer = true;
2549        scriptElement.onerror = function(err) {
2550            resolve(false);
2551        }
2552        scriptElement.onload = function() {
2553            resolve(true);
2554        }
2555        window.document.head.appendChild(scriptElement);
2556    })
2557}
2558
2559function clientHints() {
2560    function getBrandsConcatenated(brands) {
2561        return brands.map(function(value) {
2562            let brandEscaped = escapeDoubleQuoteAndBackslash(value.brand);
2563            return "\"" + brandEscaped +"\";v=\"" + value.version + "\"";
2564        }).join(", ");
2565    }
2566
2567    function escapeDoubleQuoteAndBackslash(value) {
2568        if (typeof value === 'string' && value){
2569            value = value.replace(/\\/, "\\\\").replace(/"/g, '\\"');
2570        }
2571        return value;
2572    }
2573
2574    function getBrowserList(fullVersionList, brands) {
2575        if (Array.isArray(fullVersionList) ){
2576            return getBrandsConcatenated(fullVersionList);
2577        } else if (Array.isArray(brands) ){
2578            return getBrandsConcatenated(brands);
2579        }
2580    }
2581
2582    function getPropertyQuoted(property) {
2583        if (property !== undefined && property !== null && property !== "") {
2584            return "\"" + escapeDoubleQuoteAndBackslash(property) + "\"";
2585        }
2586        return property;
2587    }
2588
2589    return {
2590        clientHintHeaders: new Promise(function(resolve, reject) {
2591            const navUAData = navigator && navigator.userAgentData
2592            if (navUAData && navUAData.getHighEntropyValues) {
2593                navUAData.getHighEntropyValues([
2594                    'model',
2595                    'platform',
2596                    'platformVersion',
2597                    'fullVersionList',
2598                ]).then(function(ua) {
2599                    resolve({
2600                        'Sec-CH-UA-Model': getPropertyQuoted(ua.model),
2601                        'Sec-CH-UA-Platform': getPropertyQuoted(ua.platform),
2602                        'Sec-CH-UA-Platform-Version': getPropertyQuoted(ua.platformVersion),
2603                        'Sec-CH-UA-Full-Version-List': getBrowserList(ua.fullVersionList, ua.brands)
2604                    })
2605                })
2606            } else {
2607                resolve(false);
2608            }
2609        })
2610    }
2611}

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.