Issues (130)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  Header Injection
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

create.php (6 issues)

Labels
1
<?php
2
3
// $Id$
4
//  ------------------------------------------------------------------------ //
5
//                XOOPS - PHP Content Management System                      //
6
//                    Copyright (c) 2000 XOOPS.org                           //
7
//                       <https://xoops.org>                             //
8
// ------------------------------------------------------------------------- //
9
//  This program is free software; you can redistribute it and/or modify     //
10
//  it under the terms of the GNU General Public License as published by     //
11
//  the Free Software Foundation; either version 2 of the License, or        //
12
//  (at your option) any later version.                                      //
13
//                                                                           //
14
//  You may not change or alter any portion of this comment or credits       //
15
//  of supporting developers from this source code or any supporting         //
16
//  source code which is considered copyrighted (c) material of the          //
17
//  original comment or credit authors.                                      //
18
//                                                                           //
19
//  This program is distributed in the hope that it will be useful,          //
20
//  but WITHOUT ANY WARRANTY; without even the implied warranty of           //
21
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            //
22
//  GNU General Public License for more details.                             //
23
//                                                                           //
24
//  You should have received a copy of the GNU General Public License        //
25
//  along with this program; if not, write to the Free Software              //
26
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA //
27
//  ------------------------------------------------------------------------ //
28
29
/**
30
 * This module handles chess game creation.
31
 *
32
 * The following forms are generated and processed:
33
 *
34
 *  - Create-form 1 - Specify game type (open challenge, individual challenge or self-play).
35
 *  - Create-form 2 - Specify opponent (for individual challenge), and color and rating options (for open challenge and individual challenge).
36
 *  - Create-form 3 - Confirm entries from forms 1 and 2.
37
 *  - Accept-form   - Accept challenge.
38
 *  - Delete-form   - Delete challenge.
39
 *
40
 * @package    chess
41
 * @subpackage challenge
42
 */
43
44
use XoopsModules\Chess;
45
use \Xmf\Request;
46
47
/**#@+
48
 */
49
50
require __DIR__ . '/header.php';
51
$xoopsConfig['module_cache'][$xoopsModule->getVar('mid')] = 0; // disable caching
52
53
require_once XOOPS_ROOT_PATH . '/class/xoopsformloader.php';
54
require_once XOOPS_ROOT_PATH . '/modules/chess/include/constants.inc.php';
55
require_once XOOPS_ROOT_PATH . '/modules/chess/include/functions.php';
56
57
#var_dump($_REQUEST);#*#DEBUG#
58
59
if (!chess_can_play()) {
60
    redirect_header(XOOPS_URL . '/index.php', _CHESS_REDIRECT_DELAY_FAILURE, _NOPERM);
61
}
62
63
// user input
64
//$gametype          = chess_sanitize(@$_POST['gametype']);
65
//$opponent          = chess_sanitize(trim(@$_POST['opponent']), _CHESS_USERNAME_ALLOWED_CHARACTERS);
66
$gametype     = Request::getCmd('gametype', '', 'POST');
67
$opponent     = preg_replace('/[^' . _CHESS_USERNAME_ALLOWED_CHARACTERS . ']/i', '', Request::getString('opponent', '', 'POST'));
68
$opponent     = trim($opponent);
69
$opponent_uid      = !empty($opponent) ? chess_opponent_uid($opponent) : 0;
70
//$fen               = chess_moduleConfig('allow_setup') ? chess_sanitize(trim(@$_POST['fen']), 'A-Za-z0-9 /-') : '';
71
$fen               = chess_moduleConfig('allow_setup') ? preg_replace('/[^a-z0-9 \/\-]/i', '', Request::getString('fen', '', 'POST')) : '';
72
$coloroption       = chess_sanitize(@$_POST['coloroption']);
73
$rated             = Request::getInt('rated', 0);
74
$notify_accept     = Request::hasVar('notify_accept', 'POST');
75
$notify_move       = Request::hasVar('notify_move', 'POST');
76
$challenge_id      = Request::getInt('challenge_id', 0);
77
$show_arbiter_ctrl = Request::hasVar('show_arbiter_ctrl', 'POST');
78
$submit_challenge1 = Request::hasVar('submit_challenge1', 'POST');
79
$submit_challenge2 = Request::hasVar('submit_challenge2', 'POST');
80
$submit_challenge3 = Request::hasVar('submit_challenge3', 'POST');
81
$cancel_challenge1 = Request::hasVar('cancel_challenge1', 'POST');
82
$cancel_challenge2 = Request::hasVar('cancel_challenge2', 'POST');
83
$cancel_challenge3 = Request::hasVar('cancel_challenge3', 'POST');
84
$submit_accept     = Request::hasVar('submit_accept', 'POST');
85
$cancel_accept     = Request::hasVar('cancel_accept', 'POST');
86
$submit_delete     = Request::hasVar('submit_delete', 'POST');
87
$confirm_delete    = Request::getInt('confirm_delete', 0, 'POST');
88
89
// If form-submit, check security token.
90
if (($submit_challenge1 || $submit_challenge2 || $submit_challenge3 || $submit_accept || $submit_delete || $show_arbiter_ctrl) && is_object($GLOBALS['xoopsSecurity']) && !$GLOBALS['xoopsSecurity']->check()) {
91
    redirect_header(
92
        XOOPS_URL . '/modules/chess/',
93
        _CHESS_REDIRECT_DELAY_FAILURE,
94
        _MD_CHESS_TOKEN_ERROR . '<br>' . implode('<br>', $GLOBALS['xoopsSecurity']->getErrors())
95
    );
96
}
97
98
// If rating feature disabled, force ratings to off.
99
if ('none' == chess_moduleConfig('rating_system')) {
100
    $rated = 0;
101
}
102
103
$uid = is_object($xoopsUser) ? $xoopsUser->getVar('uid') : 0;
104
105
// Determine if user is a valid arbiter.
106
$is_arbiter = is_object($xoopsUser) && $xoopsUser->isAdmin($xoopsModule->getVar('mid'));
107
108
if ($cancel_challenge1) {
109
    redirect_header(XOOPS_URL . '/modules/chess/', _CHESS_REDIRECT_DELAY_SUCCESS, _TAKINGBACK);
110
} elseif ($cancel_challenge2) {
111
    chess_show_create_form1($gametype);
112
} elseif ($cancel_challenge3) {
113
    if (_CHESS_GAMETYPE_OPEN == $gametype || _CHESS_GAMETYPE_USER == $gametype) {
114
        chess_show_create_form2($gametype, $fen);
115
    } else {
116
        chess_show_create_form1($gametype, $fen);
117
    }
118
} elseif ($cancel_accept) {
119
    redirect_header(XOOPS_URL . '/modules/chess/', _CHESS_REDIRECT_DELAY_SUCCESS, _TAKINGBACK);
120
} elseif ($submit_challenge1) {
121
    $fen_error = chess_fen_error($fen);
122
123
    if (!empty($fen_error)) {
124
        chess_show_create_form1($gametype, $fen, _MD_CHESS_FEN_INVALID . ': ' . $fen_error);
125
    } elseif (_CHESS_GAMETYPE_OPEN == $gametype || _CHESS_GAMETYPE_USER == $gametype) {
126
        chess_show_create_form2($gametype, $fen);
127
    } else {
128
        chess_show_create_form3($gametype, $fen, $coloroption, $opponent_uid, $rated);
129
    }
130
} elseif ($submit_challenge2) {
131
    if (_CHESS_GAMETYPE_USER == $gametype) {
132
        if (empty($opponent)) {
133
            chess_show_create_form2($gametype, $fen, $coloroption, $opponent_uid, $rated, _MD_CHESS_OPPONENT_MISSING);
134
        } elseif (!$opponent_uid) {
135
            chess_show_create_form2($gametype, $fen, $coloroption, $opponent_uid, $rated, _MD_CHESS_OPPONENT_INVALID);
136
        } elseif ($opponent_uid == $uid) {
137
            chess_show_create_form2($gametype, $fen, $coloroption, $opponent_uid, $rated, _MD_CHESS_OPPONENT_SELF);
138
        } else {
139
            chess_show_create_form3($gametype, $fen, $coloroption, $opponent_uid, $rated);
140
        }
141
    } else {
142
        chess_show_create_form3($gametype, $fen, $coloroption, $opponent_uid, $rated);
143
    }
144
} elseif ($submit_challenge3) {
145
    if (_CHESS_GAMETYPE_OPEN == $gametype) {
146
        chess_create_challenge($gametype, $fen, $coloroption, $rated, $notify_accept, $notify_move);
147
148
        redirect_header(XOOPS_URL . '/modules/chess/', _CHESS_REDIRECT_DELAY_SUCCESS, _MD_CHESS_GAME_CREATED);
149
    } elseif (_CHESS_GAMETYPE_USER == $gametype) {
150
        if (empty($opponent)) {
151
            chess_show_create_form2($gametype, $fen, $coloroption, $opponent_uid, $rated, _MD_CHESS_OPPONENT_MISSING);
152
        } elseif (!$opponent_uid) {
153
            chess_show_create_form2($gametype, $fen, $coloroption, $opponent_uid, $rated, _MD_CHESS_OPPONENT_INVALID);
154
        } elseif ($opponent_uid == $uid) {
155
            chess_show_create_form2($gametype, $fen, $coloroption, $opponent_uid, $rated, _MD_CHESS_OPPONENT_SELF);
156
        } else {
157
            chess_create_challenge($gametype, $fen, $coloroption, $rated, $notify_accept, $notify_move, $opponent_uid);
158
159
            redirect_header(XOOPS_URL . '/modules/chess/', _CHESS_REDIRECT_DELAY_SUCCESS, _MD_CHESS_GAME_CREATED);
160
        }
161
    } elseif (_CHESS_GAMETYPE_SELF == $gametype) {
162
        $game_id = chess_create_game($uid, $uid, $fen, $rated);
163
164
        redirect_header(XOOPS_URL . "/modules/chess/game.php?game_id=$game_id", _CHESS_REDIRECT_DELAY_SUCCESS, _MD_CHESS_GAME_CREATED);
165
    } else {
166
        chess_show_create_form1($gametype, $fen, _MD_CHESS_GAMETYPE_INVALID);
167
    }
168
} elseif ($submit_accept) {
169
    chess_accept_challenge($challenge_id, $coloroption, $notify_move);
170
} elseif ($submit_delete) {
171
    if ($confirm_delete) {
172
        if ($is_arbiter || chess_is_challenger($challenge_id)) {
173
            chess_delete_challenge($challenge_id);
174
175
            redirect_header(XOOPS_URL . '/modules/chess/', _CHESS_REDIRECT_DELAY_SUCCESS, _MD_CHESS_GAME_DELETED);
176
        } else {
177
            redirect_header(XOOPS_URL . '/modules/chess/', _CHESS_REDIRECT_DELAY_FAILURE, _NOPERM);
178
        }
179
    } else {
180
        chess_show_delete_form($challenge_id, $show_arbiter_ctrl && $is_arbiter, _MD_CHESS_NO_CONFIRM_DELETE);
181
    }
182
} elseif ($challenge_id) {
183
    if (($show_arbiter_ctrl && $is_arbiter) || chess_is_challenger($challenge_id)) {
184
        chess_show_delete_form($challenge_id, $show_arbiter_ctrl && $is_arbiter);
185
    } else {
186
        chess_show_accept_form($challenge_id);
187
    }
188
} else {
189
    chess_show_create_form1($gametype);
190
}
191
192
require_once XOOPS_ROOT_PATH . '/footer.php';
193
/**#@-*/
194
195
/**
196
 * Generate form to get game type and optional FEN setup.
197
 *
198
 * @param string $gametype  _CHESS_GAMETYPE_OPEN, _CHESS_GAMETYPE_USER or _CHESS_GAMETYPE_SELF
199
 * @param string $fen       FEN setup
200
 * @param string $error_msg Error message to display
201
 */
202
function chess_show_create_form1($gametype = _CHESS_GAMETYPE_OPEN, $fen = '', $error_msg = '')
203
{
204
    $form = new XoopsThemeForm(_MD_CHESS_CREATE_FORM, 'create_form1', 'create.php', 'post', true);
205
206
    if ($error_msg) {
207
        $form->addElement(new XoopsFormLabel(_MD_CHESS_ERROR . ': ', '<div class="errorMsg">' . $error_msg . '</div>'));
208
    }
209
210
    $menu_gametype = new XoopsFormSelect(_MD_CHESS_LABEL_GAMETYPE . ':', 'gametype', $gametype, 1, false);
211
212
    $menu_gametype->addOption(_CHESS_GAMETYPE_OPEN, _MD_CHESS_MENU_GAMETYPE_OPEN);
213
214
    $menu_gametype->addOption(_CHESS_GAMETYPE_USER, _MD_CHESS_MENU_GAMETYPE_USER);
215
216
    $menu_gametype->addOption(_CHESS_GAMETYPE_SELF, _MD_CHESS_MENU_GAMETYPE_SELF);
217
218
    $form->addElement($menu_gametype);
219
220
    if (chess_moduleConfig('allow_setup')) {
221
        $form->addElement(new XoopsFormLabel('', '&nbsp;'));
222
223
        $form->addElement(new XoopsFormLabel('', _MD_CHESS_LABEL_FEN_EXPLAIN));
224
225
        $form->addElement(new XoopsFormText(_MD_CHESS_LABEL_FEN_SETUP . ':', 'fen', 80, _CHESS_TEXTBOX_FEN_MAXLEN, $fen));
226
    }
227
228
    $form->addElement(new XoopsFormLabel('&nbsp;', '&nbsp;'));
229
230
    $buttons = new XoopsFormElementTray('');
231
232
    $buttons->addElement(new XoopsFormButton('', 'submit_challenge1', _MD_CHESS_CREATE_SUBMIT, 'submit'));
233
234
    $buttons->addElement(new XoopsFormButton('', 'cancel_challenge1', _MD_CHESS_CREATE_CANCEL, 'submit'));
235
236
    $form->addElement($buttons);
237
238
    $form->display();
239
}
240
241
/**
242
 * Generate form to get color and rating options and, if game type is _CHESS_GAMETYPE_USER (Individual challenge), get opponent.
243
 *
244
 * @param string $gametype     _CHESS_GAMETYPE_OPEN, _CHESS_GAMETYPE_USER or _CHESS_GAMETYPE_SELF
245
 * @param string $fen          FEN setup
246
 * @param string $coloroption  _CHESS_COLOROPTION_OPPONENT, _CHESS_COLOROPTION_RANDOM, _CHESS_COLOROPTION_WHITE or _CHESS_COLOROPTION_BLACK
247
 * @param int    $opponent_uid Opponent's user ID ('0' for open challenge)
248
 * @param int    $rated        '1' if rated, '0' if not rated
249
 * @param string $error_msg    Error message to display
250
 */
251
function chess_show_create_form2($gametype, $fen, $coloroption = _CHESS_COLOROPTION_OPPONENT, $opponent_uid = 0, $rated = 1, $error_msg = '')
252
{
253
    $form = new XoopsThemeForm(_MD_CHESS_CREATE_FORM, 'create_form2', 'create.php', 'post', true);
254
255
    $form->addElement(new XoopsFormHidden('gametype', $gametype));
256
257
    $form->addElement(new XoopsFormHidden('fen', $fen));
258
259
    if ($error_msg) {
260
        $form->addElement(new XoopsFormLabel(_MD_CHESS_ERROR . ':', '<div class="errorMsg">' . $error_msg . '</div>'));
261
    }
262
263
    $memberHandler = xoops_getHandler('member');
264
265
    $opponent_user = $memberHandler->getUser($opponent_uid);
0 ignored issues
show
The method getUser() does not exist on XoopsObjectHandler. It seems like you code against a sub-type of XoopsObjectHandler such as XoopsAvatarHandler or XoopsPersistableObjectHandler. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

265
    /** @scrutinizer ignore-call */ 
266
    $opponent_user = $memberHandler->getUser($opponent_uid);
Loading history...
266
267
    $opponent_username = is_object($opponent_user) ? $opponent_user->getVar('uname') : '';
268
269
    if (_CHESS_GAMETYPE_USER == $gametype) {
270
        $form->addElement(
271
            new XoopsFormText(
272
                _MD_CHESS_LABEL_OPPONENT . ':', 'opponent', _CHESS_TEXTBOX_OPPONENT_SIZE, _CHESS_TEXTBOX_OPPONENT_MAXLEN, $opponent_username
273
            )
274
        );
275
    }
276
277
    $radio_color = new XoopsFormRadio(_MD_CHESS_LABEL_COLOR . ':', 'coloroption', $coloroption);
278
279
    $radio_color->addOption(_CHESS_COLOROPTION_OPPONENT, _MD_CHESS_RADIO_COLOR_OPPONENT);
280
281
    $radio_color->addOption(_CHESS_COLOROPTION_RANDOM, _MD_CHESS_RADIO_COLOR_RANDOM);
282
283
    $radio_color->addOption(_CHESS_COLOROPTION_WHITE, _MD_CHESS_RADIO_COLOR_WHITE);
284
285
    $radio_color->addOption(_CHESS_COLOROPTION_BLACK, _MD_CHESS_RADIO_COLOR_BLACK);
286
287
    $form->addElement($radio_color);
288
289
    if ('none' !== chess_moduleConfig('rating_system')) {
290
        if (_CHESS_GAMETYPE_OPEN == $gametype || _CHESS_GAMETYPE_USER == $gametype) {
291
            if (chess_moduleConfig('allow_unrated_games')) {
292
                $radio_rated = new XoopsFormRadio(_MD_CHESS_RATED_GAME . ':', 'rated', $rated);
293
294
                $radio_rated->addOption(1, _YES);
295
296
                $radio_rated->addOption(0, _NO);
297
298
                $form->addElement($radio_rated);
299
            } else {
300
                $form->addElement(new XoopsFormHidden('rated', $rated));
301
            }
302
        }
303
    } else {
304
        $form->addElement(new XoopsFormHidden('rated', 0));
305
    }
306
307
    $buttons = new XoopsFormElementTray('');
308
309
    $buttons->addElement(new XoopsFormButton('', 'submit_challenge2', _MD_CHESS_CREATE_SUBMIT, 'submit'));
310
311
    $buttons->addElement(new XoopsFormButton('', 'cancel_challenge2', _MD_CHESS_CREATE_CANCEL, 'submit'));
312
313
    $form->addElement($buttons);
314
315
    $form->display();
316
}
317
318
/**
319
 * Generate form to get confirmation of a new challenge.
320
 *
321
 * @param string $gametype     _CHESS_GAMETYPE_OPEN, _CHESS_GAMETYPE_USER or _CHESS_GAMETYPE_SELF
322
 * @param string $fen          FEN setup
323
 * @param string $coloroption  _CHESS_COLOROPTION_OPPONENT, _CHESS_COLOROPTION_RANDOM, _CHESS_COLOROPTION_WHITE or _CHESS_COLOROPTION_BLACK
324
 * @param int    $opponent_uid Opponent's user ID ('0' for open challenge)
325
 * @param int    $rated        '1' if rated, '0' if not rated
326
 */
327
function chess_show_create_form3($gametype, $fen, $coloroption, $opponent_uid, $rated)
328
{
329
    $memberHandler = xoops_getHandler('member');
330
331
    $opponent_user = $memberHandler->getUser($opponent_uid);
332
333
    $opponent_username = is_object($opponent_user) ? $opponent_user->getVar('uname') : '';
334
335
    $form = new XoopsThemeForm(_MD_CHESS_CREATE_FORM, 'create_form3', 'create.php', 'post', true);
336
337
    $form->addElement(new XoopsFormHidden('gametype', $gametype));
338
339
    $form->addElement(new XoopsFormHidden('fen', $fen));
340
341
    $form->addElement(new XoopsFormHidden('opponent', $opponent_username));
342
343
    $form->addElement(new XoopsFormHidden('coloroption', $coloroption));
344
345
    $form->addElement(new XoopsFormHidden('rated', $rated));
346
347
    $form->addElement(new XoopsFormLabel('', '<div class="confirmMsg">' . _MD_CHESS_GAME_CONFIRM . '</div>'));
348
349
    switch ($gametype) {
350
        case _CHESS_GAMETYPE_OPEN:
351
            $label_gametype = _MD_CHESS_LABEL_GAMETYPE_OPEN;
352
            break;
353
        case _CHESS_GAMETYPE_USER:
354
            $label_gametype = _MD_CHESS_LABEL_GAMETYPE_USER;
355
            break;
356
        case _CHESS_GAMETYPE_SELF:
357
            $label_gametype = _MD_CHESS_LABEL_GAMETYPE_SELF;
358
            break;
359
        default:
360
            $label_gametype = _MD_CHESS_LABEL_ERROR;
361
            break;
362
    }
363
364
    $form->addElement(new XoopsFormLabel(_MD_CHESS_LABEL_GAMETYPE . ':', $label_gametype));
365
366
    if (!empty($fen)) {
367
        $form->addElement(new XoopsFormLabel(_MD_CHESS_LABEL_FEN_SETUP . ':', $fen));
368
    }
369
370
    if (_CHESS_GAMETYPE_USER == $gametype) {
371
        $memberHandler = xoops_getHandler('member');
372
373
        $opponent_user = $memberHandler->getUser($opponent_uid);
374
375
        $opponent_username = is_object($opponent_user) ? $opponent_user->getVar('uname') : '';
376
377
        $form->addElement(new XoopsFormLabel(_MD_CHESS_LABEL_OPPONENT . ':', $opponent_username));
378
    }
379
380
    if (_CHESS_GAMETYPE_OPEN == $gametype || _CHESS_GAMETYPE_USER == $gametype) {
381
        switch ($coloroption) {
382
            case _CHESS_COLOROPTION_OPPONENT:
383
                $label_coloroption = _MD_CHESS_RADIO_COLOR_OPPONENT;
384
                break;
385
            case _CHESS_COLOROPTION_RANDOM:
386
                $label_coloroption = _MD_CHESS_RADIO_COLOR_RANDOM;
387
                break;
388
            case _CHESS_COLOROPTION_WHITE:
389
                $label_coloroption = _MD_CHESS_RADIO_COLOR_WHITE;
390
                break;
391
            case _CHESS_COLOROPTION_BLACK:
392
                $label_coloroption = _MD_CHESS_RADIO_COLOR_BLACK;
393
                break;
394
            default:
395
                $label_coloroption = _MD_CHESS_LABEL_ERROR;
396
                break;
397
        }
398
399
        $form->addElement(new XoopsFormLabel(_MD_CHESS_LABEL_COLOR . ':', $label_coloroption));
400
401
        if ('none' != chess_moduleConfig('rating_system')) {
402
            $form->addElement(new XoopsFormLabel(_MD_CHESS_RATED_GAME . ':', $rated ? _YES : _NO));
403
        }
404
405
        // Determine whether current user is subscribed to receive a notification when his challenge is accepted.
406
407
        global $xoopsModule, $xoopsUser;
408
409
        $uid = $xoopsUser->getVar('uid');
410
411
        $mid = $xoopsModule->getVar('mid');
412
413
        $notificationHandler = xoops_getHandler('notification');
414
415
        $is_subscribed = 0 != $notificationHandler->isSubscribed('global', 0, 'notify_accept_challenge', $mid, $uid);
0 ignored issues
show
The method isSubscribed() does not exist on XoopsObjectHandler. It seems like you code against a sub-type of XoopsObjectHandler such as XoopsNotificationHandler or XoopsPersistableObjectHandler. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

415
        $is_subscribed = 0 != $notificationHandler->/** @scrutinizer ignore-call */ isSubscribed('global', 0, 'notify_accept_challenge', $mid, $uid);
Loading history...
416
417
        // Display checkbox with checked-state reflecting subscription status.
418
419
        $checked_value = 1;
420
421
        $checkbox_notify_acpt_chal = new XoopsFormCheckBox('', 'notify_accept', $is_subscribed ? $checked_value : null);
422
423
        $checkbox_notify_acpt_chal->addOption($checked_value, _MD_CHESS_NEVT_ACPT_CHAL_CAP);
424
425
        $form->addElement($checkbox_notify_acpt_chal);
426
427
        // Display checkbox, initially checked.
428
429
        $checked_value = 1;
430
431
        $checkbox_notify_move = new XoopsFormCheckBox('', 'notify_move', $checked_value);
432
433
        $checkbox_notify_move->addOption($checked_value, _MD_CHESS_NEVT_MOVE_CAP);
434
435
        $form->addElement($checkbox_notify_move);
436
    }
437
438
    $buttons = new XoopsFormElementTray('');
439
440
    $buttons->addElement(new XoopsFormButton('', 'submit_challenge3', _MD_CHESS_CREATE_SUBMIT, 'submit'));
441
442
    $buttons->addElement(new XoopsFormButton('', 'cancel_challenge3', _MD_CHESS_CREATE_CANCEL, 'submit'));
443
444
    $form->addElement($buttons);
445
446
    $form->display();
447
}
448
449
/**
450
 * Generate form to get acceptance of a challenge.
451
 *
452
 * @param int $challenge_id Challenge ID
453
 */
454
function chess_show_accept_form($challenge_id)
455
{
456
    global $xoopsDB, $xoopsUser;
457
458
    $challenges_table = $xoopsDB->prefix('chess_challenges');
459
460
    $result = $xoopsDB->query(
461
        trim(
462
            "
463
        SELECT game_type, fen, color_option, player1_uid, player2_uid, UNIX_TIMESTAMP(create_date) as create_date, is_rated
464
        FROM   $challenges_table
465
        WHERE  challenge_id = '$challenge_id'
466
    "
467
        )
468
    );
469
470
    if ($xoopsDB->getRowsNum($result) < 1) {
471
        redirect_header(XOOPS_URL . '/modules/chess/', _CHESS_REDIRECT_DELAY_FAILURE, _MD_CHESS_GAME_NOT_FOUND);
472
    }
473
474
    $row = $xoopsDB->fetchArray($result);
475
476
    $xoopsDB->freeRecordSet($result);
477
478
    $form = new XoopsThemeForm(_MD_CHESS_ACCEPT_FORM, 'accept_form', 'create.php', 'post', true);
479
480
    $form->addElement(new XoopsFormHidden('challenge_id', $challenge_id));
481
482
    $form->addElement(new XoopsFormLabel(_MD_CHESS_LABEL_DATE_CREATED . ':', formatTimestamp($row['create_date'], 'm')));
483
484
    $memberHandler = xoops_getHandler('member');
485
486
    switch ($row['game_type']) {
487
        case _CHESS_GAMETYPE_OPEN:
488
            $label_gametype = _MD_CHESS_LABEL_GAMETYPE_OPEN;
489
            break;
490
        case _CHESS_GAMETYPE_USER:
491
            $player2_user     = $memberHandler->getUser($row['player2_uid']);
492
            $player2_username = is_object($player2_user) ? $player2_user->getVar('uname') : '?';
493
            $label_gametype   = _MD_CHESS_LABEL_GAMETYPE_USER . ': ' . $player2_username;
494
            break;
495
        case _CHESS_GAMETYPE_SELF:
496
            $label_gametype = _MD_CHESS_LABEL_GAMETYPE_SELF;
497
            break;
498
        default:
499
            $label_gametype = _MD_CHESS_LABEL_ERROR;
500
            break;
501
    }
502
503
    $form->addElement(new XoopsFormLabel(_MD_CHESS_LABEL_GAMETYPE . ':', $label_gametype));
504
505
    $player1_user = $memberHandler->getUser($row['player1_uid']);
506
507
    $player1_username = is_object($player1_user) ? $player1_user->getVar('uname') : '?';
508
509
    $form->addElement(
510
        new XoopsFormLabel(
511
            _MD_CHESS_LABEL_CHALLENGER . ':', "<a href='" . XOOPS_URL . "/modules/chess/player_stats.php?player_uid={$row['player1_uid']}'>$player1_username</a>"
512
        )
513
    );
514
515
    $player2_username = $xoopsUser ? $xoopsUser->getVar('uname') : '?';
516
517
    $form->addElement(new XoopsFormLabel(_MD_CHESS_LABEL_OPPONENT . ':', $player2_username));
518
519
    if (!empty($row['fen'])) {
520
        $form->addElement(new XoopsFormLabel(_MD_CHESS_LABEL_FEN_SETUP . ':', $row['fen']));
521
    }
522
523
    if (_CHESS_COLOROPTION_OPPONENT == $row['color_option']) {
524
        $radio_color = new XoopsFormRadio(_MD_CHESS_LABEL_COLOR . ':', 'coloroption', _CHESS_COLOROPTION_RANDOM);
525
526
        $radio_color->addOption(_CHESS_COLOROPTION_RANDOM, _MD_CHESS_RADIO_COLOR_RANDOM);
527
528
        $radio_color->addOption(_CHESS_COLOROPTION_WHITE, _MD_CHESS_RADIO_COLOR_WHITE);
529
530
        $radio_color->addOption(_CHESS_COLOROPTION_BLACK, _MD_CHESS_RADIO_COLOR_BLACK);
531
532
        $form->addElement($radio_color);
533
    } else {
534
        switch ($row['color_option']) {
535
            case _CHESS_COLOROPTION_RANDOM:
536
                $label_coloroption = _MD_CHESS_RADIO_COLOR_RANDOM;
537
                break;
538
            case _CHESS_COLOROPTION_WHITE:
539
                $label_coloroption = _MD_CHESS_RADIO_COLOR_BLACK; // player1 white, player2 black
540
                break;
541
            case _CHESS_COLOROPTION_BLACK:
542
                $label_coloroption = _MD_CHESS_RADIO_COLOR_WHITE; // player1 black, player2 white
543
                break;
544
            default:
545
                $label_coloroption = _MD_CHESS_LABEL_ERROR;
546
                break;
547
        }
548
549
        $form->addElement(new XoopsFormLabel(_MD_CHESS_LABEL_COLOR . ':', $label_coloroption));
550
    }
551
552
    if ('none' != chess_moduleConfig('rating_system')) {
553
        $form->addElement(new XoopsFormLabel(_MD_CHESS_RATED_GAME . ':', $row['is_rated'] ? _YES : _NO));
554
    }
555
556
    // Display notification-subscribe checkbox, initially checked.
557
558
    $checked_value = 1;
559
560
    $checkbox_notify_move = new XoopsFormCheckBox('', 'notify_move', $checked_value);
561
562
    $checkbox_notify_move->addOption($checked_value, _MD_CHESS_NEVT_MOVE_CAP);
563
564
    $form->addElement($checkbox_notify_move);
565
566
    $tray = new XoopsFormElementTray('');
567
568
    $tray->addElement(new XoopsFormButton('', 'submit_accept', _MD_CHESS_CREATE_ACCEPT, 'submit'));
569
570
    $tray->addElement(new XoopsFormButton('', 'cancel_accept', _MD_CHESS_CREATE_CANCEL, 'submit'));
571
572
    $form->addElement($tray);
573
574
    $form->display();
575
}
576
577
/**
578
 * Generate form to delete challenge.
579
 *
580
 * @param int    $challenge_id      Challenge ID
581
 * @param bool   $show_arbiter_ctrl True if form generated from admin page
582
 * @param string $error_msg         Error message to display
583
 */
584
function chess_show_delete_form($challenge_id, $show_arbiter_ctrl, $error_msg = '')
585
{
586
    global $xoopsDB;
587
588
    $challenges_table = $xoopsDB->prefix('chess_challenges');
589
590
    $result = $xoopsDB->query(
591
        trim(
592
            "
593
        SELECT game_type, fen, color_option, player1_uid, player2_uid, UNIX_TIMESTAMP(create_date) as create_date, is_rated
594
        FROM   $challenges_table
595
        WHERE  challenge_id = '$challenge_id'
596
    "
597
        )
598
    );
599
600
    if ($xoopsDB->getRowsNum($result) < 1) {
601
        redirect_header(XOOPS_URL . '/modules/chess/', _CHESS_REDIRECT_DELAY_FAILURE, _MD_CHESS_GAME_NOT_FOUND);
602
    }
603
604
    $row = $xoopsDB->fetchArray($result);
605
606
    $xoopsDB->freeRecordSet($result);
607
608
    $form = new XoopsThemeForm(_MD_CHESS_DELETE_FORM, 'delete_form', 'create.php', 'post', true);
609
610
    $form->addElement(new XoopsFormHidden('challenge_id', $challenge_id));
611
612
    if ($show_arbiter_ctrl) {
613
        $form->addElement(new XoopsFormHidden('show_arbiter_ctrl', $show_arbiter_ctrl));
0 ignored issues
show
$show_arbiter_ctrl of type true is incompatible with the type string expected by parameter $value of XoopsFormHidden::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

613
        $form->addElement(new XoopsFormHidden('show_arbiter_ctrl', /** @scrutinizer ignore-type */ $show_arbiter_ctrl));
Loading history...
614
    }
615
616
    if ($error_msg) {
617
        $form->addElement(new XoopsFormLabel(_MD_CHESS_ERROR . ': ', '<div class="errorMsg">' . $error_msg . '</div>'));
618
    }
619
620
    $form->addElement(new XoopsFormLabel(_MD_CHESS_LABEL_DATE_CREATED . ':', formatTimestamp($row['create_date'], 'm')));
621
622
    $memberHandler = xoops_getHandler('member');
623
624
    switch ($row['game_type']) {
625
        case _CHESS_GAMETYPE_OPEN:
626
            $label_gametype = _MD_CHESS_LABEL_GAMETYPE_OPEN;
627
            break;
628
        case _CHESS_GAMETYPE_USER:
629
            $player2_user     = $memberHandler->getUser($row['player2_uid']);
630
            $player2_username = is_object($player2_user) ? $player2_user->getVar('uname') : '?';
631
            $label_gametype   = _MD_CHESS_LABEL_GAMETYPE_USER . ': ' . $player2_username;
632
            break;
633
        case _CHESS_GAMETYPE_SELF:
634
            $label_gametype = _MD_CHESS_LABEL_GAMETYPE_SELF;
635
            break;
636
        default:
637
            $label_gametype = _MD_CHESS_LABEL_ERROR;
638
            break;
639
    }
640
641
    $form->addElement(new XoopsFormLabel(_MD_CHESS_LABEL_GAMETYPE . ':', $label_gametype));
642
643
    $player1_user = $memberHandler->getUser($row['player1_uid']);
644
645
    $player1_username = is_object($player1_user) ? $player1_user->getVar('uname') : '?';
646
647
    $form->addElement(new XoopsFormLabel(_MD_CHESS_LABEL_CHALLENGER . ':', $player1_username));
648
649
    if (!empty($row['fen'])) {
650
        $form->addElement(new XoopsFormLabel(_MD_CHESS_LABEL_FEN_SETUP . ':', $row['fen']));
651
    }
652
653
    switch ($row['color_option']) {
654
        case _CHESS_COLOROPTION_OPPONENT:
655
            $label_coloroption = _MD_CHESS_RADIO_COLOR_OPPONENT;
656
            break;
657
        case _CHESS_COLOROPTION_RANDOM:
658
            $label_coloroption = _MD_CHESS_RADIO_COLOR_RANDOM;
659
            break;
660
        case _CHESS_COLOROPTION_WHITE:
661
            $label_coloroption = _MD_CHESS_RADIO_COLOR_WHITE;
662
            break;
663
        case _CHESS_COLOROPTION_BLACK:
664
            $label_coloroption = _MD_CHESS_RADIO_COLOR_BLACK;
665
            break;
666
        default:
667
            $label_coloroption = _MD_CHESS_LABEL_ERROR;
668
            break;
669
    }
670
671
    $form->addElement(new XoopsFormLabel(_MD_CHESS_LABEL_COLOR . ':', $label_coloroption));
672
673
    if ('none' != chess_moduleConfig('rating_system')) {
674
        $form->addElement(new XoopsFormLabel(_MD_CHESS_RATED_GAME . ':', $row['is_rated'] ? _YES : _NO));
675
    }
676
677
    // Display confirm-delete checkbox, initially unchecked.
678
679
    $checked_value = 1;
680
681
    $checkbox_confirm_delete = new XoopsFormCheckBox('', 'confirm_delete', !$checked_value);
682
683
    $checkbox_confirm_delete->addOption($checked_value, _MD_CHESS_CONFIRM_DELETE);
684
685
    $tray = new XoopsFormElementTray('');
686
687
    $tray->addElement(new XoopsFormButton('', 'submit_delete', _MD_CHESS_CREATE_DELETE, 'submit'));
688
689
    $tray->addElement($checkbox_confirm_delete);
690
691
    $form->addElement($tray);
692
693
    $form->display();
694
}
695
696
/**
697
 * Accept a challenge.
698
 *
699
 * @param int    $challenge_id        Challenge ID
700
 * @param string $coloroption         _CHESS_COLOROPTION_OPPONENT, _CHESS_COLOROPTION_RANDOM, _CHESS_COLOROPTION_WHITE or _CHESS_COLOROPTION_BLACK
701
 * @param bool   $notify_move_player2 If true, subscribe the accepter to receive a notification when a new move is made.
702
 * @throws \Exception
703
 */
704
function chess_accept_challenge($challenge_id, $coloroption, $notify_move_player2 = false)
705
{
706
    global $xoopsDB, $xoopsUser;
707
708
    $challenges_table = $xoopsDB->prefix('chess_challenges');
709
710
    $result = $xoopsDB->query(
711
        trim(
712
            "
713
        SELECT game_type, fen, color_option, notify_move_player1, player1_uid, player2_uid, UNIX_TIMESTAMP(create_date) as create_date, is_rated
714
        FROM   $challenges_table
715
        WHERE  challenge_id = '$challenge_id'
716
    "
717
        )
718
    );
719
720
    if ($xoopsDB->getRowsNum($result) < 1) {
721
        redirect_header(XOOPS_URL . '/modules/chess/', _CHESS_REDIRECT_DELAY_FAILURE, _MD_CHESS_GAME_NOT_FOUND);
722
    }
723
724
    $row = $xoopsDB->fetchArray($result);
725
726
    $xoopsDB->freeRecordSet($result);
727
728
    $uid = $xoopsUser ? $xoopsUser->getVar('uid') : 0;
729
730
    if (_CHESS_GAMETYPE_USER == $row['game_type'] && $uid != $row['player2_uid']) {
731
        redirect_header(XOOPS_URL . '/modules/chess/', _CHESS_REDIRECT_DELAY_FAILURE, _MD_CHESS_WRONG_PLAYER2);
732
    } elseif ($uid == $row['player1_uid']) {
733
        redirect_header(XOOPS_URL . '/modules/chess/', _CHESS_REDIRECT_DELAY_FAILURE, _MD_CHESS_SAME_PLAYER2);
734
    }
735
736
    switch ($row['color_option']) {
737
        case _CHESS_COLOROPTION_OPPONENT:
738
            switch ($coloroption) {
739
                default:
740
                case _CHESS_COLOROPTION_RANDOM:
741
                    if (1 == random_int(1, 2)) {
742
                        $white_uid = $row['player1_uid'];
743
                        $black_uid = $uid;
744
                    } else {
745
                        $white_uid = $uid;
746
                        $black_uid = $row['player1_uid'];
747
                    }
748
                    break;
749
                case _CHESS_COLOROPTION_WHITE:
750
                    $white_uid = $uid;
751
                    $black_uid = $row['player1_uid'];
752
                    break;
753
                case _CHESS_COLOROPTION_BLACK:
754
                    $white_uid = $row['player1_uid'];
755
                    $black_uid = $uid;
756
                    break;
757
            }
758
            break;
759
        default:
760
        case _CHESS_COLOROPTION_RANDOM:
761
            if (1 == random_int(1, 2)) {
762
                $white_uid = $row['player1_uid'];
763
764
                $black_uid = $uid;
765
            } else {
766
                $white_uid = $uid;
767
768
                $black_uid = $row['player1_uid'];
769
            }
770
            break;
771
        case _CHESS_COLOROPTION_WHITE:
772
            $white_uid = $row['player1_uid'];
773
            $black_uid = $uid;
774
            break;
775
        case _CHESS_COLOROPTION_BLACK:
776
            $white_uid = $uid;
777
            $black_uid = $row['player1_uid'];
778
            break;
779
    }
780
781
    $game_id = chess_create_game($white_uid, $black_uid, $row['fen'], $row['is_rated'], $row['notify_move_player1'] ? $row['player1_uid'] : 0, $notify_move_player2);
782
783
    $xoopsDB->query("DELETE FROM $challenges_table WHERE challenge_id = '$challenge_id'");
784
785
    if ($xoopsDB->errno()) {
786
        trigger_error($xoopsDB->errno() . ':' . $xoopsDB->error(), E_USER_ERROR);
787
    }
788
789
    // Notify player 1 that his challenge has been accepted (if he has subscribed to the notification).
790
791
    $player2_username = $xoopsUser ? $xoopsUser->getVar('uname') : '*unknown*';
792
793
    $notificationHandler = xoops_getHandler('notification');
794
795
    $extra_tags = ['CHESS_PLAYER' => $player2_username, 'CHESS_GAME_ID' => $game_id];
796
797
    $notificationHandler->triggerEvent('global', 0, 'notify_accept_challenge', $extra_tags, [$row['player1_uid']]);
0 ignored issues
show
The method triggerEvent() does not exist on XoopsObjectHandler. It seems like you code against a sub-type of XoopsObjectHandler such as XoopsNotificationHandler or XoopsPersistableObjectHandler. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

797
    $notificationHandler->/** @scrutinizer ignore-call */ 
798
                          triggerEvent('global', 0, 'notify_accept_challenge', $extra_tags, [$row['player1_uid']]);
Loading history...
798
799
    redirect_header(XOOPS_URL . "/modules/chess/game.php?game_id=$game_id", _CHESS_REDIRECT_DELAY_SUCCESS, _MD_CHESS_GAME_CREATED);
800
}
801
802
/**
803
 * Determine whether current user offered the specified challenge.
804
 *
805
 * @param int $challenge_id Challenge ID
806
 * @return bool
807
 */
808
function chess_is_challenger($challenge_id)
809
{
810
    global $xoopsDB, $xoopsUser;
811
812
    $challenges_table = $xoopsDB->prefix('chess_challenges');
813
814
    $result = $xoopsDB->query("SELECT player1_uid FROM $challenges_table WHERE challenge_id = '$challenge_id'");
815
816
    if ($xoopsDB->getRowsNum($result) < 1) {
817
        redirect_header(XOOPS_URL . '/modules/chess/', _CHESS_REDIRECT_DELAY_FAILURE, _MD_CHESS_GAME_NOT_FOUND);
818
    }
819
820
    $row = $xoopsDB->fetchArray($result);
821
822
    $xoopsDB->freeRecordSet($result);
823
824
    $uid = is_object($xoopsUser) ? $xoopsUser->getVar('uid') : 0;
825
826
    return $uid == $row['player1_uid'];
827
}
828
829
/**
830
 * Create a new challenge in the database.
831
 *
832
 * @param string $gametype            _CHESS_GAMETYPE_OPEN, _CHESS_GAMETYPE_USER or _CHESS_GAMETYPE_SELF
833
 * @param string $fen                 FEN setup
834
 * @param string $coloroption         _CHESS_COLOROPTION_OPPONENT, _CHESS_COLOROPTION_RANDOM, _CHESS_COLOROPTION_WHITE or _CHESS_COLOROPTION_BLACK
835
 * @param int    $rated               '1' if rated, '0' if not rated
836
 * @param bool   $notify_accept       Subscribe/unsubscribe the challenger for receiving a notification when the challenge is accepted.
837
 * @param bool   $notify_move_player1 If true, subscribe the challenger to receive a notification when a new move is made.
838
 * @param int    $opponent_uid        Opponent's user ID ('0' for open challenge)
839
 */
840
function chess_create_challenge($gametype, $fen, $coloroption, $rated, $notify_accept, $notify_move_player1, $opponent_uid = 0)
841
{
842
    #$where = __CLASS__ . '::' . __FUNCTION__;#*#DEBUG#
843
844
    #echo "In $where\n";#*#DEBUG#
845
846
    global $xoopsUser;
847
848
    $uid = is_object($xoopsUser) ? $xoopsUser->getVar('uid') : 0;
849
850
    $myts = MyTextSanitizer::getInstance();
851
852
    $fen_q = $myts->addSlashes($fen);
853
854
    #trigger_error("inserting new game'", E_USER_NOTICE);#*#DEBUG#
855
856
    global $xoopsDB;
857
858
    $table = $xoopsDB->prefix('chess_challenges');
859
860
    $xoopsDB->query(
861
        trim(
862
            "
863
        INSERT INTO $table
864
        SET
865
            game_type           = '$gametype',
866
            fen                 = '$fen_q',
867
            color_option        = '$coloroption',
868
            notify_move_player1 = '$notify_move_player1',
869
            player1_uid         = '$uid',
870
            player2_uid         = '$opponent_uid',
871
            create_date         = NOW(),
872
            is_rated            = '$rated'
873
    "
874
        )
875
    );
876
877
    if ($xoopsDB->errno()) {
878
        trigger_error($xoopsDB->errno() . ':' . $xoopsDB->error(), E_USER_ERROR);
879
    }
880
881
    $challenge_id = $xoopsDB->getInsertId();
882
883
    $notificationHandler = xoops_getHandler('notification');
884
885
    // Update the challenger's subscription for receiving a notification when the challenge is accepted.
886
887
    if ($notify_accept) {
888
        $notificationHandler->subscribe('global', 0, 'notify_accept_challenge');
0 ignored issues
show
The method subscribe() does not exist on XoopsObjectHandler. It seems like you code against a sub-type of XoopsObjectHandler such as XoopsNotificationHandler or XoopsPersistableObjectHandler. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

888
        $notificationHandler->/** @scrutinizer ignore-call */ 
889
                              subscribe('global', 0, 'notify_accept_challenge');
Loading history...
889
    } else {
890
        $notificationHandler->unsubscribe('global', 0, 'notify_accept_challenge');
0 ignored issues
show
The method unsubscribe() does not exist on XoopsObjectHandler. It seems like you code against a sub-type of XoopsObjectHandler such as XoopsNotificationHandler or XoopsPersistableObjectHandler. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

890
        $notificationHandler->/** @scrutinizer ignore-call */ 
891
                              unsubscribe('global', 0, 'notify_accept_challenge');
Loading history...
891
    }
892
893
    // Notify any subscribers that a challenge has been offered.
894
895
    $player1_username = $xoopsUser ? $xoopsUser->getVar('uname') : '*unknown*';
896
897
    $extra_tags = ['CHESS_CHALLENGER' => $player1_username, 'CHESS_CHALLENGE_ID' => $challenge_id];
898
899
    if (_CHESS_GAMETYPE_OPEN == $gametype) {
900
        $notificationHandler->triggerEvent('global', 0, 'notify_challenge_open', $extra_tags);
901
    } elseif (_CHESS_GAMETYPE_USER == $gametype) {
902
        $notificationHandler->triggerEvent('global', 0, 'notify_challenge_user', $extra_tags, [$opponent_uid]);
903
    }
904
}
905
906
/**
907
 * Delete a challenge from the database.
908
 *
909
 * @param int $challenge_id Challenge ID
910
 */
911
function chess_delete_challenge($challenge_id)
912
{
913
    global $xoopsDB;
914
915
    $table = $xoopsDB->prefix('chess_challenges');
916
917
    $xoopsDB->query("DELETE FROM $table WHERE challenge_id='$challenge_id'");
918
919
    if ($xoopsDB->errno()) {
920
        trigger_error($xoopsDB->errno() . ':' . $xoopsDB->error(), E_USER_ERROR);
921
    }
922
}
923
924
/**
925
 * Create a new game in the database.
926
 *
927
 * @param int    $white_uid               White's user ID
928
 * @param int    $black_uid               Black's user ID
929
 * @param string $fen                     FEN setup
930
 * @param int    $rated                   '1' if rated, '0' if not rated
931
 * @param int    $notify_move_player1_uid If nonzero, subscribe the challenger to receive a notification when a new move is made.
932
 * @param bool   $notify_move_player2     If true, subscribe the accepter to receive a notification when a new move is made.
933
 * @return int
934
 */
935
function chess_create_game($white_uid, $black_uid, $fen, $rated, $notify_move_player1_uid = 0, $notify_move_player2 = false)
936
{
937
    #$where = __CLASS__ . '::' . __FUNCTION__;#*#DEBUG#
938
939
    #echo "In $where\n";#*#DEBUG#
940
941
    #var_dump('white_uid', $white_uid, 'black_uid', $black_uid);#*#DEBUG#
942
943
    $chessgame = new Chess\ChessGame($fen);
944
945
    empty($chessgame->error) or trigger_error('chessgame invalid', E_USER_ERROR);
946
947
    $gamestate = $chessgame->gamestate();
948
949
    is_array($gamestate) or trigger_error('gamestate invalid', E_USER_ERROR);
950
951
    #trigger_error("inserting new game'", E_USER_NOTICE);#*#DEBUG#
952
953
    $myts = MyTextSanitizer::getInstance();
954
955
    $fen_q = $myts->addSlashes($fen);
956
957
    global $xoopsDB;
958
959
    $table = $xoopsDB->prefix('chess_games');
960
961
    $xoopsDB->query(
962
        trim(
963
            "
964
        INSERT INTO $table
965
        SET
966
            white_uid                    = '$white_uid',
967
            black_uid                    = '$black_uid',
968
            create_date                  = NOW(),
969
            start_date                   = '0000-00-00 00:00:00',
970
            last_date                    = '0000-00-00 00:00:00',
971
            fen_piece_placement          = '{$gamestate['fen_piece_placement']}',
972
            fen_active_color             = '{$gamestate['fen_active_color']}',
973
            fen_castling_availability    = '{$gamestate['fen_castling_availability']}',
974
            fen_en_passant_target_square = '{$gamestate['fen_en_passant_target_square']}',
975
            fen_halfmove_clock           = '{$gamestate['fen_halfmove_clock']}',
976
            fen_fullmove_number          = '{$gamestate['fen_fullmove_number']}',
977
            pgn_fen                      = '$fen_q',
978
            pgn_result                   = '{$gamestate['pgn_result']}',
979
            pgn_movetext                 = '{$gamestate['pgn_movetext']}',
980
            is_rated                     = '$rated'
981
    "
982
        )
983
    );
984
985
    if ($xoopsDB->errno()) {
986
        trigger_error($xoopsDB->errno() . ':' . $xoopsDB->error(), E_USER_ERROR);
987
    }
988
989
    $game_id = $xoopsDB->getInsertId();
990
991
    $notificationHandler = xoops_getHandler('notification');
992
993
    // If requested, subscribe the challenger to receive a notification when a new move is made.
994
995
    if ($notify_move_player1_uid) {
996
        $notificationHandler->subscribe('game', $game_id, 'notify_game_move', null, null, $notify_move_player1_uid);
997
    }
998
999
    // If requested, subscribe the accepter to receive a notification when a new move is made.
1000
1001
    if ($notify_move_player2) {
1002
        $notificationHandler->subscribe('game', $game_id, 'notify_game_move');
1003
    }
1004
1005
    return $game_id;
1006
}
1007
1008
/**
1009
 * Check whether a FEN setup is valid.
1010
 *
1011
 * @param string $fen FEN setup
1012
 * @return string  Empty string if FEN setup is valid, otherwise contains error message.
1013
 */
1014
function chess_fen_error($fen)
1015
{
1016
    if (!empty($fen)) {
1017
        $chessgame = new Chess\ChessGame($fen);
1018
1019
        $fen_error = $chessgame->error;
1020
    } else {
1021
        $fen_error = '';
1022
    }
1023
1024
    return $fen_error;
1025
}
1026
1027
/**
1028
 * Get user ID of specified chess opponent.
1029
 *
1030
 * This function is used to check whether the specified opponent is available, when offering an individual challenge.
1031
 *
1032
 * @param string $username Opponent's username
1033
 * @return int Opponent's user ID if opponent is registered and allowed to play chess, otherwise zero.
1034
 */
1035
function chess_opponent_uid($username)
1036
{
1037
    $uid = chess_uname_to_uid($username);
1038
1039
    $can_play = $uid > 0 ? chess_can_play($uid) : false;
1040
1041
    return $can_play ? $uid : 0;
1042
}
1043