fix recovery of postgres connection
[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 (($res = @pg_query($this->dbconn->db(), $sql)) == FALSE) {
117             error_log('pg_result_status: ' .  pg_result_status($res));
118             error_log('pg_connection_status: ' .  pg_connection_status($this->dbconn->db()));
119             // try to recover the connection
120             if (($this->dbconn = DBConn::recover()) == FALSE)
121                 return FALSE;
122             return (@pg_query($this->dbconn->db(), $sql));
123         }
124
125         return ($res);
126     }
127
128     function last_error()
129     {
130         return pg_last_error($this->dbconn->db);
131     }
132
133     function users_load()
134     {
135     }
136
137     function login_exists($login)
138     {
139         GLOBAL $G_dbpfx;
140
141         /* check the existence of the nick in the BriskDB */
142         log_main("login_exists: ".$login);
143
144         $user_sql = sprintf("SELECT * FROM %susers WHERE login = '%s'",
145                             $G_dbpfx, escsql($login));
146         if (($user_pg = $this->query($user_sql)) != FALSE)
147             if (pg_numrows($user_pg) == 1)
148                 return TRUE;
149
150         return FALSE;
151     }
152
153     function getrecord_bylogin($login) {
154         GLOBAL $G_dbpfx;
155
156         $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);
157         if (($user_pg  = $this->query($user_sql)) == FALSE) {
158             return FALSE;
159         }
160         if (pg_numrows($user_pg) != 1)
161             return FALSE;
162
163         $user_obj = pg_fetch_object($user_pg, 0);
164
165         return ($user_obj);
166     }
167
168     function user_add($login, $pass, $email, $type, $disa_reas, $guar_code) {
169         GLOBAL $G_dbpfx;
170
171         $usr_sql = sprintf("INSERT INTO %susers (login, pass, email, type, disa_reas, guar_code, lintm)
172                             VALUES ('%s', '%s', '%s', %d, %d, %d, now()) RETURNING *;",
173                            $G_dbpfx, escsql(strtolower($login)), escsql($pass), escsql($email),
174                            $type, $disa_reas, $guar_code);
175
176         if (! (($usr_pg  = $this->query($usr_sql)) != FALSE && pg_affected_rows($usr_pg) == 1) ) {
177             return FALSE;
178         }
179         $usr_obj = pg_fetch_object($usr_pg, 0);
180
181         return $usr_obj;
182     }
183
184     function transaction($cmd) {
185         if ($cmd != "BEGIN" && $cmd != "COMMIT" && $cmd != "ROLLBACK")
186             return FALSE;
187
188         $trans_sql = sprintf("%s;", $cmd);
189         if (($trans_pg  = $this->query($trans_sql)) == FALSE) {
190             return FALSE;
191         }
192
193         return (TRUE);
194     }
195
196     /*
197       $laddr is native php int (32 or 64 bit)
198       if ret True is ip is free
199     */
200     function selfreg_check($laddr)
201     {
202         GLOBAL $G_dbpfx, $G_selfreg_tout, $G_selfreg_mask;
203
204         $sere_sql = sprintf("DELETE from %sselfreg_chk WHERE atime < now();", $G_dbpfx);
205         if (($sere_pg = $this->query($sere_sql)) == FALSE) {
206             return (FALSE);
207         }
208
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         fprintf(STDERR, "REQUEST [%s]\n", $user_sql);
359         if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
360              return FALSE;
361         }
362         fprintf(STDERR, "REQUEST GOOD [%s]\n", $user_sql);
363
364         return TRUE;
365     }
366
367     function user_state_update($code, $flags, $disa_reas)
368     {
369         GLOBAL $G_dbpfx;
370
371         $user_sql = sprintf("UPDATE %susers SET (type, disa_reas) = (%d, %d) WHERE code = %d;",
372                             $G_dbpfx, $flags, $disa_reas, $code);
373         fprintf(STDERR, "REQUEST [%s]\n", $user_sql);
374         if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
375              return FALSE;
376         }
377         fprintf(STDERR, "REQUEST GOOD [%s]\n", $user_sql);
378
379         return TRUE;
380     }
381
382     function user_tos_update($code, $tos_vers)
383     {
384         GLOBAL $G_dbpfx;
385
386         $user_sql = sprintf("UPDATE %susers SET (tos_vers) = ('%s') WHERE code = %d;",
387                             $G_dbpfx, escsql($tos_vers), $code);
388         fprintf(STDERR, "REQUEST [%s]\n", $user_sql);
389         if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
390              return FALSE;
391         }
392         fprintf(STDERR, "REQUEST GOOD [%s]\n", $user_sql);
393
394         return TRUE;
395     }
396
397     /*
398       if success return a LoginDBItem object
399      */
400     function login_verify($login, $pass)
401     {
402         GLOBAL $G_dbpfx;
403
404         $ret = FALSE;
405
406         log_main("login_verify: ".$login);
407
408         //O /* check the existence of the nick in the BriskDB */
409         //O for ($i = 0 ; $i < $this->item_n ; $i++) {
410         //O log_main("login_verify: BEGIN");
411
412         if (($user_obj = $this->getrecord_bylogin($login)) == FALSE) {
413             return FALSE;
414         }
415
416         log_main("login[".$user_obj->code."]: ".$user_obj->login);
417
418         /* if it exists check for a valid challenge */
419         if (($a_sem = Challenges::lock_data(TRUE)) != FALSE) {
420             if (($chals = &Challenges::load_data()) != FALSE) {
421                 for ($e = 0 ; $e < $chals->item_n ; $e++) {
422                     log_main("challenge[".$e."]: ".$chals->item[$e]->login);
423                     if (strcmp($login, $chals->item[$e]->login) == 0) {
424                         log_main("login_verify [".$pass."] with [".md5($chals->item[$e]->token.$user_obj->pass)."]");
425
426                         if (strcmp($pass, md5($chals->item[$e]->token.$user_obj->pass)) == 0) {
427                             log_main("login_verify SUCCESS for ".$login);
428
429                             $chals->rem($login);
430                             $this->user_update_login_time($user_obj->code, time());
431                             $ret = LoginDBItem::LoginDBItemFromRecord($user_obj);
432                             break;
433                         }
434                     }
435                 } // end for ($e = 0 ...
436             }
437
438             if ($chals->ismod()) {
439                 Challenges::save_data(&$chals);
440             }
441
442             Challenges::unlock_data($a_sem);
443         }
444         //O break;
445         // O } //  if (strcasecmp($this->item[$i]->login, ...
446         //O }
447
448         return ($ret);
449     }
450
451     function getitem_bylogin($login, &$id) {
452         $ret = FALSE;
453         $id = -1;
454
455         log_main("getitem_bylogin: ".$login);
456
457         if (($user_obj = $this->getrecord_bylogin($login)) == FALSE)
458             return $ret;
459
460         $id = $user_obj->code;
461         return (LoginDBItem::LoginDBItemFromRecord($user_obj));
462     }
463
464     function getitem_bycode($code) {
465         $ret = FALSE;
466
467         log_main("getitem_bycode: ".$code);
468
469         if (($user_obj = $this->getrecord_bycode($code)) == FALSE)
470             return $ret;
471
472         return (LoginDBItem::LoginDBItemFromRecord($user_obj));
473     }
474
475     // TODO FOR DB
476     function getmail($login)
477     {
478         log_main("getmail");
479
480         if (($ret = $this->getrecord_bylogin($login)) == FALSE)
481             return FALSE;
482
483         return ($ret->email);
484     }
485
486     function addusers_from_olddb($olddb, &$cont)
487     {
488         GLOBAL $G_dbpfx;
489
490         for ($i = 0 ; $i < $olddb->count() ; $i++) {
491             $user_sql = sprintf("INSERT INTO %susers ( login, pass, email, type) VALUES ('%s', '%s', '%s', %d);",
492                                 $G_dbpfx, escsql(strtolower($olddb->item[$i]->login)), escsql($olddb->item[$i]->pass),
493                                 escsql($olddb->item[$i]->email), $olddb->item[$i]->type & USER_FLAG_TY_ALL);
494
495             if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
496                 $cont .= sprintf("ERROR IN LINE: %s\n", eschtml($user_sql));
497
498                 return FALSE;
499             }
500         }
501         return TRUE;
502     }
503
504     function getdbconn()
505     {
506         return ($this->dbconn);
507     }
508
509     // return array of array('code', 'login' [, 'first', 'last', 'tidx']) ordered by table position
510     function users_get($match_code, $with_minmaxtidx, $is_newmatch)
511     {
512         GLOBAL $G_dbpfx;
513
514         if ($is_newmatch) { // is new
515             $usr_sql = sprintf("SELECT u.code AS code, u.login AS login%s
516                                   FROM %sbin5_matches AS m, %sbin5_games AS g, %sbin5_points AS p,
517                                        %susers AS u, %sbin5_table_orders AS o
518                                   WHERE m.code = g.mcode AND g.code = p.gcode AND u.code = p.ucode
519                                        AND m.code = o.mcode AND u.code = o.ucode AND m.code = %d
520                                   GROUP BY u.code, u.login%s, o.pos
521                                   ORDER BY o.pos;",
522                                ($with_minmaxtidx ? ", min(g.tstamp) AS first, max(g.tstamp) AS last, m.tidx AS tidx" : ""),
523                                $G_dbpfx, $G_dbpfx, $G_dbpfx, $G_dbpfx, $G_dbpfx, $match_code,
524                                ($with_minmaxtidx ? ", m.tidx" : ""));
525         }
526         else { // is old
527             $usr_sql = sprintf("SELECT u.code AS code, u.login AS login%s
528                                   FROM %sbin5_matches AS m, %sbin5_games AS g, %sbin5_points AS p, %susers AS u
529                                   WHERE m.code = g.mcode AND g.code = p.gcode AND u.code = p.ucode AND m.code = %d
530                                   GROUP BY u.code, u.login%s;",
531                                ($with_minmaxtidx ? ", min(g.tstamp) AS first, max(g.tstamp) AS last, m.tidx AS tidx" : ""),
532                                $G_dbpfx, $G_dbpfx, $G_dbpfx, $G_dbpfx, $match_code,
533                                ($with_minmaxtidx ? ", m.tidx" : ""));
534         }
535
536         if (($usr_pg  = pg_query($this->dbconn->db(), $usr_sql)) == FALSE ) {
537             log_crit(sprintf("%s::%s: pg_query usr_sql failed [%s]", __CLASS__, __FUNCTION__, $usr_sql));
538             return (FALSE);
539         }
540         $usr_n = pg_numrows($usr_pg);
541         if ($usr_n != BIN5_PLAYERS_N) {
542             log_crit(sprintf("%s::%s: wrong number of players [%s] %d", __CLASS__, __FUNCTION__, $usr_sql, $usr_n));
543             return (FALSE);
544         }
545         $users = array();
546
547         if ($with_minmaxtidx)
548             $fields = array('code', 'login', 'first', 'last', 'tidx');
549         else
550             $fields = array('code', 'login');
551
552         for ($u = 0 ; $u < $usr_n ; $u++) {
553             $usr_obj = pg_fetch_object($usr_pg, $u);
554             $users[$u] = array();
555             foreach($fields as $field) {
556                 $users[$u][$field] = $usr_obj->$field;
557             }
558         }
559         return ($users);
560     }
561
562     // out: tab->{points,points_n,old_reason}, in: tab->ttok
563     function match_continue($match_code, $table, $tidx)
564     {
565         GLOBAL $G_dbpfx;
566         $sql_ttok = escsql($table->table_token);
567
568         if (($users = $this->users_get($match_code, FALSE /*without minmaxidx*/, TRUE /*new game*/)) == FALSE) {
569             log_crit(sprintf("%s::%s: retrieve users fails", __CLASS__, __FUNCTION__));
570             return (FALSE);
571         }
572
573         $num_sql = sprintf("SELECT count(*) AS points_n FROM %sbin5_games WHERE mcode = %d;", $G_dbpfx, $match_code);
574         if (($num_pg  = $this->query($num_sql)) == FALSE || pg_numrows($num_pg) != 1) {
575             log_crit(sprintf("%s::%s: get games number fails", __CLASS__, __FUNCTION__));
576             return (FALSE);
577         }
578         $num_obj = pg_fetch_object($num_pg, 0);
579         $table->points_n = $num_obj->points_n;
580
581         // TAG: POINTS_MANAGEMENT
582         $tot_sql = sprintf("SELECT sum(p.pts * (2^g.mult)) AS pts
583                             FROM %sbin5_games AS g, %sbin5_points AS p, %susers AS u,
584                                  %sbin5_table_orders AS o
585                             WHERE g.mcode = %d AND g.code = p.gcode AND p.ucode = u.code
586                                   AND p.ucode = o.ucode AND g.mcode = o.mcode
587                             GROUP BY p.ucode, o.pos
588                             ORDER BY o.pos;",
589                            $G_dbpfx, $G_dbpfx, $G_dbpfx, $G_dbpfx, $match_code);
590         if (($tot_pg  = pg_query($this->dbconn->db(), $tot_sql)) == FALSE
591             || pg_numrows($tot_pg) != BIN5_PLAYERS_N) {
592             log_crit(sprintf("%s::%s: get games totals fails", __CLASS__, __FUNCTION__));
593             return(FALSE);
594         }
595
596         $u = 0;
597         foreach ($users as $user) {
598             // TAG: POINTS_MANAGEMENT
599             $pts_sql = sprintf("SELECT p.pts AS pts, g.mult AS mult
600                                     FROM %sbin5_points as p, %sbin5_games as g
601                                     WHERE p.gcode = g.code AND g.mcode = %d AND p.ucode = %d
602                                     ORDER BY g.tstamp ASC
603                                     LIMIT %d OFFSET %d;",
604                                $G_dbpfx, $G_dbpfx, $match_code, $user['code'],
605                                MAX_POINTS,
606                                ($num_obj->points_n < MAX_POINTS ? 0 : $num_obj->points_n - MAX_POINTS));
607
608             // points of the match for each user
609             if (($pts_pg  = $this->query($pts_sql)) == FALSE) {
610                 log_crit(sprintf("%s::%s: get points fails", __CLASS__, __FUNCTION__));
611                 return (FALSE);
612             }
613             $pts_n = pg_numrows($pts_pg);
614             if ($pts_n > $table->points_n) {
615                 // inconsistent scenario number of points great than number of games
616                 log_crit(sprintf("%s::%s: number of points great than number of games", __CLASS__, __FUNCTION__));
617                 return (FALSE);
618             }
619             // TAG: POINTS_MANAGEMENT
620             for ($i = 0 , $ct = $table->points_n - $pts_n; $ct < $table->points_n ; $ct++, $i++) {
621                 $pts_obj = pg_fetch_object($pts_pg, $i);
622                 $table->points[$ct % MAX_POINTS][$u] = $pts_obj->pts * pow(2, $pts_obj->mult);
623             }
624             $tot_obj = pg_fetch_object($tot_pg, $u);
625             $table->total[$u] = $tot_obj->pts;
626
627             $u++;
628         }
629
630         $gam_sql = sprintf("SELECT * FROM %sbin5_games WHERE mcode = %d ORDER BY tstamp DESC LIMIT 1;", $G_dbpfx, $match_code);
631         if (($gam_pg  = $this->query($gam_sql)) == FALSE || pg_numrows($gam_pg) != 1) {
632             log_crit(sprintf("%s::%s: get last game fails", __CLASS__, __FUNCTION__));
633             return (FALSE);
634         }
635         $gam_obj = pg_fetch_object($gam_pg, 0);
636
637         $table->old_reason = game_description($gam_obj->act, 'html', $gam_obj->mult,
638                                               $gam_obj->asta_win, ($gam_obj->asta_win != -1 ?
639                                                                    $users[$gam_obj->asta_win]['login'] : ""),
640                                               $gam_obj->friend, ($gam_obj->friend != -1 ?
641                                                                  $users[$gam_obj->friend]['login'] : ""),
642                                               $gam_obj->pnt, $gam_obj->asta_pnt);
643
644         // update matches with new ttok and table idx
645         $mtc_sql = sprintf("UPDATE %sbin5_matches SET (ttok, tidx) = ('%s', %d) WHERE code = %d RETURNING *;",
646                            $G_dbpfx, $sql_ttok, $tidx, $match_code);
647         if (($mtc_pg  = $this->query($mtc_sql)) == FALSE || pg_numrows($mtc_pg) != 1) {
648             log_crit(sprintf("%s::%s: update matches table failed", __CLASS__, __FUNCTION__));
649             return (FALSE);
650         }
651
652         return (TRUE);
653     }
654
655     function match_order_get(&$match_data, $match_code, $exp_num)
656     {
657         GLOBAL $G_dbpfx;
658
659         $ord_sql = sprintf("SELECT ucode FROM %sbin5_table_orders WHERE mcode = %d ORDER BY pos ASC;",
660                            $G_dbpfx, $match_code);
661
662         if (($ord_pg  = $this->query($ord_sql)) == FALSE || pg_numrows($ord_pg) != $exp_num) {
663             log_crit(sprintf("%s: fails for id or users number", __FUNCTION__));
664             return (FALSE);
665         }
666
667         $ucodes = array();
668         for ($i = 0 ; $i < $exp_num ; $i++) {
669             $ord_obj = pg_fetch_object($ord_pg, $i);
670             $ucodes[$i] = $ord_obj->ucode;
671         }
672
673         if ($match_data !== NULL) {
674             $mtdt_sql = sprintf("SELECT * FROM %sbin5_matches WHERE code = %d;",
675                                 $G_dbpfx, $match_code);
676
677             if (($mtdt_pg  = $this->query($mtdt_sql)) == FALSE || pg_numrows($mtdt_pg) != 1) {
678                 log_crit(sprintf("%s: fails retrieve match_data values [%d]", __FUNCTION__, $match_code));
679                 return (FALSE);
680             }
681
682             $mtdt_obj = pg_fetch_object($mtdt_pg, 0);
683
684             foreach (array('ttok', 'tidx', 'mult_next', 'mazzo_next', 'tcode') as $match_name) {
685                 $match_data[$match_name] = $mtdt_obj->$match_name;
686             }
687         }
688
689         return ($ucodes);
690     }
691
692     //   ttok   text UNIQUE,
693     //   tidx
694     function bin5_points_save($date, $table, $tidx, $action, $ucodes, $pts)
695     {
696         GLOBAL $G_dbpfx;
697         $sql_ttok = escsql($table->table_token);
698
699         $is_trans = FALSE;
700         $ret = FALSE;
701
702         $n = count($ucodes);
703         /* check the existence of the nick in the BriskDB */
704         log_main("bin5_points_save: ");
705
706         do {
707             if ($this->query("BEGIN") == FALSE) {
708                 break;
709             }
710             $is_trans = TRUE;
711
712             /*
713              * matches management
714              */
715             $codes_where = "";
716             $mtc_sql = sprintf("UPDATE %sbin5_matches SET (mazzo_next, mult_next) = (%d, %d) WHERE ttok = '%s' RETURNING *;",
717                                $G_dbpfx, $table->mazzo, $table->mult, $sql_ttok);
718             if (($mtc_pg  = $this->query($mtc_sql)) == FALSE || pg_numrows($mtc_pg) != 1) {
719
720                 // match not exists, insert it
721                 $mtc_sql = sprintf("INSERT INTO %sbin5_matches (ttok, tidx, mazzo_next, mult_next) VALUES ('%s', %d, %d, %d) RETURNING *;",
722                                    $G_dbpfx, $sql_ttok, $tidx, $table->mazzo, $table->mult);
723                 if (($mtc_pg  = $this->query($mtc_sql)) == FALSE || pg_affected_rows($mtc_pg) != 1) {
724                     log_crit(sprintf("bin5_points_save: failed at insert match [%s]", $mtc_sql));
725                     break;
726                 }
727                 $mtc_obj = pg_fetch_object($mtc_pg, 0);
728
729                 for ($i = 0 ; $i < $n ; $i++) {
730                     $ord_sql = sprintf("INSERT INTO %sbin5_table_orders (mcode, ucode, pos) VALUES (%d, %d, %d);",
731                                        $G_dbpfx, $mtc_obj->code, $ucodes[$i], $i);
732                     if (($ord_pg = $this->query($ord_sql)) == FALSE || pg_affected_rows($ord_pg) != 1 ) {
733                         log_crit(sprintf("bin5_points_save: failed at insert table order [%s]", $ord_sql));
734                         break;
735                     }
736                     $codes_where .= sprintf("%scode = %d", ($i == 0  ? "" : " OR "), $ucodes[$i]);
737                 }
738                 if ($i < $n)
739                     break;
740
741                 $cnt_sql = sprintf("UPDATE %susers SET (match_cnt, game_cnt)
742                                         = (match_cnt+1, game_cnt+1) WHERE %s;",
743                                    $G_dbpfx, $codes_where);
744                 error_log($cnt_sql);
745                 if (($cnt_pg = $this->query($cnt_sql)) == FALSE || pg_affected_rows($cnt_pg) != $n) {
746                     log_crit(sprintf("bin5_points_save: failed increment match and game [%s]", $cnt_sql));
747                     break;
748                 }
749             }
750             else {
751                 $mtc_obj = pg_fetch_object($mtc_pg,0);
752
753                 for ($i = 0 ; $i < $n ; $i++) {
754                     $codes_where .= sprintf("%scode = %d", ($i == 0 ? "" : " OR "), $ucodes[$i]);
755                 }
756                 $cnt_sql = sprintf("UPDATE %susers SET (game_cnt)
757                                         = (game_cnt+1) WHERE %s;",
758                                    $G_dbpfx, $codes_where);
759                 error_log($cnt_sql);
760                 if (($cnt_pg = $this->query($cnt_sql)) == FALSE || pg_affected_rows($cnt_pg) != $n) {
761                     log_crit(sprintf("bin5_points_save: failed increment game [%s]", $cnt_sql));
762                     break;
763                 }
764             }
765
766             /*
767              * games management
768              */
769             $gam_sql = sprintf("INSERT INTO %sbin5_games (mcode, tstamp, act, asta_pnt, pnt, asta_win, friend, mazzo, mult)
770                                                VALUES (%d, to_timestamp(%d), %d, %d, %d, %d, %d, %d, %d) RETURNING *;",
771                                $G_dbpfx, $mtc_obj->code, $date, $action,
772                                $table->old_asta_pnt, $table->old_pnt,
773                                $table->old_asta_win,
774                                $table->old_friend,
775                                $table->old_mazzo, $table->old_mult);
776             if (($gam_pg  = $this->query($gam_sql)) == FALSE || pg_affected_rows($gam_pg) != 1) {
777                 log_crit(sprintf("bin5_points_save: failed at insert game [%s]", $gam_sql));
778                 break;
779             }
780
781             $gam_obj = pg_fetch_object($gam_pg,0);
782
783             /*
784              * points management
785              */
786             for ($i = 0 ; $i < $n ; $i++) {
787                 /* put points */
788                 $pts_sql = sprintf("INSERT INTO %sbin5_points (gcode, ucode, pts)
789                                                VALUES (%d, %d, %d);",
790                                    $G_dbpfx, $gam_obj->code, $ucodes[$i], $pts[$i]);
791                 if (($pts_pg  = $this->query($pts_sql)) == FALSE || pg_affected_rows($pts_pg) != 1) {
792                     log_crit(sprintf("bin5_points_save: failed at insert point [%s]", $pts_sql));
793                     break;
794                 }
795             }
796             if ($i < $n)
797                 break;
798
799             if ($this->query("COMMIT") == FALSE) {
800                 break;
801             }
802
803             $is_trans = FALSE;
804
805             $table->match_id = $mtc_obj->code;
806             $ret = TRUE;
807         } while (0);
808
809         if ($is_trans)
810             $this->query("ROLLBACK");
811
812         return $ret;
813     }
814
815     function mail_add_fromitem($mail) {
816         GLOBAL $G_dbpfx;
817
818         $usr_sql = sprintf("
819 INSERT INTO %smails (code, ucode, type, tstamp, subj, body_txt, body_htm, hash)
820             VALUES (%d, %d, %d, to_timestamp(%d), '%s', '%s', '%s', '%s') RETURNING *;",
821                            $G_dbpfx, $mail->code, $mail->ucode, $mail->type, $mail->tstamp,
822                            escsql($mail->subj), escsql($mail->body_txt), escsql($mail->body_htm),
823                            ($mail->hash == NULL ? "" : escsql($mail->hash))
824                            );
825
826         if (! (($usr_pg  = $this->query($usr_sql)) != FALSE && pg_affected_rows($usr_pg) == 1) ) {
827             return FALSE;
828         }
829         $usr_obj = pg_fetch_object($usr_pg, 0);
830
831         return $usr_obj;
832     }
833
834     function mail_check($code, $type, $hash)
835     {
836         GLOBAL $G_dbpfx;
837
838         $mai_sql = sprintf("SELECT * FROM %smails WHERE code = %d AND type = %d AND hash = '%s';",
839                            $G_dbpfx, $code, $type, escsql($hash));
840         if (($mai_pg  = $this->query($mai_sql)) == FALSE || pg_numrows($mai_pg) != 1) {
841             // check failed
842             return (FALSE);
843         }
844
845         $mai_obj = pg_fetch_object($mai_pg, 0);
846         return ($mai_obj);
847     }
848
849     function mail_delete($code)
850     {
851         GLOBAL $G_dbpfx;
852
853         $mai_sql = sprintf("DELETE FROM %smails WHERE code = %d;", $G_dbpfx, $code);
854
855         if (($mai_pg = $this->query($mai_sql)) == FALSE || pg_affected_rows($mai_pg) != 1) {
856             return (FALSE);
857         }
858         return (TRUE);
859     }
860
861     function usersnet_bycode($owner, $target)
862     {
863         GLOBAL $G_dbpfx;
864         $ret = FALSE;
865
866         $net_sql = sprintf("SELECT * FROM %susersnet WHERE owner = %d AND target = %d;",
867                             $G_dbpfx, $owner, $target);
868         if (($net_pg  = $this->query($net_sql)) == FALSE) {
869             return FALSE;
870         }
871         if (pg_numrows($net_pg) != 1)
872             return FALSE;
873
874         $net_obj = pg_fetch_object($net_pg, 0);
875
876         return (UsersNetItem::UsersNetItemFromRecord($net_obj));
877     }
878
879     function usersnet_default($owner, $target)
880     {
881         return (UsersNetItem::UsersNetItemDefaults($owner, $target));
882     }
883
884 } // End class BriskDB
885
886 class LoginDBOld
887 {
888     var $item;
889     var $item_n;
890
891     function LoginDBOld($filename)
892     {
893         GLOBAL $DOCUMENT_ROOT;
894         log_main("LoginDBOld create:start");
895
896         if (file_exists("$DOCUMENT_ROOT/Etc/".$filename)) {
897             require("$DOCUMENT_ROOT/Etc/".$filename);
898         }
899         else {
900             return (FALSE);
901         }
902         $this->item_n = count($this->item);
903         log_main("LoginDBOld create:end");
904     }
905
906     function count()
907     {
908         return ($this->item_n);
909     }
910
911 } // End class LoginDBOld
912
913 ?>