1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
17: class Gollem
18: {
19:
20: const SORT_TYPE = 0;
21: const SORT_NAME = 1;
22: const SORT_DATE = 2;
23: const SORT_SIZE = 3;
24:
25: const SORT_ASCEND = 0;
26: const SORT_DESCEND = 1;
27:
28: 29: 30: 31: 32:
33: static public $backend;
34:
35: 36: 37: 38: 39: 40: 41: 42:
43: static public function setDir($dir)
44: {
45: $dir = Horde_Util::realPath($dir);
46:
47: if (!self::verifyDir($dir)) {
48: throw new Gollem_Exception(sprintf(_("Access denied to folder \"%s\"."), $dir));
49: }
50: self::$backend['dir'] = $dir;
51:
52: self::_setLabel();
53: }
54:
55: 56: 57: 58: 59: 60:
61: static public function changeDir()
62: {
63: $dir = Horde_Util::getFormData('dir');
64: if (is_null($dir)) {
65: self::_setLabel();
66: } else {
67: if (strpos($dir, '/') !== 0) {
68: $dir = self::$backend['dir'] . '/' . $dir;
69: }
70: self::setDir($dir);
71: }
72: }
73:
74: 75: 76:
77: static protected function _setLabel()
78: {
79: self::$backend['label'] = self::getDisplayPath(self::$backend['dir']);
80: if (empty(self::$backend['label'])) {
81: self::$backend['label'] = '/';
82: }
83: }
84:
85: 86: 87:
88: static protected function _sortDirs($a, $b)
89: {
90:
91: $dira = ($a['type'] === '**dir') ||
92: (($a['type'] === '**sym') && ($a['linktype'] === '**dir'));
93: $dirb = ($b['type'] === '**dir') ||
94: (($b['type'] === '**sym') && ($b['linktype'] === '**dir'));
95:
96: if ($GLOBALS['prefs']->getValue('sortdirsfirst')) {
97: if ($dira && !$dirb) {
98: return -1;
99: } elseif (!$dira && $dirb) {
100: return 1;
101: }
102: }
103: return 0;
104: }
105:
106: 107: 108:
109: static public function sortDate($a, $b)
110: {
111: $dirs = self::_sortDirs($a, $b);
112: if ($dirs) {
113: return $dirs;
114: }
115:
116: if ($a['date'] > $b['date']) {
117: return $GLOBALS['prefs']->getValue('sortdir') ? -1 : 1;
118: } elseif ($a['date'] === $b['date']) {
119: return self::sortName($a, $b);
120: } else {
121: return $GLOBALS['prefs']->getValue('sortdir') ? 1 : -1;
122: }
123: }
124:
125: 126: 127:
128: static public function sortSize($a, $b)
129: {
130: $dirs = self::_sortDirs($a, $b);
131: if ($dirs) {
132: return $dirs;
133: }
134:
135: if ($a['size'] > $b['size']) {
136: return $GLOBALS['prefs']->getValue('sortdir') ? -1 : 1;
137: } elseif ($a['size'] === $b['size']) {
138: return 0;
139: } else {
140: return $GLOBALS['prefs']->getValue('sortdir') ? 1 : -1;
141: }
142: }
143:
144: 145: 146:
147: static public function sortType($a, $b)
148: {
149: $dirs = self::_sortDirs($a, $b);
150: if ($dirs) {
151: return $dirs;
152: }
153:
154: if ($a['type'] === $b['type']) {
155: return self::sortName($a, $b);
156: } elseif ($a['type'] === '**dir') {
157: return $GLOBALS['prefs']->getValue('sortdir') ? 1 : -1;
158: } elseif ($b['type'] === '**dir') {
159: return $GLOBALS['prefs']->getValue('sortdir') ? -1 : 1;
160: } else {
161: $res = strcasecmp($a['type'], $b['type']);
162: return $GLOBALS['prefs']->getValue('sortdir') ? ($res * -1) : $res;
163: }
164: }
165:
166: 167: 168:
169: static public function sortName($a, $b)
170: {
171: $dirs = self::_sortDirs($a, $b);
172: if ($dirs) {
173: return $dirs;
174: }
175:
176: $res = strcasecmp($a['name'], $b['name']);
177: return $GLOBALS['prefs']->getValue('sortdir') ? ($res * -1) : $res;
178: }
179:
180: 181: 182: 183: 184: 185: 186: 187:
188: static public function listFolder($dir)
189: {
190: global $conf;
191:
192: if (!empty($conf['foldercache']['use_cache']) &&
193: !empty($conf['cache']['driver']) &&
194: ($conf['cache']['driver'] != 'none')) {
195: $key = self::_getCacheID($dir);
196:
197: $cache = $GLOBALS['injector']->getInstance('Horde_Cache');
198: $res = $cache->get($key, $conf['foldercache']['lifetime']);
199: if ($res !== false) {
200: $res = Horde_Serialize::unserialize($res, Horde_Serialize::BASIC);
201: if (is_array($res)) {
202: return $res;
203: }
204: }
205: }
206:
207: try {
208: $files = $GLOBALS['injector']
209: ->getInstance('Gollem_Vfs')
210: ->listFolder($dir,
211: isset(self::$backend['filter']) ? self::$backend['filter'] : null,
212: $GLOBALS['prefs']->getValue('show_dotfiles'));
213: } catch (Horde_Vfs_Exception $e) {
214: throw new Gollem_Exception($e);
215: }
216: $sortcols = array(
217: self::SORT_TYPE => 'sortType',
218: self::SORT_NAME => 'sortName',
219: self::SORT_DATE => 'sortDate',
220: self::SORT_SIZE => 'sortSize',
221: );
222: usort($files, array('Gollem', $sortcols[$GLOBALS['prefs']->getValue('sortby')]));
223:
224: if (isset($cache)) {
225: $cache->set($key, Horde_Serialize::serialize($files, Horde_Serialize::BASIC), $conf['foldercache']['lifetime']);
226: }
227:
228: return $files;
229: }
230:
231: 232: 233: 234: 235:
236: static protected function _getCacheID($dir)
237: {
238: return implode('|', array($GLOBALS['registry']->getAuth(),
239: $GLOBALS['session']->get('gollem', 'backend_key'),
240: $GLOBALS['prefs']->getValue('show_dotfiles'),
241: $GLOBALS['prefs']->getValue('sortdirsfirst'),
242: $GLOBALS['prefs']->getValue('sortby'),
243: $GLOBALS['prefs']->getValue('sortdir'),
244: $dir));
245: }
246:
247: 248: 249: 250: 251:
252: static public function expireCache($dir)
253: {
254: global $conf;
255:
256: if (!empty($conf['foldercache']['use_cache']) &&
257: !empty($conf['cache']['driver']) &&
258: ($conf['cache']['driver'] != 'none')) {
259: $cache = $GLOBALS['injector']->getInstance('Horde_Cache');
260: $cache->expire(self::_getCacheID($dir));
261: }
262: }
263:
264: 265: 266: 267: 268: 269: 270: 271:
272: static public function subdirectory($base, $dir)
273: {
274: if (empty($base)) {
275: return $dir;
276: }
277:
278: if (substr($base, -1) == '/') {
279: return $base . $dir;
280: }
281:
282: return $base . '/' . $dir;
283: }
284:
285: 286: 287: 288: 289: 290: 291: 292: 293: 294:
295: static public function createFolder($dir, $name, $gollem_vfs = null)
296: {
297: $totalpath = Horde_Util::realPath($dir . '/' . $name);
298: if (!self::verifyDir($totalpath)) {
299: throw new Gollem_Exception(sprintf(_("Access denied to folder \"%s\"."), $totalpath));
300: }
301:
302: 303:
304: $pos = strrpos($totalpath, '/');
305: $dir = substr($totalpath, 0, $pos);
306: $name = substr($totalpath, $pos + 1);
307:
308: if (!$gollem_vfs) {
309: $gollem_vfs = $GLOBALS['injector']->getInstance('Gollem_Vfs');
310: }
311: $gollem_vfs->autocreatePath($dir);
312: $gollem_vfs->createFolder($dir, $name);
313:
314: if (!empty(self::$backend['params']['permissions'])) {
315: $gollem_vfs->changePermissions($dir, $name, self::$backend['params']['permissions']);
316: }
317: }
318:
319: 320: 321: 322: 323: 324: 325: 326: 327: 328:
329: static public function renameItem($oldDir, $old, $newDir, $new)
330: {
331: $GLOBALS['injector']
332: ->getInstance('Gollem_Vfs')
333: ->rename($oldDir, $old, $newDir, $new);
334: }
335:
336: 337: 338: 339: 340: 341: 342: 343: 344:
345: static public function deleteFolder($dir, $name)
346: {
347: if (!self::verifyDir($dir)) {
348: throw new Gollem_Exception(sprintf(_("Access denied to folder \"%s\"."), $dir));
349: }
350:
351: $GLOBALS['injector']
352: ->getInstance('Gollem_Vfs')
353: ->deleteFolder($dir,
354: $name,
355: $GLOBALS['prefs']->getValue('recursive_deletes') != 'disabled');
356: }
357:
358: 359: 360: 361: 362: 363: 364: 365: 366:
367: static public function deleteFile($dir, $name)
368: {
369: if (!self::verifyDir($dir)) {
370: throw new Gollem_Exception(sprintf(_("Access denied to folder \"%s\"."), $dir));
371: }
372: $GLOBALS['injector']
373: ->getInstance('Gollem_Vfs')
374: ->deleteFile($dir, $name);
375: }
376:
377: 378: 379: 380: 381: 382: 383: 384: 385: 386:
387: static public function changePermissions($dir, $name, $permission)
388: {
389: if (!self::verifyDir($dir)) {
390: throw new Gollem_Exception(sprintf(_("Access denied to folder \"%s\"."), $dir));
391: }
392: $GLOBALS['injector']
393: ->getInstance('Gollem_Vfs')
394: ->changePermissions($dir, $name, $permission);
395: }
396:
397: 398: 399: 400: 401: 402: 403: 404: 405:
406: static public function writeFile($dir, $name, $filename)
407: {
408: $gollem_vfs = $GLOBALS['injector']->getInstance('Gollem_Vfs');
409: $gollem_vfs->write($dir, $name, $filename, true);
410: if (!empty(self::$backend['params']['permissions'])) {
411: $gollem_vfs->changePermissions($dir, $name, self::$backend['params']['permissions']);
412: }
413: }
414:
415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425:
426: static public function moveFile($backend_f, $dir, $name, $backend_t,
427: $newdir)
428: {
429: self::_copyFile('move', $backend_f, $dir, $name, $backend_t, $newdir);
430: }
431:
432: 433: 434: 435: 436: 437: 438: 439: 440: 441: 442:
443: static public function copyFile($backend_f, $dir, $name, $backend_t,
444: $newdir)
445: {
446: self::_copyFile('copy', $backend_f, $dir, $name, $backend_t, $newdir);
447: }
448:
449: 450: 451: 452: 453:
454: static protected function _copyFile($mode, $backend_f, $dir, $name,
455: $backend_t, $newdir)
456: {
457: $backend_key = $GLOBALS['session']->get('gollem', 'backend_key');
458:
459: 460:
461: if ($backend_f == $backend_t) {
462: $ob = $GLOBALS['injector']->getInstance('Gollem_Factory_Vfs')->create($backend_f);
463: if ($backend_f != $backend_key) {
464: $ob->checkCredentials();
465: }
466: return $mode == 'copy'
467: ? $ob->copy($dir, $name, $newdir)
468: : $ob->move($dir, $name, $newdir);
469: }
470:
471:
472: $from_be = $GLOBALS['injector']->getInstance('Gollem_Factory_Vfs')->create($backend_f);
473: if ($backend_f != $backend_key) {
474: $from_be->checkCredentials();
475: }
476:
477: $to_be = $GLOBALS['injector']->getInstance('Gollem_Factory_Vfs')->create($backend_t);
478: if ($backend_t != $backend_key) {
479: $to_be->checkCredentials();
480: }
481:
482:
483: $data = $from_be->read($dir, $name);
484:
485:
486: $to_be->writeData($newdir, $name, $data);
487:
488:
489: if ($mode == 'move') {
490: $from_be->deleteFile($dir, $name);
491: }
492: }
493:
494: 495: 496: 497: 498: 499: 500:
501: static public function verifyDir($dir)
502: {
503: return Horde_String::substr(Horde_Util::realPath($dir), 0, Horde_String::length(self::$backend['root'])) == self::$backend['root'];
504: }
505:
506: 507: 508: 509: 510: 511: 512: 513: 514: 515: 516:
517: static public function checkPermissions($filter,
518: $permission = Horde_Perms::READ,
519: $backend = null)
520: {
521: $userID = $GLOBALS['registry']->getAuth();
522: if (is_null($backend)) {
523: $backend = $GLOBALS['session']->get('gollem', 'backend_key');
524: }
525:
526: switch ($filter) {
527: case 'backend':
528: $backendTag = 'gollem:backends:' . $backend;
529: return (!$GLOBALS['injector']->getInstance('Horde_Perms')->exists($backendTag) ||
530: $GLOBALS['injector']->getInstance('Horde_Perms')->hasPermission($backendTag, $userID, $permission));
531: }
532:
533: return false;
534: }
535:
536: 537: 538: 539: 540: 541: 542: 543:
544: static public function directoryNavLink($currdir, $url)
545: {
546: $label = array();
547: $root_dir_name = self::$backend['name'];
548:
549: if ($currdir == $root_dir_name) {
550: $label[] = '[' . $root_dir_name . ']';
551: } else {
552: $parts = explode('/', $currdir);
553: $parts_count = count($parts);
554:
555: $url = new Horde_Url($url);
556: $label[] = Horde::link($url->add('dir', self::$backend['root']), sprintf(_("Up to %s"), $root_dir_name)) . '[' . $root_dir_name . ']</a>';
557:
558: for ($i = 1; $i <= $parts_count; ++$i) {
559: $part = array_slice($parts, 0, $i);
560: $dir = implode('/', $part);
561: if ((strstr($dir, self::$backend['root']) !== false) &&
562: (self::$backend['root'] != $dir)) {
563: if ($i == $parts_count) {
564: $label[] = $parts[($i - 1)];
565: } else {
566: $label[] = Horde::link($url->add('dir', $dir), sprintf(_("Up to %s"), $dir)) . $parts[($i - 1)] . '</a>';
567: }
568: }
569: }
570: }
571:
572: return implode('/', $label);
573: }
574:
575: 576: 577: 578: 579:
580: static public function ()
581: {
582: $t = $GLOBALS['injector']->createInstance('Horde_Template');
583:
584: $t->set('login_url', Horde::getServiceLink('login', 'horde'));
585: $t->set('forminput', Horde_Util::formInput());
586: $t->set('hidden', array(array('key' => 'url', 'value' => (string)Horde::url('manager.php', true)),
587: array('key' => 'app', 'value' => 'gollem')));
588: $t->set('be_select', self::backendSelect(), true);
589: if ($t->get('be_select')) {
590: $t->set('accesskey', $GLOBALS['prefs']->getValue('widget_accesskey') ? Horde::getAccessKey(_("_Change Server")) : '');
591: $menu_view = $GLOBALS['prefs']->getValue('menu_view');
592: $link = Horde::link('#', _("Change Server"), '', '', 'serverSubmit(true);return false;');
593: $t->set('slink', sprintf('<ul><li>%s%s<br />%s</a></li></ul>', $link, ($menu_view != 'text') ? Horde::img('gollem.png') : '', ($menu_view != 'icon') ? Horde::highlightAccessKey(_("_Change Server"), $t->get('accesskey')) : ''));
594: }
595: $t->set('menu_string', Horde::menu(array('menu_ob' => true))->render());
596:
597: $menu = $t->fetch(GOLLEM_TEMPLATES . '/menu.html');
598:
599: 600:
601: Horde::startBuffer();
602: require HORDE_BASE . '/services/sidebar.php';
603: return $menu .= Horde::endBuffer();
604: }
605:
606: 607: 608:
609: static public function status()
610: {
611: $GLOBALS['notification']->notify(array('listeners' => 'status'));
612: }
613:
614: 615: 616: 617: 618:
619: static public function backendSelect()
620: {
621: $backends = Gollem_Auth::getBackend();
622: $backend = Gollem_Auth::getPreferredBackend();
623: $text = '';
624:
625: if ($GLOBALS['conf']['backend']['backend_list'] == 'shown' &&
626: count($backends) > 1) {
627: foreach ($backends as $key => $val) {
628: $sel = ($backend == $key) ? ' selected="selected"' : '';
629: $text .= sprintf('<option value="%s"%s>%s</option>%s',
630: empty($sel) ? $key : '',
631: $sel,
632: $val['name'],
633: "\n");
634: }
635: }
636:
637: return $text;
638: }
639:
640: 641: 642: 643: 644: 645: 646: 647:
648: static public function getDisplayPath($path)
649: {
650: $path = Horde_Util::realPath($path);
651: if (self::$backend['root'] != '/' &&
652: strpos($path, self::$backend['root']) === 0) {
653: $path = substr($path, Horde_String::length(self::$backend['root']));
654: }
655: return $path;
656: }
657:
658: 659: 660: 661: 662: 663: 664: 665: 666: 667: 668: 669: 670:
671: static public function stripAPIPath($path)
672: {
673:
674: if (substr($path, 0, 1) == '/') {
675: $path = substr($path, 1);
676: }
677:
678: if (substr($path, 0, 6) == 'gollem') {
679: $path = substr($path, 6);
680: }
681:
682: if (substr($path, 0, 1) == '/') {
683: $path = substr($path, 1);
684: }
685:
686: if (substr($path, -1) == '/') {
687: $path = substr($path, 0, -1);
688: }
689: return $path;
690: }
691:
692: 693: 694: 695: 696: 697: 698: 699: 700:
701: static public function pathEncode($path)
702: {
703: return str_ireplace(array('%2F', '%2f'), '/', rawurlencode($path));
704: }
705:
706: 707: 708: 709: 710: 711: 712: 713:
714: static public function getVFSPath($fullpath)
715: {
716:
717: $i = strrpos($fullpath, '/');
718: if ($i !== false) {
719: $path = substr($fullpath, 0, $i);
720: $name = substr($fullpath, $i + 1);
721: } else {
722: $name = $fullpath;
723: $path = '';
724: }
725: return array($name, $path);
726: }
727: }
728: