]> mj.ucw.cz Git - pciids.git/blob - PciIds/DBQ.pm
Email needs at last one dot after @
[pciids.git] / PciIds / DBQ.pm
1 package PciIds::DBQ;
2 use strict;
3 use warnings;
4 use base 'PciIds::DBQAny';
5
6 my $adminDumpSql = 'SELECT
7                         locations.id, locations.name, locations.note, locations.mainhistory, musers.email, musers.login, main.discussion, main.time,
8                         history.id, history.discussion, history.nodename, history.nodenote, users.email, users.login, history.time
9                 FROM
10                         locations INNER JOIN history ON history.location = locations.id
11                         LEFT OUTER JOIN users ON history.owner = users.id
12                         LEFT OUTER JOIN history AS main ON locations.mainhistory = main.id
13                         LEFT OUTER JOIN users AS musers ON main.owner = musers.id
14                 WHERE history.seen = "0" AND locations.id LIKE ?
15                 ORDER BY locations.id, history.id
16                 LIMIT ';
17
18 sub new( $ ) {
19         my( $dbh ) = @_;
20         my $node = 'SELECT id, name, note, mainhistory FROM locations WHERE parent = ? ORDER BY ';
21         my $noder = 'SELECT id, name, note, mainhistory FROM locations WHERE parent = ? AND id LIKE ? ORDER BY ';
22         return bless PciIds::DBQAny::new( $dbh, {
23                 'nodes-id' => $node.'id',
24                 'nodes-name' => $node.'name',
25                 'nodes-rid' => $node.'id DESC',
26                 'nodes-rname' => $node.'name DESC',
27                 'nodes-id-r' => $noder.'id',
28                 'nodes-name-r' => $noder.'name',
29                 'nodes-rid-r' => $noder.'id DESC',
30                 'nodes-rname-r' => $noder.'name DESC',
31                 'item' => 'SELECT parent, name, note, mainhistory FROM locations WHERE id = ?',
32                 'login' => 'SELECT id FROM users WHERE login = ?',
33                 'email' => 'SELECT id FROM users WHERE email = ?',
34                 'adduser' => 'INSERT INTO users (login, email, passwd) VALUES(?, ?, ?)',
35                 'adduser-null' => 'INSERT users (email, passwd) VALUES(?, ?)',
36                 'loginfomail' => 'SELECT id, passwd, logtime, lastlog FROM users WHERE email = ?',
37                 'loginfoname' => 'SELECT id, passwd, logtime, lastlog, email FROM users WHERE login = ?',
38                 'resetinfo' => 'SELECT id, login, passwd FROM users WHERE email = ?',
39                 'changepasswd' => 'UPDATE users SET passwd = ? WHERE id = ?',
40                 'setlastlog' => 'UPDATE users SET logtime = now(), lastlog = ? WHERE id = ?',
41                 'rights' => 'SELECT rightId FROM rights WHERE userId = ?',
42                 'newitem' => 'INSERT INTO locations (id, parent) VALUES(?, ?)',
43                 'newhistory' => 'INSERT INTO history (location, owner, discussion, nodename, nodenote) VALUES(?, ?, ?, ?, ?)',
44                 'history' => 'SELECT history.id, history.discussion, history.time, history.nodename, history.nodenote, history.seen, users.login, users.email FROM history LEFT OUTER JOIN users ON history.owner = users.id WHERE history.location = ? ORDER BY history.time',
45                 'admindump' => "$adminDumpSql 100",#Dumps new discussion submits with their senders and corresponding main history and names
46                 'delete-hist' => 'DELETE FROM history WHERE id = ?',
47                 'mark-checked' => 'UPDATE history SET seen = 1 WHERE id = ?',
48                 'delete-item' => 'DELETE FROM locations WHERE id = ?',
49                 'set-mainhist' => 'UPDATE locations SET
50                                 mainhistory = ?,
51                                 name = ( SELECT nodename FROM history WHERE id = ? ),
52                                 note = ( SELECT nodenote FROM history WHERE id = ? )
53                         WHERE
54                                 id = ?',
55                 'profiledata' => 'SELECT email, xmpp, login, mailgather, xmppgather FROM users WHERE id = ?',
56                 'pushprofile' => 'UPDATE users SET xmpp = ?, login = ?, mailgather = ?, xmppgather = ? WHERE id = ?',
57                 'setemail' => 'UPDATE users SET email = ?, passwd = ? WHERE id = ?',
58                 'notifuser' => 'SELECT location, recursive FROM notifications WHERE user = ? ORDER BY location',
59                 'notifdata' => 'SELECT recursive, type, notification FROM notifications WHERE user = ? AND location = ?',
60                 'drop-notif' => 'DELETE FROM notifications WHERE user = ? AND location = ?',
61                 'new-notif' => 'INSERT INTO notifications (user, location, recursive, type, notification) VALUES (?, ?, ?, ?, ?)',
62                 'notify' => 'INSERT INTO pending (user, history, notification, reason) SELECT DISTINCT user, ?, ?, ? FROM notifications WHERE ( notification = 2 OR notification = ? ) AND type <= ? AND ( location = ? OR ( recursive = 1 AND SUBSTR( ?, 1, LENGTH( location ) ) = location ) )',
63                 'newtime-mail' => 'UPDATE users SET nextmail = FROM_UNIXTIME( UNIX_TIMESTAMP( NOW() ) + 60 * mailgather ) WHERE nextmail < NOW() AND EXISTS ( SELECT 1 FROM notifications WHERE ( notification = 0 OR notification = 2 ) AND type <= ? AND ( location = ? OR ( recursive = 1 AND SUBSTR( ?, 1, LENGTH( location ) ) = location ) ) )',
64                 'newtime-xmpp' => 'UPDATE users SET nextxmpp = FROM_UNIXTIME( UNIX_TIMESTAMP( NOW() ) + 60 * xmppgather ) WHERE nextxmpp < NOW() AND EXISTS ( SELECT 1 FROM notifications WHERE ( notification = 1 OR notification = 2 ) AND type <= ? AND ( location = ? OR ( recursive = 1 AND SUBSTR( ?, 1, LENGTH( location ) ) = location ) ) )',
65                 'mailout' => 'SELECT
66                                 pending.user, users.email,
67                                 pending.reason, history.discussion, history.nodename, history.nodenote, history.time,
68                                 auth.login, history.location, locations.name, locations.note
69                         FROM
70                                 pending
71                                 INNER JOIN users ON users.id = pending.user
72                                 INNER JOIN history ON history.id = pending.history
73                                 INNER JOIN locations ON history.location = locations.id
74                                 INNER JOIN users AS auth ON auth.id = history.owner
75                         WHERE
76                                 pending.notification = 0
77                                 AND users.nextmail <= ?
78                         ORDER BY
79                                 pending.user, pending.reason, history.time, history.location',
80                 'xmppout' => 'SELECT
81                                 pending.user, users.xmpp,
82                                 pending.reason, history.discussion, history.nodename, history.nodenote, history.time,
83                                 auth.login, history.location, locations.name, locations.note
84                         FROM
85                                 pending
86                                 INNER JOIN users ON users.id = pending.user
87                                 INNER JOIN history ON history.id = pending.history
88                                 INNER JOIN locations ON history.location = locations.id
89                                 INNER JOIN users AS auth ON auth.id = history.owner
90                         WHERE
91                                 pending.notification = 1
92                                 AND users.nextxmpp <= ?
93                         ORDER BY
94                                 pending.user, pending.reason, history.time, history.location',
95                 'dropnotifsxmpp' => 'DELETE FROM pending WHERE notification = 1 AND EXISTS ( SELECT 1 FROM users WHERE users.id = pending.user AND nextxmpp <= ? )',
96                 'dropnotifsmail' => 'DELETE FROM pending WHERE notification = 0 AND EXISTS ( SELECT 1 FROM users WHERE users.id = pending.user AND nextmail <= ? )',
97                 'time' => 'SELECT NOW()',
98                 'searchname' => 'SELECT l.id, l.name, p.name FROM locations AS l JOIN locations AS p ON l.parent = p.id WHERE l.name LIKE ? ORDER BY l.id',
99                 'searchlocalname' => 'SELECT l.id, l.name, p.name FROM locations AS l JOIN locations AS p ON l.parent = p.id WHERE l.name LIKE ? AND l.id LIKE ? ORDER BY l.id',
100                 'hasChildren' => 'SELECT DISTINCT 1 FROM locations WHERE parent = ?',
101                 'hasMain' => 'SELECT DISTINCT 1 FROM locations WHERE id = ? AND mainhistory IS NOT NULL',
102                 'notif-exists' => 'SELECT DISTINCT 1 FROM notifications WHERE user = ? AND ( location = ? OR ( recursive = 1 AND type <= 1 AND SUBSTR( ?, 1, LENGTH( location ) ) = location ) )'
103         } );
104 }
105
106 sub hasChildren( $$ ) {
107         my( $self, $parent ) = @_;
108         return scalar @{$self->query( 'hasChildren', [ $parent ] )};
109 }
110
111 sub hasMain( $$ ) {
112         my( $self, $id ) = @_;
113         return scalar @{$self->query( 'hasMain', [ $id ] )};
114 }
115
116 my %sorts = ( 'id' => 1, 'rid' => 1, 'name' => 1, 'rname' => 1 );
117
118 sub nodes( $$$$ ) {
119         my( $self, $parent, $args, $restrict ) = @_;
120         my $q = 'id';
121         $q = $args->{'sort'} if( defined( $args->{'sort'} ) && defined( $sorts{$args->{'sort'}} ) );
122         if( defined( $restrict ) && ( $restrict ne "" ) ) {
123                 return $self->query( 'nodes-'.$q.'-r', [ $parent, $parent.'/'.$restrict.'%' ] );
124         } else {
125                 return $self->query( 'nodes-'.$q, [ $parent ] );
126         }
127 }
128
129 sub item( $$ ) {
130         my( $self, $id ) = @_;
131         my $result = $self->query( "item", [ $id ] );
132         if( scalar @{$result} ) {
133                 return $result->[ 0 ];
134         } else {
135                 return undef;
136         }
137 }
138
139 sub hasLogin( $$ ) {
140         my( $self, $login ) = @_;
141         my $result = $self->query( 'login', [ $login ] );
142         return scalar @{$result};
143 }
144
145 sub hasEmail( $$ ) {
146         my( $self, $email ) = @_;
147         my $result = $self->query( 'email', [ $email ] );
148         return scalar @{$result};
149 }
150
151 sub addUser( $$$$ ) {
152         my( $self, $login, $email, $passwd ) = @_;
153         eval {
154                 if( ( defined $login ) && ( $login ne '' ) ) {
155                         $self->command( 'adduser', [ $login, $email, $passwd ] );
156                 } else {
157                         $self->command( 'adduser-null', [ $email, $passwd ] );
158                 }
159         };
160         if( $@ ) {
161                 return 0;
162         } else {
163                 return $self->last();
164         }
165 }
166
167 sub getLogInfo( $$ ) {
168         my( $self, $info ) = @_;
169         my $data;
170         if( $info =~ /@/ ) {#An email address
171                 $data = $self->query( 'loginfomail', [ $info ] );
172         } else {
173                 $data = $self->query( 'loginfoname', [ $info ] );
174         }
175         if( scalar @{$data} ) {
176                 my( $id, $passwd, $logtime, $lastlog, $email ) = @{$data->[ 0 ]};
177                 my $logstring;
178                 $logstring = "Last logged from $lastlog at $logtime" if( defined $logtime && defined $lastlog );
179                 $email = $info if( $info =~ /@/ );
180                 return( $id, $passwd, $email, $logstring );
181         } else {
182                 return undef;
183         }
184 }
185
186 sub rights( $$ ) {
187         my( $self, $id ) = @_;
188         return $self->query( 'rights', [ $id ] );
189 }
190
191 sub setLastLog( $$$ ) {
192         my( $self, $id, $from ) = @_;
193         $self->command( 'setlastlog', [ $from, $id ] );
194 }
195
196 sub history( $$ ) {
197         my( $self, $addr ) = @_;
198         return $self->query( 'history', [ $addr ] );
199 }
200
201 sub submitItem( $$$ ) {
202         my( $self, $data, $auth ) = @_;
203         my( $addr ) = ( $data->{'address'} );
204         foreach( @{$addr->addressDeps()} ) {
205                 my( $dep, $error ) = @{$_};
206                 return ( $error, undef ) unless defined $self->item( $dep->get(), 0 );
207         }
208         return( 'exists', undef ) if( defined( $self->item( $addr->get(), 0 ) ) );
209         eval {
210                 $self->command( 'newitem', [ $addr->get(), $addr->parent()->get() ] );
211                 $self->command( 'newhistory', [ $addr->get(), $auth->{'authid'}, $data->{'discussion'}, $data->{'name'}, $data->{'note'} ] );
212         };
213         if( $@ ) {
214                 $self->rollback();
215                 return( 'internal: '.$@, undef );
216         }
217         return( '', $self->last() );
218 }
219
220 sub submitHistory( $$$$ ) {
221         my( $self, $data, $auth, $address ) = @_;
222         if( $data->{'delete'} ) {
223                 $self->command( 'newhistory', [ $address->get(), $auth->{'authid'}, $data->{'text'}, '', $data->{'note'} ], 1 );
224         } else {
225                 $data->{'name'} = undef if defined $data->{'name'} && $data->{'name'} eq '';
226                 $self->command( 'newhistory', [ $address->get(), $auth->{'authid'}, $data->{'text'}, $data->{'name'}, $data->{'note'} ], 1 );
227         }
228         return $self->last();
229 }
230
231 sub adminDump( $$$ ) {
232         my( $self, $prefix, $limit ) = @_;
233         if( $limit ) {
234                 $limit = int( $limit * 1.2 );
235                 my $q = $self->{'dbh'}->prepare( "$adminDumpSql $limit" );
236                 $q->execute( "$prefix%" );
237                 my @result = @{$q->fetchall_arrayref()};#Copy the array, finish() deletes the content
238                 $q->finish();
239                 return \@result;
240         } else {
241                 return $self->query( 'admindump', [ "$prefix%" ] );
242         }
243 }
244
245 sub deleteHistory( $$ ) {
246         my( $self, $id ) = @_;
247         $self->command( 'delete-hist', [ $id ] );
248 }
249
250 sub markChecked( $$ ) {
251         my( $self, $id ) = @_;
252         $self->command( 'mark-checked', [ $id ] );
253 }
254
255 sub deleteItem( $$ ) {
256         my( $self, $id ) = @_;
257         $self->command( 'delete-item', [ $id ] );
258 }
259
260 sub setMainHistory( $$$ ) {
261         my( $self, $location, $history ) = @_;
262         $self->command( 'set-mainhist', [ $history, $history, $history, $location ] );
263 }
264
265 sub resetInfo( $$ ) {
266         my( $self, $mail ) = @_;
267         my $result = $self->query( 'resetinfo', [ $mail ] );
268         if( scalar @{$result} ) {
269                 return ( @{$result->[0]} );
270         } else {
271                 return undef;
272         }
273 }
274
275 sub changePasswd( $$$ ) {
276         my( $self, $id, $passwd ) = @_;
277         $self->command( 'changepasswd', [ $passwd, $id ] );
278 }
279
280 sub profileData( $$ ) {
281         my( $self, $id ) = @_;
282         my %result;
283         ( $result{'email'}, $result{'xmpp'}, $result{'login'}, $result{'email_time'}, $result{'xmpp_time'} ) = @{$self->query( 'profiledata', [ $id ] )->[0]};
284         return \%result;
285 }
286
287 sub setEmail( $$$$ ) {
288         my( $self, $id, $email, $passwd ) = @_;
289         $self->command( 'setemail', [ $email, $passwd, $id ] );
290 }
291
292 sub pushProfile( $$$$$$ ) {
293         my( $self, $id, $login, $xmpp, $mailgather, $xmppgather ) = @_;
294         $self->command( 'pushprofile', [ $xmpp, $login, $mailgather, $xmppgather, $id ] );
295 }
296
297 sub notificationsUser( $$ ) {
298         my( $self, $uid ) = @_;
299         return $self->query( 'notifuser', [ $uid ] );
300 }
301
302 sub getNotifData( $$$ ) {
303         my( $self, $uid, $location ) = @_;
304         my $result = $self->query( 'notifdata', [ $uid, $location ] );
305         if( @{$result} ) {
306                 my( $recursive, $notification, $way ) = @{$result->[0]};
307                 return {
308                         'recursive' => $recursive,
309                         'notification' => $notification,
310                         'way' => $way };
311         } else {
312                 return { 'recursive' => 1 };
313         }
314 }
315
316 sub submitNotification( $$$$ ) {
317         my( $self, $uid, $location, $data ) = @_;
318         $self->command( 'drop-notif', [ $uid, $location ] );
319         $self->command( 'new-notif', [ $uid, $location, $data->{'recursive'}, $data->{'notification'}, $data->{'way'} ] ) unless( $data->{'notification'} == 3 );
320 }
321
322 sub pushNotifications( $$$$$ ) {
323         my( $self, $location, $history, $priority, $reason ) = @_;
324         $self->command( 'notify', [ $history, 0, $reason, 0, $priority, $location, $location ] );
325         $self->command( 'notify', [ $history, 1, $reason, 1, $priority, $location, $location ] );
326         $self->command( 'newtime-mail', [ $priority, $location, $location ] );
327         $self->command( 'newtime-xmpp', [ $priority, $location, $location ] );
328 }
329
330 sub notifExists( $$$ ) {
331         my( $self, $user, $location ) = @_;
332         return scalar @{$self->query( 'notif-exists', [ $user, $location, $location ] )};
333 }
334
335 sub mailNotifs( $$ ) {
336         my( $self, $time ) = @_;
337         return $self->query( 'mailout', [ $time ] );
338 }
339
340 sub xmppNotifs( $$ ) {
341         my( $self, $time ) = @_;
342         return $self->query( 'xmppout', [ $time ] );
343 }
344
345 sub time( $ ) {
346         my( $self ) = @_;
347         return $self->query( 'time', [] )->[0]->[0];
348 }
349
350 sub dropNotifs( $$ ) {
351         my( $self, $time ) = @_;
352         $self->command( 'dropnotifsmail', [ $time ] );
353         $self->command( 'dropnotifsxmpp', [ $time ] );
354 }
355
356 sub searchName( $$$ ) {
357         my( $self, $search, $prefix ) = @_;
358         return $self->query( 'searchlocalname', [ "%$search%", "$prefix/%" ] ) if defined $prefix;
359         return $self->query( 'searchname', [ "%$search%" ] );
360 }
361
362 1;