check for info parameters
[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         if (($sere_pg = $this->query($sere_sql)) == FALSE) {
214             return (FALSE);
215         }
216
217         $sere_sql = sprintf("SELECT * FROM %sselfreg_chk WHERE (ip & %d) = %d;",
218                             $G_dbpfx, int2four($G_selfreg_mask), int2four($laddr & $G_selfreg_mask));
219         if (($sere_pg  = $this->query($sere_sql)) == FALSE) {
220             return(FALSE);
221         }
222
223         $ret = pg_numrows($sere_pg);
224
225         if ($ret === FALSE) {
226             return(FALSE);
227         }
228         else if ($ret === 0) {
229             return(TRUE);
230         }
231         else if ($ret > 0) {
232             // already present
233             return(FALSE);
234         }
235         else {
236             // unreachable branch
237             return(FALSE);
238         }
239     }
240
241     /*
242       $laddr is native php int (32 or 64 bit)
243       if ret True is ip is free
244     */
245     function selfreg_set($laddr)
246     {
247         GLOBAL $G_dbpfx, $G_selfreg_tout, $G_selfreg_mask;
248
249         $newi_sql = sprintf("INSERT INTO %sselfreg_chk (ip, atime) VALUES (%d, now() + interval '%d seconds');",
250                             $G_dbpfx, int2four($laddr & $G_selfreg_mask), $G_selfreg_tout);
251         if (($newi_pg  = $this->query($newi_sql)) == FALSE) {
252             return(FALSE);
253         }
254         return(TRUE);
255     }
256
257     /*
258       to be able to add mail record code into the record itself I must reserve it before.
259      */
260     function mail_reserve_code() {
261         GLOBAL $G_dbpfx;
262
263         $mail_sql = sprintf("SELECT nextval('%smails_code_seq'::regclass) AS nextval;", $G_dbpfx);
264         if (($mail_pg  = $this->query($mail_sql)) == FALSE) {
265             return FALSE;
266         }
267         if (pg_numrows($mail_pg) != 1)
268             return FALSE;
269
270         $mail_obj = pg_fetch_object($mail_pg, 0);
271
272         return ($mail_obj->nextval);
273     }
274
275     function check_record_by_login_or_email($login, $email) {
276         GLOBAL $G_dbpfx;
277
278         $arr_fie = array('login', 'email');
279         $arr_val = array($login, $email);
280
281         for ($i = 0 ; $i < 2 ; $i++) {
282             $user_sql = sprintf("SELECT * FROM %susers WHERE %s = lower('%s');",
283                                 $G_dbpfx, $arr_fie[$i], escsql($arr_val[$i]));
284             if (($user_pg  = $this->query($user_sql)) == FALSE) {
285                 fprintf(STDERR, "QUERY [%s]_ FALSE", $user_sql);
286                 return (3);
287             }
288             if (pg_numrows($user_pg) == 1) {
289                 return ($i + 1);
290             }
291         }
292
293         return (0);
294     }
295
296     function getrecord_bycode($code) {
297         GLOBAL $G_dbpfx;
298
299         $user_sql = sprintf("SELECT * FROM %susers WHERE code = %d;",  $G_dbpfx, $code);
300         if (($user_pg  = $this->query($user_sql)) == FALSE) {
301             return FALSE;
302         }
303         if (pg_numrows($user_pg) != 1)
304             return FALSE;
305
306         $user_obj = pg_fetch_object($user_pg, 0);
307
308         return ($user_obj);
309     }
310
311     function user_update_login_time($code, $lintm)
312     {
313         GLOBAL $G_dbpfx;
314
315         $user_sql = sprintf("UPDATE %susers SET (lintm) = (date 'epoch' + %d * INTERVAL '1 second') WHERE code = %d;", $G_dbpfx, $lintm, $code);
316
317         if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
318              return FALSE;
319         }
320
321         return TRUE;
322     }
323
324     function user_update_flag_ty($code, $type, $old_val, $old_reas, $new_val, $new_reas)
325     {
326         GLOBAL $G_dbpfx;
327
328         $user_sql = sprintf("UPDATE %susers SET (type, disa_reas)
329             = (type & ~(CAST (X'%08x' as integer)) | (CAST (X'%08x' as integer)), %d)
330             WHERE code = %d AND (type & (CAST (X'%08x' as integer)))
331                 = (CAST (X'%08x' as integer)) AND disa_reas = %d;",
332                             $G_dbpfx, $type, ($new_val ? $type : 0), $new_reas,
333                             $code, $type, ($old_val ? $type : 0), $old_reas);
334
335         if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
336              return FALSE;
337         }
338
339         return TRUE;
340     }
341
342     function user_update_passwd($code, $passwd)
343     {
344         GLOBAL $G_dbpfx;
345
346         $user_sql = sprintf("UPDATE %susers SET (pass) = (md5('%s')) WHERE code = %d;",
347                             $G_dbpfx, $passwd, $code);
348
349         if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
350              return FALSE;
351         }
352
353         return TRUE;
354     }
355
356     function user_prefs_update($code, $flags, $supp_comp)
357     {
358         GLOBAL $G_dbpfx;
359
360         $user_sql = sprintf("UPDATE %susers SET (type, supp_comp) = (%d, '%s') WHERE code = %d;",
361                             $G_dbpfx, $flags, escsql($supp_comp), $code);
362         if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
363              return FALSE;
364         }
365
366         return TRUE;
367     }
368
369     function user_state_update($code, $flags, $disa_reas)
370     {
371         GLOBAL $G_dbpfx;
372
373         $user_sql = sprintf("UPDATE %susers SET (type, disa_reas) = (%d, %d) WHERE code = %d;",
374                             $G_dbpfx, $flags, $disa_reas, $code);
375         if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
376              return FALSE;
377         }
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         if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
389              return FALSE;
390         }
391
392         return TRUE;
393     }
394
395     /*
396       if success return a LoginDBItem object
397      */
398     function login_verify($login, $pass)
399     {
400         GLOBAL $G_dbpfx;
401
402         $ret = FALSE;
403
404         log_main("login_verify: ".$login);
405
406         //O /* check the existence of the nick in the BriskDB */
407         //O for ($i = 0 ; $i < $this->item_n ; $i++) {
408         //O log_main("login_verify: BEGIN");
409
410         if (($user_obj = $this->getrecord_bylogin($login)) == FALSE) {
411             return FALSE;
412         }
413
414         log_main("login[".$user_obj->code."]: ".$user_obj->login);
415
416         /* if it exists check for a valid challenge */
417         if (($a_sem = Challenges::lock_data(TRUE)) != FALSE) {
418             if (($chals = &Challenges::load_data()) != FALSE) {
419                 for ($e = 0 ; $e < $chals->item_n ; $e++) {
420                     log_main("challenge[".$e."]: ".$chals->item[$e]->login);
421                     if (strcmp($login, $chals->item[$e]->login) == 0) {
422                         log_main("login_verify [".$pass."] with [".md5($chals->item[$e]->token.$user_obj->pass)."]");
423
424                         if (strcmp($pass, md5($chals->item[$e]->token.$user_obj->pass)) == 0) {
425                             log_main("login_verify SUCCESS for ".$login);
426
427                             $chals->rem($login);
428                             $this->user_update_login_time($user_obj->code, time());
429                             $ret = LoginDBItem::LoginDBItemFromRecord($user_obj);
430                             break;
431                         }
432                     }
433                 } // end for ($e = 0 ...
434             }
435
436             if ($chals->ismod()) {
437                 Challenges::save_data(&$chals);
438             }
439
440             Challenges::unlock_data($a_sem);
441         }
442         //O break;
443         // O } //  if (strcasecmp($this->item[$i]->login, ...
444         //O }
445
446         return ($ret);
447     }
448
449     function getitem_bylogin($login, &$id) {
450         $ret = FALSE;
451         $id = -1;
452
453         log_main("getitem_bylogin: ".$login);
454
455         if (($user_obj = $this->getrecord_bylogin($login)) == FALSE)
456             return $ret;
457
458         $id = $user_obj->code;
459         return (LoginDBItem::LoginDBItemFromRecord($user_obj));
460     }
461
462     function getitem_bycode($code) {
463         $ret = FALSE;
464
465         log_main("getitem_bycode: ".$code);
466
467         if (($user_obj = $this->getrecord_bycode($code)) == FALSE)
468             return $ret;
469
470         return (LoginDBItem::LoginDBItemFromRecord($user_obj));
471     }
472
473     // TODO FOR DB
474     function getmail($login)
475     {
476         log_main("getmail");
477
478         if (($ret = $this->getrecord_bylogin($login)) == FALSE)
479             return FALSE;
480
481         return ($ret->email);
482     }
483
484     function addusers_from_olddb($olddb, &$cont)
485     {
486         GLOBAL $G_dbpfx;
487
488         for ($i = 0 ; $i < $olddb->count() ; $i++) {
489             $user_sql = sprintf("INSERT INTO %susers ( login, pass, email, type) VALUES ('%s', '%s', '%s', %d);",
490                                 $G_dbpfx, escsql(strtolower($olddb->item[$i]->login)), escsql($olddb->item[$i]->pass),
491                                 escsql($olddb->item[$i]->email), $olddb->item[$i]->type & USER_FLAG_TY_ALL);
492
493             if ( ! (($user_pg  = $this->query($user_sql)) != FALSE && pg_affected_rows($user_pg) == 1) ) {
494                 $cont .= sprintf("ERROR IN LINE: %s\n", eschtml($user_sql));
495
496                 return FALSE;
497             }
498         }
499         return TRUE;
500     }
501
502     function getdbconn()
503     {
504         return ($this->dbconn);
505     }
506
507     // return array of array('code', 'login' [, 'first', 'last', 'tidx']) ordered by table position
508     function users_get($match_code, $with_minmaxtidx, $is_newmatch)
509     {
510         GLOBAL $G_dbpfx;
511
512         if ($is_newmatch) { // is new
513             $usr_sql = sprintf("SELECT u.code AS code, u.login AS login%s
514                                   FROM %sbin5_matches AS m, %sbin5_games AS g, %sbin5_points AS p,
515                                        %susers AS u, %sbin5_table_orders AS o
516                                   WHERE m.code = g.mcode AND g.code = p.gcode AND u.code = p.ucode
517                                        AND m.code = o.mcode AND u.code = o.ucode AND m.code = %d
518                                   GROUP BY u.code, u.login%s, o.pos
519                                   ORDER BY o.pos;",
520                                ($with_minmaxtidx ? ", min(g.tstamp) AS first, max(g.tstamp) AS last, m.tidx AS tidx" : ""),
521                                $G_dbpfx, $G_dbpfx, $G_dbpfx, $G_dbpfx, $G_dbpfx, $match_code,
522                                ($with_minmaxtidx ? ", m.tidx" : ""));
523         }
524         else { // is old
525             $usr_sql = sprintf("SELECT u.code AS code, u.login AS login%s
526                                   FROM %sbin5_matches AS m, %sbin5_games AS g, %sbin5_points AS p, %susers AS u
527                                   WHERE m.code = g.mcode AND g.code = p.gcode AND u.code = p.ucode AND m.code = %d
528                                   GROUP BY u.code, u.login%s;",
529                                ($with_minmaxtidx ? ", min(g.tstamp) AS first, max(g.tstamp) AS last, m.tidx AS tidx" : ""),
530                                $G_dbpfx, $G_dbpfx, $G_dbpfx, $G_dbpfx, $match_code,
531                                ($with_minmaxtidx ? ", m.tidx" : ""));
532         }
533
534         if (($usr_pg  = pg_query($this->dbconn->db(), $usr_sql)) == FALSE ) {
535             log_crit(sprintf("%s::%s: pg_query usr_sql failed [%s]", __CLASS__, __FUNCTION__, $usr_sql));
536             return (FALSE);
537         }
538         $usr_n = pg_numrows($usr_pg);
539         if ($usr_n != BIN5_PLAYERS_N) {
540             log_crit(sprintf("%s::%s: wrong number of players [%s] %d", __CLASS__, __FUNCTION__, $usr_sql, $usr_n));
541             return (FALSE);
542         }
543         $users = array();
544
545         if ($with_minmaxtidx)
546             $fields = array('code', 'login', 'first', 'last', 'tidx');
547         else
548             $fields = array('code', 'login');
549
550         for ($u = 0 ; $u < $usr_n ; $u++) {
551             $usr_obj = pg_fetch_object($usr_pg, $u);
552             $users[$u] = array();
553             foreach($fields as $field) {
554                 $users[$u][$field] = $usr_obj->$field;
555             }
556         }
557         return ($users);
558     }
559
560     // out: tab->{points,points_n,old_reason}, in: tab->ttok
561     function match_continue($match_code, $table, $tidx)
562     {
563         GLOBAL $G_dbpfx;
564         $sql_ttok = escsql($table->table_token);
565
566         if (($users = $this->users_get($match_code, FALSE /*without minmaxidx*/, TRUE /*new game*/)) == FALSE) {
567             log_crit(sprintf("%s::%s: retrieve users fails", __CLASS__, __FUNCTION__));
568             return (FALSE);
569         }
570
571         $num_sql = sprintf("SELECT count(*) AS points_n FROM %sbin5_games WHERE mcode = %d;", $G_dbpfx, $match_code);
572         if (($num_pg  = $this->query($num_sql)) == FALSE || pg_numrows($num_pg) != 1) {
573             log_crit(sprintf("%s::%s: get games number fails", __CLASS__, __FUNCTION__));
574             return (FALSE);
575         }
576         $num_obj = pg_fetch_object($num_pg, 0);
577         $table->points_n = $num_obj->points_n;
578
579         // TAG: POINTS_MANAGEMENT
580         $tot_sql = sprintf("SELECT sum(p.pts * (2^g.mult)) AS pts
581                             FROM %sbin5_games AS g, %sbin5_points AS p, %susers AS u,
582                                  %sbin5_table_orders AS o
583                             WHERE g.mcode = %d AND g.code = p.gcode AND p.ucode = u.code
584                                   AND p.ucode = o.ucode AND g.mcode = o.mcode
585                             GROUP BY p.ucode, o.pos
586                             ORDER BY o.pos;",
587                            $G_dbpfx, $G_dbpfx, $G_dbpfx, $G_dbpfx, $match_code);
588         if (($tot_pg  = pg_query($this->dbconn->db(), $tot_sql)) == FALSE
589             || pg_numrows($tot_pg) != BIN5_PLAYERS_N) {
590             log_crit(sprintf("%s::%s: get games totals fails", __CLASS__, __FUNCTION__));
591             return(FALSE);
592         }
593
594         $u = 0;
595         foreach ($users as $user) {
596             // TAG: POINTS_MANAGEMENT
597             $pts_sql = sprintf("SELECT p.pts AS pts, g.mult AS mult
598                                     FROM %sbin5_points as p, %sbin5_games as g
599                                     WHERE p.gcode = g.code AND g.mcode = %d AND p.ucode = %d
600                                     ORDER BY g.tstamp ASC
601                                     LIMIT %d OFFSET %d;",
602                                $G_dbpfx, $G_dbpfx, $match_code, $user['code'],
603                                MAX_POINTS,
604                                ($num_obj->points_n < MAX_POINTS ? 0 : $num_obj->points_n - MAX_POINTS));
605
606             // points of the match for each user
607             if (($pts_pg  = $this->query($pts_sql)) == FALSE) {
608                 log_crit(sprintf("%s::%s: get points fails", __CLASS__, __FUNCTION__));
609                 return (FALSE);
610             }
611             $pts_n = pg_numrows($pts_pg);
612             if ($pts_n > $table->points_n) {
613                 // inconsistent scenario number of points great than number of games
614                 log_crit(sprintf("%s::%s: number of points great than number of games", __CLASS__, __FUNCTION__));
615                 return (FALSE);
616             }
617             // TAG: POINTS_MANAGEMENT
618             for ($i = 0 , $ct = $table->points_n - $pts_n; $ct < $table->points_n ; $ct++, $i++) {
619                 $pts_obj = pg_fetch_object($pts_pg, $i);
620                 $table->points[$ct % MAX_POINTS][$u] = $pts_obj->pts * pow(2, $pts_obj->mult);
621             }
622             $tot_obj = pg_fetch_object($tot_pg, $u);
623             $table->total[$u] = $tot_obj->pts;
624
625             $u++;
626         }
627
628         $gam_sql = sprintf("SELECT * FROM %sbin5_games WHERE mcode = %d ORDER BY tstamp DESC LIMIT 1;", $G_dbpfx, $match_code);
629         if (($gam_pg  = $this->query($gam_sql)) == FALSE || pg_numrows($gam_pg) != 1) {
630             log_crit(sprintf("%s::%s: get last game fails", __CLASS__, __FUNCTION__));
631             return (FALSE);
632         }
633         $gam_obj = pg_fetch_object($gam_pg, 0);
634
635         $table->old_reason = game_description($gam_obj->act, 'html', $gam_obj->mult,
636                                               $gam_obj->asta_win, ($gam_obj->asta_win != -1 ?
637                                                                    $users[$gam_obj->asta_win]['login'] : ""),
638                                               $gam_obj->friend, ($gam_obj->friend != -1 ?
639                                                                  $users[$gam_obj->friend]['login'] : ""),
640                                               $gam_obj->pnt, $gam_obj->asta_pnt);
641
642         // update matches with new ttok and table idx
643         $mtc_sql = sprintf("UPDATE %sbin5_matches SET (ttok, tidx) = ('%s', %d) WHERE code = %d RETURNING *;",
644                            $G_dbpfx, $sql_ttok, $tidx, $match_code);
645         if (($mtc_pg  = $this->query($mtc_sql)) == FALSE || pg_numrows($mtc_pg) != 1) {
646             log_crit(sprintf("%s::%s: update matches table failed", __CLASS__, __FUNCTION__));
647             return (FALSE);
648         }
649
650         return (TRUE);
651     }
652
653     function match_order_get(&$match_data, $match_code, $exp_num)
654     {
655         GLOBAL $G_dbpfx;
656
657         $ord_sql = sprintf("SELECT ucode FROM %sbin5_table_orders WHERE mcode = %d ORDER BY pos ASC;",
658                            $G_dbpfx, $match_code);
659
660         if (($ord_pg  = $this->query($ord_sql)) == FALSE || pg_numrows($ord_pg) != $exp_num) {
661             log_crit(sprintf("%s: fails for id or users number", __FUNCTION__));
662             return (FALSE);
663         }
664
665         $ucodes = array();
666         for ($i = 0 ; $i < $exp_num ; $i++) {
667             $ord_obj = pg_fetch_object($ord_pg, $i);
668             $ucodes[$i] = $ord_obj->ucode;
669         }
670
671         if ($match_data !== NULL) {
672             $mtdt_sql = sprintf("SELECT * FROM %sbin5_matches WHERE code = %d;",
673                                 $G_dbpfx, $match_code);
674
675             if (($mtdt_pg  = $this->query($mtdt_sql)) == FALSE || pg_numrows($mtdt_pg) != 1) {
676                 log_crit(sprintf("%s: fails retrieve match_data values [%d]", __FUNCTION__, $match_code));
677                 return (FALSE);
678             }
679
680             $mtdt_obj = pg_fetch_object($mtdt_pg, 0);
681
682             foreach (array('ttok', 'tidx', 'mult_next', 'mazzo_next', 'tcode') as $match_name) {
683                 $match_data[$match_name] = $mtdt_obj->$match_name;
684             }
685         }
686
687         return ($ucodes);
688     }
689
690     //   ttok   text UNIQUE,
691     //   tidx
692     function bin5_points_save($date, $table, $tidx, $action, $ucodes, $pts)
693     {
694         GLOBAL $G_dbpfx;
695         $sql_ttok = escsql($table->table_token);
696
697         $is_trans = FALSE;
698         $ret = FALSE;
699
700         $n = count($ucodes);
701         /* check the existence of the nick in the BriskDB */
702         log_main("bin5_points_save: ");
703
704         do {
705             if ($this->query("BEGIN") == FALSE) {
706                 break;
707             }
708             $is_trans = TRUE;
709
710             /*
711              * matches management
712              */
713             $codes_where = "";
714             $mtc_sql = sprintf("UPDATE %sbin5_matches SET (mazzo_next, mult_next) = (%d, %d) WHERE ttok = '%s' RETURNING *;",
715                                $G_dbpfx, $table->mazzo, $table->mult, $sql_ttok);
716             if (($mtc_pg  = $this->query($mtc_sql)) == FALSE || pg_numrows($mtc_pg) != 1) {
717
718                 // match not exists, insert it
719                 $mtc_sql = sprintf("INSERT INTO %sbin5_matches (ttok, tidx, mazzo_next, mult_next) VALUES ('%s', %d, %d, %d) RETURNING *;",
720                                    $G_dbpfx, $sql_ttok, $tidx, $table->mazzo, $table->mult);
721                 if (($mtc_pg  = $this->query($mtc_sql)) == FALSE || pg_affected_rows($mtc_pg) != 1) {
722                     log_crit(sprintf("bin5_points_save: failed at insert match [%s]", $mtc_sql));
723                     break;
724                 }
725                 $mtc_obj = pg_fetch_object($mtc_pg, 0);
726
727                 for ($i = 0 ; $i < $n ; $i++) {
728                     $ord_sql = sprintf("INSERT INTO %sbin5_table_orders (mcode, ucode, pos) VALUES (%d, %d, %d);",
729                                        $G_dbpfx, $mtc_obj->code, $ucodes[$i], $i);
730                     if (($ord_pg = $this->query($ord_sql)) == FALSE || pg_affected_rows($ord_pg) != 1 ) {
731                         log_crit(sprintf("bin5_points_save: failed at insert table order [%s]", $ord_sql));
732                         break;
733                     }
734                     $codes_where .= sprintf("%scode = %d", ($i == 0  ? "" : " OR "), $ucodes[$i]);
735                 }
736                 if ($i < $n)
737                     break;
738
739                 $cnt_sql = sprintf("UPDATE %susers SET (match_cnt, game_cnt)
740                                         = (match_cnt+1, game_cnt+1) WHERE %s;",
741                                    $G_dbpfx, $codes_where);
742                 error_log($cnt_sql);
743                 if (($cnt_pg = $this->query($cnt_sql)) == FALSE || pg_affected_rows($cnt_pg) != $n) {
744                     log_crit(sprintf("bin5_points_save: failed increment match and game [%s]", $cnt_sql));
745                     break;
746                 }
747             }
748             else {
749                 $mtc_obj = pg_fetch_object($mtc_pg,0);
750
751                 for ($i = 0 ; $i < $n ; $i++) {
752                     $codes_where .= sprintf("%scode = %d", ($i == 0 ? "" : " OR "), $ucodes[$i]);
753                 }
754                 $cnt_sql = sprintf("UPDATE %susers SET (game_cnt)
755                                         = (game_cnt+1) WHERE %s;",
756                                    $G_dbpfx, $codes_where);
757                 error_log($cnt_sql);
758                 if (($cnt_pg = $this->query($cnt_sql)) == FALSE || pg_affected_rows($cnt_pg) != $n) {
759                     log_crit(sprintf("bin5_points_save: failed increment game [%s]", $cnt_sql));
760                     break;
761                 }
762             }
763
764             /*
765              * games management
766              */
767             $gam_sql = sprintf("INSERT INTO %sbin5_games (mcode, tstamp, act, asta_pnt, pnt, asta_win, friend, mazzo, mult)
768                                                VALUES (%d, to_timestamp(%d), %d, %d, %d, %d, %d, %d, %d) RETURNING *;",
769                                $G_dbpfx, $mtc_obj->code, $date, $action,
770                                $table->old_asta_pnt, $table->old_pnt,
771                                $table->old_asta_win,
772                                $table->old_friend,
773                                $table->old_mazzo, $table->old_mult);
774             if (($gam_pg  = $this->query($gam_sql)) == FALSE || pg_affected_rows($gam_pg) != 1) {
775                 log_crit(sprintf("bin5_points_save: failed at insert game [%s]", $gam_sql));
776                 break;
777             }
778
779             $gam_obj = pg_fetch_object($gam_pg,0);
780
781             /*
782              * points management
783              */
784             for ($i = 0 ; $i < $n ; $i++) {
785                 /* put points */
786                 $pts_sql = sprintf("INSERT INTO %sbin5_points (gcode, ucode, pts)
787                                                VALUES (%d, %d, %d);",
788                                    $G_dbpfx, $gam_obj->code, $ucodes[$i], $pts[$i]);
789                 if (($pts_pg  = $this->query($pts_sql)) == FALSE || pg_affected_rows($pts_pg) != 1) {
790                     log_crit(sprintf("bin5_points_save: failed at insert point [%s]", $pts_sql));
791                     break;
792                 }
793             }
794             if ($i < $n)
795                 break;
796
797             if ($this->query("COMMIT") == FALSE) {
798                 break;
799             }
800
801             $is_trans = FALSE;
802
803             $table->match_id = $mtc_obj->code;
804             $ret = TRUE;
805         } while (0);
806
807         if ($is_trans)
808             $this->query("ROLLBACK");
809
810         return $ret;
811     }
812
813     function mail_add_fromitem($mail) {
814         GLOBAL $G_dbpfx;
815
816         $usr_sql = sprintf("
817 INSERT INTO %smails (code, ucode, type, tstamp, subj, body_txt, body_htm, hash)
818             VALUES (%d, %d, %d, to_timestamp(%d), '%s', '%s', '%s', '%s') RETURNING *;",
819                            $G_dbpfx, $mail->code, $mail->ucode, $mail->type, $mail->tstamp,
820                            escsql($mail->subj), escsql($mail->body_txt), escsql($mail->body_htm),
821                            ($mail->hash == NULL ? "" : escsql($mail->hash))
822                            );
823
824         if (! (($usr_pg  = $this->query($usr_sql)) != FALSE && pg_affected_rows($usr_pg) == 1) ) {
825             return FALSE;
826         }
827         $usr_obj = pg_fetch_object($usr_pg, 0);
828
829         return $usr_obj;
830     }
831
832     function mail_check($code, $type, $hash)
833     {
834         GLOBAL $G_dbpfx;
835
836         $mai_sql = sprintf("SELECT * FROM %smails WHERE code = %d AND type = %d AND hash = '%s';",
837                            $G_dbpfx, $code, $type, escsql($hash));
838         if (($mai_pg  = $this->query($mai_sql)) == FALSE || pg_numrows($mai_pg) != 1) {
839             // check failed
840             return (FALSE);
841         }
842
843         $mai_obj = pg_fetch_object($mai_pg, 0);
844         return ($mai_obj);
845     }
846
847     function mail_delete($code)
848     {
849         GLOBAL $G_dbpfx;
850
851         $mai_sql = sprintf("DELETE FROM %smails WHERE code = %d;", $G_dbpfx, $code);
852
853         if (($mai_pg = $this->query($mai_sql)) == FALSE || pg_affected_rows($mai_pg) != 1) {
854             return (FALSE);
855         }
856         return (TRUE);
857     }
858
859     function usersnet_bycode($owner, $target)
860     {
861         GLOBAL $G_dbpfx;
862         $ret = FALSE;
863
864         $net_sql = sprintf("SELECT * FROM %susersnet WHERE owner = %d AND target = %d;",
865                             $G_dbpfx, $owner, $target);
866         if (($net_pg  = $this->query($net_sql)) == FALSE) {
867             return FALSE;
868         }
869         if (pg_numrows($net_pg) != 1)
870             return FALSE;
871
872         $net_obj = pg_fetch_object($net_pg, 0);
873
874         return (UsersNetItem::UsersNetItemFromRecord($net_obj));
875     }
876
877     function usersnet_default($owner, $target)
878     {
879         return (UsersNetItem::UsersNetItemDefaults($owner, $target));
880     }
881     function usersnet_save($owner_id, $json)
882     {
883         GLOBAL $G_dbpfx;
884         $ret = 99999;
885         $trans = FALSE;
886
887         do {
888             $friend = usersnet_friend_getid($json->friend);
889
890             $json->skill = intval($json->skill);
891             $json->trust = intval($json->trust);
892
893             if ($json->skill < 1 || $json->skill > 5 ||
894                 $json->trust < 1 || $json->trust > 5 ||
895                 $friend == FALSE) {
896                 $ret = 1;
897                 break;
898             }
899             $this->transaction('BEGIN');
900             $trans = TRUE;
901
902             // try to update
903             $net_sql = sprintf("
904                     UPDATE %susersnet SET (friend, skill, trust, mtime) =
905                         (%d, %d, %d, now())
906                         FROM %susers as us
907                         WHERE owner = %d AND us.login = '%s' AND target = us.code RETURNING *;",
908                                $G_dbpfx,
909                                $friend, $json->skill, $json->trust,
910                                $G_dbpfx,
911                                $owner_id, escsql($json->login));
912             if (($net_pg  = $this->query($net_sql)) == FALSE || pg_numrows($net_pg) == 0) {
913                 $net_sql = sprintf("
914                 INSERT INTO %susersnet SELECT %d AS owner, us.code as target,
915                         %d as friend, %d as skill, %d as trust
916                     FROM %susers as us WHERE us.login = '%s' RETURNING *;",
917                                    $G_dbpfx, $owner_id,
918                                    $friend, $json->skill, $json->trust,
919                                    $G_dbpfx, $json->login);
920                 if (($net_pg  = $this->query($net_sql)) == FALSE) {
921                     log_wr('insert query failed');
922                     $ret = 2;
923                     break;
924                 }
925                 if (pg_numrows($net_pg) != 1) {
926                     log_wr(sprintf('insert numrow failed [%s] [%d]', $net_sql, pg_numrows($net_pg)));
927                     $ret = 3;
928                     break;
929                 }
930             }
931             else {
932                 if (pg_numrows($net_pg) != 1) {
933                     log_wr('update numrow failed');
934                     $ret = 4;
935                     break;
936                 }
937             }
938
939             $net_obj = pg_fetch_object($net_pg, 0);
940             $this->transaction('COMMIT');
941             return (0);
942         } while (0);
943
944         if ($trans)
945             $this->transaction('ROLLBACK');
946
947         return ($ret);
948     }
949 } // End class BriskDB
950
951 class LoginDBOld
952 {
953     var $item;
954     var $item_n;
955
956     function LoginDBOld($filename)
957     {
958         GLOBAL $DOCUMENT_ROOT;
959         log_main("LoginDBOld create:start");
960
961         if (file_exists("$DOCUMENT_ROOT/Etc/".$filename)) {
962             require("$DOCUMENT_ROOT/Etc/".$filename);
963         }
964         else {
965             return (FALSE);
966         }
967         $this->item_n = count($this->item);
968         log_main("LoginDBOld create:end");
969     }
970
971     function count()
972     {
973         return ($this->item_n);
974     }
975
976 } // End class LoginDBOld
977
978 ?>