1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
13: class Horde_Vfs_Kolab extends Horde_Vfs_Base
14: {
15: 16: 17: 18: 19:
20: protected $_imap = false;
21:
22: 23: 24: 25: 26:
27: protected $_folders;
28:
29: 30: 31: 32: 33: 34: 35: 36: 37:
38: public function read($path, $name)
39: {
40: list($app, $uid) = $this->_getAppUid($path);
41: if ($app && $uid) {
42: $handler = $this->_getAppHandler($app, $uid);
43: $object = $handler->getObject($uid);
44:
45: if (isset($object['_attachments'][$name])) {
46: return $handler->getAttachment($object['_attachments'][$name]['key']);
47: }
48: }
49:
50:
51: if ($this->isFolder(dirname($path), basename($path))) {
52: $session = Horde_Kolab_Session::singleton();
53: $imap = $session->getImap();
54:
55: $result = $imap->select(substr($path,1));
56: if ($result instanceof PEAR_Error) {
57: throw new Horde_Vfs_Exception($result->getMessage());
58: }
59:
60: $file = explode('/', $name);
61:
62: return $this->_getFile($imap, $file[0], $file[1]);
63: }
64:
65: return '';
66: }
67:
68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78:
79: public function write($path, $name, $tmpFile, $autocreate = false)
80: {
81: list($app, $uid) = $this->_getAppUid($path);
82: if ($app) {
83: $handler = $this->_getAppHandler($app, $uid);
84: $object = $handler->getObject($uid);
85: $object['_attachments'][$name]['path'] = $tmpFile;
86: if (empty($object['link-attachment'])) {
87: $object['link-attachment'] = array($name);
88: } else {
89: $object['link-attachment'][] = $name;
90: }
91:
92: return $handler->save($object, $uid);
93: }
94:
95: if ($autocreate && !$this->isFolder(dirname($path), basename($path))) {
96: $this->autocreatePath($path);
97: }
98:
99:
100: throw new Horde_Vfs_Exception('Not supported.');
101: }
102:
103: 104: 105: 106: 107: 108: 109: 110:
111: public function deleteFile($path, $name)
112: {
113: list($app, $uid) = $this->_getAppUid($path);
114: if ($app) {
115: $handler = $this->_getAppHandler($app, $uid);
116: $object = $handler->getObject($uid);
117: if (!isset($object['_attachments'][$name])) {
118: throw new Horde_Vfs_Exception('Unable to delete VFS file.');
119: }
120: unset($object['_attachments'][$name]);
121: $object['link-attachment'] = array_values(array_diff($object['link-attachment'], array($name)));
122:
123: return $handler->save($object, $uid);
124: }
125:
126:
127: throw new Horde_Vfs_Exception('Not supported.');
128: }
129:
130: 131: 132: 133: 134: 135: 136: 137:
138: public function createFolder($path, $name)
139: {
140: $list = Kolab_List::singleton();
141: $folder = $this->_getFolder($path, $name);
142:
143: $object = $list->getNewFolder();
144: $object->setName($folder);
145:
146: $object->save(array('type' => 'h-file'));
147: if ($result instanceof PEAR_Error) {
148: throw new Horde_Vfs_Exception($result->getMessage());
149: }
150:
151: $this->_folders = null;
152: }
153:
154: 155: 156: 157: 158: 159: 160: 161: 162:
163: public function deleteFolder($path, $name, $recursive = false)
164: {
165: if ($recursive) {
166: $this->emptyFolder($path . '/' . $name);
167: } else {
168: $list = $this->listFolder($path . '/' . $name, null, false);
169: if (count($list)) {
170: throw new Horde_Vfs_Exception(sprintf('Unable to delete %s, the directory is not empty', $path . '/' . $name));
171: }
172: }
173:
174: list($app, $uid) = $this->_getAppUid($path . '/' . $name);
175: if ($app) {
176: 177: 178:
179: return;
180: }
181:
182: $folders = $this->_getFolders();
183: $folder = $this->_getFolder($path, $name);
184:
185: if (!empty($folders['/' . $folder])) {
186: $folders['/' . $folder]->delete();
187: $this->_folders = null;
188: return;
189: }
190:
191: throw new Horde_Vfs_Exception(sprintf('No such folder %s!', '/' . $folder));
192: }
193:
194: 195: 196: 197: 198: 199: 200: 201:
202: public function emptyFolder($path)
203: {
204:
205: $list = $this->listFolder($path, null, false, true);
206: foreach ($list as $folder) {
207: $this->deleteFolder($path, $folder['name'], true);
208: }
209:
210:
211: $list = $this->listFolder($path, null, false);
212: foreach ($list as $file) {
213: $this->deleteFile($path, $file['name']);
214: }
215: }
216:
217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227:
228: protected function _listFolder($path = '', $filter = null, $dotfiles = true,
229: $dironly = false)
230: {
231: list($app, $uid) = $this->_getAppUid($path);
232: if ($app) {
233: if ($dironly) {
234: 235: 236:
237: return array();
238: }
239: if ($uid) {
240: $handler = $this->_getAppHandler($app, $uid);
241: $object = $handler->getObject($uid);
242: if ($object instanceof PEAR_Error) {
243: throw new Horde_Vfs_Exception($object->getMessage());
244: }
245:
246: $filenames = isset($object['_attachments'])
247: ? array_keys($object['_attachments'])
248: : array();
249: } else {
250: $filenames = $this->_getAppUids($app);
251: }
252:
253: $owner = $GLOBALS['registry']->getAuth();
254:
255: $file = $files = array();
256: foreach ($filenames as $filename) {
257: $name = explode('.', $filename);
258:
259: if (count($name) == 1) {
260: $file['type'] = '**none';
261: } else {
262: $file['type'] = Horde_String::lower($name[count($name) - 1]);
263: }
264:
265: $file['size'] = '-1';
266: $file['name'] = $filename;
267: $file['group'] = 'none';
268: $file['owner'] = $owner;
269: $file['date'] = 0;
270: $file['perms'] = 'rwxrwx---';
271:
272: $files[$file['name']] = $file;
273: }
274:
275: return $files;
276: }
277:
278: $owner = $GLOBALS['registry']->getAuth();
279:
280: $file = $files = array();
281:
282: $folders = $this->listFolders($path, $filter, $dotfiles);
283: $list = $this->_getFolders();
284:
285: foreach ($folders as $folder) {
286: $file['type'] = '**dir';
287: $file['size'] = -1;
288: $file['name'] = $folder['abbrev'];
289:
290: $file['group'] = 'none';
291:
292: $file['owner'] = $owner;
293:
294: $file['date'] = 0;
295:
296: $file['perms'] = 'rwxrwx---';
297:
298: $files[$file['name']] = $file;
299: }
300:
301: if (!$dironly &&
302: $this->isFolder(basename($path), basename($path)) &&
303: !empty($list[$path])) {
304: $session = Horde_Kolab_Session::singleton();
305: $imap = $session->getImap();
306:
307: $result = $imap->select(substr($path, 1));
308: if ($result instanceof PEAR_Error) {
309: throw new Horde_Vfs_Exception($result->getMessage());
310: }
311:
312: $uids = $imap->getUids();
313: if ($uids instanceof PEAR_Error) {
314: throw new Horde_Vfs_Exception($uids->getMessage());
315: }
316:
317: foreach ($uids as $uid) {
318: $result = array_merge($files, $this->_parseMessage($imap, $uid));
319: $files = $result;
320: }
321: }
322:
323: return $files;
324: }
325:
326: 327:
328: protected function _parseMessage($imap, $uid)
329: {
330: $result = $imap->getMessageHeader($uid);
331: if ($result instanceof PEAR_Error) {
332: throw new Horde_Vfs_Exception($result->getMessage());
333: }
334:
335: $raw_headers = $result;
336:
337: $body = $imap->getMessageBody($uid);
338: if ($body instanceof PEAR_Error) {
339: throw new Horde_Vfs_Exception($body->getMessage());
340: }
341:
342: $raw_message = $raw_headers . $body;
343:
344: $mime_message = Horde_Mime_Part::parseMessage($raw_message);
345: $parts = $mime_message->contentTypeMap();
346:
347: $owner = $GLOBALS['registry']->getAuth();
348:
349: $file = $files = array();
350:
351: foreach ($parts as $part_id => $disposition) {
352: $part = $mime_message->getPart($part_id);
353:
354: $filename = $part->getDispositionParameter('filename');
355:
356: if ($filename) {
357: $file['type'] = '**file';
358: $file['size'] = $part->getSize();
359: $file['name'] = $uid . '/' . $filename;
360:
361: $file['group'] = 'none';
362:
363: $file['owner'] = $owner;
364:
365: $file['date'] = 0;
366:
367: $file['perms'] = 'rwxrwx---';
368:
369: $files[$file['name']] = $file;
370: }
371:
372: }
373:
374: return $files;
375: }
376:
377: 378:
379: protected function _getFile($imap, $uid, $filename)
380: {
381: $result = $imap->getMessageHeader($uid);
382: if ($result instanceof PEAR_Error) {
383: throw new Horde_Vfs_Exception($result->getMessage());
384: }
385:
386: $raw_headers = $result;
387:
388: $body = $imap->getMessageBody($uid);
389: if ($body instanceof PEAR_Error) {
390: throw new Horde_Vfs_Exception($body->getMessage());
391: }
392:
393: $raw_message = $raw_headers . $body;
394:
395: $mime_message = Horde_Mime_Part::parseMessage($raw_message);
396: $parts = $mime_message->contentTypeMap();
397:
398: $owner = $GLOBALS['registry']->getAuth();
399:
400: foreach ($parts as $part_id => $disposition) {
401: $part = $mime_message->getPart($part_id);
402:
403: $f = $part->getDispositionParameter('filename');
404: if ($f && $f == $filename) {
405: return $part->transferDecode();
406: }
407: }
408:
409: return '';
410: }
411:
412: 413: 414: 415: 416: 417: 418: 419: 420: 421: 422:
423: public function listFolders($path = '', $filter = null, $dotfolders = true)
424: {
425: if (substr($path, -1) != '/') {
426: $path .= '/';
427: }
428:
429: $aFolder = $aFolders = array();
430:
431: if ($dotfolders && $path != '/') {
432: $aFolder['val'] = dirname($path);
433: $aFolder['abbrev'] = '..';
434: $aFolder['label'] = '..';
435:
436: $aFolders[$aFolder['val']] = $aFolder;
437: }
438:
439: $folders = $this->_getFolders();
440:
441: $base_len = strlen($path);
442: foreach (array_keys($folders) as $folder) {
443: if (substr($folder, 0, $base_len) == $path) {
444: $name = substr($folder, $base_len);
445: if (!strpos($name, '/')) {
446: $aFolder['val'] = $folder;
447: $aFolder['abbrev'] = $name;
448: $aFolder['label'] = $folder;
449: $aFolders[$aFolder['val']] = $aFolder;
450: }
451: }
452: }
453:
454: ksort($aFolders);
455: return $aFolders;
456: }
457:
458: 459:
460: protected function _getFolder($path, $name)
461: {
462: $folder = $path . '/' . $name;
463:
464: while (substr($folder, 0, 1) == '/') {
465: $folder = substr($folder, 1);
466: }
467:
468: while (substr($folder, -1) == '/') {
469: $folder = substr($folder, 0, -1);
470: }
471:
472: return $folder;
473: }
474:
475: 476:
477: protected function _getFolders()
478: {
479: if (!isset($this->_folders)) {
480: $vfs_folders = array();
481:
482: $list = Kolab_List::singleton();
483:
484: if (!empty($this->_params['all_folders'])) {
485: $folders = $list->getFolders();
486: } else {
487: $folders = $list->getByType('h-file');
488: }
489:
490: if ($folders instanceof PEAR_Error) {
491: throw new Horde_Vfs_Exception($folders->getMessage());
492: }
493:
494: foreach ($folders as $folder) {
495: $vfs_folders['/' . $folder->name] = &$folder;
496: }
497:
498: foreach (array_keys($vfs_folders) as $name) {
499: $dir = dirname($name);
500: while ($dir != '/') {
501: if (!isset($vfs_folders[$dir])) {
502: $vfs_folders[$dir] = null;
503: }
504: $dir = dirname($dir);
505: }
506: }
507: $this->_folders = $vfs_folders;
508: }
509:
510: return $this->_folders;
511: }
512:
513: 514:
515: protected function _getAppUid($path)
516: {
517: if (defined('TURBA_VFS_PATH') &&
518: substr($path, 0, strlen(TURBA_VFS_PATH)) == TURBA_VFS_PATH) {
519: return array('turba', substr($path, strlen(TURBA_VFS_PATH) + 1));
520: }
521:
522: return array(false, false);
523: }
524:
525: 526:
527: protected function _getAppHandler($app, $uid)
528: {
529: global $registry;
530:
531: switch ($app) {
532: case 'turba':
533: $sources = $registry->call('contacts/sources',
534: array('writeable' => true));
535: $fields = array();
536: foreach (array_keys($sources) as $source) {
537: $fields[$source] = array('__uid');
538: }
539: $result = $registry->call('contacts/search',
540: array('names' => $uid,
541: 'sources' => array_keys($sources),
542: 'fields' => $fields));
543: if (!isset($result[$uid])) {
544: throw new Horde_Vfs_Exception('No such contact!');
545: }
546: $list = Kolab_List::singleton();
547: $share = $list->getByShare($result[$uid][0]['source'], 'contact');
548: if ($share instanceof PEAR_Error) {
549: throw new Horde_Vfs_Exception($share->getMessage());
550: }
551: return $share->getData();
552: }
553: }
554:
555: 556:
557: protected function _getAppUids($app)
558: {
559: global $registry;
560:
561: switch ($app) {
562: case 'turba':
563: $sources = $registry->call('contacts/sources',
564: array('writeable' => true));
565: $result = $registry->call('contacts/search',
566: array('names' => '',
567: 'sources' => array_keys($sources),
568: 'fields' => array()));
569: $uids = array();
570: foreach ($result[''] as $contact) {
571: if (isset($contact['__uid'])) {
572: $uids[] = $contact['__uid'];
573: }
574: }
575: return $uids;
576: }
577: }
578:
579: }
580: