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: