6299f81e206db418708697ef6aa1a8880c157ab1
[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             DBConn::$dbcnnx = FALSE;
66             return (pg_close(DBConn::$dbcnnx));
67         }
68         return TRUE;
69     }
70
71     static function recover()
72     {
73         self::destroy();
74         return (self::create());
75     }
76
77     function db()
78     {
79         return ($this->db);
80     }
81 }
82
83 class BriskDB
84 {
85     var $dbconn;
86     var $item;
87     var $item_n;
88
89     function BriskDB($dbconn)
90     {
91         $this->dbconn = $dbconn;
92     }
93
94     static function create()
95     {
96         GLOBAL $DOCUMENT_ROOT, $G_dbpfx;
97
98         $ret = FALSE;
99
100         log_main("BriskDB create:start");
101
102         do {
103             if (($dbconn = DBConn::create()) == FALSE) {
104                 break;
105             }
106
107             $ret = new BriskDB($dbconn);
108         } while (0);
109
110         return ($ret);
111     }
112
113     function query($sql)
114     {
115         if (($res = pg_query($this->dbconn->db(), $sql)) == FALSE) {
116             // try to recover the connection
117             if (($this->dbconn = DBConn::recover()) == FALSE)
118                 return FALSE;
119             return (pg_query($this->dbconn->db(), $sql));
120         }
121
122         return ($res);
123     }
124
125     function last_error()
126     {
127         return pg_last_error($this->dbconn->db);
128     }
129
130     function users_load()
131     {
132     }
133
134     function login_exists($login)
135     {
136         GLOBAL $G_dbpfx;
137
138         /* check the existence of the nick in the BriskDB */
139         log_main("login_exists: ".$login);
140
141         $user_sql = sprintf("SELECT * FROM %susers WHERE login = lower('%s')",
142                             $G_dbpfx, escsql($login));
143         if (($user_pg = $this->query($user_sql)) != FALSE)
144             if (pg_numrows($user_pg) == 1)
145                 return TRUE;
146
147         return FALSE;
148     }
149
150     function getrecord_bylogin($login) {
151         GLOBAL $G_dbpfx;
152
153         $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);
154         if (($user_pg  = $this->query($user_sql)) == FALSE) {
155             return FALSE;
156         }
157         if (pg_numrows($user_pg) != 1)
158             return FALSE;
159
160         $user_obj = pg_fetch_object($user_pg, 0);
161
162         return ($user_obj);
163     }
164
165     function user_add($login, $pass, $email, $type, $disa_reas, $guar_code) {
166         GLOBAL $G_dbpfx;
167
168         $usr_sql = sprintf("INSERT INTO %susers (login, pass, email, type, disa_reas, guar_code, lintm)
169                             VALUES ('%s', '%s', '%s', %d, %d, %d, now()) RETURNING *;",
170                            $G_dbpfx, escsql(strtolower($login)), escsql($pass), escsql($email),
171                            $type, $disa_reas, $guar_code);
172
173         if (! (($usr_pg  = $this->query($usr_sql)) != FALSE && pg_affected_rows($usr_pg) == 1) ) {
174             return FALSE;
175         }
176         $usr_obj = pg_fetch_object($usr_pg, 0);
177
178         return $usr_obj;
179     }
180
181     function transaction($cmd) {
182         if ($cmd != "BEGIN" && $cmd != "COMMIT" && $cmd != "ROLLBACK")
183             return FALSE;
184
185         $trans_sql = sprintf("%s;", $cmd);
186         if (($trans_pg  = $this->query($trans_sql)) == FALSE) {
187             return FALSE;
188         }
189
190         return (TRUE);
191     }
192
193     /*
194       $laddr is native php int (32 or 64 bit)
195       if ret True is ip is free
196     */
197     function selfreg_check($laddr)
198     {
199         GLOBAL $G_dbpfx, $G_selfreg_tout, $G_selfreg_mask;
200
201         $sere_sql = sprintf("DELETE from %sselfreg_chk WHERE atime < now();", $G_dbpfx);
202         if (($sere_pg = $this->query($sere_sql)) == FALSE) {
203             return (FALSE);
204         }
205
206         if (($sere_pg = $this->query($sere_sql)) == FALSE) {
207             return (FALSE);
208         }
209
210         $sere_sql = sprintf("SELECT * FROM %sselfreg_chk WHERE (ip & %d) = %d;",
211                             $G_dbpfx, int2four($G_selfreg_mask), int2four($laddr & $G_selfreg_mask));
212         if (($sere_pg  = $this->query($sere_sql)) == FALSE) {
213             return(FALSE);
214         }
215
216         $ret = pg_numrows($sere_pg);
217
218         if ($ret === FALSE) {
219             return(FALSE);
220         }
221         else if ($ret === 0) {
222             return(TRUE);
223         }
224         else if ($ret > 0) {
225             // already present
226             return(FALSE);
227         }
228         else {
229             // unreachable branch
230             return(FALSE);
231         }
232     }
233
234     /*
235       $laddr is native php int (32 or 64 bit)
236       if ret True is ip is free
237     */
238     function selfreg_set($laddr)
239     {
240         GLOBAL $G_dbpfx, $G_selfreg_tout, $G_selfreg_mask;
241
242         $newi_sql = sprintf("INSERT INTO %sselfreg_chk (ip, atime) VALUES (%d, now() + interval '%d seconds');",
243                             $G_dbpfx, int2four($laddr & $G_selfreg_mask), $G_selfreg_tout);
244         if (($newi_pg  = $this->query($newi_sql)) == FALSE) {
245             return(FALSE);
246         }
247         return(TRUE);
248     }
249
250     /*
251       to be able to add mail record code into the record itself I must reserve it before.
252      */
253     function mail_reserve_code() {
254         GLOBAL $G_dbpfx;
255
256         $mail_sql = sprintf("SELECT nextval('%smails_code_seq'::regclass) AS nextval;", $G_dbpfx);
257         if (($mail_pg  = $this->query($mail_sql)) == FALSE) {
258             return FALSE;
259         }
260         if (pg_numrows($mail_pg) != 1)
261             return FALSE;
262
263         $mail_obj = pg_fetch_object($mail_pg, 0);
264
265         return ($mail_obj->nextval);
266     }
267
268     function check_record_by_login_or_email($login, $email) {
269         GLOBAL $G_dbpfx;
270
271         $arr_fie = array('login', 'email');
272         $arr_val = array($login, $email);
273
274         for ($i = 0 ; $i < 2 ; $i++) {
275             $user_sql = sprintf("SELECT * FROM %susers WHERE %s = lower('%s');",
276                                 $G_dbpfx, $arr_fie[$i], escsql($arr_val[$i]));
277             if (($user_pg  = $this->query($user_sql)) == FALSE) {
278                 fprintf(STDERR, "QUERY [%s]_ FALSE", $user_sql);
279                 return (3);
280             }
281             if (pg_numrows($user_pg) == 1) {
282                 return ($i + 1);
283             }
284         }
285
286         return (0);
287     }
288
289     function getrecord_bycode($code) {
290         GLOBAL $G_dbpfx;
291
292         $user_sql = sprintf("SELECT * FROM %susers WHERE code = %d;",  $G_dbpfx, $code);
293         if (($user_pg  = $this->query($user_sql)) == FALSE) {
294             return FALSE;
295         }
296         if (pg_numrows($user_pg) != 1)
297             return FALSE;
298
299         $user_obj = pg_fetch_object($user_pg, 0);
300
301         return ($user_obj);
302     }
303
304     function user_update_login_time($code, $lintm)
305     {
306         GLOBAL $G_dbpfx;
307
308         $user_sql = sprintf("UPDATE %susers SET (lintm) = (date 'epoch' + %d * INTERVAL '1 second') WHERE code = %d;", $G_dbpfx, $lintm, $code);
309
310         if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
311              return FALSE;
312         }
313
314         return TRUE;
315     }
316
317     function user_update_flag_ty($code, $type, $old_val, $old_reas, $new_val, $new_reas)
318     {
319         GLOBAL $G_dbpfx;
320
321         $user_sql = sprintf("UPDATE %susers SET (type, disa_reas)
322             = (type & ~(CAST (X'%08x' as integer)) | (CAST (X'%08x' as integer)), %d)
323             WHERE code = %d AND (type & (CAST (X'%08x' as integer)))
324                 = (CAST (X'%08x' as integer)) AND disa_reas = %d;",
325                             $G_dbpfx, $type, ($new_val ? $type : 0), $new_reas,
326                             $code, $type, ($old_val ? $type : 0), $old_reas);
327
328         if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
329              return FALSE;
330         }
331
332         return TRUE;
333     }
334
335     function user_update_passwd($code, $passwd)
336     {
337         GLOBAL $G_dbpfx;
338
339         $user_sql = sprintf("UPDATE %susers SET (pass) = (md5('%s')) WHERE code = %d;",
340                             $G_dbpfx, $passwd, $code);
341
342         if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
343              return FALSE;
344         }
345
346         return TRUE;
347     }
348
349     function user_prefs_update($code, $flags, $supp_comp)
350     {
351         GLOBAL $G_dbpfx;
352
353         $user_sql = sprintf("UPDATE %susers SET (type, supp_comp) = (%d, '%s') WHERE code = %d;",
354                             $G_dbpfx, $flags, escsql($supp_comp), $code);
355         fprintf(STDERR, "REQUEST [%s]\n", $user_sql);
356         if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
357              return FALSE;
358         }
359         fprintf(STDERR, "REQUEST GOOD [%s]\n", $user_sql);
360
361         return TRUE;
362     }
363
364     function user_state_update($code, $flags, $disa_reas)
365     {
366         GLOBAL $G_dbpfx;
367
368         $user_sql = sprintf("UPDATE %susers SET (type, disa_reas) = (%d, %d) WHERE code = %d;",
369                             $G_dbpfx, $flags, $disa_reas, $code);
370         fprintf(STDERR, "REQUEST [%s]\n", $user_sql);
371         if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
372              return FALSE;
373         }
374         fprintf(STDERR, "REQUEST GOOD [%s]\n", $user_sql);
375
376         return TRUE;
377     }
378
379     function user_tos_update($code, $tos_vers)
380     {
381         GLOBAL $G_dbpfx;
382
383         $user_sql = sprintf("UPDATE %susers SET (tos_vers) = ('%s') WHERE code = %d;",
384                             $G_dbpfx, escsql($tos_vers), $code);
385         fprintf(STDERR, "REQUEST [%s]\n", $user_sql);
386         if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
387              return FALSE;
388         }
389         fprintf(STDERR, "REQUEST GOOD [%s]\n", $user_sql);
390
391         return TRUE;
392     }
393
394     /*
395       if success return a LoginDBItem object
396      */
397     function login_verify($login, $pass)
398     {
399         GLOBAL $G_dbpfx;
400
401         $ret = FALSE;
402
403         log_main("login_verify: ".$login);
404
405         //O /* check the existence of the nick in the BriskDB */
406         //O for ($i = 0 ; $i < $this->item_n ; $i++) {
407         //O log_main("login_verify: BEGIN");
408
409         if (($user_obj = $this->getrecord_bylogin($login)) == FALSE) {
410             return FALSE;
411         }
412
413         log_main("login[".$user_obj->code."]: ".$user_obj->login);
414
415         /* if it exists check for a valid challenge */
416         if (($a_sem = Challenges::lock_data(TRUE)) != FALSE) {
417             if (($chals = &Challenges::load_data()) != FALSE) {
418                 for ($e = 0 ; $e < $chals->item_n ; $e++) {
419                     log_main("challenge[".$e."]: ".$chals->item[$e]->login);
420                     if (strcmp($login, $chals->item[$e]->login) == 0) {
421                         log_main("login_verify [".$pass."] with [".md5($chals->item[$e]->token.$user_obj->pass)."]");
422
423                         if (strcmp($pass, md5($chals->item[$e]->token.$user_obj->pass)) == 0) {
424                             log_main("login_verify SUCCESS for ".$login);
425
426                             $chals->rem($login);
427                             $this->user_update_login_time($user_obj->code, time());
428                             $ret = LoginDBItem::LoginDBItemFromRecord($user_obj);
429                             break;
430                         }
431                     }
432                 } // end for ($e = 0 ...
433             }
434
435             if ($chals->ismod()) {
436                 Challenges::save_data(&$chals);
437             }
438
439             Challenges::unlock_data($a_sem);
440         }
441         //O break;
442         // O } //  if (strcasecmp($this->item[$i]->login, ...
443         //O }
444
445         return ($ret);
446     }
447
448     function getitem_bylogin($login, &$id) {
449         $ret = FALSE;
450         $id = -1;
451
452         log_main("getitem_bylogin: ".$login);
453
454         if (($user_obj = $this->getrecord_bylogin($login)) == FALSE)
455             return $ret;
456
457         $id = $user_obj->code;
458         return (LoginDBItem::LoginDBItemFromRecord($user_obj));
459     }
460
461     function getitem_bycode($code) {
462         $ret = FALSE;
463
464         log_main("getitem_bycode: ".$code);
465
466         if (($user_obj = $this->getrecord_bycode($code)) == FALSE)
467             return $ret;
468
469         return (LoginDBItem::LoginDBItemFromRecord($user_obj));
470     }
471
472     // TODO FOR DB
473     function getmail($login)
474     {
475         log_main("getmail");
476
477         if (($ret = $this->getrecord_bylogin($login)) == FALSE)
478             return FALSE;
479
480         return ($ret->email);
481     }
482
483     function addusers_from_olddb($olddb, &$cont)
484     {
485         GLOBAL $G_dbpfx;
486
487         for ($i = 0 ; $i < $olddb->count() ; $i++) {
488             $user_sql = sprintf("INSERT INTO %susers ( login, pass, email, type) VALUES ('%s', '%s', '%s', %d);",
489                                 $G_dbpfx, escsql(strtolower($olddb->item[$i]->login)), escsql($olddb->item[$i]->pass),
490                                 escsql($olddb->item[$i]->email), $olddb->item[$i]->type & USER_FLAG_TY_ALL);
491
492             if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
493                 $cont .= sprintf("ERROR IN LINE: %s\n", eschtml($user_sql));
494
495                 return FALSE;
496             }
497         }
498         return TRUE;
499     }
500
501     function getdbconn()
502     {
503         return ($this->dbconn);
504     }
505
506     // return array of array('code', 'login' [, 'first', 'last', 'tidx']) ordered by table position
507     function users_get($match_code, $with_minmaxtidx, $is_newmatch)
508     {
509         GLOBAL $G_dbpfx;
510
511         if ($is_newmatch) { // is new
512             $usr_sql = sprintf("SELECT u.code AS code, u.login AS login%s
513                                   FROM %sbin5_matches AS m, %sbin5_games AS g, %sbin5_points AS p,
514                                        %susers AS u, %sbin5_table_orders AS o
515                                   WHERE m.code = g.mcode AND g.code = p.gcode AND u.code = p.ucode
516                                        AND m.code = o.mcode AND u.code = o.ucode AND m.code = %d
517                                   GROUP BY u.code, u.login%s, o.pos
518                                   ORDER BY o.pos;",
519                                ($with_minmaxtidx ? ", min(g.tstamp) AS first, max(g.tstamp) AS last, m.tidx AS tidx" : ""),
520                                $G_dbpfx, $G_dbpfx, $G_dbpfx, $G_dbpfx, $G_dbpfx, $match_code,
521                                ($with_minmaxtidx ? ", m.tidx" : ""));
522         }
523         else { // is old
524             $usr_sql = sprintf("SELECT u.code AS code, u.login AS login%s
525                                   FROM %sbin5_matches AS m, %sbin5_games AS g, %sbin5_points AS p, %susers AS u
526                                   WHERE m.code = g.mcode AND g.code = p.gcode AND u.code = p.ucode AND m.code = %d
527                                   GROUP BY u.code, u.login%s;",
528                                ($with_minmaxtidx ? ", min(g.tstamp) AS first, max(g.tstamp) AS last, m.tidx AS tidx" : ""),
529                                $G_dbpfx, $G_dbpfx, $G_dbpfx, $G_dbpfx, $match_code,
530                                ($with_minmaxtidx ? ", m.tidx" : ""));
531         }
532
533         if (($usr_pg  = pg_query($this->dbconn->db(), $usr_sql)) == FALSE ) {
534             log_crit(sprintf("%s::%s: pg_query usr_sql failed [%s]", __CLASS__, __FUNCTION__, $usr_sql));
535             return (FALSE);
536         }
537         $usr_n = pg_numrows($usr_pg);
538         if ($usr_n != BIN5_PLAYERS_N) {
539             log_crit(sprintf("%s::%s: wrong number of players [%s] %d", __CLASS__, __FUNCTION__, $usr_sql, $usr_n));
540             return (FALSE);
541         }
542         $users = array();
543
544         if ($with_minmaxtidx)
545             $fields = array('code', 'login', 'first', 'last', 'tidx');
546         else
547             $fields = array('code', 'login');
548
549         for ($u = 0 ; $u < $usr_n ; $u++) {
550             $usr_obj = pg_fetch_object($usr_pg, $u);
551             $users[$u] = array();
552             foreach($fields as $field) {
553                 $users[$u][$field] = $usr_obj->$field;
554             }
555         }
556         return ($users);
557     }
558
559     // out: tab->{points,points_n,old_reason}, in: tab->ttok
560     function match_continue($match_code, $table, $tidx)
561     {
562         GLOBAL $G_dbpfx;
563         $sql_ttok = escsql($table->table_token);
564
565         if (($users = $this->users_get($match_code, FALSE /*without minmaxidx*/, TRUE /*new game*/)) == FALSE) {
566             log_crit(sprintf("%s::%s: retrieve users fails", __CLASS__, __FUNCTION__));
567             return (FALSE);
568         }
569
570         $num_sql = sprintf("SELECT count(*) AS points_n FROM %sbin5_games WHERE mcode = %d;", $G_dbpfx, $match_code);
571         if (($num_pg  = $this->query($num_sql)) == FALSE || pg_numrows($num_pg) != 1) {
572             log_crit(sprintf("%s::%s: get games number fails", __CLASS__, __FUNCTION__));
573             return (FALSE);
574         }
575         $num_obj = pg_fetch_object($num_pg, 0);
576         $table->points_n = $num_obj->points_n;
577
578         // TAG: POINTS_MANAGEMENT
579         $tot_sql = sprintf("SELECT sum(p.pts * (2^g.mult)) AS pts
580                             FROM %sbin5_games AS g, %sbin5_points AS p, %susers AS u,
581                                  %sbin5_table_orders AS o
582                             WHERE g.mcode = %d AND g.code = p.gcode AND p.ucode = u.code
583                                   AND p.ucode = o.ucode AND g.mcode = o.mcode
584                             GROUP BY p.ucode, o.pos
585                             ORDER BY o.pos;",
586                            $G_dbpfx, $G_dbpfx, $G_dbpfx, $G_dbpfx, $match_code);
587         if (($tot_pg  = pg_query($this->dbconn->db(), $tot_sql)) == FALSE
588             || pg_numrows($tot_pg) != BIN5_PLAYERS_N) {
589             log_crit(sprintf("%s::%s: get games totals fails", __CLASS__, __FUNCTION__));
590             return(FALSE);
591         }
592
593         $u = 0;
594         foreach ($users as $user) {
595             // TAG: POINTS_MANAGEMENT
596             $pts_sql = sprintf("SELECT p.pts AS pts, g.mult AS mult
597                                     FROM %sbin5_points as p, %sbin5_games as g
598                                     WHERE p.gcode = g.code AND g.mcode = %d AND p.ucode = %d
599                                     ORDER BY g.tstamp ASC
600                                     LIMIT %d OFFSET %d;",
601                                $G_dbpfx, $G_dbpfx, $match_code, $user['code'],
602                                MAX_POINTS,
603                                ($num_obj->points_n < MAX_POINTS ? 0 : $num_obj->points_n - MAX_POINTS));
604
605             // points of the match for each user
606             if (($pts_pg  = $this->query($pts_sql)) == FALSE) {
607                 log_crit(sprintf("%s::%s: get points fails", __CLASS__, __FUNCTION__));
608                 return (FALSE);
609             }
610             $pts_n = pg_numrows($pts_pg);
611             if ($pts_n > $table->points_n) {
612                 // inconsistent scenario number of points great than number of games
613                 log_crit(sprintf("%s::%s: number of points great than number of games", __CLASS__, __FUNCTION__));
614                 return (FALSE);
615             }
616             // TAG: POINTS_MANAGEMENT
617             for ($i = 0 , $ct = $table->points_n - $pts_n; $ct < $table->points_n ; $ct++, $i++) {
618                 $pts_obj = pg_fetch_object($pts_pg, $i);
619                 $table->points[$ct % MAX_POINTS][$u] = $pts_obj->pts * pow(2, $pts_obj->mult);
620             }
621             $tot_obj = pg_fetch_object($tot_pg, $u);
622             $table->total[$u] = $tot_obj->pts;
623
624             $u++;
625         }
626
627         $gam_sql = sprintf("SELECT * FROM %sbin5_games WHERE mcode = %d ORDER BY tstamp DESC LIMIT 1;", $G_dbpfx, $match_code);
628         if (($gam_pg  = $this->query($gam_sql)) == FALSE || pg_numrows($gam_pg) != 1) {
629             log_crit(sprintf("%s::%s: get last game fails", __CLASS__, __FUNCTION__));
630             return (FALSE);
631         }
632         $gam_obj = pg_fetch_object($gam_pg, 0);
633
634         $table->old_reason = game_description($gam_obj->act, 'html', $gam_obj->mult,
635                                               $gam_obj->asta_win, ($gam_obj->asta_win != -1 ?
636                                                                    $users[$gam_obj->asta_win]['login'] : ""),
637                                               $gam_obj->friend, ($gam_obj->friend != -1 ?
638                                                                  $users[$gam_obj->friend]['login'] : ""),
639                                               $gam_obj->pnt, $gam_obj->asta_pnt);
640
641         // update matches with new ttok and table idx
642         $mtc_sql = sprintf("UPDATE %sbin5_matches SET (ttok, tidx) = ('%s', %d) WHERE code = %d RETURNING *;",
643                            $G_dbpfx, $sql_ttok, $tidx, $match_code);
644         if (($mtc_pg  = $this->query($mtc_sql)) == FALSE || pg_numrows($mtc_pg) != 1) {
645             log_crit(sprintf("%s::%s: update matches table failed", __CLASS__, __FUNCTION__));
646             return (FALSE);
647         }
648
649         return (TRUE);
650     }
651
652     function match_order_get(&$match_data, $match_code, $exp_num)
653     {
654         GLOBAL $G_dbpfx;
655
656         $ord_sql = sprintf("SELECT ucode FROM %sbin5_table_orders WHERE mcode = %d ORDER BY pos ASC;",
657                            $G_dbpfx, $match_code);
658
659         if (($ord_pg  = $this->query($ord_sql)) == FALSE || pg_numrows($ord_pg) != $exp_num) {
660             log_crit(sprintf("%s: fails for id or users number", __FUNCTION__));
661             return (FALSE);
662         }
663
664         $ucodes = array();
665         for ($i = 0 ; $i < $exp_num ; $i++) {
666             $ord_obj = pg_fetch_object($ord_pg, $i);
667             $ucodes[$i] = $ord_obj->ucode;
668         }
669
670         if ($match_data !== NULL) {
671             $mtdt_sql = sprintf("SELECT * FROM %sbin5_matches WHERE code = %d;",
672                                 $G_dbpfx, $match_code);
673
674             if (($mtdt_pg  = $this->query($mtdt_sql)) == FALSE || pg_numrows($mtdt_pg) != 1) {
675                 log_crit(sprintf("%s: fails retrieve match_data values [%d]", __FUNCTION__, $match_code));
676                 return (FALSE);
677             }
678
679             $mtdt_obj = pg_fetch_object($mtdt_pg, 0);
680
681             foreach (array('ttok', 'tidx', 'mult_next', 'mazzo_next', 'tcode') as $match_name) {
682                 $match_data[$match_name] = $mtdt_obj->$match_name;
683             }
684         }
685
686         return ($ucodes);
687     }
688
689     //   ttok   text UNIQUE,
690     //   tidx
691     function bin5_points_save($date, $table, $tidx, $action, $ucodes, $pts)
692     {
693         GLOBAL $G_dbpfx;
694         $sql_ttok = escsql($table->table_token);
695
696         $is_trans = FALSE;
697         $ret = FALSE;
698
699         $n = count($ucodes);
700         /* check the existence of the nick in the BriskDB */
701         log_main("bin5_points_save: ");
702
703         do {
704             if ($this->query("BEGIN") == FALSE) {
705                 break;
706             }
707             $is_trans = TRUE;
708
709             /*
710              * matches management
711              */
712             $codes_where = "";
713             $mtc_sql = sprintf("UPDATE %sbin5_matches SET (mazzo_next, mult_next) = (%d, %d) WHERE ttok = '%s' RETURNING *;",
714                                $G_dbpfx, $table->mazzo, $table->mult, $sql_ttok);
715             if (($mtc_pg  = $this->query($mtc_sql)) == FALSE || pg_numrows($mtc_pg) != 1) {
716
717                 // match not exists, insert it
718                 $mtc_sql = sprintf("INSERT INTO %sbin5_matches (ttok, tidx, mazzo_next, mult_next) VALUES ('%s', %d, %d, %d) RETURNING *;",
719                                    $G_dbpfx, $sql_ttok, $tidx, $table->mazzo, $table->mult);
720                 if (($mtc_pg  = $this->query($mtc_sql)) == FALSE || pg_affected_rows($mtc_pg) != 1) {
721                     log_crit(sprintf("bin5_points_save: failed at insert match [%s]", $mtc_sql));
722                     break;
723                 }
724                 $mtc_obj = pg_fetch_object($mtc_pg, 0);
725
726                 for ($i = 0 ; $i < $n ; $i++) {
727                     $ord_sql = sprintf("INSERT INTO %sbin5_table_orders (mcode, ucode, pos) VALUES (%d, %d, %d);",
728                                        $G_dbpfx, $mtc_obj->code, $ucodes[$i], $i);
729                     if (($ord_pg = $this->query($ord_sql)) == FALSE || pg_affected_rows($ord_pg) != 1 ) {
730                         log_crit(sprintf("bin5_points_save: failed at insert table order [%s]", $ord_sql));
731                         break;
732                     }
733                     $codes_where .= sprintf("%scode = %d", ($i == 0  ? "" : " OR "), $ucodes[$i]);
734                 }
735                 if ($i < $n)
736                     break;
737
738                 // FIXME: uncomment when counters are updated
739                 if (0 == 1) {
740                     $cnt_sql = sprintf("UPDATE %susers SET (match_cnt, game_cnt)
741                                         = (match_cnt+1, game_cnt+1) WHERE %s;",
742                                        $G_dbpfx, $codes_where);
743                     error_log($cnt_sql);
744                     if (($cnt_pg = $this->query($cnt_sql)) == FALSE || pg_affected_rows($cnt_pg) != $n) {
745                         log_crit(sprintf("bin5_points_save: failed increment match and game [%s]", $cnt_sql));
746                         break;
747                     }
748                 }
749             }
750             else {
751                 $mtc_obj = pg_fetch_object($mtc_pg,0);
752
753                 // FIXME: uncomment when counters are updated
754                 if (0 == 1) {
755                     for ($i = 0 ; $i < $n ; $i++) {
756                         $codes_where .= sprintf("%scode = %d", ($i == 0 ? "" : " OR "), $ucodes[$i]);
757                     }
758                     $cnt_sql = sprintf("UPDATE %susers SET (game_cnt)
759                                         = (game_cnt+1) WHERE %s;",
760                                        $G_dbpfx, $codes_where);
761                     error_log($cnt_sql);
762                     if (($cnt_pg = $this->query($cnt_sql)) == FALSE || pg_affected_rows($cnt_pg) != $n) {
763                         log_crit(sprintf("bin5_points_save: failed increment game [%s]", $cnt_sql));
764                         break;
765                     }
766                 }
767             }
768
769             /*
770              * games management
771              */
772             $gam_sql = sprintf("INSERT INTO %sbin5_games (mcode, tstamp, act, asta_pnt, pnt, asta_win, friend, mazzo, mult)
773                                                VALUES (%d, to_timestamp(%d), %d, %d, %d, %d, %d, %d, %d) RETURNING *;",
774                                $G_dbpfx, $mtc_obj->code, $date, $action,
775                                $table->old_asta_pnt, $table->old_pnt,
776                                $table->old_asta_win,
777                                $table->old_friend,
778                                $table->old_mazzo, $table->old_mult);
779             if (($gam_pg  = $this->query($gam_sql)) == FALSE || pg_affected_rows($gam_pg) != 1) {
780                 log_crit(sprintf("bin5_points_save: failed at insert game [%s]", $gam_sql));
781                 break;
782             }
783
784             $gam_obj = pg_fetch_object($gam_pg,0);
785
786             /*
787              * points management
788              */
789             for ($i = 0 ; $i < $n ; $i++) {
790                 /* put points */
791                 $pts_sql = sprintf("INSERT INTO %sbin5_points (gcode, ucode, pts)
792                                                VALUES (%d, %d, %d);",
793                                    $G_dbpfx, $gam_obj->code, $ucodes[$i], $pts[$i]);
794                 if (($pts_pg  = $this->query($pts_sql)) == FALSE || pg_affected_rows($pts_pg) != 1) {
795                     log_crit(sprintf("bin5_points_save: failed at insert point [%s]", $pts_sql));
796                     break;
797                 }
798             }
799             if ($i < $n)
800                 break;
801
802             if ($this->query("COMMIT") == FALSE) {
803                 break;
804             }
805
806             $is_trans = FALSE;
807
808             $table->match_id = $mtc_obj->code;
809             $ret = TRUE;
810         } while (0);
811
812         if ($is_trans)
813             $this->query("ROLLBACK");
814
815         return $ret;
816     }
817
818     function mail_add_fromitem($mail) {
819         GLOBAL $G_dbpfx;
820
821         $usr_sql = sprintf("
822 INSERT INTO %smails (code, ucode, type, tstamp, subj, body_txt, body_htm, hash)
823             VALUES (%d, %d, %d, to_timestamp(%d), '%s', '%s', '%s', '%s') RETURNING *;",
824                            $G_dbpfx, $mail->code, $mail->ucode, $mail->type, $mail->tstamp,
825                            escsql($mail->subj), escsql($mail->body_txt), escsql($mail->body_htm),
826                            ($mail->hash == NULL ? "" : escsql($mail->hash))
827                            );
828
829         if (! (($usr_pg  = $this->query($usr_sql)) != FALSE && pg_affected_rows($usr_pg) == 1) ) {
830             return FALSE;
831         }
832         $usr_obj = pg_fetch_object($usr_pg, 0);
833
834         return $usr_obj;
835     }
836
837     function mail_check($code, $type, $hash)
838     {
839         GLOBAL $G_dbpfx;
840
841         $mai_sql = sprintf("SELECT * FROM %smails WHERE code = %d AND type = %d AND hash = '%s';",
842                            $G_dbpfx, $code, $type, escsql($hash));
843         if (($mai_pg  = $this->query($mai_sql)) == FALSE || pg_numrows($mai_pg) != 1) {
844             // check failed
845             return (FALSE);
846         }
847
848         $mai_obj = pg_fetch_object($mai_pg, 0);
849         return ($mai_obj);
850     }
851
852     function mail_delete($code)
853     {
854         GLOBAL $G_dbpfx;
855
856         $mai_sql = sprintf("DELETE FROM %smails WHERE code = %d;", $G_dbpfx, $code);
857
858         if (($mai_pg = $this->query($mai_sql)) == FALSE || pg_affected_rows($mai_pg) != 1) {
859             return (FALSE);
860         }
861         return (TRUE);
862     }
863
864
865 } // End class BriskDB
866
867 class LoginDBOld
868 {
869     var $item;
870     var $item_n;
871
872     function LoginDBOld($filename)
873     {
874         GLOBAL $DOCUMENT_ROOT;
875         log_main("LoginDBOld create:start");
876
877         if (file_exists("$DOCUMENT_ROOT/Etc/".$filename)) {
878             require("$DOCUMENT_ROOT/Etc/".$filename);
879         }
880         else {
881             return (FALSE);
882         }
883         $this->item_n = count($this->item);
884         log_main("LoginDBOld create:end");
885     }
886
887     function count()
888     {
889         return ($this->item_n);
890     }
891
892 } // End class LoginDBOld
893
894 ?>