investigation about callerimg placement
[brisk.git] / web / Obj / dbase_pgsql.phh
1 <?php
2   /*
3    *  brisk - dbase_pgsql.phh
4    *
5    *  Copyright (C) 2006-2015 Matteo Nastasi
6    *                          mailto: nastasi@alternativeoutput.it
7    *                                  matteo.nastasi@milug.org
8    *                          web: http://www.alternativeoutput.it
9    *
10    * This program is free software; you can redistribute it and/or modify
11    * it under the terms of the GNU General Public License as published by
12    * the Free Software Foundation; either version 2 of the License, or
13    * (at your option) any later version.
14    *
15    * This program is distributed in the hope that it will be useful, but
16    * WITHOUT ANY WARRANTY; without even the implied warranty of
17    * MERCHANTABLILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18    * General Public License for more details. You should have received a
19    * copy of the GNU General Public License along with this program; if
20    * not, write to the Free Software Foundation, Inc, 59 Temple Place -
21    * Suite 330, Boston, MA 02111-1307, USA.
22    *
23    */
24
25 require_once("${G_base}Obj/dbase_base.phh");
26
27 $escsql_from = array( "\\",   "'"   );
28 $escsql_to   = array( "\\\\", "''" );
29
30 function escsql($s)
31 {
32     GLOBAL $escsql_from, $escsql_to;
33
34     return str_replace($escsql_from, $escsql_to, $s);
35 }
36
37 class DBConn
38 {
39     static $dbcnnx = FALSE;
40     var $db = FALSE;
41
42     function DBConn()
43     {
44         $this->db = DBConn::$dbcnnx;
45     }
46
47     static function create()
48     {
49         GLOBAL $G_dbauth;
50
51         if (DBConn::$dbcnnx == FALSE) {
52             if (!(DBConn::$dbcnnx = @pg_connect ($G_dbauth, PGSQL_CONNECT_FORCE_NEW))) {
53                 return (FALSE);
54             }
55         }
56
57         $out = new DBConn();
58
59         return $out;
60     }
61
62     static function destroy()
63     {
64         if (DBConn::$dbcnnx != FALSE) {
65             $ret = pg_close(DBConn::$dbcnnx);
66             DBConn::$dbcnnx = FALSE;
67             return ($ret);
68         }
69         return TRUE;
70     }
71
72     static function recover()
73     {
74         self::destroy();
75         return (self::create());
76     }
77
78     function db()
79     {
80         return ($this->db);
81     }
82 }
83
84 class BriskDB
85 {
86     var $dbconn;
87     var $item;
88     var $item_n;
89
90     function BriskDB($dbconn)
91     {
92         $this->dbconn = $dbconn;
93     }
94
95     static function create()
96     {
97         GLOBAL $DOCUMENT_ROOT, $G_dbpfx;
98
99         $ret = FALSE;
100
101         log_main("BriskDB create:start");
102
103         do {
104             if (($dbconn = DBConn::create()) == FALSE) {
105                 break;
106             }
107
108             $ret = new BriskDB($dbconn);
109         } while (0);
110
111         return ($ret);
112     }
113
114     function query($sql)
115     {
116         if (!$this->dbconn)
117             if (($this->dbconn = DBConn::recover()) == FALSE)
118                 return FALSE;
119
120         if (($res = @pg_query($this->dbconn->db(), $sql)) == FALSE) {
121             error_log('pg_result_status: ' .  pg_result_status($res));
122             error_log('pg_connection_status: ' .  pg_connection_status($this->dbconn->db()));
123             // try to recover the connection
124             if (($this->dbconn = DBConn::recover()) == FALSE)
125                 return FALSE;
126             return (@pg_query($this->dbconn->db(), $sql));
127         }
128
129         return ($res);
130     }
131
132     function last_error()
133     {
134         return pg_last_error($this->dbconn->db);
135     }
136
137     function users_load()
138     {
139     }
140
141     function login_exists($login)
142     {
143         GLOBAL $G_dbpfx;
144
145         /* check the existence of the nick in the BriskDB */
146         log_main("login_exists: ".$login);
147
148         $user_sql = sprintf("SELECT * FROM %susers WHERE login = '%s'",
149                             $G_dbpfx, escsql($login));
150         if (($user_pg = $this->query($user_sql)) != FALSE)
151             if (pg_numrows($user_pg) == 1)
152                 return TRUE;
153
154         return FALSE;
155     }
156
157     function getrecord_bylogin($login) {
158         GLOBAL $G_dbpfx;
159
160         $user_sql = sprintf("SELECT * FROM %susers WHERE login = lower('%s') AND (type & CAST (X'%08x' as integer)) = 0;",  $G_dbpfx, escsql($login), USER_FLAG_TY_DISABLE);
161         if (($user_pg  = $this->query($user_sql)) == FALSE) {
162             return FALSE;
163         }
164         if (pg_numrows($user_pg) != 1)
165             return FALSE;
166
167         $user_obj = pg_fetch_object($user_pg, 0);
168
169         return ($user_obj);
170     }
171
172     function user_add($login, $pass, $email, $type, $disa_reas, $guar_code) {
173         GLOBAL $G_dbpfx;
174
175         $usr_sql = sprintf("INSERT INTO %susers (login, pass, email, type, disa_reas, guar_code, lintm)
176                             VALUES ('%s', '%s', '%s', %d, %d, %d, now()) RETURNING *;",
177                            $G_dbpfx, escsql(strtolower($login)), escsql($pass), escsql($email),
178                            $type, $disa_reas, $guar_code);
179
180         if (! (($usr_pg  = $this->query($usr_sql)) != FALSE && pg_affected_rows($usr_pg) == 1) ) {
181             return FALSE;
182         }
183         $usr_obj = pg_fetch_object($usr_pg, 0);
184
185         return $usr_obj;
186     }
187
188     function transaction($cmd) {
189         if ($cmd != "BEGIN" && $cmd != "COMMIT" && $cmd != "ROLLBACK")
190             return FALSE;
191
192         $trans_sql = sprintf("%s;", $cmd);
193         if (($trans_pg  = $this->query($trans_sql)) == FALSE) {
194             return FALSE;
195         }
196
197         return (TRUE);
198     }
199
200     /*
201       $laddr is native php int (32 or 64 bit)
202       if ret True is ip is free
203     */
204     function selfreg_check($laddr)
205     {
206         GLOBAL $G_dbpfx, $G_selfreg_tout, $G_selfreg_mask;
207
208         $sere_sql = sprintf("DELETE from %sselfreg_chk WHERE atime < now();", $G_dbpfx);
209         if (($sere_pg = $this->query($sere_sql)) == FALSE) {
210             return (FALSE);
211         }
212
213         $sere_sql = sprintf("SELECT * FROM %sselfreg_chk WHERE (ip & %d) = %d;",
214                             $G_dbpfx, int2four($G_selfreg_mask), int2four($laddr & $G_selfreg_mask));
215         if (($sere_pg  = $this->query($sere_sql)) == FALSE) {
216             return(FALSE);
217         }
218
219         $ret = pg_numrows($sere_pg);
220
221         if ($ret === FALSE) {
222             return(FALSE);
223         }
224         else if ($ret === 0) {
225             return(TRUE);
226         }
227         else if ($ret > 0) {
228             // already present
229             return(FALSE);
230         }
231         else {
232             // unreachable branch
233             return(FALSE);
234         }
235     }
236
237     /*
238       $laddr is native php int (32 or 64 bit)
239       if ret True is ip is free
240     */
241     function selfreg_set($laddr)
242     {
243         GLOBAL $G_dbpfx, $G_selfreg_tout, $G_selfreg_mask;
244
245         $newi_sql = sprintf("INSERT INTO %sselfreg_chk (ip, atime) VALUES (%d, now() + interval '%d seconds');",
246                             $G_dbpfx, int2four($laddr & $G_selfreg_mask), $G_selfreg_tout);
247         if (($newi_pg  = $this->query($newi_sql)) == FALSE) {
248             return(FALSE);
249         }
250         return(TRUE);
251     }
252
253     /*
254       to be able to add mail record code into the record itself I must reserve it before.
255      */
256     function mail_reserve_code() {
257         GLOBAL $G_dbpfx;
258
259         $mail_sql = sprintf("SELECT nextval('%smails_code_seq'::regclass) AS nextval;", $G_dbpfx);
260         if (($mail_pg  = $this->query($mail_sql)) == FALSE) {
261             return FALSE;
262         }
263         if (pg_numrows($mail_pg) != 1)
264             return FALSE;
265
266         $mail_obj = pg_fetch_object($mail_pg, 0);
267
268         return ($mail_obj->nextval);
269     }
270
271     function check_record_by_login_or_email($login, $email) {
272         GLOBAL $G_dbpfx;
273
274         $arr_fie = array('login', 'email');
275         $arr_val = array($login, $email);
276
277         for ($i = 0 ; $i < 2 ; $i++) {
278             $user_sql = sprintf("SELECT * FROM %susers WHERE %s = lower('%s');",
279                                 $G_dbpfx, $arr_fie[$i], escsql($arr_val[$i]));
280             if (($user_pg  = $this->query($user_sql)) == FALSE) {
281                 fprintf(STDERR, "QUERY [%s]_ FALSE", $user_sql);
282                 return (3);
283             }
284             if (pg_numrows($user_pg) == 1) {
285                 return ($i + 1);
286             }
287         }
288
289         return (0);
290     }
291
292     function getrecord_bycode($code) {
293         GLOBAL $G_dbpfx;
294
295         $user_sql = sprintf("SELECT * FROM %susers WHERE code = %d;",  $G_dbpfx, $code);
296         if (($user_pg  = $this->query($user_sql)) == FALSE) {
297             return FALSE;
298         }
299         if (pg_numrows($user_pg) != 1)
300             return FALSE;
301
302         $user_obj = pg_fetch_object($user_pg, 0);
303
304         return ($user_obj);
305     }
306
307     function user_update_login_time($code, $lintm)
308     {
309         GLOBAL $G_dbpfx;
310
311         $user_sql = sprintf("UPDATE %susers SET (lintm) = (date 'epoch' + %d * INTERVAL '1 second') WHERE code = %d;", $G_dbpfx, $lintm, $code);
312
313         if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
314              return FALSE;
315         }
316
317         return TRUE;
318     }
319
320     function user_update_flag_ty($code, $type, $old_val, $old_reas, $new_val, $new_reas)
321     {
322         GLOBAL $G_dbpfx;
323
324         $user_sql = sprintf("UPDATE %susers SET (type, disa_reas)
325             = (type & ~(CAST (X'%08x' as integer)) | (CAST (X'%08x' as integer)), %d)
326             WHERE code = %d AND (type & (CAST (X'%08x' as integer)))
327                 = (CAST (X'%08x' as integer)) AND disa_reas = %d;",
328                             $G_dbpfx, $type, ($new_val ? $type : 0), $new_reas,
329                             $code, $type, ($old_val ? $type : 0), $old_reas);
330
331         if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
332              return FALSE;
333         }
334
335         return TRUE;
336     }
337
338     function user_update_passwd($code, $passwd)
339     {
340         GLOBAL $G_dbpfx;
341
342         $user_sql = sprintf("UPDATE %susers SET (pass) = (md5('%s')) WHERE code = %d;",
343                             $G_dbpfx, $passwd, $code);
344
345         if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
346              return FALSE;
347         }
348
349         return TRUE;
350     }
351
352     function user_prefs_update($code, $flags, $supp_comp)
353     {
354         GLOBAL $G_dbpfx;
355
356         $user_sql = sprintf("UPDATE %susers SET (type, supp_comp) = (%d, '%s') WHERE code = %d;",
357                             $G_dbpfx, $flags, escsql($supp_comp), $code);
358         if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
359              return FALSE;
360         }
361
362         return TRUE;
363     }
364
365     function user_state_update($code, $flags, $disa_reas)
366     {
367         GLOBAL $G_dbpfx;
368
369         $user_sql = sprintf("UPDATE %susers SET (type, disa_reas) = (%d, %d) WHERE code = %d;",
370                             $G_dbpfx, $flags, $disa_reas, $code);
371         if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
372              return FALSE;
373         }
374
375         return TRUE;
376     }
377
378     function user_tos_update($code, $tos_vers)
379     {
380         GLOBAL $G_dbpfx;
381
382         $user_sql = sprintf("UPDATE %susers SET (tos_vers) = ('%s') WHERE code = %d;",
383                             $G_dbpfx, escsql($tos_vers), $code);
384         if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
385              return FALSE;
386         }
387
388         return TRUE;
389     }
390
391     /*
392       if success return a LoginDBItem object
393      */
394     function login_verify($login, $pass)
395     {
396         GLOBAL $G_dbpfx;
397
398         $ret = FALSE;
399
400         log_main("login_verify: ".$login);
401
402         //O /* check the existence of the nick in the BriskDB */
403         //O for ($i = 0 ; $i < $this->item_n ; $i++) {
404         //O log_main("login_verify: BEGIN");
405
406         if (($user_obj = $this->getrecord_bylogin($login)) == FALSE) {
407             return FALSE;
408         }
409
410         log_main("login[".$user_obj->code."]: ".$user_obj->login);
411
412         /* if it exists check for a valid challenge */
413         if (($a_sem = Challenges::lock_data(TRUE)) != FALSE) {
414             if (($chals = &Challenges::load_data()) != FALSE) {
415                 for ($e = 0 ; $e < $chals->item_n ; $e++) {
416                     log_main("challenge[".$e."]: ".$chals->item[$e]->login);
417                     if (strcmp($login, $chals->item[$e]->login) == 0) {
418                         log_main("login_verify [".$pass."] with [".md5($chals->item[$e]->token.$user_obj->pass)."]");
419
420                         if (strcmp($pass, md5($chals->item[$e]->token.$user_obj->pass)) == 0) {
421                             log_main("login_verify SUCCESS for ".$login);
422
423                             $chals->rem($login);
424                             $this->user_update_login_time($user_obj->code, time());
425                             $ret = LoginDBItem::LoginDBItemFromRecord($user_obj);
426                             break;
427                         }
428                     }
429                 } // end for ($e = 0 ...
430             }
431
432             if ($chals->ismod()) {
433                 Challenges::save_data($chals);
434             }
435
436             Challenges::unlock_data($a_sem);
437         }
438         //O break;
439         // O } //  if (strcasecmp($this->item[$i]->login, ...
440         //O }
441
442         return ($ret);
443     }
444
445     function getitem_bylogin($login, &$id) {
446         $ret = FALSE;
447         $id = -1;
448
449         log_main("getitem_bylogin: ".$login);
450
451         if (($user_obj = $this->getrecord_bylogin($login)) == FALSE)
452             return $ret;
453
454         $id = $user_obj->code;
455         return (LoginDBItem::LoginDBItemFromRecord($user_obj));
456     }
457
458     function getitem_bycode($code) {
459         $ret = FALSE;
460
461         log_main("getitem_bycode: ".$code);
462
463         if (($user_obj = $this->getrecord_bycode($code)) == FALSE)
464             return $ret;
465
466         return (LoginDBItem::LoginDBItemFromRecord($user_obj));
467     }
468
469     // TODO FOR DB
470     function getmail($login)
471     {
472         log_main("getmail");
473
474         if (($ret = $this->getrecord_bylogin($login)) == FALSE)
475             return FALSE;
476
477         return ($ret->email);
478     }
479
480     function addusers_from_olddb($olddb, &$cont)
481     {
482         GLOBAL $G_dbpfx;
483
484         for ($i = 0 ; $i < $olddb->count() ; $i++) {
485             $user_sql = sprintf("INSERT INTO %susers ( login, pass, email, type) VALUES ('%s', '%s', '%s', %d);",
486                                 $G_dbpfx, escsql(strtolower($olddb->item[$i]->login)), escsql($olddb->item[$i]->pass),
487                                 escsql($olddb->item[$i]->email), $olddb->item[$i]->type & USER_FLAG_TY_ALL);
488
489             if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
490                 $cont .= sprintf("ERROR IN LINE: %s\n", eschtml($user_sql));
491
492                 return FALSE;
493             }
494         }
495         return TRUE;
496     }
497
498     function getdbconn()
499     {
500         return ($this->dbconn);
501     }
502
503     // return array of array('code', 'login' [, 'first', 'last', 'tidx']) ordered by table position
504     function users_get($match_code, $with_minmaxtidx, $is_newmatch)
505     {
506         GLOBAL $G_dbpfx;
507
508         if ($is_newmatch) { // is new
509             $usr_sql = sprintf("SELECT u.code AS code, u.login AS login%s
510                                   FROM %sbin5_matches AS m, %sbin5_games AS g, %sbin5_points AS p,
511                                        %susers AS u, %sbin5_table_orders AS o
512                                   WHERE m.code = g.mcode AND g.code = p.gcode AND u.code = p.ucode
513                                        AND m.code = o.mcode AND u.code = o.ucode AND m.code = %d
514                                   GROUP BY u.code, u.login%s, o.pos
515                                   ORDER BY o.pos;",
516                                ($with_minmaxtidx ? ", min(g.tstamp) AS first, max(g.tstamp) AS last, m.tidx AS tidx" : ""),
517                                $G_dbpfx, $G_dbpfx, $G_dbpfx, $G_dbpfx, $G_dbpfx, $match_code,
518                                ($with_minmaxtidx ? ", m.tidx" : ""));
519         }
520         else { // is old
521             $usr_sql = sprintf("SELECT u.code AS code, u.login AS login%s
522                                   FROM %sbin5_matches AS m, %sbin5_games AS g, %sbin5_points AS p, %susers AS u
523                                   WHERE m.code = g.mcode AND g.code = p.gcode AND u.code = p.ucode AND m.code = %d
524                                   GROUP BY u.code, u.login%s;",
525                                ($with_minmaxtidx ? ", min(g.tstamp) AS first, max(g.tstamp) AS last, m.tidx AS tidx" : ""),
526                                $G_dbpfx, $G_dbpfx, $G_dbpfx, $G_dbpfx, $match_code,
527                                ($with_minmaxtidx ? ", m.tidx" : ""));
528         }
529
530         if (($usr_pg  = pg_query($this->dbconn->db(), $usr_sql)) == FALSE ) {
531             log_crit(sprintf("%s::%s: pg_query usr_sql failed [%s]", __CLASS__, __FUNCTION__, $usr_sql));
532             return (FALSE);
533         }
534         $usr_n = pg_numrows($usr_pg);
535         if ($usr_n != BIN5_PLAYERS_N) {
536             log_crit(sprintf("%s::%s: wrong number of players [%s] %d", __CLASS__, __FUNCTION__, $usr_sql, $usr_n));
537             return (FALSE);
538         }
539         $users = array();
540
541         if ($with_minmaxtidx)
542             $fields = array('code', 'login', 'first', 'last', 'tidx');
543         else
544             $fields = array('code', 'login');
545
546         for ($u = 0 ; $u < $usr_n ; $u++) {
547             $usr_obj = pg_fetch_object($usr_pg, $u);
548             $users[$u] = array();
549             foreach($fields as $field) {
550                 $users[$u][$field] = $usr_obj->$field;
551             }
552         }
553         return ($users);
554     }
555
556     // out: tab->{points,points_n,old_reason}, in: tab->ttok
557     function match_continue($match_code, $table, $tidx)
558     {
559         GLOBAL $G_dbpfx;
560         $sql_ttok = escsql($table->table_token);
561
562         if (($users = $this->users_get($match_code, FALSE /*without minmaxidx*/, TRUE /*new game*/)) == FALSE) {
563             log_crit(sprintf("%s::%s: retrieve users fails", __CLASS__, __FUNCTION__));
564             return (FALSE);
565         }
566
567         $num_sql = sprintf("SELECT count(*) AS points_n FROM %sbin5_games WHERE mcode = %d;", $G_dbpfx, $match_code);
568         if (($num_pg  = $this->query($num_sql)) == FALSE || pg_numrows($num_pg) != 1) {
569             log_crit(sprintf("%s::%s: get games number fails", __CLASS__, __FUNCTION__));
570             return (FALSE);
571         }
572         $num_obj = pg_fetch_object($num_pg, 0);
573         $table->points_n = $num_obj->points_n;
574
575         // TAG: POINTS_MANAGEMENT
576         $tot_sql = sprintf("SELECT sum(p.pts * (2^g.mult)) AS pts
577                             FROM %sbin5_games AS g, %sbin5_points AS p, %susers AS u,
578                                  %sbin5_table_orders AS o
579                             WHERE g.mcode = %d AND g.code = p.gcode AND p.ucode = u.code
580                                   AND p.ucode = o.ucode AND g.mcode = o.mcode
581                             GROUP BY p.ucode, o.pos
582                             ORDER BY o.pos;",
583                            $G_dbpfx, $G_dbpfx, $G_dbpfx, $G_dbpfx, $match_code);
584         if (($tot_pg  = pg_query($this->dbconn->db(), $tot_sql)) == FALSE
585             || pg_numrows($tot_pg) != BIN5_PLAYERS_N) {
586             log_crit(sprintf("%s::%s: get games totals fails", __CLASS__, __FUNCTION__));
587             return(FALSE);
588         }
589
590         $u = 0;
591         foreach ($users as $user) {
592             // TAG: POINTS_MANAGEMENT
593             $pts_sql = sprintf("SELECT p.pts AS pts, g.mult AS mult
594                                     FROM %sbin5_points as p, %sbin5_games as g
595                                     WHERE p.gcode = g.code AND g.mcode = %d AND p.ucode = %d
596                                     ORDER BY g.tstamp ASC
597                                     LIMIT %d OFFSET %d;",
598                                $G_dbpfx, $G_dbpfx, $match_code, $user['code'],
599                                MAX_POINTS,
600                                ($num_obj->points_n < MAX_POINTS ? 0 : $num_obj->points_n - MAX_POINTS));
601
602             // points of the match for each user
603             if (($pts_pg  = $this->query($pts_sql)) == FALSE) {
604                 log_crit(sprintf("%s::%s: get points fails", __CLASS__, __FUNCTION__));
605                 return (FALSE);
606             }
607             $pts_n = pg_numrows($pts_pg);
608             if ($pts_n > $table->points_n) {
609                 // inconsistent scenario number of points great than number of games
610                 log_crit(sprintf("%s::%s: number of points great than number of games", __CLASS__, __FUNCTION__));
611                 return (FALSE);
612             }
613             // TAG: POINTS_MANAGEMENT
614             for ($i = 0 , $ct = $table->points_n - $pts_n; $ct < $table->points_n ; $ct++, $i++) {
615                 $pts_obj = pg_fetch_object($pts_pg, $i);
616                 $table->points[$ct % MAX_POINTS][$u] = $pts_obj->pts * pow(2, $pts_obj->mult);
617             }
618             $tot_obj = pg_fetch_object($tot_pg, $u);
619             $table->total[$u] = $tot_obj->pts;
620
621             $u++;
622         }
623
624         $gam_sql = sprintf("SELECT * FROM %sbin5_games WHERE mcode = %d ORDER BY tstamp DESC LIMIT 1;", $G_dbpfx, $match_code);
625         if (($gam_pg  = $this->query($gam_sql)) == FALSE || pg_numrows($gam_pg) != 1) {
626             log_crit(sprintf("%s::%s: get last game fails", __CLASS__, __FUNCTION__));
627             return (FALSE);
628         }
629         $gam_obj = pg_fetch_object($gam_pg, 0);
630
631         // update matches with new ttok and table idx
632         $mtc_sql = sprintf("UPDATE %sbin5_matches SET (ttok, tidx) = ('%s', %d) WHERE code = %d RETURNING *;",
633                            $G_dbpfx, $sql_ttok, $tidx, $match_code);
634         if (($mtc_pg  = $this->query($mtc_sql)) == FALSE || pg_numrows($mtc_pg) != 1) {
635             log_crit(sprintf("%s::%s: update matches table failed", __CLASS__, __FUNCTION__));
636             return (FALSE);
637         }
638         $mtc_obj = pg_fetch_object($mtc_pg, 0);
639
640         $old_rules = $table->rules;
641         $rules_name = rules_id2name($mtc_obj->tcode);
642         $table->rules = new $rules_name($table);
643         unset($old_rules);
644
645         $table->old_reason = ${rules_name}::game_description($gam_obj->act, 'html', $gam_obj->mult,
646                                               $gam_obj->asta_win, ($gam_obj->asta_win != -1 ?
647                                                                    $users[$gam_obj->asta_win]['login'] : ""),
648                                               $gam_obj->friend, ($gam_obj->friend != -1 ?
649                                                                  $users[$gam_obj->friend]['login'] : ""),
650                                               $gam_obj->pnt, $gam_obj->asta_pnt, $gam_obj->tourn_pts);
651
652
653         return (TRUE);
654     }
655
656     function match_order_get(&$match_data, $match_code, $exp_num)
657     {
658         GLOBAL $G_dbpfx;
659
660         $ord_sql = sprintf("SELECT ucode FROM %sbin5_table_orders WHERE mcode = %d ORDER BY pos ASC;",
661                            $G_dbpfx, $match_code);
662
663         if (($ord_pg  = $this->query($ord_sql)) == FALSE || pg_numrows($ord_pg) != $exp_num) {
664             log_crit(sprintf("%s: fails for id or users number", __FUNCTION__));
665             return (FALSE);
666         }
667
668         $ucodes = array();
669         for ($i = 0 ; $i < $exp_num ; $i++) {
670             $ord_obj = pg_fetch_object($ord_pg, $i);
671             $ucodes[$i] = $ord_obj->ucode;
672         }
673
674         if ($match_data !== NULL) {
675             $mtdt_sql = sprintf("SELECT * FROM %sbin5_matches WHERE code = %d;",
676                                 $G_dbpfx, $match_code);
677
678             if (($mtdt_pg  = $this->query($mtdt_sql)) == FALSE || pg_numrows($mtdt_pg) != 1) {
679                 log_crit(sprintf("%s: fails retrieve match_data values [%d]", __FUNCTION__, $match_code));
680                 return (FALSE);
681             }
682
683             $mtdt_obj = pg_fetch_object($mtdt_pg, 0);
684
685             foreach (array('ttok', 'tidx', 'mult_next', 'mazzo_next', 'tcode') as $match_name) {
686                 $match_data[$match_name] = $mtdt_obj->$match_name;
687             }
688         }
689
690         return ($ucodes);
691     }
692
693     //   ttok   text UNIQUE,
694     //   tidx
695     function bin5_points_save($date, $table, $tidx, $action, $ucodes, $pts)
696     {
697         GLOBAL $G_dbpfx;
698         $sql_ttok = escsql($table->table_token);
699
700         $is_trans = FALSE;
701         $ret = FALSE;
702
703         $n = count($ucodes);
704         /* check the existence of the nick in the BriskDB */
705         log_main("bin5_points_save: ");
706
707         do {
708             if ($this->query("BEGIN") == FALSE) {
709                 break;
710             }
711             $is_trans = TRUE;
712
713             /*
714              * matches management
715              */
716             $codes_where = "";
717             $mtc_sql = sprintf("UPDATE %sbin5_matches SET (mazzo_next, mult_next) = (%d, %d) WHERE ttok = '%s' RETURNING *;",
718                                $G_dbpfx, $table->mazzo, $table->mult, $sql_ttok);
719             if (($mtc_pg  = $this->query($mtc_sql)) == FALSE || pg_numrows($mtc_pg) != 1) {
720
721                 // match not exists, insert it
722                 // , BIN5_TOURNAMENT_NO_DRAW
723                 $mtc_sql = sprintf("INSERT INTO %sbin5_matches (ttok, ttype, tidx, mazzo_next, mult_next, tcode) VALUES ('%s', %d, %d, %d, %d, %d) RETURNING *;",
724                                    $G_dbpfx, $sql_ttok,
725                                    ($tidx < TABLES_CERT_N ? 1 : ($tidx < TABLES_AUTH_N ? 2 : (
726                                        $tidx < TABLES_APPR_N ? 3 : 4))),
727                                    $tidx, $table->mazzo, $table->mult, $table->rules->id_get());
728                 if (($mtc_pg  = $this->query($mtc_sql)) == FALSE || pg_affected_rows($mtc_pg) != 1) {
729                     log_crit(sprintf("bin5_points_save: failed at insert match [%s]", $mtc_sql));
730                     break;
731                 }
732                 $mtc_obj = pg_fetch_object($mtc_pg, 0);
733
734                 for ($i = 0 ; $i < $n ; $i++) {
735                     $ord_sql = sprintf("INSERT INTO %sbin5_table_orders (mcode, ucode, pos) VALUES (%d, %d, %d);",
736                                        $G_dbpfx, $mtc_obj->code, $ucodes[$i], $i);
737                     if (($ord_pg = $this->query($ord_sql)) == FALSE || pg_affected_rows($ord_pg) != 1 ) {
738                         log_crit(sprintf("bin5_points_save: failed at insert table order [%s]", $ord_sql));
739                         break;
740                     }
741                     $codes_where .= sprintf("%scode = %d", ($i == 0  ? "" : " OR "), $ucodes[$i]);
742                 }
743                 if ($i < $n)
744                     break;
745
746                 $cnt_sql = sprintf("UPDATE %susers SET (match_cnt, game_cnt)
747                                         = (match_cnt+1, game_cnt+1) WHERE %s;",
748                                    $G_dbpfx, $codes_where);
749                 error_log($cnt_sql);
750                 if (($cnt_pg = $this->query($cnt_sql)) == FALSE || pg_affected_rows($cnt_pg) != $n) {
751                     log_crit(sprintf("bin5_points_save: failed increment match and game [%s]", $cnt_sql));
752                     break;
753                 }
754             }
755             else {
756                 $mtc_obj = pg_fetch_object($mtc_pg,0);
757
758                 for ($i = 0 ; $i < $n ; $i++) {
759                     $codes_where .= sprintf("%scode = %d", ($i == 0 ? "" : " OR "), $ucodes[$i]);
760                 }
761                 $cnt_sql = sprintf("UPDATE %susers SET (game_cnt)
762                                         = (game_cnt+1) WHERE %s;",
763                                    $G_dbpfx, $codes_where);
764                 error_log($cnt_sql);
765                 if (($cnt_pg = $this->query($cnt_sql)) == FALSE || pg_affected_rows($cnt_pg) != $n) {
766                     log_crit(sprintf("bin5_points_save: failed increment game [%s]", $cnt_sql));
767                     break;
768                 }
769             }
770
771             /*
772              * games management
773              */
774             $gam_sql = sprintf("INSERT INTO %sbin5_games (mcode, tstamp, act, asta_pnt, pnt, asta_win, friend, mazzo, mult, tourn_pts)
775                                                VALUES (%d, to_timestamp(%d), %d, %d, %d, %d, %d, %d, %d, %d) RETURNING *;",
776                                $G_dbpfx, $mtc_obj->code, $date, $action,
777                                $table->old_asta_pnt, $table->old_pnt,
778                                $table->old_asta_win,
779                                $table->old_friend,
780                                $table->old_mazzo, $table->old_mult,
781                                $table->old_tourn_pts);
782             if (($gam_pg  = $this->query($gam_sql)) == FALSE || pg_affected_rows($gam_pg) != 1) {
783                 log_crit(sprintf("bin5_points_save: failed at insert game [%s]", $gam_sql));
784                 break;
785             }
786
787             $gam_obj = pg_fetch_object($gam_pg,0);
788
789             /*
790              * points management
791              */
792             for ($i = 0 ; $i < $n ; $i++) {
793                 /* put points */
794                 $pts_sql = sprintf("INSERT INTO %sbin5_points (gcode, ucode, pts)
795                                                VALUES (%d, %d, %d);",
796                                    $G_dbpfx, $gam_obj->code, $ucodes[$i], $pts[$i]);
797                 if (($pts_pg  = $this->query($pts_sql)) == FALSE || pg_affected_rows($pts_pg) != 1) {
798                     log_crit(sprintf("bin5_points_save: failed at insert point [%s]", $pts_sql));
799                     break;
800                 }
801             }
802             if ($i < $n)
803                 break;
804
805             if ($this->query("COMMIT") == FALSE) {
806                 break;
807             }
808
809             $is_trans = FALSE;
810
811             $table->match_id = $mtc_obj->code;
812             $ret = TRUE;
813         } while (0);
814
815         if ($is_trans)
816             $this->query("ROLLBACK");
817
818         return $ret;
819     }
820
821     function mail_add_fromitem($mail) {
822         GLOBAL $G_dbpfx;
823
824         $usr_sql = sprintf("
825 INSERT INTO %smails (code, ucode, type, tstamp, subj, body_txt, body_htm, hash)
826             VALUES (%d, %d, %d, to_timestamp(%d), '%s', '%s', '%s', '%s') RETURNING *;",
827                            $G_dbpfx, $mail->code, $mail->ucode, $mail->type, $mail->tstamp,
828                            escsql($mail->subj), escsql($mail->body_txt), escsql($mail->body_htm),
829                            ($mail->hash == NULL ? "" : escsql($mail->hash))
830                            );
831
832         if (! (($usr_pg  = $this->query($usr_sql)) != FALSE && pg_affected_rows($usr_pg) == 1) ) {
833             return FALSE;
834         }
835         $usr_obj = pg_fetch_object($usr_pg, 0);
836
837         return $usr_obj;
838     }
839
840     function mail_check($code, $type, $hash)
841     {
842         GLOBAL $G_dbpfx;
843
844         $mai_sql = sprintf("SELECT * FROM %smails WHERE code = %d AND type = %d AND hash = '%s';",
845                            $G_dbpfx, $code, $type, escsql($hash));
846         if (($mai_pg  = $this->query($mai_sql)) == FALSE || pg_numrows($mai_pg) != 1) {
847             // check failed
848             return (FALSE);
849         }
850
851         $mai_obj = pg_fetch_object($mai_pg, 0);
852         return ($mai_obj);
853     }
854
855     function mail_delete($code)
856     {
857         GLOBAL $G_dbpfx;
858
859         $mai_sql = sprintf("DELETE FROM %smails WHERE code = %d;", $G_dbpfx, $code);
860
861         if (($mai_pg = $this->query($mai_sql)) == FALSE || pg_affected_rows($mai_pg) != 1) {
862             return (FALSE);
863         }
864         return (TRUE);
865     }
866
867     function friendship_default()
868     {
869         return (array(usersnet_friend_getlabel(1) => "0",
870                       usersnet_friend_getlabel(2) => "0",
871                       usersnet_friend_getlabel(3) => "0",
872                       usersnet_friend_getlabel(4) => "0",
873                       usersnet_friend_getlabel(5) => "0"));
874     }
875
876     function usersnet_widefriend($owner, $target)
877     {
878         GLOBAL $G_dbpfx;
879
880         $widefriend = $this->friendship_default();
881
882         $wfri_sql = sprintf("SELECT * FROM %susersnet_widefriend WHERE owner = %d AND target = %d;",
883                             $G_dbpfx, $owner, $target);
884         if (($wfri_pg  = $this->query($wfri_sql)) == FALSE) {
885             return ($widefriend);
886         }
887
888         for ($i = 0 ; $i < pg_numrows($wfri_pg) ; $i++) {
889             $wfri_obj = pg_fetch_object($wfri_pg, $i);
890             $widefriend[usersnet_friend_getlabel(intval($wfri_obj->friend))] = $wfri_obj->count;
891         }
892
893         return ($widefriend);
894     }
895
896     function usersnet_wideskill($owner, $target)
897     {
898         GLOBAL $G_dbpfx;
899
900         $wideskill = "//";
901
902         $wskl_sql = sprintf("SELECT * FROM %susersnet_wideskill WHERE owner = %d AND target = %d;",
903                             $G_dbpfx, $owner, $target);
904         if (($wskl_pg  = $this->query($wskl_sql)) == FALSE) {
905             return ($wideskill);
906         }
907
908         if (pg_numrows($wskl_pg) > 0) {
909             $wskl_obj = pg_fetch_object($wskl_pg, 0);
910             // TODO: UNCOMMENT IF THE NETWORK WORKS VERY WELL
911             // if ($wskl_obj->count >= 3)
912             $wideskill = sprintf("%3.2f", $wskl_obj->skill);
913         }
914         return ($wideskill);
915     }
916
917     function usersnet_narrowfriend($owner, $target)
918     {
919         GLOBAL $G_dbpfx;
920
921         $narrowfriend = $this->friendship_default();
922
923         $nfri_sql = sprintf("SELECT * FROM %susersnet_narrowfriend WHERE owner = %d AND target = %d;",
924                             $G_dbpfx, $owner, $target);
925         if (($nfri_pg  = $this->query($nfri_sql)) == FALSE) {
926             return $narrowfriend;
927         }
928
929         for ($i = 0 ; $i < pg_numrows($nfri_pg) ; $i++) {
930             $nfri_obj = pg_fetch_object($nfri_pg, $i);
931             $narrowfriend[usersnet_friend_getlabel(intval($nfri_obj->friend))] = $nfri_obj->count;
932         }
933         return ($narrowfriend);
934     }
935
936     function usersnet_narrowskill($owner, $target)
937     {
938         GLOBAL $G_dbpfx;
939
940         $narrowskill = "//";
941
942         $nskl_sql = sprintf("SELECT * FROM %susersnet_narrowskill WHERE owner = %d AND target = %d;",
943                             $G_dbpfx, $owner, $target);
944         if (($nskl_pg = $this->query($nskl_sql)) == FALSE) {
945             return ($narrowskill);
946         }
947
948         if (pg_numrows($nskl_pg) > 0) {
949             $nskl_obj = pg_fetch_object($nskl_pg, 0);
950             // TODO: UNCOMMENT IF THE NETWORK WORKS VERY WELL
951             // if ($nskl_obj->count >= 3)
952             $narrowskill = sprintf("%3.2f", $nskl_obj->skill);
953         }
954         return ($narrowskill);
955     }
956
957     function usersnet_partyskill($owner, $target)
958     {
959         GLOBAL $G_dbpfx;
960
961         $partyskill = "non disponibile";
962
963         $pskl_sql = sprintf("SELECT * FROM %susersnet_party WHERE owner = %d AND target = %d;",
964                             $G_dbpfx, $owner, $target);
965         if (($pskl_pg  = $this->query($pskl_sql)) == FALSE) {
966             return ($partyskill);
967         }
968
969         if (pg_numrows($pskl_pg) > 0) {
970             $pskl_obj = pg_fetch_object($pskl_pg, 0);
971             // TODO: UNCOMMENT IF THE NETWORK WORKS VERY WELL
972             // if ($wskl_obj->count >= 3)
973             $partyskill = sprintf("%3.2f", $pskl_obj->skill);
974         }
975         return ($partyskill);
976     }
977
978     function usersnet_bycode($owner, $target, $widefriend, $narrowfriend)
979     {
980         GLOBAL $G_dbpfx;
981         $ret = FALSE;
982
983         $net_sql = sprintf("SELECT * FROM %susersnet WHERE owner = %d AND target = %d;",
984                            $G_dbpfx, $owner, $target);
985         if (($net_pg  = $this->query($net_sql)) == FALSE)
986             return FALSE;
987
988         if (pg_numrows($net_pg) != 1)
989             return FALSE;
990
991         $net_obj = pg_fetch_object($net_pg, 0);
992
993         return (UsersNetItem::UsersNetItemFromRecord($net_obj, $widefriend, $narrowfriend));
994     }
995
996     function usersnet_default($owner, $target, $widefriend, $narrowfriend)
997     {
998         return (UsersNetItem::UsersNetItemDefaults($owner, $target, $widefriend, $narrowfriend));
999     }
1000
1001     function usersnet_save($owner_id, $json)
1002     {
1003         GLOBAL $G_dbpfx;
1004         $ret = 99999;
1005         $trans = FALSE;
1006
1007         do {
1008             $friend = usersnet_friend_getid($json->friend);
1009
1010             $json->skill = intval($json->skill);
1011             $json->trust = intval($json->trust);
1012
1013             if ($json->skill < 1 || $json->skill > 5 ||
1014                 $json->trust < 1 || $json->trust > 5 ||
1015                 $friend == FALSE) {
1016                 $ret = 1;
1017                 break;
1018             }
1019             $this->transaction('BEGIN');
1020             $trans = TRUE;
1021
1022             if ($friend == USERSNET_FRIEND_UNKNOWN) {
1023                // try to update
1024                 $net_sql = sprintf("
1025                     DELETE FROM %susersnet
1026                         USING %susers as us
1027                         WHERE owner = %d AND us.login = '%s' AND target = us.code;",
1028                                    $G_dbpfx, $G_dbpfx,
1029                                    $owner_id, escsql(strtolower($json->login)));
1030
1031                 if (($net_pg = $this->query($net_sql)) == FALSE) {
1032                     $ret = 5;
1033                     break;
1034                 }
1035              }
1036             else { // if ($friend == USERSNET_FRIEND_UNKNOWN
1037                 // try to update
1038                 $net_sql = sprintf("
1039                     UPDATE %susersnet SET (friend, skill, trust, mtime) =
1040                         (%d, %d, %d, now())
1041                         FROM %susers as us
1042                         WHERE owner = %d AND us.login = '%s' AND target = us.code RETURNING *;",
1043                                    $G_dbpfx,
1044                                    $friend, $json->skill, $json->trust,
1045                                    $G_dbpfx,
1046                                    $owner_id, escsql(strtolower($json->login)));
1047                 if (($net_pg  = $this->query($net_sql)) == FALSE || pg_numrows($net_pg) == 0) {
1048                     $net_sql = sprintf("
1049                 INSERT INTO %susersnet SELECT %d AS owner, us.code as target,
1050                         %d as friend, %d as skill, %d as trust
1051                     FROM %susers as us WHERE us.login = '%s' RETURNING *;",
1052                                        $G_dbpfx, $owner_id,
1053                                        $friend, $json->skill, $json->trust,
1054                                        $G_dbpfx, escsql(strtolower($json->login)));
1055                     if (($net_pg  = $this->query($net_sql)) == FALSE) {
1056                         log_wr('insert query failed');
1057                         $ret = 2;
1058                         break;
1059                     }
1060                     if (pg_numrows($net_pg) != 1) {
1061                         log_wr(sprintf('insert numrow failed [%s] [%d]', $net_sql, pg_numrows($net_pg)));
1062                         $ret = 3;
1063                         break;
1064                     }
1065                 }
1066                 else {
1067                     if (pg_numrows($net_pg) != 1) {
1068                         log_wr('update numrow failed');
1069                         $ret = 4;
1070                         break;
1071                     }
1072                 }
1073             }
1074             $this->transaction('COMMIT');
1075             return (0);
1076         } while (0);
1077
1078         if ($trans)
1079             $this->transaction('ROLLBACK');
1080
1081         return ($ret);
1082     }
1083 } // End class BriskDB
1084
1085 class LoginDBOld
1086 {
1087     var $item;
1088     var $item_n;
1089
1090     function LoginDBOld($filename)
1091     {
1092         GLOBAL $DOCUMENT_ROOT;
1093         log_main("LoginDBOld create:start");
1094
1095         if (file_exists("$DOCUMENT_ROOT/Etc/".$filename)) {
1096             require("$DOCUMENT_ROOT/Etc/".$filename);
1097         }
1098         else {
1099             return (FALSE);
1100         }
1101         $this->item_n = count($this->item);
1102         log_main("LoginDBOld create:end");
1103     }
1104
1105     function count()
1106     {
1107         return ($this->item_n);
1108     }
1109
1110 } // End class LoginDBOld
1111
1112 ?>