1: <?php
2: /**
3: * Horde_Imsp_Utils::
4: *
5: * Copyright 2003-2012 Horde LLC (http://www.horde.org/)
6: *
7: * See the enclosed file COPYING for license information (LGPL). If you
8: * did not receive this file, see http://www.horde.org/licenses/lgpl21.
9: *
10: * @author Michael Rubinsky <mrubinsk@horde.org>
11: * @package Horde_Imsp
12: */
13: class Horde_Core_Imsp_Utils
14: {
15: /**
16: * Utility function to retrieve the names of all the address books
17: * that the user has access to, along with the acl for those
18: * books. For information about the $serverInfo array see
19: * turba/config/sources.php as this is the cfgSources[] entry for
20: * the address books.
21: *
22: * @param array $serverInfo Information about the server
23: * and the current user.
24: *
25: * @return array Information about all the address books or PEAR_Error.
26: */
27: static public function getAllBooks(array $serverInfo)
28: {
29: $foundDefault = false;
30: $results = array();
31: $imsp = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Imsp')->create('Book', $serverInfo['params']);
32: $books = $imsp->getAddressBookList();
33: $bCount = count($books);
34: for ($i = 0; $i < $bCount; $i++) {
35: $newBook = $serverInfo;
36: if ($books[$i] != $serverInfo['params']['username']) {
37: $newBook['title'] = $books[$i];
38: // We need the 'name' param to store the IMSP
39: // address book name when not using shares (for BC).
40: $newBook['params']['name'] = $books[$i];
41: $newBook['params']['is_root'] = false;
42: $newBook['params']['my_rights'] = $imsp->myRights($books[$i]);
43: } else {
44: $foundDefault = true;
45: $newBook['params']['my_rights'] = $imsp->myRights($books[$i]);
46: }
47: $results[] = $newBook;
48: }
49:
50: /* If there is no default address book (named username) then we should create one. */
51: if (!$foundDefault) {
52: $imsp->createAddressBook($serverInfo['params']['username']);
53: }
54:
55: return $results;
56: }
57:
58: /**
59: * Utility function to help clients create new address books without having
60: * to create an imsp driver instance first.
61: *
62: * @param array $source Information about the user's default IMSP
63: * address book.
64: * @param string $newName The name of the new address book.
65: *
66: * @return mixed true on success or PEAR_Error on failure.
67: */
68: static public function createBook(array $source, $newName)
69: {
70: $imsp = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Imsp')->create('Book', $source['params']);
71:
72: // We now check if the username is already prepended to
73: // the address book name or not.
74: if (strpos($newName, $source['params']['username'] . '.') === 0) {
75: $name = $newName;
76: } else {
77: $name = $source['params']['username'] . '.' . $newName;
78: }
79: $imsp->createAddressBook($name);
80: return true;
81: }
82:
83: /**
84: * Synchronize Horde_Shares to existing IMSP address books.
85: *
86: * @param Horde_Share $share_obj The Horde_Share object to use.
87: * @param array $serverInfo Information about the IMSP server and
88: * the current user.
89: *
90: * @return mixed Array describing any shares added or removed | PEAR_Error.
91: */
92: public function synchShares($share_obj, array $serverInfo)
93: {
94: $found_shares = array();
95: $return = array('added' => array(), 'removed' => array());
96: $params = array();
97:
98: $imsp = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Imsp')->create('Book', $serverInfo['params']);
99: $abooks = $imsp->getAddressBookList();
100:
101: // Do we have a default address book? If not, create one.
102: if (array_search($serverInfo['params']['username'], $abooks) === false) {
103: $imsp->createAddressbook($serverInfo['params']['username']);
104: // Make sure we add it to our list of books.
105: $abooks[] = $serverInfo['params']['username'];
106: }
107:
108: $shares = $share_obj->listShares($GLOBALS['registry']->getAuth());
109: // A share for each IMSP adress book we can see.
110: foreach ($abooks as $abook_uid) {
111: $found = false;
112: foreach ($shares as $id => $share) {
113: $params = @unserialize($share->get('params'));
114: if (!empty($params['name']) && $params['name'] == $abook_uid &&
115: $params['source'] == 'imsp') {
116: $found = true;
117: break;
118: }
119: }
120: if (!$found) {
121: $shareparams = array('name' => $abook_uid,
122: 'source' => 'imsp');
123:
124: $params['uid'] = md5(mt_rand());
125: $params['name'] = $abook_uid . ' (IMSP)';
126: $params['acl'] = $imsp->myRights($abook_uid);
127: if ($abook_uid == $serverInfo['params']['username']) {
128: // This is the default address book
129: $shareparams['default'] = true;
130: } else {
131: $shareparams['default'] = false;
132: }
133: if (self::_isOwner($abook_uid,
134: $serverInfo['params']['username'],
135: $params['acl'])) {
136: $params['owner'] = $GLOBALS['registry']->getAuth();
137: } else {
138: // TODO: What to do for the owner when it's not current user?
139: // We'd have to try to match the owner per IMSP
140: // address book name to a Horde user...how to do that
141: // without assuming usernames are equal?
142: }
143: self::_createShare($share_obj, $params, $shareparams);
144: $return['added'][] = $params['uid'];
145: } else {
146: // Share already exists, just update the acl.
147: $params['acl'] = $imsp->myRights($abook_uid);
148: }
149: $found_shares[] = $abook_uid;
150: }
151:
152: // Now prune any shares that no longer exist on the IMSP server.
153: $existing = $share_obj->listShares($GLOBALS['registry']->getAuth(), array('perm' => Horde_Perms::READ));
154: foreach ($existing as $key => $share) {
155: $temp = unserialize($share->get('params'));
156: if (is_array($temp)) {
157: $sourceType = $temp['source'];
158: if ($sourceType == 'imsp' &&
159: array_search($temp['name'], $found_shares) === false) {
160: $share_obj->removeShare($share);
161: $return['removed'][] = $share->getName();
162: }
163: }
164: }
165: return $return;
166: }
167:
168: /**
169: * Creates a Horde_Share for an *existing* IMSP address book.
170: * Needed for creating shares for address books created outside
171: * of Horde.
172: *
173: * @param Horde_Share The share object to create the new share with.
174: * @param array Parameters for the share
175: *
176: * @return mixed True | PEAR_Error
177: */
178: static protected function _createShare($share_obj, array $params, array $shareparams)
179: {
180: $share = $share_obj->newShare($GLOBALS['registry']->getAuth(), $params['uid'], $params['name']);
181: if (is_a($share, 'PEAR_Error')) {
182: return $share;
183: }
184: $share->set('params', serialize($shareparams));
185: self::_setPerms($share, $params['acl']);
186: $share->save();
187: return true;
188: }
189:
190: /**
191: * Determine if we are the owner of the address book.
192: * Assumes ownership if username is beginning address book name or
193: * if user has admin rights ('a') in acl.
194: *
195: * @param string $bookName The address book name to check
196: *
197: * @return boolean True if $user is owner, otherwise false.
198: */
199: static protected function _isOwner($bookName, $username, $acl)
200: {
201: if (strpos($bookName, $username) === 0) {
202: return true;
203: } elseif (strpos($acl, 'a')) {
204: return true;
205: }
206: return false;
207: }
208:
209: /**
210: * Translates IMSP acl into share permissions and sets them in share.
211: *
212: * @param Datatree_Object_Share $share The share to assign perms to
213: * @param string $acl The IMSP acl string.
214: */
215: static protected function _setPerms(&$share, $acl)
216: {
217: $hPerms = 0;
218: if (strpos($acl, 'w') !== false) {
219: $hPerms |= Horde_Perms::EDIT;
220: }
221: if (strpos($acl, 'r') !== false) {
222: $hPerms |= Horde_Perms::READ;
223: }
224: if (strpos($acl, 'd') !== false) {
225: $hPerms |= Horde_Perms::DELETE;
226: }
227: if (strpos($acl, 'l') !== false) {
228: $hPerms |= Horde_Perms::SHOW;
229: }
230: $share->addUserPermission($GLOBALS['registry']->getAuth(), $hPerms);
231: }
232:
233: /**
234: * Translates Horde_Share permissions into IMSP acl.
235: *
236: * @param integer $perms Horde_Perms style permission bitmask.
237: *
238: * @return string An IMSP acl string
239: */
240: static public function permsToACL($perms)
241: {
242: $acl = '';
243:
244: if ($perms & Horde_Perms::SHOW) {
245: $acl = 'l';
246: }
247: if ($perms & Horde_Perms::READ) {
248: $acl .= 'r';
249: }
250: if ($perms & Horde_Perms::EDIT) {
251: $acl .= 'w';
252: }
253: if ($perms & Horde_Perms::DELETE) {
254: $acl .= 'd';
255: }
256: return $acl;
257: }
258:
259: /**
260: * Set's an address book's acl on the IMSP server.
261: *
262: * @param string $book The address book name to set
263: * @param string $name The user name to set for.
264: * @param string $acl The acl string to set.
265: *
266: * @return mixed True | Pear_Error
267: */
268: static public function setACL($params, $book, $name, $acl)
269: {
270: $imsp = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Imsp')->create('Book', $params);
271: return $imsp->setACL($book, $name, $acl);
272: }
273:
274: }
275: