Overview

Packages

  • Luxor
  • None

Classes

  • Luxor
  • Luxor_Driver
  • Luxor_Driver_sql
  • Luxor_Files
  • Luxor_Files_plain
  • Luxor_Lang
  • Luxor_Lang_Generic
  • Luxor_SimpleParse
  • Luxor_Tagger
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * @author  Jan Schneider <jan@horde.org>
  4:  * @since   Luxor 0.1
  5:  * @package Luxor
  6:  */
  7: class Luxor
  8: {
  9:     /**
 10:      * Initial app setup code.
 11:      */
 12:     public static function initialize()
 13:     {
 14:         global $sources, $sourceid, $source, $files, $index, $pathname;
 15: 
 16:         require LUXOR_BASE . '/config/backends.php';
 17: 
 18:         /* Default to the first source; overridden elsewhere if necessary. */
 19:         $sourceid = Horde_Util::getFormData('source');
 20:         if (!isset($sources[$sourceid])) {
 21:             $sourceid = key($sources);
 22:         }
 23:         $source = $sources[$sourceid];
 24:         $files = Luxor_Files::factory($source['driver'], $source);
 25:         $index = Luxor_Driver::factory($sourceid);
 26:         $pathname = Luxor::fixPaths(Horde_Util::getFormData('f'));
 27:     }
 28: 
 29:     /**
 30:      * Generate a URL that links into Luxor.
 31:      *
 32:      * @param string $uri     The path being browsed.
 33:      * @param array  $args    Key/value pair of any GET parameters to append
 34:      * @param string $anchor  Anchor entity name
 35:      */
 36:     function url($uri = '', $args = array(), $anchor = '')
 37:     {
 38:         global $conf, $sourceid;
 39: 
 40:         $arglist = array_merge(array('source' => $sourceid), $args);
 41: 
 42:         if ($conf['options']['urls'] == 'rewrite') {
 43:             if (substr($uri, 0, 1) == '/') {
 44:                 $uri = substr($uri, 1);
 45:             }
 46:         } else {
 47:             $arglist['f'] = $uri;
 48:             $uri = 'source.php';
 49:         }
 50: 
 51:         $url = Horde_Util::addParameter(Horde::url($uri), $arglist);
 52:         if (!empty($anchor)) {
 53:             $url .= "#$anchor";
 54:         }
 55: 
 56:         return $url;
 57:     }
 58: 
 59:     /**
 60:      * Generate a list of sources available from this installation
 61:      * of Luxor.
 62:      *
 63:      * @return XHTML code representing links to the repositories
 64:      */
 65:     function sources()
 66:     {
 67:         global $source, $sources;
 68: 
 69:         $arr = array();
 70:         foreach ($sources as $key => $val) {
 71:             if ($val != $source) {
 72:                 $arr[] = Horde::link(Luxor::url('', array('source' => $key))) .
 73:                     htmlspecialchars($val['name']) . '</a>';
 74:             }
 75:         }
 76: 
 77:         if (count($arr)) {
 78:             return _("Other Sources") . ': ' . implode(', ', $arr);
 79:         } else {
 80:             return '';
 81:         }
 82:     }
 83: 
 84:     /**
 85:      * Sanitizes path names passed by the user.
 86:      *
 87:      * @param string $node  The path name to clean up.
 88:      *
 89:      * @return string       The cleaned up path.
 90:      */
 91:     function fixPaths($node)
 92:     {
 93:         global $files;
 94: 
 95:         $node = '/' . $node;
 96:         $node = preg_replace('|/[^/]+/\.\./|', '/', $node);
 97:         $node = preg_replace('|/\.\./|', '/', $node);
 98:         if ($files->isDir($node)) {
 99:             $node .= '/';
100:         }
101: 
102:         return preg_replace('|//+|', '/', $node);
103:     }
104: 
105:     /**
106:      *
107:      */
108:     function outfun($str, $arr)
109:     {
110:         return str_replace("\n", "\n" . array_shift($arr), $str);
111:     }
112: 
113:     function dirExpand($dir)
114:     {
115:         global $files, $mime_drivers, $mime_drivers_map;
116: 
117:         $result = Horde::loadConfiguration('mime_drivers.php', array('mime_drivers', 'mime_drivers_map'), 'horde');
118:         extract($result);
119:         $result = Horde::loadConfiguration('mime_drivers.php', array('mime_drivers', 'mime_drivers_map'), 'luxor');
120:         if (isset($result['mime_drivers'])) {
121:             $mime_drivers = Horde_Array::replaceRecursive($mime_drivers, $result['mime_drivers']);
122:         }
123:         if (isset($result['mime_drivers_map'])) {
124:             $mime_drivers_map = Horde_Array::replaceRecursive($mime_drivers_map, $result['mime_drivers_map']);
125:         }
126: 
127:         $nodes = $files->getDir($dir);
128:         if (is_a($nodes, 'PEAR_Error')) {
129:             return $nodes;
130:         }
131:         $index = $files->getIndex($dir);
132:         if (is_a($index, 'PEAR_Error')) {
133:             return $index;
134:         }
135: 
136:         if ($dir != '/') {
137:             array_unshift($nodes, '../');
138:         }
139: 
140:         $list = array();
141:         foreach ($nodes as $node) {
142:             $link = Luxor::url($dir . $node);
143:             $modtime = $files->getFiletime($dir . $node);
144:             $modtime = $modtime ? gmdate('Y-m-d H:i:s', $modtime) : '-';
145:             $description = empty($index[$node]) ? '&nbsp;' : $index[$node];
146: 
147:             if (substr($node, -1) == '/') {
148:                 $filesize = '-';
149:                 $bytes = '';
150:                 if ($node == '../') {
151:                     $icon = Horde::img('parent.png', _("Up to parent"));
152:                     $node = _("Parent Directory");
153:                 } else {
154:                     $icon = Horde::img('folder.png', $node);
155:                 }
156:             } else {
157:                 if (preg_match('/^.*\.[oa]$|^core$|^00-INDEX$/', $node)) {
158:                     continue;
159:                 }
160:                 $icon = Horde::img($GLOBALS['injector']->getInstance('Horde_Core_Factory_MimeViewer')->getIcon(Horde_Mime_Magic::filenameToMime($node)), '', '', '');
161:                 $filesize = $files->getFilesize($dir . $node);
162:                 if ($filesize < 1 << 10) {
163:                     $bytes = _("bytes");
164:                 } else {
165:                     $bytes = _("kbytes");
166:                     $filesize = $filesize >> 10;
167:                 }
168:             }
169: 
170:             $list[] = array('icon'        => $icon,
171:                             'name'        => $node,
172:                             'link'        => $link,
173:                             'filesize'    => $filesize,
174:                             'bytes'       => $bytes,
175:                             'modtime'     => $modtime,
176:                             'description' => $description);
177:         }
178: 
179:         return $list;
180:     }
181: 
182:     /**
183:      * Prints a descriptive blurb at the end of directory listings.
184:      *
185:      * @param Luxor_File $files  An instance of Luxor_File.
186:      * @param string $path       The directory where to look for a README file.
187:      */
188:     function dirDesc($files, $path)
189:     {
190:         $table_head = '<br /><br /><table width="100%" cellpadding="5"><tr><td class="text"><span class="fixed">';
191:         $table_foot = '</span></td></tr></table>';
192:         if (file_exists($filename = $files->toReal($path . '/README')) ||
193:             file_exists($filename = $files->toReal($path . '/README.txt'))) {
194:             $contents = file_get_contents($filename);
195: 
196:             return $table_head . $GLOBALS['injector']->getInstance('Horde_Core_Factory_TextFilter')->filter($contents, 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO)) . $table_foot;
197:         } elseif ($filename = file_exists($files->toReal($path . '/README.html'))) {
198:             global $mime_drivers, $mime_drivers_map;
199:             $result = Horde::loadConfiguration('mime_drivers.php', array('mime_drivers', 'mime_drivers_map'), 'horde');
200:             extract($result);
201:             $result = Horde::loadConfiguration('mime_drivers.php', array('mime_drivers', 'mime_drivers_map'), 'luxor');
202:             $mime_drivers = Horde_Array::replaceRecursive($mime_drivers, $result['mime_drivers']);
203:             $mime_drivers_map = Horde_Array::replaceRecursive($mime_drivers_map, $result['mime_drivers_map']);
204: 
205:             $contents = file_get_contents($filename);
206: 
207:             $mime_part = new Horde_Mime_Part('text/plain', $contents);
208:             $mime_part->setName('README');
209: 
210:             return $table_head .
211:                 $GLOBALS['injector']->getInstance('Horde_Core_Factory_MimeViewer')->create($mime_part)->render() .
212:                 $table_foot;
213:         }
214:     }
215: 
216:     /**
217:      * Smaller version of the markupFile() function meant for marking up
218:      * the descriptions in source directory listings.
219:      *
220:      * @see markupFile()
221:      *
222:      * @todo most of this can be done by Horde_Text::toHtml()
223:      */
224:     function markupString($string, $virtp)
225:     {
226:         $string = htmlspecialchars($string);
227: 
228:         // HTMLify email addresses and urls.
229:         $string = preg_replace('#((ftp|http|nntp|snews|news)://(\w|\w\.\w|\~|\-|\/|\#)+(?!\.\b))#',
230:                                '<a href="$1">$1</a>', $string);
231: 
232:         // HTMLify file names, assuming file is in the current directory.
233:         $string = preg_replace('#\b(([\w\-_\/]+\.(c|h|cc|cp|hpp|cpp|java))|README)\b#e',
234:                                '"<a href=\" . Luxor::url("' . $virtp . '$1") . "$1</a>"', $string);
235: 
236:         return $string;
237:     }
238: 
239:     function whereMenu()
240:     {
241:         global $pathname;
242: 
243:         $res = '';
244:         $wherePath = '';
245:         foreach (explode('/', $pathname) as $dir) {
246:             $wherePath .= $dir ? "/$dir" : '';
247:             if (!empty($dir)) {
248:                 $res .= ' :: ' . Horde::link(Luxor::url($wherePath)) .
249:                     htmlspecialchars($dir) . '</a>';
250:             }
251:         }
252:         return $res;
253:     }
254: 
255:     function fileRef($desc, $css, $path, $line = 0, $args = array())
256:     {
257:         if ($line > 0 && strlen($line) < 3) {
258:             $line = str_repeat('0', (3 - strlen($line))) . $line;
259:         }
260: 
261:         return '<a href="' . Luxor::url($path, $args, $line > 0 ? 'l' . $line : '') . '" class="' . htmlspecialchars($css) . '">' .
262:             htmlspecialchars($desc) . '</a>';
263:     }
264: 
265:     function incRef($name, $css, $file, $paths = array())
266:     {
267:         global $files;
268: 
269:         foreach ($paths as $dir) {
270:             $dir = preg_replace('|/+$|', '', $dir);
271:             $path = $dir . '/' . $file;
272:             if ($files->isFile($path)) {
273:                 return Luxor::fileRef($name, $css, $path);
274:             }
275:         }
276: 
277:         return htmlspecialchars($name);
278:     }
279: 
280:     /**
281:      * Check if the given item is restricted from being shown.
282:      *
283:      * @param string $filename  The filename to check
284:      *
285:      * @return boolean  Whether or not the item is allowed to be displayed
286:      */
287:     function isRestricted($filename)
288:     {
289:         global $source;
290: 
291:         if ($GLOBALS['registry']->isAdmin()) {
292:             return false;
293:         }
294: 
295:         if (isset($source['restrictions']) && is_array($source['restrictions'])) {
296:             foreach ($source['restrictions'] as $restriction) {
297:                 if (preg_match('|' . str_replace('|', '\|', $restriction) . '|', $filename)) {
298:                     return true;
299:                 }
300:             }
301:         }
302: 
303:         return false;
304:     }
305: 
306:     /**
307:      * Check if the given directory is filtered out.
308:      *
309:      * @param string $dir  The path to check.
310:      *
311:      * @return boolean  True if the directory should be shown/parsed, false otherwise.
312:      */
313:     function isDirParsed($dir)
314:     {
315:         global $source;
316: 
317:         if (isset($source['dirFilter']) && is_array($source['dirFilter'])) {
318:             foreach ($source['dirFilter'] as $filter) {
319:                 if (preg_match('/' . str_replace('/', '\/', substr($filter, 1)) . '/', $dir)) {
320:                     return (substr($filter, 0, 1) == '+');
321:                 }
322:             }
323:         }
324: 
325:         if (isset($source['dirUnmatched'])) {
326:             return $source['dirUnmatched'];
327:         }
328:         return true;
329:     }
330: 
331:     /**
332:      * Check if the given file should be parsed an/or displayed.
333:      *
334:      * @param string $file  The filename to check.
335:      *
336:      * @return boolean  True if the file should be shown/parsed, false otherwise.
337:      */
338:     function isFileParsed($file)
339:     {
340:         global $source;
341: 
342:         if (isset($source['fileFilter']) && is_array($source['fileFilter'])) {
343:             foreach ($source['fileFilter'] as $filter) {
344:                 if (preg_match('/' . str_replace('/', '\/', substr($filter, 1)) . '/', $file, $matches)) {
345:                     return (substr($filter, 0, 1) == '+');
346:                 }
347:             }
348:         }
349: 
350:         if (isset($source['fileUnmatched'])) {
351:             return $source['fileUnmatched'];
352:         }
353:         return true;
354:     }
355: 
356:     /**
357:      * Pre- and post-fix every line of a string with strings.
358:      */
359:     function fixString($string, $pre = '', $post = '')
360:     {
361:         $lines = preg_split('(\r\n|\n|\r)', $string);
362:         $res = '';
363:         foreach ($lines as $line) {
364:             $res .= !empty($res) ? "\n" : '';
365:             $res .= $pre . $GLOBALS['injector']->getInstance('Horde_Core_Factory_TextFilter')->filter($line, 'space2html', array('encode' => true, 'encode_all' => true)) . $post;
366:         }
367:         return $res;
368:     }
369: 
370:     /**
371:      */
372:     function markupfile($pathname, $fileh, $ann = array())
373:     {
374:         global $files, $conf;
375: 
376:         preg_match_all('|^(.*/)|', $pathname, $dir);
377:         $dir = $dir[0];
378: 
379:         /* Determine the file's language and create a Luxor_Lang
380:          * instance. */
381:         $lang = &Luxor_Lang::builder($files, $pathname);
382:         if (is_a($lang, 'PEAR_Error')) {
383:             return $lang;
384:         }
385: 
386:         $html = '<table cellspacing="0" width="100%" class="text">';
387: 
388:         // A source code file.
389:         if (!$lang) {
390:             return false;
391:         }
392: 
393:         $parser = new Luxor_SimpleParse($fileh, 1, $lang->_langmap['spec']);
394:         $linenum = 1;
395: 
396:         list($btype, $frag) = $parser->nextFrag();
397:         $ofrag = '';
398:         while ($frag) {
399:             $frag = preg_replace('/([&<>])/', chr(0) . '$1', $frag);
400:             switch ($btype) {
401:             case 'comment':
402:                 // Comment
403:                 // Convert mail adresses to mailto:
404:                 // &freetextmarkup($frag);
405:                 // $lang->processComment(\$frag);
406:                 $frag = Luxor::fixString($frag, '<span class="comment">', '</span>');
407:                 break;
408: 
409:             case 'string':
410:                 $frag = Luxor::fixString($frag, '<span class="string">', '</span>');
411:                 break;
412: 
413:             case 'include':
414:                 // Include directive
415:                 $frag = $lang->processInclude($frag, $dir);
416:                 break;
417: 
418:             case 'variable':
419:                 if (!empty($conf['options']['use_show_var'])) {
420:                     $pre = sprintf('<span class="variable"><span class="var_%s" onmouseover="show_var(\'var_%s\');" onmouseout="unshow_var(\'var_%s\');">', substr($frag, 1), substr($frag, 1), substr($frag, 1));
421:                     $frag = Luxor::fixString($frag, $pre, '</span></span>');
422:                 } else {
423:                     $frag = Luxor::fixString($frag, '<span class="variable">', '</span>');
424:                 }
425:                 break;
426: 
427:             default:
428:                 // Code
429:                 // somehow get $source['may_reference'] into the second parameter here.
430:                 $frag = $lang->processCode($frag);
431:             }
432: 
433:             $frag = preg_replace('/\0([&<>])/', '$1', $frag);
434: 
435:             $ofrag .= $frag;
436:             list($btype, $frag) = $parser->nextFrag();
437:         }
438: 
439:         $lines = preg_split('(\r\n|\n|\r)', $ofrag);
440:         foreach ($lines as $line) {
441:             $html .= '<tr><td align="right" style="padding-left:10px; padding-right:10px;"><a id="l' . $linenum . '" class="fixed" style="color:black">' . $linenum++ . '</a></td><td width="100%" class="fixed">' . $line . "</td></tr>\n";
442:         }
443:         return $html . '</table>';
444:     }
445: 
446:     /**
447:      * Build Luxor's list of menu items.
448:      */
449:     function getMenu($returnType = 'object')
450:     {
451:         global $registry;
452: 
453:         $menu = new Horde_Menu(Horde_Menu::MASK_ALL);
454:         $menu->add(Horde::url('source.php'), _("_Browse"), 'luxor.png');
455: 
456:         if ($returnType == 'object') {
457:             return $menu;
458:         } else {
459:             return $menu->render();
460:         }
461:     }
462: }
463: 
API documentation generated by ApiGen