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: