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