1<?php
2/**
3 * Copyright 2010-2017 Horde LLC (http://www.horde.org/)
4 *
5 * @author     Jan Schneider <jan@horde.org>
6 * @category   Horde
7 * @package    Share
8 * @subpackage UnitTests
9 * @license    http://www.horde.org/licenses/lgpl21 LGPL 2.1
10 */
11class Horde_Share_TestBase extends Horde_Test_Case
12{
13    protected static $share;
14
15    protected static $shares = array();
16
17    public function getApp($app)
18    {
19        $this->assertEquals($app, self::$share->getApp());
20    }
21
22    public function addShare()
23    {
24        $share = self::$share->newShare('john', 'myshare', 'My Share');
25        $this->assertInstanceOf('Horde_Share_Object', $share);
26        $share->set('desc', '行事曆');
27        $share->set('clob', '行事曆');
28        $share->addDefaultPermission(Horde_Perms::SHOW);
29        $share->addUserPermission('jane', Horde_Perms::SHOW);
30        $share->addGroupPermission('mygroup', Horde_Perms::SHOW);
31        self::$share->addShare($share);
32
33        // Add a child to the share to test hierarchical functions
34        $child = self::$share->newShare('john', 'mychildshare', 'My Child Share');
35        $child->set('desc', 'description');
36        $this->assertInstanceOf('Horde_Share_Object', $child);
37        $child->setParent($share);
38        $child->save();
39
40        return $share;
41    }
42
43    public function permissions()
44    {
45        $this->switchAuth(null);
46        $this->permissionsSystemShare();
47        $this->switchAuth('john');
48        $this->permissionsChildShare();
49        $this->switchAuth('jane');
50        $this->permissionsJaneShare();
51        $this->permissionsGroupShare();
52        $this->permissionsNoShare();
53        $this->switchAuth('john');
54    }
55
56    protected function permissionsSystemShare()
57    {
58        // System share.
59        $share = self::$share->newShare(null, 'systemshare', 'System Share');
60        $this->assertInstanceOf('Horde_Perms_Permission', $share->getPermission());
61        $share->addDefaultPermission(Horde_Perms::SHOW | Horde_Perms::READ);
62        $share->addGuestPermission(Horde_Perms::SHOW);
63        $share->save();
64        $this->assertTrue($share->hasPermission('john', Horde_Perms::SHOW));
65        $this->assertTrue($share->hasPermission('john', Horde_Perms::READ));
66        $this->assertFalse($share->hasPermission('john', Horde_Perms::EDIT));
67        $this->assertFalse($share->hasPermission('john', Horde_Perms::DELETE));
68        $this->assertTrue($share->hasPermission(false, Horde_Perms::SHOW));
69        $this->assertFalse($share->hasPermission(false, Horde_Perms::EDIT));
70    }
71
72    protected function permissionsChildShare()
73    {
74        // Child share
75        $childshare = self::$share->getShare('mychildshare');
76    }
77
78    protected function permissionsJaneShare()
79    {
80        // Foreign share with user permissions.
81        $janeshare = self::$share->newShare('jane', 'janeshare', 'Jane\'s Share');
82        $janeshare->addUserPermission('john', Horde_Perms::SHOW | Horde_Perms::READ | Horde_Perms::EDIT);
83        $janeshare->addUserPermission('peter', Horde_Perms::SHOW);
84        $janeshare->save();
85        $this->assertTrue($janeshare->hasPermission('john', Horde_Perms::SHOW));
86        $this->assertTrue($janeshare->hasPermission('john', Horde_Perms::READ));
87        $this->assertTrue($janeshare->hasPermission('john', Horde_Perms::EDIT));
88        $this->assertFalse($janeshare->hasPermission('john', Horde_Perms::DELETE));
89        $this->assertTrue($janeshare->hasPermission('peter', Horde_Perms::SHOW));
90    }
91
92    protected function permissionsGroupShare()
93    {
94        // Foreign share with group permissions.
95        $groupshare = self::$share->newShare('jane', 'groupshare', 'Group Share');
96        $groupshare->addGroupPermission('mygroup', Horde_Perms::SHOW | Horde_Perms::READ | Horde_Perms::DELETE);
97        $groupshare->save();
98        $this->assertTrue($groupshare->hasPermission('john', Horde_Perms::SHOW));
99        $this->assertTrue($groupshare->hasPermission('john', Horde_Perms::READ));
100        $this->assertFalse($groupshare->hasPermission('john', Horde_Perms::EDIT));
101        $this->assertTrue($groupshare->hasPermission('john', Horde_Perms::DELETE));
102    }
103
104    protected function permissionsNoShare()
105    {
106        // Foreign share without permissions.
107        $fshare = self::$share->newShare('jane', 'noshare', 'No Share');
108        $fshare->save();
109    }
110
111    public function exists()
112    {
113        // Getting shares from cache.
114        $this->assertTrue(self::$share->exists('myshare'));
115
116        // Reset cache.
117        self::$share->resetCache();
118
119        // Getting shares from backend.
120        $this->assertTrue(self::$share->exists('myshare'));
121    }
122
123    public function countShares()
124    {
125        // Getting shares from cache.
126        $this->assertEquals(5, self::$share->countShares('john'));
127        // Top level only.
128        $this->assertEquals(2, self::$share->countShares('john', Horde_Perms::EDIT, null, null, false));
129        $this->assertEquals(3, self::$share->countShares('john', Horde_Perms::EDIT));
130
131        // Reset cache.
132        self::$share->resetCache();
133
134        // Getting shares from backend.
135        $this->assertEquals(5, self::$share->countShares('john'));
136        $this->assertEquals(2, self::$share->countShares('john', Horde_Perms::EDIT, null, null, false));
137        $this->assertEquals(3, self::$share->countShares('john', Horde_Perms::EDIT));
138    }
139
140    public function hierarchy()
141    {
142        $share = self::$share->getShare('myshare');
143        $child = self::$share->getShare('mychildshare');
144        $this->assertEquals($share->getId(), $child->getParent()->getId());
145        $this->assertEquals(1, $share->countChildren('john'));
146        $this->assertContains($child->getName(), array_keys($share->getChildren('john')));
147    }
148
149    public function getShare()
150    {
151        // Getting shares from cache.
152        $share = self::$share->getShare('myshare');
153        $this->assertInstanceOf('Horde_Share_Object', $share);
154        try {
155            self::$share->getShare('nonexistant');
156            $this->fail('Share "nonexistant" was expected to not exist.');
157        } catch (Horde_Exception_NotFound $e) {
158        }
159
160        // Reset cache.
161        self::$share->resetCache();
162
163        // Getting shares from backend.
164        $share = self::$share->getShare('myshare');
165        $this->assertInstanceOf('Horde_Share_Object', $share);
166
167        self::$shares['myshare'] = $share;
168        self::$shares['systemshare'] = self::$share->getShare('systemshare');
169        self::$shares['janeshare'] = self::$share->getShare('janeshare');
170        self::$shares['janeshare']->getPermission();
171        self::$shares['groupshare'] = self::$share->getShare('groupshare');
172        self::$shares['groupshare']->getPermission();
173
174        $this->switchAuth('jane');
175        self::$shares['jane']['janeshare'] = self::$share->getShare('janeshare');
176        self::$shares['jane']['groupshare'] = self::$share->getShare('groupshare');
177
178        $this->switchAuth(null);
179        self::$shares['system']['systemshare'] = self::$share->getShare('systemshare');
180        $this->switchAuth('john');
181
182        return $share;
183    }
184
185    public function getShareById()
186    {
187        // Getting shares from cache.
188        $this->_getShareById();
189        try {
190            self::$share->getShareById(99999);
191            $this->fail('Share 99999 was expected to not exist.');
192        } catch (Horde_Exception_NotFound $e) {
193        }
194
195        // Reset cache.
196        self::$share->resetCache();
197
198        // Getting shares from backend.
199        $this->_getShareById();
200    }
201
202    protected function _getShareById()
203    {
204        $myshare = self::$share->getShareById(self::$shares['myshare']->getId());
205        $this->assertInstanceOf('Horde_Share_Object', $myshare);
206        $this->assertEquals(self::$shares['myshare'], $myshare);
207        $this->assertEquals('行事曆', $myshare->get('desc'));
208        $this->assertEquals('行事曆', $myshare->get('clob'));
209        $this->switchAuth('jane');
210        $janeshare = self::$share->getShareById(self::$shares['jane']['janeshare']->getId());
211        $janeshare->getPermission();
212        $this->assertInstanceOf('Horde_Share_Object', $janeshare);
213        $this->assertEquals(self::$shares['jane']['janeshare'], $janeshare);
214        $users = $janeshare->listUsers();
215        sort($users);
216        $this->assertEquals(array('jane', 'john', 'peter'), $users);
217        $users = $janeshare->listUsers(Horde_Perms::EDIT);
218        sort($users);
219        $this->assertEquals(array('jane', 'john'), $users);
220        $users = $janeshare->listUsers(Horde_Perms::DELETE);
221        sort($users);
222        $this->assertEquals(array('jane'), $users);
223        $this->assertEquals('Jane\'s Share', $janeshare->get('name'));
224        $this->assertTrue($janeshare->hasPermission('john', Horde_Perms::EDIT));
225
226        $groupshare = self::$share->getShareById(self::$shares['jane']['groupshare']->getId());
227        $groupshare->getPermission();
228        $this->assertInstanceOf('Horde_Share_Object', $groupshare);
229        $this->assertEquals(self::$shares['jane']['groupshare'], $groupshare);
230        $this->assertEquals(array('mygroup'), $groupshare->listGroups());
231        $this->assertEquals(array(), $groupshare->listGroups(Horde_Perms::EDIT));
232        $this->assertEquals(array('mygroup'), $groupshare->listGroups(Horde_Perms::DELETE));
233        $this->assertEquals('Group Share', $groupshare->get('name'));
234
235        $this->switchAuth('john');
236    }
237
238    public function getShares()
239    {
240        // Getting shares from cache.
241        $this->_getShares();
242
243        // Reset cache.
244        self::$share->resetCache();
245
246        // Getting shares from backend.
247        $this->_getShares();
248    }
249
250    protected function _getShares()
251    {
252        $newshares = self::$share->getShares(array(self::$shares['myshare']->getId(), self::$shares['janeshare']->getId(), self::$shares['groupshare']->getId()));
253        $this->assertEquals(
254            array('myshare', 'janeshare', 'groupshare'),
255            array_keys($newshares));
256        $this->assertInstanceOf('Horde_Share_Object', $newshares['myshare']);
257        $this->assertEquals(self::$shares['myshare'], $newshares['myshare']);
258        $newshares['janeshare']->getPermission();
259        $this->assertEquals(self::$shares['janeshare'], $newshares['janeshare']);
260        $newshares['groupshare']->getPermission();
261        $this->assertEquals(self::$shares['groupshare'], $newshares['groupshare']);
262    }
263
264    public function listAllShares()
265    {
266        // Getting shares from cache.
267        $this->_listAllShares();
268
269        // Reset cache.
270        self::$share->resetCache();
271
272        // Getting shares from backend.
273        $this->_listAllShares();
274    }
275
276    protected function _listAllShares()
277    {
278        $this->switchAuth(null);
279        $shares = self::$share->listAllShares();
280        $this->assertInternalType('array', $shares);
281        $this->assertEquals(6, count($shares));
282        $this->assertArrayHasKey('myshare', $shares);
283        $this->assertArrayHasKey('systemshare', $shares);
284        $this->assertArrayHasKey('janeshare', $shares);
285        $this->assertArrayHasKey('groupshare', $shares);
286        $this->assertArrayHasKey('noshare', $shares);
287        $this->switchAuth('john');
288    }
289
290    public function listShares()
291    {
292        // Getting shares from cache.
293        $this->_listShares();
294
295        // Reset cache.
296        self::$share->resetCache();
297
298        // Getting shares from backend.
299        $this->_listShares();
300    }
301
302    public function _listShares()
303    {
304        $this->_listSharesJohn();
305        $this->_listSharesGuest();
306        $this->_listSharesJohnTwo();
307    }
308
309    public function _listSharesJohn()
310    {
311        // Default listing.
312        $shares = self::$share->listShares('john');
313        $this->assertInternalType('array', $shares);
314        $this->assertEquals(5, count($shares));
315
316        // Test arguments for default listing.
317        $this->assertEquals($shares, self::$share->listShares('john', array('perm' => Horde_Perms::SHOW, 'attributes' => null, 'from' => 0, 'count' => 0, 'sort_by' => null, 'direction' => 0)));
318
319        // Getting back the correct shares?
320        $shares = self::$share->listShares('john', array('all_levels' => false, 'sort_by' => 'id'));
321        $this->assertSortedById(
322            array('myshare', 'systemshare', 'janeshare', 'groupshare'),
323            $shares);
324
325        // Shares of a certain owner.
326        $shares = self::$share->listShares('john', array('attributes' => 'jane', 'sort_by' => 'id'));
327        $this->assertSortedById(
328            array('janeshare', 'groupshare'),
329            $shares);
330    }
331
332    public function _listSharesGuest()
333    {
334        $this->switchAuth(null);
335
336        // Guest shares.
337        $shares = self::$share->listShares(false, array('perm' => Horde_Perms::SHOW, 'sort_by' => 'id'));
338        $this->assertEquals(
339            array('systemshare'),
340            array_keys($shares));
341
342        $this->switchAuth('john');
343    }
344
345    public function _listSharesJohnTwo()
346    {
347        // Shares with certain permissions.
348        $this->assertEquals(5, count(self::$share->listShares('john', array('perm' => Horde_Perms::READ))));
349        $shares = self::$share->listShares('john', array('perm' => Horde_Perms::EDIT, 'sort_by' => 'id'));
350        $this->assertSortedById(
351            array('myshare', 'mychildshare', 'janeshare'),
352            $shares
353        );
354
355        // Again with only toplevel
356        $shares = self::$share->listShares('john', array('all_levels' => false, 'perm' => Horde_Perms::EDIT, 'sort_by' => 'id'));
357        $this->assertSortedById(
358            array('myshare', 'janeshare'),
359            $shares
360        );
361
362        $shares = self::$share->listShares('john', array('perm' => Horde_Perms::DELETE, 'sort_by' => 'id'));
363        $this->assertSortedById(
364            array('myshare', 'mychildshare', 'groupshare'),
365            $shares
366        );
367
368        $shares = self::$share->listShares('john', array('perm' => Horde_Perms::EDIT | Horde_Perms::DELETE, 'sort_by' => 'id'));
369        $this->assertSortedById(
370            array('myshare', 'mychildshare', 'janeshare', 'groupshare'),
371            $shares
372        );
373        $shares = self::$share->listShares('john', array('perm' => Horde_Perms::ALL));
374        $this->assertInternalType('array', $shares);
375        $this->assertEquals(5, count($shares));
376
377        // Paging.
378        $all_shares = self::$share->listShares('john', array('perm' => Horde_Perms::ALL, 'sort_by' => 'id'));
379        $this->assertSortedById(
380            array('janeshare', 'groupshare', 'myshare', 'mychildshare', 'systemshare'),
381            $all_shares);
382        $shares = self::$share->listShares('john', array('perm' => Horde_Perms::ALL, 'sort_by' => 'id', 'from' => 2, 'count' => 2));
383        $this->assertEquals(
384            array_slice(array_keys($all_shares), 2, 2),
385            array_keys($shares));
386
387        // Paging with top level only
388        $all_top_shares = self::$share->listShares('john', array('all_levels' => false, 'perm' => Horde_Perms::ALL, 'sort_by' => 'id'));
389        $this->assertSortedById(
390            array('janeshare', 'groupshare', 'myshare', 'systemshare'),
391            $all_top_shares);
392        $shares = self::$share->listShares('john', array('all_levels' => false, 'perm' => Horde_Perms::ALL, 'sort_by' => 'id', 'from' => 2, 'count' => 2));
393        $this->assertEquals(
394            array_slice(array_keys($all_top_shares), 2, 2),
395            array_keys($shares));
396
397        // Restrict to children of a share only
398        $shares = self::$share->listShares('john', array('perm' => Horde_Perms::ALL, 'parent' => self::$shares['myshare']));
399        $this->assertEquals(
400            array('mychildshare'),
401            array_keys($shares));
402
403        // Sort order and direction.
404        $shares = self::$share->listShares('john', array('perm' => Horde_Perms::ALL, 'sort_by' => 'id', 'direction' => 1));
405        $this->assertSortedById(
406            array('groupshare', 'janeshare', 'systemshare', 'mychildshare', 'myshare'),
407            array_reverse($shares));
408
409        // Attribute searching.
410        $shares = self::$share->listShares('john', array('attributes' => array('name' => 'Jane\'s Share')));
411        $this->assertEquals(
412            array('janeshare'),
413            array_keys($shares));
414        $shares = self::$share->listShares('john', array('attributes' => array('desc' => '行事曆')));
415        $this->assertEquals(
416            array('myshare'),
417            array_keys($shares));
418    }
419
420    public function listSystemShares()
421    {
422        // Getting shares from cache.
423        $this->_listSystemShares();
424
425        // Reset cache.
426        self::$share->resetCache();
427
428        // Getting shares from backend.
429        $this->_listSystemShares();
430    }
431
432    public function _listSystemShares()
433    {
434        $this->switchAuth(null);
435        $shares = self::$share->listSystemShares();
436        $this->assertInternalType('array', $shares);
437        $this->assertEquals(1, count($shares));
438        $this->assertArrayHasKey('systemshare', $shares);
439        $this->switchAuth('john');
440    }
441
442    public function getPermission()
443    {
444        $permission = self::$shares['myshare']->getPermission();
445        $this->assertEquals(Horde_Perms::SHOW, $permission->getDefaultPermissions());
446        $this->assertFalse((bool) $permission->getGuestPermissions());
447        $this->assertEquals(array('jane' => Horde_Perms::SHOW), $permission->getUserPermissions());
448        $this->assertEquals(array('mygroup' => Horde_Perms::SHOW), $permission->getGroupPermissions());
449        self::$share->resetCache();
450
451        $permission = self::$share->getShare('myshare')->getPermission();
452        $this->assertEquals(Horde_Perms::SHOW, $permission->getDefaultPermissions());
453        $this->assertFalse((bool) $permission->getGuestPermissions());
454        $this->assertEquals(array('jane' => Horde_Perms::SHOW), $permission->getUserPermissions());
455        $this->assertEquals(array('mygroup' => Horde_Perms::SHOW), $permission->getGroupPermissions());
456        self::$share->resetCache();
457
458        $shares = self::$share->getShares(array(self::$shares['myshare']->getId()));
459        $permission = $shares['myshare']->getPermission();
460        $this->assertEquals(Horde_Perms::SHOW, $permission->getDefaultPermissions());
461        $this->assertFalse((bool) $permission->getGuestPermissions());
462        $this->assertEquals(array('jane' => Horde_Perms::SHOW), $permission->getUserPermissions());
463        $this->assertEquals(array('mygroup' => Horde_Perms::SHOW), $permission->getGroupPermissions());
464        self::$share->resetCache();
465
466        $shares = self::$share->listShares('john');
467        $permission = $shares['myshare']->getPermission();
468        $this->assertEquals(Horde_Perms::SHOW, $permission->getDefaultPermissions());
469        $this->assertFalse((bool) $permission->getGuestPermissions());
470        $this->assertEquals(array('jane' => Horde_Perms::SHOW), $permission->getUserPermissions());
471        $this->assertEquals(array('mygroup' => Horde_Perms::SHOW), $permission->getGroupPermissions());
472
473        $permission = self::$shares['system']['systemshare']->getPermission();
474        $this->assertEquals(Horde_Perms::SHOW  | Horde_Perms::READ, $permission->getDefaultPermissions());
475        $this->assertEquals(Horde_Perms::SHOW, $permission->getGuestPermissions());
476
477        $permission = self::$shares['jane']['janeshare']->getPermission();
478        $this->assertEquals(array('john' => Horde_Perms::SHOW | Horde_Perms::READ | Horde_Perms::EDIT, 'peter' => Horde_Perms::SHOW), $permission->getUserPermissions());
479
480        $permission = self::$shares['jane']['groupshare']->getPermission();
481        $this->assertEquals(array('mygroup' => Horde_Perms::SHOW | Horde_Perms::READ | Horde_Perms::DELETE), $permission->getGroupPermissions());
482
483        $this->switchAuth('john');
484    }
485
486    public function removeUserPermissions()
487    {
488        $this->removeUserPermissionsJane();
489        $this->switchAuth('john');
490        $this->removeUserPermissionsJohn();
491    }
492
493    protected function removeUserPermissionsJane()
494    {
495        $janeshare = self::$shares['jane']['janeshare'];
496        $janeshare->removeUserPermission('john', Horde_Perms::EDIT);
497        $janeshare->save();
498
499        $this->switchAuth('john');
500        // Getting shares from cache.
501        $this->assertEquals(5, count(self::$share->listShares('john', array('perm' => Horde_Perms::READ))));
502        $this->assertEquals(2, count(self::$share->listShares('john', array('perm' => Horde_Perms::EDIT))));
503
504        // Reset cache.
505        self::$share->resetCache();
506
507        // Getting shares from backend.
508        $this->assertEquals(5, count(self::$share->listShares('john', array('perm' => Horde_Perms::READ))));
509        $this->assertEquals(2, count(self::$share->listShares('john', array('perm' => Horde_Perms::EDIT))));
510
511        $janeshare->removeUser('john');
512        $janeshare->save();
513    }
514
515    protected function removeUserPermissionsJohn()
516    {
517        // Getting shares from cache.
518        $this->assertEquals(4, count(self::$share->listShares('john', array('perm' => Horde_Perms::READ))));
519
520        // Reset cache.
521        self::$share->resetCache();
522
523        // Getting shares from backend.
524        $this->assertEquals(4, count(self::$share->listShares('john', array('perm' => Horde_Perms::READ))));
525    }
526
527    public function removeGroupPermissions()
528    {
529        $groupshare = self::$shares['jane']['groupshare'];
530        $this->removeGroupPermissionsJane($groupshare);
531        $this->removeGroupPermissionsJohn();
532        $this->removeGroupPermissionsJaneTwo($groupshare);
533        $this->removeGroupPermissionsJohnTwo();
534    }
535
536    public function removeGroupPermissionsJane($groupshare)
537    {
538        $groupshare->removeGroupPermission('mygroup', Horde_Perms::DELETE);
539        $groupshare->save();
540    }
541
542    public function removeGroupPermissionsJohn()
543    {
544        $this->switchAuth('john');
545        // Getting shares from cache.
546        $this->assertEquals(4, count(self::$share->listShares('john', array('perm' => Horde_Perms::READ))));
547        $this->assertEquals(2, count(self::$share->listShares('john', array('perm' => Horde_Perms::DELETE))));
548
549        // Reset cache.
550        self::$share->resetCache();
551
552        // Getting shares from backend.
553        $this->assertEquals(4, count(self::$share->listShares('john', array('perm' => Horde_Perms::READ))));
554        $this->assertEquals(2, count(self::$share->listShares('john', array('perm' => Horde_Perms::DELETE))));
555    }
556
557    public function removeGroupPermissionsJaneTwo($groupshare)
558    {
559        $groupshare->removeGroup('mygroup');
560        $groupshare->save();
561    }
562
563    public function removeGroupPermissionsJohnTwo()
564    {
565        $this->switchAuth('john');
566        // Getting shares from cache.
567        $this->assertEquals(3, count(self::$share->listShares('john', array('perm' => Horde_Perms::READ))));
568
569        // Reset cache.
570        self::$share->resetCache();
571
572        // Getting shares from backend.
573        $this->assertEquals(3, count(self::$share->listShares('john', array('perm' => Horde_Perms::READ))));
574    }
575
576    public function removeShare()
577    {
578        self::$share->removeShare(self::$shares['myshare']);
579        try {
580            self::$share->getShareById(self::$shares['myshare']->getId());
581            $this->fail('Share "myshare" should be removed by now.');
582        } catch (Horde_Exception_NotFound $e) {
583        }
584    }
585
586    public function renameShare()
587    {
588        self::$share->renameShare(self::$shares['janeshare'], 'joeshare');
589        $this->assertArrayNotHasKey('janeshare', self::$share->listAllShares());
590        $this->assertArrayHasKey('joeshare', self::$share->listAllShares());
591    }
592
593    public function callbackSetShareOb($share)
594    {
595        $share->setShareOb(new Horde_Support_Stub());
596        $this->assertEquals($share, unserialize(serialize($share)));
597    }
598
599
600    protected function assertSortedById($expected, $shares)
601    {
602        $sort = array();
603        foreach ($shares as $key => $share) {
604            $sort[$share->getId()] = $key;
605        }
606        ksort($sort);
607        $keys = array_keys($shares);
608        $this->assertEquals($keys, array_values($sort));
609        sort($expected);
610        sort($keys);
611        $this->assertEquals($expected, $keys);
612    }
613
614    protected function switchAuth($user)
615    {
616    }
617
618}
619