1: <?php
  2:   3:   4:   5:   6:   7:   8:   9:  10:  11:  12:  13: 
 14: 
 15: class Folks_Driver {
 16: 
 17:      18:  19:  20:  21: 
 22:     protected $_params = array();
 23: 
 24:      25:  26:  27:  28:  29:  30:  31:  32:  33:  34:  35:  36:  37: 
 38:     public function factory($driver = null, $params = null)
 39:     {
 40:         if ($driver === null) {
 41:             $driver = $GLOBALS['conf']['storage']['driver'];
 42:         }
 43: 
 44:         $driver = basename($driver);
 45: 
 46:         if ($params === null) {
 47:             $params = Horde::getDriverConfig('storage', $driver);
 48:         }
 49: 
 50:         $clas = 'Folks_Driver_' . $driver;
 51:         if (!class_exists($clas)) {
 52:             include dirname(__FILE__) . '/Driver/' . $driver . '.php';
 53:         }
 54:         if (class_exists($clas)) {
 55:             return new $clas($params);
 56:         } else {
 57:             return false;
 58:         }
 59:     }
 60: 
 61:      62:  63:  64:  65:  66: 
 67:     protected function _saveImage($file, $user)
 68:     {
 69:         global $conf;
 70: 
 71:         $vfs = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Vfs')->create('images');
 72:         $p = hash('md5', $user);
 73:         $vfspath = Folks::VFS_PATH . '/' . substr(str_pad($p, 2, 0, STR_PAD_LEFT), -2) . '/';
 74:         $vfs_name = $p . '.' . $conf['images']['image_type'];
 75:         try {
 76:             $img = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Image')->create(array('type' => $conf['images']['image_type']));
 77:             $result = $img->loadFile($file);
 78:         } catch (Horde_Exception $e) {
 79:             throw new Horde_Exception_Wrapped($e);
 80:         }
 81:         $dimensions = $img->getDimensions();
 82:         if ($dimensions instanceof PEAR_Error) {
 83:             return $dimensions;
 84:         }
 85:         $img->resize(min($conf['images']['screen_width'], $dimensions['width']),
 86:                         min($conf['images']['screen_height'], $dimensions['height']));
 87: 
 88:         
 89:         try {
 90:             $vfs->writeData($vfspath . '/big/', $vfs_name, $img->raw(), true);
 91:         } catch (Horde_Vfs_Exception $e) {
 92:             return PEAR::raiseError($result->getMessage());
 93:         }
 94: 
 95:         
 96:         $dimensions = $img->getDimensions();
 97:         $img->resize(min($conf['images']['thumbnail_width'], $dimensions['width']),
 98:                      min($conf['images']['thumbnail_height'], $dimensions['height']));
 99: 
100:         
101:         return $vfs->writeData($vfspath . '/small/', $vfs_name, $img->raw(), true);
102:     }
103: 
104:     105: 106: 107: 108: 
109:     public function deleteImage($user)
110:     {
111:         $vfs = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Vfs')->create('images');
112:         $p = hash('md5', $user);
113:         $vfspath = Folks::VFS_PATH . '/' . substr(str_pad($p, 2, 0, STR_PAD_LEFT), -2) . '/';
114:         $vfs_name = $p . '.' . $GLOBALS['conf']['images']['image_type'];
115: 
116:         try {
117:             $vfs->deleteFile($vfspath . '/big/', $vfs_name);
118:             $vfs->deleteFile($vfspath . '/small/', $vfs_name);
119:         } catch (Horde_Vfs_Exception $e) {
120:             return $e->getMessage();
121:         }
122: 
123:         
124:         $GLOBALS['cache']->expire('folksProfile' . $user);
125: 
126:         return $this->_deleteImage($user);
127:     }
128: 
129:     130: 131: 132: 133: 
134:     public function getOnlineUsers()
135:     {
136:         static $online;
137: 
138:         if ($online !== null) {
139:             return $online;
140:         }
141: 
142:         $online = $GLOBALS['cache']->get('folksOnlineUsers', $GLOBALS['conf']['online']['ttl']);
143:         if ($online) {
144:             $online = unserialize($online);
145:         } else {
146:             $online = $this->_getOnlineUsers();
147:             if ($online instanceof PEAR_Error) {
148:                 return $online;
149:             }
150:             $online = array_flip($online);
151:             $GLOBALS['cache']->set('folksOnlineUsers', serialize($online));
152:         }
153: 
154:         return $online;
155:     }
156: 
157:     158: 159: 160: 161: 
162:     public function resetOnlineUsers()
163:     {
164:         $this->_updateOnlineStatus();
165:         return $GLOBALS['cache']->expire('folksOnlineUsers');
166:     }
167: 
168:     169: 170: 171: 172: 
173:     public function getRecentVisitors($limit = 10)
174:     {
175:         $recent = $GLOBALS['cache']->get('folksRecentVisitors' . $limit, $GLOBALS['conf']['online']['ttl']);
176:         if ($recent) {
177:             $recent = unserialize($recent);
178:         } else {
179:             $recent = $this->_getRecentVisitors($limit);
180:             if ($recent instanceof PEAR_Error) {
181:                 return $recent;
182:             }
183:             $GLOBALS['cache']->set('folksRecentVisitors' . $limit, serialize($recent));
184:         }
185: 
186:         return $recent;
187:     }
188: 
189:     190: 191: 192: 193: 
194:     public function getNewUsers($limit = 10)
195:     {
196:         $new = $GLOBALS['cache']->get('folksNewUsers', $GLOBALS['conf']['cache']['default_lifetime']);
197:         if ($new) {
198:             $new = unserialize($new);
199:         } else {
200:             $new = $this->getUsers(array('sort_by' => 'signup_at',
201:                                         'sort_dir' => 0), 0, $limit);
202:             if ($new instanceof PEAR_Error) {
203:                 return $new;
204:             }
205:             $GLOBALS['cache']->set('folksNewUsers', serialize($new));
206:         }
207: 
208:         return $new;
209:     }
210: 
211:     212: 213: 214: 215: 216: 217: 218: 
219:     public function getRandomUsers($limit = 10, $online = true)
220:     {
221:         $random = $GLOBALS['cache']->get('folksRandomUsers' . $limit . '-' . $online, $GLOBALS['conf']['online']['ttl']);
222:         if ($random) {
223:             $random = unserialize($random);
224:         } else {
225:             $random = $this->_getRandomUsers($limit, $online);
226:             if ($random instanceof PEAR_Error) {
227:                 return $random;
228:             }
229:             $GLOBALS['cache']->set('folksRandomUsers' . $limit . '-' . $online, serialize($random));
230:         }
231: 
232:         return $random;
233:     }
234: 
235:     236: 237: 238: 239: 240: 241: 
242:     public function isOnline($user)
243:     {
244:         $online = $this->getOnlineUsers();
245: 
246:         return array_key_exists($user, $online);
247:     }
248: 
249:     250: 251: 
252:     public function updateOnlineStatus()
253:     {
254:         
255:         
256:         
257:         if ($GLOBALS['conf']['online']['autoupdate'] &&
258:             (!$GLOBALS['session']->exists('folks', 'last_update') ||
259:              $GLOBALS['session']->get('folks', 'last_update') + $GLOBALS['conf']['online']['ttl'] < $_SERVER['REQUEST_TIME'])) {
260: 
261:             
262:             $this->_updateOnlineStatus();
263: 
264:             
265:             if ($GLOBALS['registry']->isAuthenticated()) {
266:                 $this->_saveProfile(array('last_online_on' => $_SERVER['REQUEST_TIME']), $GLOBALS['registry']->getAuth());
267:             }
268:         }
269: 
270:         
271:         if ($GLOBALS['conf']['online']['autodelete']) {
272:             $to = $_SERVER['REQUEST_TIME'] - $GLOBALS['conf']['online']['ttl'];
273:             $this->_deleteOnlineStatus($to);
274:         }
275:     }
276: 
277:     278: 279: 
280:     public function getRawProfile($user)
281:     {
282:         return $this->_getProfile($user);
283:     }
284: 
285:     286: 287: 288: 289: 
290:     public function getProfile($user = null)
291:     {
292:         static $profiles;
293: 
294:         if ($user == null) {
295:             $user = $GLOBALS['registry']->getAuth();
296:         }
297: 
298:         if (empty($user)) {
299:             return PEAR::raiseError(sprintf(_("User \"%s\" does not exists."), $user));
300:         }
301: 
302:         if (isset($profiles[$user])) {
303:             return $profiles[$user];
304:         }
305: 
306:         $profile = $GLOBALS['cache']->get('folksProfile' . $user, $GLOBALS['conf']['cache']['default_lifetime']);
307:         if ($profile || ($GLOBALS['registry']->isAdmin() && Horde_Util::getGet('debug'))) {
308: 
309:             $profile = unserialize($profile);
310: 
311:         } else {
312:             
313:             $profile = $this->_getProfile($user);
314:             if ($profile instanceof PEAR_Error) {
315:                 return $profile;
316:             }
317: 
318:             
319:             $filters = array('text2html', 'bbcode', 'highlightquotes', 'emoticons');
320:             $filters_params = array(array('parselevel' => Horde_Text_Filter_Text2html::MICRO),
321:                                     array(),
322:                                     array(),
323:                                     array());
324: 
325:             if (($hasBBcode = strpos($profile['user_description'], '[')) !== false &&
326:                     strpos($profile['user_description'], '[/', $hasBBcode) !== false) {
327:                 $filters_params[0]['parselevel'] = Horde_Text_Filter_Text2html::NOHTML;
328:             }
329: 
330:             $profile['user_description'] = $GLOBALS['injector']->getInstance('Horde_Core_Factory_TextFilter')->filter(trim($profile['user_description']), $filters, $filters_params);
331: 
332:             
333:             foreach ($profile as $key => $value) {
334:                 if (substr($key, 0, 6) != 'count_') {
335:                     continue;
336:                 }
337:                 $service = substr($key, 6);
338:                 if ($GLOBALS['conf']['services']['countcron']) {
339:                     if (empty($value)) {
340:                         continue;
341:                     }
342:                 } else {
343:                     try {
344:                         $profile['count_' . $service] = Horde::callHook('countService', array($service, $user), 'folks');
345:                     } catch (Horde_Exception_HookNotSet $e) {}
346:                     if (empty($profile['count_' . $service])) {
347:                         continue;
348:                     }
349:                 }
350:                 try {
351:                     $profile['count_' . $service . '_list'] = Horde::callHook('getService', array($service, $user), 'folks');
352:                 } catch (Horde_Exception_HookNotSet $e) {}
353:                 if (empty($profile['count_' . $service . '_list'])) {
354:                     $profile['count_' . $service] = 0;
355:                 }
356:             }
357: 
358:             
359: 
360:             
361:             $GLOBALS['cache']->set('folksProfile' . $user, serialize($profile));
362:         }
363: 
364:         $profiles[$user] = $profile;
365: 
366:         return $profile;
367:     }
368: 
369:     370: 371: 372: 373: 374: 
375:     public function changePassword($password, $user = null)
376:     {
377:         if ($user == null) {
378:             $user = $GLOBALS['registry']->getAuth();
379:         }
380: 
381:         $password = hash('md5', $password);
382: 
383:         return $this->_saveProfile(array('user_password' => $password), $user);
384:     }
385: 
386:     387: 388: 389: 390: 391: 
392:     public function saveProfile($data, $user = null)
393:     {
394:         if ($user == null) {
395:             $user = $GLOBALS['registry']->getAuth();
396:         }
397: 
398:         $GLOBALS['cache']->expire('folksProfile' . $user);
399: 
400:         return $this->_saveProfile($data, $user);
401:     }
402: 
403:     404: 405: 406: 407: 408: 409: 
410:     function logView($id)
411:     {
412:         if (!$GLOBALS['registry']->isAuthenticated() || Horde_Auth::getAUth() == $id) {
413:             return false;
414:         }
415: 
416:         
417:         if (isset($_COOKIE['folks_viewed_user']) &&
418:             strpos($_COOKIE['folks_viewed_user'], $id . ':') !== false) {
419:             return false;
420:         }
421: 
422:         
423:         if (!isset($_COOKIE['folks_viewed_user'])) {
424:             $_COOKIE['folks_viewed_user'] = $id . ':';
425:         } else {
426:             $_COOKIE['folks_viewed_user'] .= $id . ':';
427:         }
428: 
429:         setcookie('folks_viewed_user', $_COOKIE['folks_viewed_user'], $_SERVER['REQUEST_TIME'] + 22896000, $GLOBALS['conf']['cookie']['path'],
430:                   $GLOBALS['conf']['cookie']['domain'],  $GLOBALS['conf']['use_ssl'] == 1 ? 1 : 0);
431: 
432:         return $this->_logView($id);
433:     }
434: 
435:    436: 437: 438: 439: 440: 441: 
442:     public function deleteUser($user)
443:     {
444:         if (!$GLOBALS['registry']->isAdmin()) {
445:             return false;
446:         }
447: 
448:         
449:         $result = $this->deleteImage($user);
450:         if ($result instanceof PEAR_Error) {
451:             return $result;
452:         }
453: 
454:         
455:         if ($GLOBALS['conf']['friends']) {
456:             $shares = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Share')->create();
457:             $groups = $shares->listShares($GLOBALS['registry']->getAuth(), array('perm' => Horde_Perms::SHOW));
458:             foreach ($groups as $share) {
459:                 $result = $shares->removeShare($share);
460:                 if ($result instanceof PEAR_Error) {
461:                     return $result;
462:                 }
463:             }
464:         }
465: 
466:         
467:         if ($registry->hasMethod('forums/deleteForum')) {
468:             $registry->call('forums/deleteForum', array('folks', $user));
469:         }
470: 
471:         
472:         $result = $this->_deleteUser($user);
473:         if ($result instanceof PEAR_Error) {
474:             return $result;
475:         }
476: 
477:         
478:         $GLOBALS['cache']->expire('folksProfile' . $user);
479: 
480:         return true;
481:     }
482: 
483:     484: 485: 486: 487: 488: 
489:     public function getAttributes($user = null, $group = null)
490:     {
491:         if ($user == null) {
492:             $user = $GLOBALS['registry']->getAuth();
493:         }
494: 
495:         $attributes = $GLOBALS['cache']->get('folksUserAttributes' . $user, $GLOBALS['conf']['cache']['default_lifetime']);
496:         if ($attributes) {
497:             $attributes = unserialize($attributes);
498:         } else {
499:             $attributes = $this->_getAttributes($user);
500:             if ($attributes instanceof PEAR_Error) {
501:                 return $attributes;
502:             }
503:             $GLOBALS['cache']->set('folksUserAttributes' . $user, serialize($attributes));
504:         }
505: 
506:         return $group ? (isset($attributes[$group]) ? $attributes[$group] : array()) : $attributes;
507:     }
508: 
509:     510: 511: 512: 513: 514: 515: 
516:     public function saveAttributes($data, $group, $user = null)
517:     {
518:         if ($user == null) {
519:             $user = $GLOBALS['registry']->getAuth();
520:         }
521: 
522:         $GLOBALS['cache']->expire('folksAttributes' . $user);
523: 
524:         return $this->_saveAttributes($data, $group, $user);
525:     }
526: 
527:     528: 529: 530: 531: 532: 533: 534: 535: 
536:     public function comparePassword($user, $plaintext)
537:     {
538:         $encrypted = $this->_getCryptedPassword($user);
539:         if ($encrypted instanceof PEAR_Error) {
540:             return $encrypted;
541:         } elseif (empty($encrypted)) {
542:             return false;
543:         }
544: 
545:         return $encrypted == hash('md5', $plaintext);
546:     }
547: 
548:     549: 550: 551: 552: 553: 554: 
555:     public function getCookie($user)
556:     {
557:         $encrypted = $this->_getCryptedPassword($user);
558:         if ($encrypted instanceof PEAR_Error) {
559:             return $encrypted;
560:         }
561: 
562:         
563:         $key = date('m') . $encrypted;
564: 
565:         return Folks::encodeString($user, $key);
566:     }
567: 
568:     569: 570: 571: 572: 573: 574: 575: 
576:     public function getConfirmationCode($user, $type = 'activate')
577:     {
578:         $encrypted = $this->_getCryptedPassword($user);
579:         if ($encrypted instanceof PEAR_Error) {
580:             return $encrypted;
581:         }
582: 
583:         return Folks::encodeString($user, $type . $encrypted);
584:     }
585: 
586:    587: 588: 589: 590: 591: 
592:     public function saveSearch($criteria, $name)
593:     {
594:         $GLOBALS['cache']->expire('folksearch' . $GLOBALS['registry']->getAuth());
595: 
596:         return $this->_saveSearch($criteria, $name);
597:     }
598: 
599:    600: 601: 602: 603: 
604:     public function getSavedSearch()
605:     {
606:         $search = $GLOBALS['cache']->get('folksearch' . $GLOBALS['registry']->getAuth(), $GLOBALS['conf']['cache']['default_lifetime']);
607:         if ($search) {
608:             return unserialize($search);
609:         }
610: 
611:         $search = $this->_getSavedSearch();
612:         if ($search instanceof PEAR_Error) {
613:             return $search;
614:         }
615: 
616:         $GLOBALS['cache']->set('folksearch' . $GLOBALS['registry']->getAuth(), serialize($search));
617: 
618:         return $search;
619:     }
620: 
621:    622: 623: 624: 625: 626: 627: 
628:     public function getSearchCriteria($name)
629:     {
630:         $criteria = $this->_getSearchCriteria($name);
631:         if ($criteria instanceof PEAR_Error) {
632:             return $criteria;
633:         }
634: 
635:         return unserialize($criteria);
636:     }
637: 
638:    639: 640: 641: 642: 
643:     public function deleteSavedSearch($name)
644:     {
645:         $GLOBALS['cache']->expire('folksearch' . $GLOBALS['registry']->getAuth());
646: 
647:         return $this->_deleteSavedSearch($name);
648:     }
649: 
650:    651: 652: 653: 654: 655: 656: 657: 658: 
659:     public function logActivity($message, $scope = 'folks', $user = null)
660:     {
661:         if ($user == null) {
662:             $user = $GLOBALS['registry']->getAuth();
663:         }
664: 
665:         if (empty($message)) {
666:             return PEAR::raiseError(_("You cannot post an empty activity message."));
667:         }
668: 
669:         
670:         if ($scope == 'folks:comments' && !$GLOBALS['prefs']->getValue('log_user_comments')) {
671:             return true;
672: 
673:         
674:         } elseif ($scope == 'folks' && !$GLOBALS['prefs']->getValue('log_account_changes')) {
675:             return true;
676:         }
677: 
678:         
679:         $scopes = unserialize($GLOBALS['prefs']->getValue('log_scopes'));
680:         if (!empty($scopes) && in_array($scopes, $scope)) {
681:             return true;
682:         }
683: 
684:         
685:         $scope_app = explode(':', $scope);
686:         $scopes = unserialize($GLOBALS['prefs']->getValue('log_scope_comments'));
687:         if (!empty($scopes) && in_array($scopes, $scope_app[0])) {
688:             return true;
689:         }
690: 
691:         $GLOBALS['cache']->expire($user . '_activity');
692:         return $this->_logActivity($message, $scope, $user);
693:     }
694: 
695:    696: 697: 698: 699: 700: 701: 702: 
703:     public function getActivity($user, $limit = 10)
704:     {
705:         $activity = $GLOBALS['cache']->get($user . '_activity', $GLOBALS['conf']['cache']['default_lifetime']);
706:         if ($activity) {
707:             return unserialize($activity);
708:         } else {
709:             $activity = $this->_getActivity($user, $limit);
710:             if ($activity instanceof PEAR_Error) {
711:                 return $activity;
712:             }
713: 
714:             $GLOBALS['cache']->set($user . '_activity', serialize($activity));
715:         }
716: 
717:         return $activity;
718:     }
719: 
720:    721: 722: 723: 724: 725: 726: 727: 
728:     public function deleteActivity($scope, $date)
729:     {
730:         $user = $GLOBALS['registry']->getAuth();
731:         $GLOBALS['cache']->expire($user . '_activity');
732:         return $this->_deleteActivity($scope, $date, $user);
733:     }
734: }
735: