First try converting Luxor to H4-git
authorChuck Hagenbuch <chuck@bluestatedigital.com>
Sat, 24 Apr 2010 16:00:04 +0000 (12:00 -0400)
committerChuck Hagenbuch <chuck@bluestatedigital.com>
Sat, 24 Apr 2010 16:00:45 +0000 (12:00 -0400)
52 files changed:
luxor/.htaccess [new file with mode: 0644]
luxor/COPYING [new file with mode: 0644]
luxor/README [new file with mode: 0644]
luxor/bin/.htaccess [new file with mode: 0644]
luxor/bin/indexer [new file with mode: 0755]
luxor/config/.htaccess [new file with mode: 0644]
luxor/config/conf.xml [new file with mode: 0644]
luxor/config/languages.php.dist [new file with mode: 0644]
luxor/config/mime_drivers.php.dist [new file with mode: 0644]
luxor/config/sources.php.dist [new file with mode: 0644]
luxor/docs/CHANGES [new file with mode: 0644]
luxor/docs/CREDITS [new file with mode: 0644]
luxor/docs/INSTALL [new file with mode: 0644]
luxor/docs/TODO [new file with mode: 0644]
luxor/index.php [new file with mode: 0644]
luxor/js/show_var.js [new file with mode: 0644]
luxor/lib/.htaccess [new file with mode: 0644]
luxor/lib/Application.php [new file with mode: 0644]
luxor/lib/Driver.php [new file with mode: 0644]
luxor/lib/Driver/sql.php [new file with mode: 0644]
luxor/lib/Files.php [new file with mode: 0644]
luxor/lib/Files/plain.php [new file with mode: 0644]
luxor/lib/Lang.php [new file with mode: 0644]
luxor/lib/Lang/Generic.php [new file with mode: 0644]
luxor/lib/Luxor.php [new file with mode: 0644]
luxor/lib/SimpleParse.php [new file with mode: 0644]
luxor/lib/Tagger.php [new file with mode: 0644]
luxor/locale/de_DE/LC_MESSAGES/luxor.mo [new file with mode: 0644]
luxor/locale/es_ES/LC_MESSAGES/luxor.mo [new file with mode: 0644]
luxor/locale/ro_RO/LC_MESSAGES/luxor.mo [new file with mode: 0644]
luxor/po/.htaccess [new file with mode: 0644]
luxor/po/README [new file with mode: 0644]
luxor/po/de_DE.po [new file with mode: 0644]
luxor/po/es_ES.po [new file with mode: 0644]
luxor/po/luxor.pot [new file with mode: 0644]
luxor/po/ro_RO.po [new file with mode: 0644]
luxor/scripts/.htaccess [new file with mode: 0644]
luxor/scripts/sql/luxor.sql [new file with mode: 0644]
luxor/search.php [new file with mode: 0644]
luxor/source.php [new file with mode: 0644]
luxor/symbol.php [new file with mode: 0644]
luxor/templates/.htaccess [new file with mode: 0644]
luxor/templates/common-header.inc [new file with mode: 0644]
luxor/templates/directory.html.php [new file with mode: 0644]
luxor/templates/headerbar.inc [new file with mode: 0644]
luxor/templates/menu.inc [new file with mode: 0644]
luxor/templates/symbol.html.php [new file with mode: 0644]
luxor/themes/graphics/favicon.ico [new file with mode: 0644]
luxor/themes/graphics/folder.png [new file with mode: 0644]
luxor/themes/graphics/luxor.png [new file with mode: 0644]
luxor/themes/graphics/parent.png [new file with mode: 0644]
luxor/themes/screen.css [new file with mode: 0644]

diff --git a/luxor/.htaccess b/luxor/.htaccess
new file mode 100644 (file)
index 0000000..140e65f
--- /dev/null
@@ -0,0 +1,6 @@
+<IfModule mod_rewrite.c>
+       RewriteEngine On
+       RewriteCond   %{REQUEST_FILENAME}  !-d
+       RewriteCond   %{REQUEST_FILENAME}  !-f
+       RewriteRule   ^(.*)$ source.php?f=$1 [QSA]
+</IfModule>
diff --git a/luxor/COPYING b/luxor/COPYING
new file mode 100644 (file)
index 0000000..a6b6756
--- /dev/null
@@ -0,0 +1,280 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
diff --git a/luxor/README b/luxor/README
new file mode 100644 (file)
index 0000000..7de305c
--- /dev/null
@@ -0,0 +1,11 @@
+Luxor
+Version 0.1
+
+What is Luxor?
+-----------------
+
+Luxor is a port of LXR to PHP, integrated into the Horde framework.
+You can find LXR at http://sourceforge.net/projects/lxr
+
+This software is OSI Certified Open Source Software.
+OSI Certified is a certification mark of the Open Source Initiative.
diff --git a/luxor/bin/.htaccess b/luxor/bin/.htaccess
new file mode 100644 (file)
index 0000000..3a42882
--- /dev/null
@@ -0,0 +1 @@
+Deny from all
diff --git a/luxor/bin/indexer b/luxor/bin/indexer
new file mode 100755 (executable)
index 0000000..81c5364
--- /dev/null
@@ -0,0 +1,149 @@
+#!/usr/bin/env php
+<?php
+/**
+ * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.horde.org/licenses/gpl.php.
+ *
+ * @author Jan Schneider <jan@horde.org>
+ */
+
+require_once dirname(__FILE__) . '/../lib/Application.php';
+Horde_Registry::appInit('luxor');
+
+// Make sure no one runs this from the web.
+if (!Horde_Cli::runningFromCLI()) {
+    exit("Must be run from the command line\n");
+}
+
+// Load the CLI environment - make sure there's no time limit, init
+// some variables, etc.
+$cli = Horde_Cli::init();
+
+// Now go ahead and load Luxor.
+$session_control = 'none';
+@define('AUTH_HANDLER', true);
+
+$p = new Horde_Argv_Parser(array('optionList' => array(
+    new Horde_Argv_Option('-q', '--quiet', array('action' => 'store_true', 'help' => 'No output except errors')),
+    new Horde_Argv_Option('-v', '--verbose', array('action' => 'store_true', 'help' => 'Debug-level output')),
+)));
+list($values, $args) = $p->parseArgs();
+
+if ($values->quiet && $values->verbose) {
+    $cli->fatal(_("Can't be both verbose and quiet"));
+}
+/*@TODO replace with a Horde_Log command-line logger? */
+define('VERBOSE', $values->verbose);
+define('QUIET', $values->quiet);
+
+$first = true;
+$skipped = array();
+foreach ($sources as $sourceid => $source) {
+    if ($args && !in_array($sourceid, $args)) {
+        continue;
+    }
+    $index = Luxor_Driver::factory($sourceid);
+    $files = Luxor_Files::factory($source['driver'], $source);
+
+    // Clear old data out of the database.
+    if ($first) {
+        $index->clearIndex();
+        $first = false;
+    }
+
+    // Index files.
+    if (!QUIET) $cli->writeln($cli->bold(sprintf(_("Indexing %s"), $source['name'])));
+    genindex($files, '/');
+    if (!QUIET) $cli->writeln();
+
+    // Reference files.
+    if (!QUIET) $cli->writeln($cli->bold(sprintf(_("Referencing %s"), $source['name'])));
+    genrefs($files, '/');
+    gensearch();
+    if (!QUIET) $cli->writeln();
+}
+
+if (VERBOSE) {
+    $cli->writeln($cli->yellow(_("Skipped files:")));
+    ksort($skipped);
+    foreach (array_keys($skipped) as $file) {
+        $cli->writeln('  ' . $file);
+    }
+}
+
+if (!QUIET) $cli->writeln($cli->green(_("DONE")));
+exit(0);
+
+
+/**
+ * Functions.
+ */
+function genindex($files, $path)
+{
+    global $cli, $skipped;
+
+    if (VERBOSE) $cli->writeln("*** $path");
+    if (substr($path, -1, 1) == '/') {
+        $dirs = $files->getDir($path);
+        if (is_a($dirs, 'PEAR_Error')) {
+            $cli->writeln($cli->red($dirs->getMessage()));
+            return;
+        }
+        foreach ($dirs as $dir) {
+            genindex($files, $path . $dir);
+        }
+    } else {
+        $lang = Luxor_Lang::builder($files, $path);
+        if ($lang === false) {
+            $skipped[$path] = true;
+            return;
+        } elseif (is_a($lang, 'PEAR_Error')) {
+            $cli->writeln($cli->red($lang->getMessage()));
+            return;
+        }
+
+        $result = Luxor_Tagger::processFile($files, $path, $lang);
+        if (is_a($result, 'PEAR_Error')) {
+            $cli->writeln($cli->red($result->getMessage()));
+            return;
+        }
+    }
+}
+
+function genrefs($files, $path)
+{
+    global $cli, $skipped;
+
+    if (VERBOSE) $cli->writeln("### $path");
+    if (substr($path, -1, 1) == '/') {
+        $dirs = $files->getDir($path);
+        if (is_a($dirs, 'PEAR_Error')) {
+            $cli->writeln($cli->red($dirs->getMessage()));
+            return;
+        }
+        foreach ($dirs as $dir) {
+            genrefs($files, $path . $dir);
+        }
+    } else {
+        $lang = Luxor_Lang::builder($files, $path);
+        if ($lang === false) {
+            $skipped[$path] = true;
+            return;
+        } elseif (is_a($lang, 'PEAR_Error')) {
+            $cli->writeln($cli->red($lang->getMessage()));
+            return;
+        }
+
+        $result = Luxor_Tagger::processRefs($files, $path, $lang);
+        if (is_a($result, 'PEAR_Error')) {
+            $cli->writeln($cli->red($result->getMessage()));
+            return;
+        }
+    }
+}
+
+function gensearch()
+{
+}
diff --git a/luxor/config/.htaccess b/luxor/config/.htaccess
new file mode 100644 (file)
index 0000000..3a42882
--- /dev/null
@@ -0,0 +1 @@
+Deny from all
diff --git a/luxor/config/conf.xml b/luxor/config/conf.xml
new file mode 100644 (file)
index 0000000..049d120
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<!-- $Horde: luxor/config/conf.xml,v 1.14 2006/03/04 22:49:19 chuck Exp $ -->
+<configuration>
+ <configsection name="storage">
+  <configheader>Storage System Settings</configheader>
+
+  <configswitch name="driver" desc="What storage driver should we use?">sql
+   <case name="sql" desc="SQL">
+    <configsection name="params">
+     <configsql switchname="driverconfig"/>
+    </configsection>
+   </case>
+  </configswitch>
+ </configsection>
+
+ <configsection name="paths" desc="Paths">
+  <configheader>Paths</configheader>
+  <configstring name="ectags" desc="Location of Exuberant Ctags executable (ctags.sourceforge.net)">/usr/bin/ctags</configstring>
+ </configsection>
+
+ <configsection name="options" desc="Look and feel">
+  <configheader>Look and feel</configheader>
+
+  <configenum name="urls" desc="Does your web server support
+  mod_rewrite?  If so, we can generate &quot;pretty&quot; URLs. If
+  not, pathnames will be propagated using a GET variable instead.">get
+   <values>
+    <value desc="GET (will always work)">get</value>
+    <value desc="mod_rewrite (pretty, short URLs)">rewrite</value>
+   </values>
+  </configenum>
+  <configboolean name="use_show_var" desc="Should we enable highlighting of variables in source listings?">true</configboolean>
+ </configsection>
+
+ <configsection name="menu" desc="Menu settings">
+  <configheader>Menu Settings</configheader>
+  <configmultienum name="apps" desc="Select any applications that should be linked in Luxor's menu">
+   <values>
+    <configspecial name="list-horde-apps" />
+   </values>
+  </configmultienum>
+ </configsection>
+</configuration>
diff --git a/luxor/config/languages.php.dist b/luxor/config/languages.php.dist
new file mode 100644 (file)
index 0000000..1bd5a11
--- /dev/null
@@ -0,0 +1,286 @@
+<?php
+/**
+ * $Horde: luxor/config/languages.php.dist,v 1.11 2008/07/30 20:51:53 chuck Exp $
+ *
+ * This file contains all the configuration information for the various
+ * languages that are supported. Documentation is inline.
+ */
+$languages = array(
+
+    // Format is
+    // Language name, filepattern regexp, module to invoke, (optional) tabwidth
+    // Note that to have another language supported by Generic.php,
+    // you must ensure that:
+    // a) exuberant ctags supports it
+    // b) generic.conf is updated to specify information about the language
+    // c) the name of the language given here matches the entry in generic.conf
+    'filetype' => array(
+        'C'      => array('C', '\.c$', 'Generic', '8'),
+        'C++'    => array('C++', '\.C$|((?i)\.c\+\+$|\.cc$|\.cpp$|\.cxx$|\.h$|\.hh$|\.hpp$|\.hxx$|\.h\+\+$)',
+                          'Generic', '8'),
+        'Java'   => array('Java', '(?i)\.java$', 'Generic', '4'),
+         // No tabwidth specified here as an example
+        'Make'   => array('Make', '(?i)\.mak$|makefile*', 'Generic'),
+        'Perl'   => array('Perl', '(?i)\.pl$|\.pm$|\.cgi$|\.perl$', 'Generic', '4'),
+        'PHP'    => array('php', '(?i)\.php$|\.php3$|\.phtml|\.phpt|\.phput$', 'Generic', '2'),
+        'Python' => array('Python', '(?i)\.py$|\.python$', 'Generic', '4'),
+    ),
+
+    // Maps interpreter names to languages.  The format is:
+    //  regexp => langname
+    //   regexp is matched against the part after #! on the first line of a file
+    //   langname must match one of the keys in filetype above.
+    //
+    // This mapping is only used if the filename doesn't match a pattern above, so
+    // a shell script called shell.c will be recognised as a C file, not a shell file.
+    'interpreters' => array(
+        'perl'   => 'Perl',
+        'php'    => 'PHP',
+        'python' => 'Python'
+    ),
+
+    // How to map a language name to the ectags language-force name
+    // if there is no mapping, then the language name is used
+    'eclangnamemapping' => array(
+        'C'      => 'c',
+        'C++'    => 'c++',
+        'Python' => 'python'
+    ),
+
+    // Options to always feed to ectags
+    'ectagsopts' => '--c-types=+px --eiffel-types=+l --fortran-types=+L',
+
+    // lang map specifies info for each language
+    // what the reserved words & comment chars are
+    'langmap' => array(
+               'C' => array(
+                       'reserved' => array(
+                                      'auto', 'break', 'case', 'char', 'const',
+                                      'continue', 'default', 'do', 'double',
+                                      'else', 'enum', 'extern', 'float', 'for',
+                                      'goto', 'if', 'int', 'long', 'register',
+                                      'return', 'short', 'signed', 'sizeof',
+                                      'static', 'struct', 'switch', 'typedef',
+                                      'union', 'unsigned', 'void', 'volatile',
+                                      'while',
+                                     ),
+
+                       'spec' => array('atom',     '\\\\.',     '',
+                                  'comment',  '/\*',        '\*/',
+                                  'comment',  '//',         "\$",
+                                  'string',   '"',          '"',
+                                  'string',   "'",          "'",
+                                  'include',  '#\s*include',    "\$"),
+
+                       'typemap' => array(
+                                     'c' => 'class',
+                                     'd' => 'macro (un)definition',
+                                     'e' => 'enumerator',
+                                     'f' => 'function definition',
+                                     'g' => 'enumeration name',
+                                     'm' => 'class, struct, or union member',
+                                     'n' => 'namespace',
+                                     'p' => 'function prototype or declaration',
+                                     's' => 'structure name',
+                                     't' => 'typedef',
+                                     'u' => 'union name',
+                                     'v' => 'variable definition',
+                                     'x' => 'extern or forward variable declaration',
+                                     'i' => 'interface'),
+                       'langid' => '1',
+                      ),
+
+               'C++' => array(
+                         'reserved' => array('and', 'and_eq', 'asm', 'auto', 'bitand',
+                                        'bitor', 'bool', 'break', 'case', 'catch',
+                                        'char', 'class', 'const', 'const_cast',
+                                        'continue', 'default', 'delete', 'do',
+                                        'double', 'dynamic_cast', 'else', 'enum',
+                                        'explicit', 'export', 'extern', 'false',
+                                        'float', 'for', 'friend', 'goto', 'if',
+                                        'inline', 'int', 'long', 'mutable',
+                                        'namespace', 'new', 'not', 'not_eq',
+                                        'operator', 'or', 'or_eq', 'private',
+                                        'protected', 'public', 'register',
+                                        'reinterpret_cast', 'return', 'short',
+                                        'signed', 'sizeof', 'static',
+                                        'static_cast','struct', 'switch',
+                                        'template','this', 'throw', 'true','try',
+                                        'typedef', 'typeid','typename',
+                                        'union', 'unsigned','using',
+                                        'virtual', 'void','volatile',
+                                        'wchar_t', 'while','xor',
+                                        'xor_eq'),
+
+                         'spec' => array('atom',     '\\\\.',       '',
+                                  'comment',  '/\*',        '\*/',
+                                  'comment',  '//',         "\$",
+                                  'string',   '"',          '"',
+                                  'string',   "'",          "'",
+                                    'include',  '#\s*include',  "\$"),
+                       'typemap' => array(
+                                     'c' => 'class',
+                                     'd' => 'macro (un)definition',
+                                     'e' => 'enumerator',
+                                     'f' => 'function definition',
+                                     'g' => 'enumeration name',
+                                     'm' => 'class, struct, or union member',
+                                     'n' => 'namespace',
+                                     'p' => 'function prototype or declaration',
+                                     's' => 'structure name',
+                                     't' => 'typedef',
+                                     'u' => 'union name',
+                                     'v' => 'variable definition',
+                                     'x' => 'extern or forward variable declaration',
+                                     'i' => 'interface'),
+                         'langid' => '2',
+
+                        ),
+
+               'Java' => array(
+                          'reserved' => array('break', 'case', 'continue', 'default',
+                                         'do', 'else', 'for', 'goto', 'if',
+                                         'return', 'static', 'switch', 'void',
+                                         'volatile', 'while', 'public', 'class',
+                                         'final', 'private', 'protected',
+                                         'synchronized', 'package', 'import',
+                                         'boolean', 'byte', 'new', 'abstract',
+                                         'extends', 'implements', 'interface',
+                                         'throws', 'instanceof', 'super', 'this',
+                                         'native', 'null'),
+
+                          'spec' => array('atom',      '\\\\.', '',
+                                     'comment', '/\*',      '\*/',
+                                     'comment', '//',       "\$",
+                                     'string',  '"',        '"',
+                                     'string',  "'",        "'",
+                                     'include', 'import',   "\$",
+                                     'include', 'package', "\$"
+                                    ),
+                          'typemap' => array(
+                                        'c' => 'class',
+                                        'f' => 'field',
+                                        'i' => 'interface',
+                                        'm' => 'method',
+                                        'p' => 'package',
+                                       ),
+                          'langid' => '3',
+                         ),
+
+               'Fortran' => array(
+                             'reserved' => array(),
+                             'typemap' => array(
+                                           'b' => 'block data',
+                                           'c' => 'common block',
+                                           'e' => 'entry point',
+                                           'f' => 'function',
+                                           'i' => 'interface',
+                                           'k' => 'type component',
+                                           'l' => 'label',
+                                           'L' => 'local and common block variable',
+                                           'm' => 'module',
+                                           'n' => 'namelist',
+                                           'p' => 'program',
+                                          ),
+                             'langid' => '4',
+                            ),
+
+               'Pascal' => array(
+                            'reserved' => array(),
+                            'langid' => '5',
+                           ),
+
+               'COBOL' => array(
+                           'reserved' => array(),
+                           'langid' => '6',
+                          ),
+               'Perl' => array(
+                          'reserved' => array(
+                                         'sub',
+                                        ),
+                          'spec' => array('atom',       '\$\W?',    '',
+                                     'atom',        '\\\\.',    '',
+                                     'include', '\buse\s+', ';',
+                                     'include', '\brequire\s+', ';',
+                                     'string',  '"',        '"',
+                                     'comment', '#',        "\$",
+                                     'comment', "^=\\w+",   "^=cut",
+                                     'string',  "'",        "'"),
+                          'typemap' => array(
+                                        's' => 'subroutine',
+                                        'p' => 'package',
+                                       ),
+                          'langid' => '7',
+
+                         ),
+               'Python' => array(
+                            'reserved' => array('def','print','del','pass',
+                                           'break','continue','return',
+                                           'raise','import','from',
+                                           'global','exec','assert',
+                                           'if','elif','else','while',
+                                           'for','try','except','finally',
+                                           'class','as','import','or',
+                                           'and','is','in','for','if',
+                                           'not','lambda','self',
+                                          ),
+
+                            'spec' => array('comment',  '#',        "\$",
+                                       'string',    '"',        '"',
+                                       'string',    "'",        "'",
+                                       'atom',      '\\\\.',    ''),
+                            'typemap' => array(
+                                          'c' => 'class',
+                                          'f' => 'function',
+                                         ),
+                            'langid' => '8',
+                           ),
+               'php' => array(
+                         'reserved' => array('and','$argv','$argc','break','case','class',
+                                             'continue','default','do','die','echo','else',
+                                             'elseif','empty','endfor','endforeach','endif',
+                                             'endswitch','endwhile','E_ALL','E_PARSE','E_ERROR',
+                                             'E_WARNING','exit','extends','FALSE','for','foreach',
+                                             'function','HTTP_COOKIE_VARS','HTTP_GET_VARS',
+                                             'HTTP_POST_VARS','HTTP_POST_FILES','HTTP_ENV_VARS',
+                                             'HTTP_SERVER_VARS','GLOBALS','_FILES','_ENV','_REQUEST',
+                                             '_GET','_POST','_COOKIE','_SESSION','if','global','list',
+                                             'new','not','NULL','or','parent','PHP_OS','PHP_SELF',
+                                             'PHP_VERSION','print','return','static','switch','stdClass',
+                                             'this','TRUE','var','xor','virtual','while','__FILE__',
+                                             '__LINE__','__sleep','__wakeup', 'header', 'global',
+                                             'array', 'double', 'fclose', 'fopen', 'fputs', 'object',
+                                             'is_a', 'in_array', 'is_null', 'unset', 'true', 'false',
+                                             'null', 'define'
+                                             ),
+
+                         'spec' => array('comment',  '/\*',       '\*/',
+                                    'comment',  '//',            "\$",
+                                    'comment',  '#',             "\$",
+                                    'string',   '"',             '"',
+                                    'string',   "'",             "'",
+                                    'include',  'require_once[^[a-zA-Z0-9_\x7f-\xff]', ";",
+                                    'include',  'include_once[^[a-zA-Z0-9_\x7f-\xff]', ";",
+                                    'include',  'require[^[a-zA-Z0-9_\x7f-\xff]',      ";",
+                                    'include',  'include[^[a-zA-Z0-9_\x7f-\xff]',      ";",
+                                    'variable', '\$', '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*',
+                                   ),
+                         'typemap' => array(
+                                       'c' => 'class',
+                                       'f' => 'function',
+                                      ),
+                         'langid' => '9',
+                        ),
+               'Make' => array(
+                          'reserved' => array(),
+                          'spec' => array('comment',    '#',        "\$",
+                                     'string',  '"',        '"',
+                                     'string',  "'",        "'",
+                                     'include', '^ *-?include', '\$'),
+                          'typemap' => array(
+                                        'm' => 'macro',
+                                       ),
+                          'langid' => '10',
+                          ),
+              )
+);
diff --git a/luxor/config/mime_drivers.php.dist b/luxor/config/mime_drivers.php.dist
new file mode 100644 (file)
index 0000000..6d35191
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+// $Horde: luxor/config/mime_drivers.php.dist,v 1.2 2003/01/30 10:40:23 mikec Exp $
+
+/**
+ * Decide which output drivers you want to activate for the Luxor
+ * module.
+ *
+ * Right now, the choices are:
+ *
+ */
+$mime_drivers_map['luxor']['registered'] = array();
+
+/**
+ * If you want to specifically override any MIME type to be handled by
+ * a specific driver, then enter it here. Normally, this is safe to
+ * leave, but it's useful when multiple drivers handle the same MIME
+ * type, and you want to specify exactly which one should handle it.
+ */
+$mime_drivers_map['luxor']['overrides'] = array();
+
+/**
+ * Driver specific settings. Here, you have to configure each driver
+ * which you chose to activate above. Default settings have been
+ * filled in for them, and if you haven't activated it, then just
+ * leave it as it is - it won't get loaded.
+ *
+ * The 'handles' setting below shouldn't be changed in most
+ * circumstances. It registers a set of MIME type that the driver can
+ * handle. The 'x-extension' MIME type is a special one to Horde that
+ * maps a file extension to a MIME type. It's useful when you know
+ * that all files ending in '.c' are C files, for example.
+ *
+ * The 'icons' entry is for the driver to register various icons for
+ * the MIME types it handles. The array consists of a 'default' icon
+ * for that driver, and can also include specific MIME-types which can
+ * have their own icons.
+ */
diff --git a/luxor/config/sources.php.dist b/luxor/config/sources.php.dist
new file mode 100644 (file)
index 0000000..695970f
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+/**
+ * $Horde: luxor/config/sources.php.dist,v 1.7 2005/10/13 12:21:09 jan Exp $
+ *
+ * This file contains all the configuration information for the various
+ * sources to display. The following fields are defined:
+ *
+ * 'name'          : Short name for the repository
+ *
+ * 'driver'        : The driver to use when accessing this source. Currently
+ *                   only 'plain' is implemented, eventually 'cvs' will be
+ *                   supported as well.
+ *
+ * 'root'          : Location on the filesystem of the source
+ *
+ * 'restrictions'  : Array of perl-style regular expressions for those files
+ *                   whose contents should be protected and not displayed.
+*/
+
+$sources['horde'] = array(
+    'name' => 'Horde',
+    'driver' => 'plain',
+    'root' => dirname(__FILE__) . '/../../',
+    'restrictions' => array('(.*)config/(\w*).php$')
+);
+
+$sources['pear'] = array(
+    'name' => 'PEAR',
+    'driver' => 'plain',
+    'root' => '/usr/local/lib/php/'
+);
diff --git a/luxor/docs/CHANGES b/luxor/docs/CHANGES
new file mode 100644 (file)
index 0000000..8ec9668
--- /dev/null
@@ -0,0 +1,23 @@
+----
+v0.1
+----
+
+[ben] Better support for MS-SQL.
+[cjh] Support mod_rewrite style URLs in addition to GET.
+[mas] Change any output of <b> and <i> tags to <strong> and <em> for better
+      accessibility support.
+[cjh] Allow disabling the show_var javascript (Bug #1270).
+[jan] Add Spanish translation (Manuel Perez Ayala <mperaya@alcazaba.unex.es>).
+[cjh] Cache markup of files.
+[cjh] Improve layout of identifier pages.
+[cjh] genxref.php is now solely a command line script and lives
+      in the scripts/ directory.
+[cjh] Make sure to clean out the database before adding new data
+      so as not to get duplicate entries for identifiers.
+[jan] Add German translation.
+[cjh] Add symbol search functionality.
+[cjh] Fix spacing of source code.
+[cjh] Add options to filter out certain directories and filenames.
+[jan] Add Romanian translation (Eugen Hoanca <eugenh@urban-grafx.ro>).
+[jan] Implement indexing and referencing.
+[jan] Initial port from LXR.
diff --git a/luxor/docs/CREDITS b/luxor/docs/CREDITS
new file mode 100644 (file)
index 0000000..b1da3ad
--- /dev/null
@@ -0,0 +1,22 @@
+============================
+|| Luxor Development Team ||
+============================
+
+===============
+Core Developers
+===============
+
+Jan Schneider <jan@horde.org>
+- initial port from LXR
+
+
+============
+Localization
+============
+
+German                  Jan Schneider <jan@horde.org>
+Romanian                Eugen Hoanca <eugenh@urban-grafx.ro>
+Spanish                 Manuel Perez Ayala <mperaya@alcazaba.unex.es>
+
+
+$Horde: luxor/docs/CREDITS,v 1.4 2004/07/29 11:25:48 jan Exp $
diff --git a/luxor/docs/INSTALL b/luxor/docs/INSTALL
new file mode 100644 (file)
index 0000000..49c0c16
--- /dev/null
@@ -0,0 +1,175 @@
+==========================
+|| INSTALLING Luxor 0.1 ||
+==========================
+
+This document contains instructions for installing the Luxor web-based
+luxor application on your system.
+
+For information on the capabilities and features of Luxor, see the file
+README in the top-level directory of the Luxor distribution.
+
+
+OBTAINING Luxor
+------------------
+
+Luxor can be obtained from the Horde website and FTP server, at
+
+   http://www.horde.org/luxor/
+   ftp://ftp.horde.org/pub/luxor/
+
+Bleeding-edge development versions of Luxor are available via CVS; see
+the file docs/HACKING in the Horde distribution for information on
+accessing the Horde CVS repository.
+
+
+PREREQUISITES
+-------------
+
+To function properly, Luxor requires the following:
+
+  1. A working Horde installation.
+
+     Luxor runs within the Horde Application Framework, a set of
+     common tools for Web applications written in PHP. You must
+     install Horde before installing Luxor.
+
+     The Horde Framework can be obtained from the Horde website and
+     FTP server, at
+
+        http://www.horde.org/horde/
+        ftp://ftp.horde.org/pub/horde/
+
+     Many of Luxor's prerequisites are also Horde prerequisites.
+     Be sure to have completed all of the steps in the INSTALL
+     file for the Horde Framework before installing Luxor.
+
+  2. SQL support in PHP.
+
+     Luxor store its data in an SQL database. Build PHP with whichever
+     SQL driver you require; see the Horde INSTALL file for details.
+
+
+INSTALLING Luxor
+-------------------
+
+Luxor is written in PHP, and must be installed in a web-accessible
+directory. The precise location of this directory will differ from
+system to system. Conventionally, Luxor is installed directly underneath
+Horde in the webserver's document tree.
+
+Since Luxor is written in PHP, there is no compilation necessary;
+simply expand the distribution where you want it to reside and rename
+the root directory of the distribution to whatever you wish to appear
+in the URL. For example, with the Apache webserver's default document
+root of '/usr/local/apache/htdocs', you would type:
+
+   cd /usr/local/apache/htdocs/horde
+   tar zxvf /path/to/luxor-1.0.tar.gz
+   mv luxor-1.0 luxor
+
+and would then find Luxor at the URL
+
+   http://your-server/horde/luxor/
+
+
+CONFIGURING Luxor
+--------------------
+
+1. Configuring Horde for Luxor
+
+   a. Register the application
+
+      In horde/config/registry.php, find the applications['luxor'] stanza.
+      The 'status' parameter should already be marked '=> active'.
+      If you have changed the location of Luxor relative to Horde,
+      either in the URL or in the filesystem or both, you must
+      update the 'fileroot' and 'webroot' settings to their correct
+      values.
+
+2. Creating the database table
+
+   The specific steps to create the Luxor database table depend
+   on which database you've chosen to use.
+
+   First, look in scripts/sql/ to see if a script already
+   exists for your database type. If so, you should be
+   able to simply execute that script as superuser in your
+   database. (Note that executing the script as the "horde" user will
+   probably fail when granting privileges.)
+
+   If such a script does not exist, you'll need to build your own, using
+   the file luxor.sql as a starting point. If you need
+   assistance in creating databases, you may wish to let us know on
+   the Luxor mailing list.
+
+3. Configuring Luxor.
+
+   To configure Luxor, change to the config/ directory of the
+   installed distribution, and make copies of all of the configuration
+   "dist" files without the "dist" suffix:
+
+      cd config/
+      for foo in *.dist; do cp $foo `basename $foo .dist`; done
+
+   Documentation on the format of those files can be found in each
+   file.   With the exception of the conf.* files (see below),
+   the other files in config/ need only be modified if you wish
+   to customize Luxor's appearance or behavior, as the defaults will
+   be correct for most sites.
+
+   You must login to Horde as a Horde Administrator to finish the
+   configuring of Luxor.  Use the Horde "Administration" menu item to get
+   to the Administration page, and then click on the "Configuration"
+   icon to get the Configuration page.  Select "Luxor" from the selection
+   list of applications, and click on the "Configure" button.  Fill in or
+   change any configuration values as needed.  When done click on "Generate
+   Luxor Configuration" to generate the conf.php file.  If your web server
+   doesn't have write permissions to the Luxor configuration directory or
+   file, it will not be able to write the file.  In this case, cut and
+   paste the returned configuration information into the file
+   luxor/config/conf.php.
+
+   Note for international users:  Luxor uses GNU gettext to provide local
+   translations of text displayed by applications; the translations are
+   found in the po/ directory.  If a translation is not yet available
+   for your locale (and you wish to create one), or if you're having
+   trouble using a provided translation, please see the horde/docs/TRANSLATIONS
+   file for instructions.
+
+4. Testing Luxor
+
+   Use Luxor to .... Test at
+   least the following:
+
+     - ....
+
+
+OBTAINING SUPPORT
+-----------------
+
+If you encounter problems with Luxor, help is available!
+
+The Horde Frequently Asked Questions List (FAQ), available on the Web
+at
+
+  http://www.horde.org/faq/
+
+The Horde Project runs a number of mailing lists, for individual
+applications and for issues relating to the project as a whole.
+Information, archives, and subscription information can be found at
+
+  http://www.horde.org/mail/
+
+Lastly, Horde developers, contributors and users may also be found on IRC,
+on the channel #horde on the Freenode Network (irc.freenode.net).
+
+Please keep in mind that Luxor is free software written by volunteers.
+For information on reasonable support expectations, please read
+
+  http://www.horde.org/support.php
+
+Thanks for using Luxor!
+
+The Horde team
+
+$Horde: luxor/docs/INSTALL,v 1.7 2008/11/11 10:14:16 jan Exp $
diff --git a/luxor/docs/TODO b/luxor/docs/TODO
new file mode 100644 (file)
index 0000000..00247a9
--- /dev/null
@@ -0,0 +1,14 @@
+Short term
+----------
+- documentation
+- standard sql for sql scripts
+- PEAR::DB sequences instead of autoincrement fields
+- port UI
+
+Mid term
+--------
+- CVS File driver
+
+Long term
+---------
+- branch support
diff --git a/luxor/index.php b/luxor/index.php
new file mode 100644 (file)
index 0000000..449794a
--- /dev/null
@@ -0,0 +1,11 @@
+<?php
+/**
+ * Luxor index script.
+ *
+ * Copyright 2001-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ */
+
+require dirname(__FILE__) . '/source.php';
diff --git a/luxor/js/show_var.js b/luxor/js/show_var.js
new file mode 100644 (file)
index 0000000..0747a73
--- /dev/null
@@ -0,0 +1,17 @@
+function show_var(varname)
+{
+    if (document.styleSheets[0].addRule) {
+        document.styleSheets[0].addRule('.' + varname, 'background: yellow;', 45);
+    } else {
+        document.styleSheets[0].insertRule('.' + varname + ' { background: yellow; }', 45);
+    }
+}
+
+function unshow_var(varname)
+{
+    if (document.styleSheets[0].removeRule) {
+        document.styleSheets[0].removeRule(45);
+    } else {
+        document.styleSheets[0].deleteRule(45);
+    }
+}
diff --git a/luxor/lib/.htaccess b/luxor/lib/.htaccess
new file mode 100644 (file)
index 0000000..3a42882
--- /dev/null
@@ -0,0 +1 @@
+Deny from all
diff --git a/luxor/lib/Application.php b/luxor/lib/Application.php
new file mode 100644 (file)
index 0000000..3807bdf
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Luxor application API.
+ *
+ * This file defines Luxor's core application definition.
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @package Luxor
+ */
+
+/* Determine the base directories. */
+if (!defined('LUXOR_BASE')) {
+    define('LUXOR_BASE', dirname(__FILE__) . '/..');
+}
+
+if (!defined('HORDE_BASE')) {
+    /* If Horde does not live directly under the app directory, the HORDE_BASE
+     * constant should be defined in config/horde.local.php. */
+    if (file_exists(LUXOR_BASE . '/config/horde.local.php')) {
+        include LUXOR_BASE . '/config/horde.local.php';
+    } else {
+        define('HORDE_BASE', LUXOR_BASE . '/..');
+    }
+}
+
+/* Load the Horde Framework core (needed to autoload
+ * Horde_Registry_Application::). */
+require_once HORDE_BASE . '/lib/core.php';
+
+class Luxor_Application extends Horde_Registry_Application
+{
+    /**
+     * The application's version.
+     *
+     * @var string
+     */
+    public $version = 'H4 (1.0-git)';
+
+    /**
+     * Initialization function.
+     *
+     * Global variables defined:
+     *   $luxor_shares - TODO
+     */
+    protected function _init()
+    {
+        // Luxor base libraries.
+        require_once LUXOR_BASE . '/lib/Luxor.php';
+        Luxor::initialize();
+    }
+
+    /**
+     * Generate the menu to use on the prefs page.
+     *
+     * @return Horde_Menu  A Horde_Menu object.
+     */
+    public function prefsMenu()
+    {
+        return Luxor::getMenu();
+    }
+}
diff --git a/luxor/lib/Driver.php b/luxor/lib/Driver.php
new file mode 100644 (file)
index 0000000..607c83b
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Luxor_Driver:: defines an API for implementing storage backends for Luxor.
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @since   Luxor 0.1
+ * @package Luxor
+ */
+class Luxor_Driver
+{
+    /**
+     * Attempts to return a concrete Luxor_Driver instance based on $driver.
+     *
+     * @param string    $driver     The type of concrete Luxor_Driver subclass
+     *                              to return.  The is based on the storage
+     *                              driver ($driver).  The code is dynamically
+     *                              included.
+     *
+     * @param array     $params     (optional) A hash containing any additional
+     *                              configuration or connection parameters a
+     *                              subclass might need.
+     *
+     * @return mixed    The newly created concrete Luxor_Driver instance, or
+     *                  false on an error.
+     */
+    function factory($source, $driver = null, $params = null)
+    {
+        if (is_null($driver)) {
+            $driver = $GLOBALS['conf']['storage']['driver'];
+        }
+
+        $driver = basename($driver);
+
+        if (is_null($params)) {
+            $params = Horde::getDriverConfig('storage', $driver);
+        }
+
+        $class = 'Luxor_Driver_' . $driver;
+        if (class_exists($class)) {
+            $luxor = new $class($source, $params);
+        } else {
+            $luxor = false;
+        }
+
+        return $luxor;
+    }
+}
diff --git a/luxor/lib/Driver/sql.php b/luxor/lib/Driver/sql.php
new file mode 100644 (file)
index 0000000..c75cbdd
--- /dev/null
@@ -0,0 +1,564 @@
+<?php
+/**
+ * Luxor storage implementation for PHP's PEAR database abstraction layer.
+ *
+ * Required values for $params:<pre>
+ *      'phptype'       The database type (e.g. 'pgsql', 'mysql', etc.).
+ *      'charset'       The database's internal charset.</pre>
+ *
+ * Required by some database implementations:<pre>
+ *      'hostspec'      The hostname of the database server.
+ *      'protocol'      The communication protocol ('tcp', 'unix', etc.).
+ *      'username'      The username with which to connect to the database.
+ *      'password'      The password associated with 'username'.
+ *      'database'      The name of the database.
+ *      'options'       Additional options to pass to the database.
+ *      'tty'           The TTY on which to connect to the database.
+ *      'port'          The port on which to connect to the database.</pre>
+ *
+ * The table structure can be created by the scripts/drivers/luxor.sql
+ * script.
+ *
+ * $Horde: luxor/lib/Driver/sql.php,v 1.29 2007/09/23 13:32:35 jan Exp $
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @since   Luxor 0.1
+ * @package Luxor
+ */
+class Luxor_Driver_sql extends Luxor_Driver {
+
+    /**
+     * Hash containing connection parameters.
+     *
+     * @var array
+     */
+    var $_params = array();
+
+    /**
+     * Handle for the current database connection.
+     *
+     * @var DB
+     */
+    var $_db;
+
+    /**
+     * The id of the source that we are dealing with.
+     *
+     * @var string
+     */
+    var $_source;
+
+    /**
+     * Boolean indicating whether or not we're connected to the SQL server.
+     *
+     * @var boolean
+     */
+    var $_connected = false;
+
+    /**
+     * Symbol cache.
+     *
+     * @var array
+     */
+    var $_symcache = array();
+
+    /**
+     * Description ID cache.
+     *
+     * @var array
+     */
+    var $_decIdcache = array();
+
+    /**
+     * Constructs a new SQL storage object.
+     *
+     * @param string $source  The name of the source.
+     * @param array  $params  A hash containing connection parameters.
+     */
+    function Luxor_Driver_sql($source, $params = array())
+    {
+        $this->_source = $source;
+        $this->_params = $params;
+    }
+
+    /**
+     * Adds a symbol definition to the sybmol index.
+     *
+     * @param string $symname  The symbol's name.
+     * @param integer $fileId  The unique ID of the file where this symbol was
+     *                         defined.
+     * @param integer $line    The linenumber where this symbol was defined.
+     * @param integer $langid  The unique ID of the language the file was
+     *                         written in.
+     * @param integer $type    The symbol type.
+     *
+     * @return mixed           PEAR_Error on error, true on success.
+     */
+    function index($symname, $fileId, $line, $langid, $type)
+    {
+        $this->_connect();
+
+        $symid = $this->symid($symname);
+        if (is_a($symid, 'PEAR_Error')) {
+            return $symid;
+        }
+
+        /* I have no idea what this is about yet
+        if ($relsym) {
+            $relsym = $this->symid($relsym);
+            if (is_a($relsym, 'PEAR_Error')) {
+                return $relsym;
+            }
+            $relsym = $this->_db->quote($relsym);
+        } else {
+            $relsym = 'NULL';
+        }
+        */
+
+        $query = 'INSERT INTO luxor_indexes (symid, fileid, line, declid)' .
+                 ' VALUES (?, ?, ?, ?)';
+        $values = array($symid, $fileId, $line, $this->getDecId($langid, $type));
+        return $this->_db->query($query, $values);
+    }
+
+    /**
+     * Add a symbol reference to the reference index.
+     *
+     * @param string $symname  The name of the used symbol.
+     * @param integer $fileId  The unique ID of the file in which the symbol
+     *                         was used.
+     * @param integer $line    The number of line in which the symbol was used.
+     *
+     * @return mixed           PEAR_Error on error, true on success.
+     */
+    function reference($symname, $fileId, $line)
+    {
+        $this->_connect();
+
+        $result = $this->_db->query('INSERT INTO luxor_usage (fileid, line, symid) VALUES (?, ?, ?)',
+                                    array($fileId, $line, $this->symid($symname)));
+        return $result;
+    }
+
+    /**
+     * Returns a unique ID for a given filename.
+     *
+     * @param string $filename  The name of the file.
+     * @param string $tag       The tag of the file.
+     *
+     * @return integer  A unique ID for this file or PEAR_Error on error.
+     */
+    function fileId($filename, $tag = '')
+    {
+        static $files = array();
+
+        /* Have we already been asked for this file? */
+        if (isset($files[$filename])) {
+            return $files[$filename];
+        }
+
+        $this->_connect();
+
+        /* Has an ID already been created for this file? */
+        $query = 'SELECT fileid FROM luxor_files' .
+                 ' WHERE tag = ? AND source = ? AND filename = ?';
+        $values = array($tag, $this->_source, $filename);
+
+        $fileId = $this->_db->getOne($query, $values);
+        if (empty($fileId) || is_a($fileId, 'PEAR_Error')) {
+            return false;
+        }
+        $files[$filename] = $fileId;
+
+        return $fileId;
+    }
+
+    /**
+     * Created a unique ID for a given filename.
+     *
+     * @param string $filename      The name of the file.
+     * @param string $tag           The tag of the file.
+     * @param integer $lastmodified The timestamp the file was last modified.
+     *
+     * @return integer              A unique ID for this file or PEAR_Error on error.
+     */
+    function createFileId($filename, $tag = '', $lastmodified)
+    {
+        $this->_connect();
+
+        $fileId = $this->_db->nextId('luxor_files');
+        if (is_a($fileId, 'PEAR_Error')) {
+            return $fileId;
+        }
+
+        /* Create an ID for this file. */
+        $query = 'INSERT INTO luxor_files (fileid, filename, source, tag, lastmodified) VALUES (?, ?, ?, ?, ?)';
+        $values = array((int)$fileId,
+                        $filename,
+                        $this->_source,
+                        $tag,
+                        $lastmodified);
+
+        $result = $this->_db->query($query, $values);
+        if (is_a($result, 'PEAR_Error')) {
+            return $result;
+        }
+
+        return $fileId;
+    }
+
+    /**
+     * Returns a unique ID for a given symbol.
+     *
+     * @param string $symname  The name of the symbol.
+     *
+     * @return int             A unique ID for this symbol or PEAR_Error on error.
+     */
+    function symid($symname)
+    {
+        /* Do we have this symbol in the symbol cache yet? */
+        if (!isset($this->_symcache[$symname])) {
+            $this->_connect();
+            /* Has an ID already been created for this symbol? */
+            $query = 'SELECT symid FROM luxor_symbols' .
+                     ' WHERE source = ? AND symname = ?';
+            $values = array($this->_source, $symname);
+            $symid = $this->_db->getOne($query, $values);
+            if (is_null($symid) || is_a($symid, 'PEAR_Error')) {
+                /* Create an ID for this symbol. */
+                $symid = $this->_db->nextId('luxor_symbols');
+                if (is_a($symid, 'PEAR_Error')) {
+                    return $symid;
+                }
+                $result = $this->_db->query('INSERT INTO luxor_symbols (symid, symname, source) VALUES (?, ?, ?)',
+                                            array((int)$symid, $symname, $this->_source));
+                if (is_a($result, 'PEAR_Error')) {
+                    return $result;
+                }
+            }
+            $this->_symcache[$symname] = $symid;
+        }
+
+        return $this->_symcache[$symname];
+    }
+
+    /**
+     * Returns the name of a symbol from its unique ID.
+     *
+     * @param integer $symid  The ID of the symbol
+     *
+     * @return string  The name of the symbol or PEAR_Error on error
+     */
+    function symname($symid)
+    {
+        /* Don't we have this symbol in the symbol cache yet? */
+        $this->_connect();
+
+        if (in_array($symid, $this->_symcache)) {
+            return array_key($symid, $this->_symcache);
+        }
+
+        $query = 'SELECT symname FROM luxor_symbols WHERE symid = ?';
+        $values = array($symid);
+        $symname = $this->_db->getOne($query, $values);
+        $this->_symcache[$symname] = $symid;
+
+        return $symname;
+    }
+
+    /**
+     * Checks if the given name is a known symbol.
+     *
+     * @param string $symname  The potential symbol name.
+     *
+     * @return integer  The symbol's id or null if it wasn't a symbol.
+     */
+    function isSymbol($symname, $altsources = array())
+    {
+        if (!isset($this->_symcache[$symname])) {
+            $this->_connect();
+
+            $altsql = '';
+            $altvalues = array();
+            if (!is_array($altsources)) {
+                $altsources = array($altsources);
+            }
+            foreach ($altsources as $source) {
+                $altsql .= ' OR source = ?';
+                $altvalues[] = $source;
+            }
+
+            array_unshift($altvalues, $this->_source);
+            $values = $altvalues;
+            $values[] = $symname;
+
+            $symid = $this->_db->getOne('SELECT symid FROM luxor_symbols' .
+                                        ' WHERE (source = ?' . $altsql . ')' .
+                                        ' AND symname = ?',
+                                        $values);
+            $this->_symcache[$symname] = $symid;
+        }
+
+        return $this->_symcache[$symname];
+    }
+
+    /**
+     * If this file has not been indexed earlier, mark it as being
+     * indexed now.
+     *
+     * @param integer $fileId  The file's unique ID.
+     *
+     * @return boolean  True if the file has been marked as being indexed,
+     *                  false if it was already indexed.
+     */
+    function toIndex($fileId)
+    {
+        $this->_connect();
+
+        $status = $this->_db->getOne('SELECT status FROM luxor_status' .
+                                     ' WHERE fileid = ?',
+                                     array($fileId));
+        if (empty($status)) {
+            $this->_db->query('INSERT INTO luxor_status (fileid, status)' .
+                              ' VALUES (?, 0)',
+                              array($fileId + 0));
+        }
+        $query = 'UPDATE luxor_status SET status = 1' .
+                 ' WHERE fileid = ? AND status <= 0';
+        $values = array($fileId);
+        return $this->_db->query($query, $values);
+    }
+
+    /**
+     * If this file has not been referenced earlier, mark it as being
+     * referenced now.
+     *
+     * @param integer $fileId  The file's unique ID.
+     *
+     * @return boolean  True if the file has been marked as being referenced,
+     *                  false if it was already referenced.
+     */
+    function toReference($fileId)
+    {
+        $this->_connect();
+
+        $query = 'UPDATE luxor_status SET status = 2' .
+                 ' WHERE fileid = ? AND status <= 1';
+        $values = array($fileId);
+        return $this->_db->query($query, $values);
+    }
+
+    /**
+     * Return the last time the entry for a file was modified.
+     *
+     * @param string $filename  The filename to check.
+     *
+     * @return integer  The last modified time, or 0 if there is an error.
+     */
+    function getLastModified($filename)
+    {
+        static $lastModified;
+
+        if (isset($lastModified[$filename])) {
+            return $lastModified[$filename];
+        }
+
+        $this->_connect();
+        $query = 'SELECT lastmodified FROM luxor_files' .
+                 ' WHERE source = ? AND filename = ?';
+        $values = array($this->_source, $filename);
+        $res = $this->_db->getOne($query, $values);
+        $lastModified[$filename] = is_a($res, 'PEAR_Error') ? 0 : $res;
+
+        return $lastModified[$filename];
+    }
+
+    /**
+     * Empties the current symbol cache.
+     *
+     * This function should be called before parsing each new file.
+     * If this is not done too much memory will be used and things
+     * will become very slow.
+     */
+    function clearCache()
+    {
+        $this->_symcache = array();
+    }
+
+    /**
+     * Cleans the database for a fresh import of data.
+     *
+     * This function should be called before parsing the source tree
+     * again, to avoid duplicate entries in the database.
+     */
+    function clearIndex()
+    {
+        $this->_connect();
+
+        $this->_db->query('DELETE FROM luxor_declarations');
+        $this->_db->query('DELETE FROM luxor_files');
+        $this->_db->query('DELETE FROM luxor_indexes');
+        $this->_db->query('DELETE FROM luxor_status');
+        $this->_db->query('DELETE FROM luxor_symbols');
+        $this->_db->query('DELETE FROM luxor_usage');
+    }
+
+    /**
+     * Returns an unique ID for a description of a symbol type.
+     *
+     * @param integer $lang   The language's unique ID.
+     * @param string $string  The symbol type description.
+     *
+     * return mixed  A unique ID for this description or PEAR_Error on error.
+     */
+    function getDecId($lang, $string)
+    {
+        $this->_connect();
+
+        if (!isset($this->_decIdcache[$lang])) {
+            $this->_decIdcache[$lang] = array();
+        }
+
+        if (!isset($this->_decIdcache[$lang][$string])) {
+            $query = 'SELECT declid FROM luxor_declarations' .
+                     ' WHERE langid = ? AND declaration = ?';
+            $values = array($lang, $string);
+            $decId = $this->_db->getOne($query, $values);
+            if (is_null($decId) || is_a($decId, 'PEAR_Error')) {
+                /* Create an ID for this declaration. */
+                $decId = $this->_db->nextId('luxor_declarations');
+                if (is_a($decId, 'PEAR_Error')) {
+                    return $decId;
+                }
+                $this->_db->query('INSERT INTO luxor_declarations (declid, langid, declaration)' .
+                                  ' VALUES (?, ?, ?)',
+                                  array((int)$decId, $lang, $string));
+            }
+            $this->_decIdcache[$lang][$string] = $decId;
+        }
+
+        return $this->_decIdcache[$lang][$string];
+    }
+
+    /**
+     * Locate the definitions of a symbol.
+     *
+     * @param integer $symid  The symbol id.
+     * @param string $tag     The tag of the file.
+     *
+     * @return array  Nested hash with elements 'filename', 'line', and
+     *                'declaration'.
+     */
+    function getIndex($symid, $tag = '')
+    {
+        $this->_connect();
+        $query = 'SELECT filename, line, declaration FROM ' .
+                 'luxor_files, luxor_indexes, luxor_declarations WHERE ' .
+                 'luxor_files.fileid = luxor_indexes.fileid AND ' . // join files to indexes
+                 'luxor_indexes.declid = luxor_declarations.declid AND ' . // join indexes to declarations
+                 'luxor_indexes.symid = ? AND ' .
+                 'luxor_files.tag = ? AND ' .
+                 'luxor_files.source = ?';
+        $values = array((int)$symid, $tag, $this->_source);
+
+        return $this->_db->getAll($query, $values, DB_FETCHMODE_ASSOC);
+    }
+
+    /**
+     * Locate the usage of a symbol.
+     *
+     * @param integer $symid  The symbol id.
+     * @param string $tag     The tag of the file.
+     *
+     * @return array  Nested hash with elements 'filename', and 'line'.
+     */
+    function getReference($symid, $tag = '')
+    {
+        $this->_connect();
+        $query = 'SELECT filename, line FROM ' .
+                 'luxor_usage, luxor_files WHERE ' .
+                 'luxor_usage.fileid = luxor_files.fileid AND ' .
+                 'luxor_usage.symid = ? AND ' .
+                 'luxor_files.tag = ? AND ' .
+                 'luxor_files.source = ?';
+        $values = array((int)$symid, $tag, $this->_source);
+
+        return $this->_db->getAll($query, $values, DB_FETCHMODE_ASSOC);
+    }
+
+    /**
+     * Search for symbols matching $symbol.
+     *
+     * @param string $symbol  The symbol name to search for.
+     *
+     * @return array  Any symids matching $symbol.
+     */
+    function searchSymbols($symbol)
+    {
+        $this->_connect();
+        $query = 'SELECT symid, symid FROM luxor_symbols WHERE symname LIKE ?';
+        $values = array($symbol . '%');
+
+        return $this->_db->getAssoc($query, false, $values);
+    }
+
+    /**
+     * Get source that a symbol is from.
+     *
+     * @param $symid  The symbol id.
+     *
+     * @return string  The source id.
+     */
+    function getSourceBySymbol($symid)
+    {
+        $this->_connect();
+
+        return $this->_db->getOne('SELECT source FROM luxor_symbols' .
+                                  ' WHERE symid = ?',
+                                  array($symid));
+    }
+
+    /**
+     * Attempts to open a persistent connection to the SQL server.
+     *
+     * @return boolean  True on success; exits (Horde::fatal()) on error.
+     */
+    function _connect()
+    {
+        if (!$this->_connected) {
+            Horde::assertDriverConfig($this->_params, 'storage',
+                array('phptype', 'charset'));
+
+            if (!isset($this->_params['database'])) {
+                $this->_params['database'] = '';
+            }
+            if (!isset($this->_params['username'])) {
+                $this->_params['username'] = '';
+            }
+            if (!isset($this->_params['hostspec'])) {
+                $this->_params['hostspec'] = '';
+            }
+
+            /* Connect to the SQL server using the supplied parameters. */
+            $this->_db = &DB::connect($this->_params,
+                                      array('persistent' => !empty($this->_params['persistent'])));
+            if (is_a($this->_db, 'PEAR_Error')) {
+                Horde::fatal($this->_db, __FILE__, __LINE__);
+            }
+
+            // Set DB portability options.
+            switch ($this->_db->phptype) {
+            case 'mssql':
+                $this->_db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS | DB_PORTABILITY_RTRIM);
+                break;
+            default:
+                $this->_db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS);
+            }
+
+            $this->_connected = true;
+        }
+
+        return true;
+    }
+
+}
diff --git a/luxor/lib/Files.php b/luxor/lib/Files.php
new file mode 100644 (file)
index 0000000..5d618bb
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Luxor_Files:: defines an API to access source file repositories.
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @since   Luxor 0.1
+ * @package Luxor
+ */
+class Luxor_Files
+{
+    /**
+     * Attempts to return a concrete Luxor_Files instance based on $driver.
+     *
+     * @param string    $driver     The type of concrete Luxor_Files subclass
+     *                              to return.  The is based on the repository
+     *                              driver ($driver).  The code is dynamically
+     *                              included.
+     * @param array     $params     (optional) A hash containing any additional
+     *                              configuration or connection parameters a
+     *                              subclass might need.
+     *
+     * @return mixed    The newly created concrete Luxor_Files instance, or
+     *                  false on an error.
+     */
+    function factory($driver, $params = array())
+    {
+        $driver = basename($driver);
+        $class = 'Luxor_Files_' . $driver;
+        if (class_exists($class)) {
+            return new $class($params);
+        } else {
+            return false;
+        }
+    }
+}
diff --git a/luxor/lib/Files/plain.php b/luxor/lib/Files/plain.php
new file mode 100644 (file)
index 0000000..45725b1
--- /dev/null
@@ -0,0 +1,172 @@
+<?php
+/**
+ * Luxor repository implementation for a simple filesystem hierarchy.
+ *
+ * $Horde: luxor/lib/Files/plain.php,v 1.18 2006/05/23 02:27:39 selsky Exp $
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @since   Luxor 0.1
+ * @package Luxor
+ */
+class Luxor_Files_plain extends Luxor_Files {
+
+    /**
+     * Hash containing parameters.
+     *
+     * @var array
+     */
+    var $_params = array();
+
+    /**
+     * Constructs a new filesystem handler.
+     *
+     * @param array  $params    A hash containing parameters.
+     */
+    function Luxor_Files_plain($params = array())
+    {
+        $this->_params = $params;
+    }
+
+    function getFiletime($filename)
+    {
+        return filemtime($this->toReal($filename));
+    }
+
+    function getFilesize($filename)
+    {
+        return filesize($this->toReal($filename));
+    }
+
+    /**
+     * Returns a file handler.
+     *
+     * @param string $filename  The name of the file to open.
+     *
+     * @return ressource        A handler of the file or false on error.
+     */
+    function getFileHandle($filename)
+    {
+        return @fopen($this->toReal($filename), 'r');
+    }
+
+    /**
+     * Creates a temporary copy of a file.
+     *
+     * @param string $filename  The name of the file to be copied.
+     *
+     * @return string           The file name of the temporary copy or false
+     *                          if the file couldn't be copied.
+     */
+    function tmpFile($filename)
+    {
+        $tmp = Horde::getTempFile('luxor');
+        if (!@copy($this->toReal($filename), $tmp)) {
+            return false;
+        }
+        return $tmp;
+    }
+
+    /**
+     * Returns a directory's content. Backup files are skipped and
+     * directories suffixed with a slash.
+     *
+     * @param string $path  The directory to list.
+     *
+     * @return array        An array containing all directories and files of
+     *                      the directory or PEAR_Error if the directory
+     *                      couldn't be read.
+     */
+    function getDir($path, $release = '')
+    {
+        $path = $this->toReal($path);
+
+        $dir = @opendir($path);
+        if (!$dir) {
+            return PEAR::raiseError(sprintf(_("Can't open directory %s"), $path));
+        }
+
+        $dirs = array();
+        $files = array();
+        while (($file = readdir($dir)) !== false) {
+            if (preg_match('/^\.|~$|\.orig$|\.bak$/i', $file) ||
+                (is_dir($path . $file) && $file == 'CVS')) {
+                continue;
+            }
+
+            if (is_dir($path . $file)) {
+                if (Luxor::isDirParsed($path . $file)) {
+                    $dirs[] = $file . '/';
+                }
+            } else {
+                if (Luxor::isFileParsed($path . $file)) {
+                    $files[] = $file;
+                }
+            }
+        }
+
+        closedir($dir);
+        natcasesort($dirs);
+        natcasesort($files);
+        return array_merge($dirs, $files);
+    }
+
+    /**
+     * Returns the full path to a file.
+     *
+     * @param string $pathname  The internally used (relative) name of the file.
+     *
+     * @return string           The full path to the file.
+     */
+    function toReal($pathname)
+    {
+        return $this->_params['root'] . $pathname;
+    }
+
+    /**
+     * Checks if the given path name is a directory.
+     *
+     * @param string $pathname  The path name to check.
+     *
+     * @return boolean  True if the path name was a directory.
+     */
+    function isDir($pathname)
+    {
+        return is_dir($this->toReal($pathname));
+    }
+
+    /**
+     * Checks if the given path name is a file.
+     *
+     * @param string $pathname  The path name to check.
+     *
+     * @return boolean  True if the path name was a file.
+     */
+    function isFile($pathname)
+    {
+        return is_file($this->toReal($pathname));
+    }
+
+    function getIndex($pathname)
+    {
+        $indexname = $this->toReal($pathname) . '00-INDEX';
+        if (file_exists($indexname)) {
+            $index = file_get_contents($indexname);
+
+            if (preg_match_all('/\n(\S*)\s*\n\t-\s*([^\n]*)/s', $index, $match)) {
+                $list = array();
+                $iMax = count($match[1]);
+                for ($i = 0; $i < $iMax; $i++) {
+                    $list[$match[1][$i]] = $match[2][$i];
+                }
+                return $list;
+            }
+        }
+        return array();
+    }
+
+    function getAnnotations($pathname)
+    {
+        return array();
+    }
+
+}
diff --git a/luxor/lib/Lang.php b/luxor/lib/Lang.php
new file mode 100644 (file)
index 0000000..64dafb0
--- /dev/null
@@ -0,0 +1,86 @@
+<?php
+/**
+ * Luxor_Lang:: defines an API for the different programming languages Luxor
+ * is able to parse.
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @since   Luxor 0.1
+ * @package Luxor
+ */
+class Luxor_Lang
+{
+    /**
+     * Attempts to return a concrete Luxor_Lang instance based on $driver.
+     *
+     * @param string    $driver     The type of concrete Luxor_Lang subclass
+     *                              to return.  The is based on the repository
+     *                              driver ($driver).  The code is dynamically
+     *                              included.
+     * @param array     $params     (optional) A hash containing any additional
+     *                              configuration or connection parameters a
+     *                              subclass might need.
+     *
+     * @return mixed    The newly created concrete Luxor_Lang instance, or
+     *                  false on an error.
+     */
+    function factory($driver, $params = array())
+    {
+        $driver = basename($driver);
+        $class = 'Luxor_Lang_' . $driver;
+        if (class_exists($class)) {
+            return new $class($params);
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Attempts to determine a files programming language and returns
+     * a parser instance for this language.
+     *
+     * @param Luxor_Files $files  An instance of Luxor_Files to use for file
+     *                            operations and path name resolution.
+     * @param string $pathname    The path name of the file to create a
+     *                            parser for.
+     *
+     * @return mixed    The created concrete Luxor_Lang instance, or false
+     *                  on error.
+     */
+    function builder($files, $pathname)
+    {
+        global $languages;
+        include LUXOR_BASE . '/config/languages.php';
+
+        /* First, check the 'filetype' hash for a matching file extension. */
+        foreach ($languages['filetype'] as $type) {
+            if (preg_match('/' . $type[1] . '/', $pathname)) {
+                return Luxor_Lang::factory($type[2], $type);
+            }
+        }
+
+        /* Next, try to detect the shebang line. */
+        $fh = $files->getFileHandle($pathname);
+        if (!$fh || is_a($fh, 'PEAR_Error')) {
+            return $fh;
+        }
+        $line = fgets($fh);
+        if (!preg_match('/^\#!\s*(\S+)/s', $line, $match)) {
+            return false;
+        }
+        if (isset($languages['interpreters'][$match[1]])) {
+            $lang = $languages['filetype'][$languages['interpreters'][$match[1]]];
+            return Luxor_Lang::factory($lang[2], $lang);
+        }
+
+        return false;
+    }
+
+    function processInclude($frag, $dir)
+    {
+        return preg_replace(array('/([\'"])(.*?)([\'"])/e',
+                                  '/(\\0<)(.*?)(\\0>)/e'),
+                            array('stripslashes(\'$1\') . Luxor::incRef(\'$2\', "fixed", \'$2\', $dir) . stripslashes(\'$3\')',
+                                  'stripslashes(\'$1\') . Luxor::incRef(\'$2\', "fixed", \'$2\') . stripslashes(\'$3\')'),
+                            $frag);
+    }
+}
diff --git a/luxor/lib/Lang/Generic.php b/luxor/lib/Lang/Generic.php
new file mode 100644 (file)
index 0000000..acb8526
--- /dev/null
@@ -0,0 +1,198 @@
+<?php
+/**
+ * A generic implementation of the Luxor_Lang API to handle all programming
+ * languages that don't have a specific driver.
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @since   Luxor 0.1
+ * @package Luxor
+ */
+class Luxor_Lang_Generic extends Luxor_Lang
+{
+    /**
+     * The current language.
+     *
+     * @var string
+     */
+    var $_language;
+
+    /**
+     * This language's copy of the 'langmap' hash from the $languages array.
+     *
+     * @var array
+     */
+    var $_langmap;
+
+    /**
+     * Constructs a new generic language parser.
+     *
+     * @param array  $params    A hash containing necessary parameters.
+     */
+    public function __construct($params)
+    {
+        global $languages;
+
+        $this->_language = $params[0];
+        $this->_langmap = $languages['langmap'][$this->_language];
+    }
+
+    /**
+     * Indexes a file.
+     *
+     * @param string $path  The full path name of the file to index.
+     * @param int $fileId   The file's unique ID.
+     *
+     * @return mixed        A PEAR_Error on error.
+     */
+    function indexFile($path, $fileId)
+    {
+        global $conf, $index;
+
+        $typemap = $this->_langmap['typemap'];
+        include LUXOR_BASE . '/config/languages.php';
+
+        if (isset($languages['eclangnamemapping'][$this->_language])) {
+            $langforce = $languages['eclangnamemapping'][$this->_language];
+        } else {
+            $langforce = $this->_language;
+        }
+
+        $version = shell_exec($conf['paths']['ectags'] . ' --version');
+        if (!preg_match('/Exuberant ctags +(\d+)/i', $version, $match) ||
+            $match[1] < 5) {
+            return PEAR::raiseError(sprintf(_("Exuberant ctags version 5 or above required, found version %s"), $version));
+        }
+
+        if (file_exists($conf['paths']['ectags'])) {
+            /* Call excuberant ctags. */
+            $ectags = @popen($conf['paths']['ectags'] . ' ' . $languages['ectagsopts'] .
+                             ' --excmd=number --language-force=' . $langforce . ' -f - ' .
+                             $path, 'r');
+
+            if (!$ectags) {
+                return PEAR::raiseError(_("Can't run ectags."));
+            }
+            while ($fgets = trim(fgets($ectags))) {
+                @list($sym, $file, $line, $type, $ext) = explode("\t", $fgets);
+                $line = preg_replace('/;"$/', '', $line);
+                preg_match('/language:(\w+)/', $ext, $match);
+                $ext = @$match[1];
+                if (!isset($typemap[$type])) {
+                    continue;
+                }
+                $type = $typemap[$type];
+                if (!empty($ext) && preg_match('/^(struct|union|class|enum):(.*)/', $ext, $match)) {
+                    $ext = str_replace('::<anonymous>', '', $match[2]);
+                } else {
+                    $ext = '';
+                }
+
+                /* Build index. */
+                $result = $index->index($sym, $fileId, $line, $this->_langmap['langid'], $type);
+                if (is_a($result, 'PEAR_Error')) {
+                    pclose($ectags);
+                    return $result;
+                }
+            }
+            pclose($ectags);
+        }
+    }
+
+    /**
+     * References a file.
+     *
+     * @param string $path  The full path name of the file to reference.
+     * @param int $fileId   The file's unique ID.
+     *
+     * @return mixed        A PEAR_Error on error.
+     */
+    function referenceFile($path, $fileId)
+    {
+        global $conf, $index;
+
+        $fp = @fopen($path, 'r');
+        if (!$fp) {
+            return PEAR::raiseError(sprintf(_("Can't open file %s."), $path));
+        }
+
+        /* Instantiate parser. */
+        $parser = new Luxor_SimpleParse($fp, 1, $this->_langmap['spec']);
+
+        $linenum = 1;
+        list($btype, $frag) = $parser->nextFrag();
+        while ($frag) {
+            $lines = array();
+            if (preg_match_all('/(.*?\\n)/', $frag, $match)) {
+                $lines = $match[1];
+            }
+            if (preg_match('/([^\\n]*)$/', $frag, $match)) {
+                $lines[] = $match[1];
+            }
+
+            if ($btype) {
+                /* Skip comments, strings and includes. */
+                if ($btype == 'comment' || $btype == 'string' || $btype == 'include') {
+                    $linenum += count($lines) - 1;
+                }
+            } else {
+                foreach ($lines as $l) {
+                    /* Strip symbol name. */
+                    preg_match_all('/(?:^|[^a-zA-Z_\#])(\\~?_*[a-zA-Z][a-zA-Z0-9_]*)\b/x', $l, $match);
+                    foreach ($match[1] as $string) {
+                        /* Create references only for known symbols and not reserved words. */
+                        if (!in_array($string, $this->_langmap['reserved']) &&
+                            $index->isSymbol($string)) {
+                            $result = $index->reference($string, $fileId, $linenum);
+                            if (is_a($result, 'PEAR_Error')) {
+                                return $result;
+                            }
+                        }
+                    }
+                    $linenum++;
+                }
+                $linenum--;
+            }
+            list($btype, $frag) = $parser->nextFrag();
+        }
+    }
+
+    /**
+     * Process a chunk of code
+     *
+     * Basically, look for anything that looks like a symbol, and if
+     * it is then make it a hyperlink, unless it's a reserved word in this
+     * language.
+     *
+     * @param string $code Reference to the code to markup.
+     */
+    function processCode($code, $altsources = array())
+    {
+        global $index, $sourceid;
+
+        // Make sure spacing is correct.
+        $code = Horde_Text_Filter::filter($code, 'space2html', array('charset' => Horde_Nls::getCharset(), 'encode' => true, 'encode_all' => true));
+
+        // Split all the symbols.
+        preg_match_all('/(^|[^\w\#&])([\w~][\w]*)\b/', $code, $match);
+
+        // Replace symbol by link unless it's a reserved word.
+        $replaced = array();
+        foreach ($match[2] as $id => $string) {
+            if (!in_array($string, $this->_langmap['reserved']) &&
+                !in_array($match[0][$id], $replaced) && $idx = $index->isSymbol($string, $altsources)) {
+
+                $link = Horde::applicationUrl(Horde_Util::addParameter('symbol.php', 'i', $idx));
+                $link = Horde_Util::addParameter($link, 'source', $sourceid);
+                $match0 = str_replace($string, '<a href="' . $link . '" class="fixed"><span class="symbol">' . $string . "</span></a>", $match[0][$id]);
+                $code = str_replace($match[0][$id], $match0, $code);
+                $replaced[] = $match[0][$id];
+            } elseif (in_array($string, $this->_langmap['reserved']) && !in_array($match[0][$id], $replaced)) {
+                $match0 = str_replace($string, '<span class="reserved">' . $string . "</span>", $match[0][$id]);
+                $code = str_replace($match[0][$id], $match0, $code);
+                $replaced[] = $match[0][$id];
+            }
+        }
+
+        return $code;
+    }
+}
diff --git a/luxor/lib/Luxor.php b/luxor/lib/Luxor.php
new file mode 100644 (file)
index 0000000..91110f3
--- /dev/null
@@ -0,0 +1,460 @@
+<?php
+/**
+ * @author  Jan Schneider <jan@horde.org>
+ * @since   Luxor 0.1
+ * @package Luxor
+ */
+class Luxor
+{
+    /**
+     * Initial app setup code.
+     */
+    public static function initialize()
+    {
+        global $sources, $sourceid, $source, $files, $index, $pathname;
+
+        require LUXOR_BASE . '/config/sources.php';
+
+        /* Default to the first source; overridden elsewhere if necessary. */
+        $sourceid = Horde_Util::getFormData('source');
+        if (!isset($sources[$sourceid])) {
+            $sourceid = key($sources);
+        }
+        $source = $sources[$sourceid];
+        $files = Luxor_Files::factory($source['driver'], $source);
+        $index = Luxor_Driver::factory($sourceid);
+        $pathname = Luxor::fixPaths(Horde_Util::getFormData('f'));
+    }
+
+    /**
+     * Generate a URL that links into Luxor.
+     *
+     * @param string $uri     The path being browsed.
+     * @param array  $args    Key/value pair of any GET parameters to append
+     * @param string $anchor  Anchor entity name
+     */
+    function url($uri = '', $args = array(), $anchor = '')
+    {
+        global $conf, $sourceid;
+
+        $arglist = array_merge(array('source' => $sourceid), $args);
+
+        if ($conf['options']['urls'] == 'rewrite') {
+            if (substr($uri, 0, 1) == '/') {
+                $uri = substr($uri, 1);
+            }
+        } else {
+            $arglist['f'] = $uri;
+            $uri = 'source.php';
+        }
+
+        $url = Horde_Util::addParameter(Horde::applicationUrl($uri), $arglist);
+        if (!empty($anchor)) {
+            $url .= "#$anchor";
+        }
+
+        return $url;
+    }
+
+    /**
+     * Generate a list of sources available from this installation
+     * of Luxor.
+     *
+     * @return XHTML code representing links to the repositories
+     */
+    function sources()
+    {
+        global $source, $sources;
+
+        $arr = array();
+        foreach ($sources as $key => $val) {
+            if ($val != $source) {
+                $arr[] = Horde::link(Luxor::url('', array('source' => $key))) .
+                    htmlspecialchars($val['name']) . '</a>';
+            }
+        }
+
+        if (count($arr)) {
+            return _("Other Sources") . ': ' . implode(', ', $arr);
+        } else {
+            return '';
+        }
+    }
+
+    /**
+     * Sanitizes path names passed by the user.
+     *
+     * @param string $node  The path name to clean up.
+     *
+     * @return string       The cleaned up path.
+     */
+    function fixPaths($node)
+    {
+        global $files;
+
+        $node = '/' . $node;
+        $node = preg_replace('|/[^/]+/\.\./|', '/', $node);
+        $node = preg_replace('|/\.\./|', '/', $node);
+        if ($files->isDir($node)) {
+            $node .= '/';
+        }
+
+        return preg_replace('|//+|', '/', $node);
+    }
+
+    /**
+     *
+     */
+    function outfun($str, $arr)
+    {
+        return str_replace("\n", "\n" . array_shift($arr), $str);
+    }
+
+    function dirExpand($dir)
+    {
+        global $files, $mime_drivers, $mime_drivers_map;
+
+        $result = Horde::loadConfiguration('mime_drivers.php', array('mime_drivers', 'mime_drivers_map'), 'horde');
+        extract($result);
+        $result = Horde::loadConfiguration('mime_drivers.php', array('mime_drivers', 'mime_drivers_map'), 'luxor');
+        if (isset($result['mime_drivers'])) {
+            $mime_drivers = Horde_Array::array_merge_recursive_overwrite($mime_drivers, $result['mime_drivers']);
+        }
+        if (isset($result['mime_drivers_map'])) {
+            $mime_drivers_map = Horde_Array::array_merge_recursive_overwrite($mime_drivers_map, $result['mime_drivers_map']);
+        }
+
+        $nodes = $files->getDir($dir);
+        if (is_a($nodes, 'PEAR_Error')) {
+            return $nodes;
+        }
+        $index = $files->getIndex($dir);
+        if (is_a($index, 'PEAR_Error')) {
+            return $index;
+        }
+
+        if ($dir != '/') {
+            array_unshift($nodes, '../');
+        }
+
+        $list = array();
+        foreach ($nodes as $node) {
+            $link = Luxor::url($dir . $node);
+            $modtime = $files->getFiletime($dir . $node);
+            $modtime = $modtime ? gmdate('Y-m-d H:i:s', $modtime) : '-';
+            $description = empty($index[$node]) ? '&nbsp;' : $index[$node];
+
+            if (substr($node, -1) == '/') {
+                $filesize = '-';
+                $bytes = '';
+                if ($node == '../') {
+                    $icon = Horde::img('parent.png', _("Up to parent"));
+                    $node = _("Parent Directory");
+                } else {
+                    $icon = Horde::img('folder.png', $node);
+                }
+            } else {
+                if (preg_match('/^.*\.[oa]$|^core$|^00-INDEX$/', $node)) {
+                    continue;
+                }
+                $icon = Horde::img(Horde_Mime_Viewer::getIcon(Horde_Mime_Magic::filenameToMime($node)), '', '', '');
+                $filesize = $files->getFilesize($dir . $node);
+                if ($filesize < 1 << 10) {
+                    $bytes = _("bytes");
+                } else {
+                    $bytes = _("kbytes");
+                    $filesize = $filesize >> 10;
+                }
+            }
+
+            $list[] = array('icon'        => $icon,
+                            'name'        => $node,
+                            'link'        => $link,
+                            'filesize'    => $filesize,
+                            'bytes'       => $bytes,
+                            'modtime'     => $modtime,
+                            'description' => $description);
+        }
+
+        return $list;
+    }
+
+    /**
+     * Prints a descriptive blurb at the end of directory listings.
+     *
+     * @param Luxor_File $files  An instance of Luxor_File.
+     * @param string $path       The directory where to look for a README file.
+     */
+    function dirDesc($files, $path)
+    {
+        $table_head = '<br /><br /><table width="100%" cellpadding="5"><tr><td class="text"><span class="fixed">';
+        $table_foot = '</span></td></tr></table>';
+        if (file_exists($filename = $files->toReal($path . '/README')) ||
+            file_exists($filename = $files->toReal($path . '/README.txt'))) {
+            $contents = file_get_contents($filename);
+
+            return $table_head . Horde_Text_Filter::filter($contents, 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO)) . $table_foot;
+        } elseif ($filename = file_exists($files->toReal($path . '/README.html'))) {
+            global $mime_drivers, $mime_drivers_map;
+            $result = Horde::loadConfiguration('mime_drivers.php', array('mime_drivers', 'mime_drivers_map'), 'horde');
+            extract($result);
+            $result = Horde::loadConfiguration('mime_drivers.php', array('mime_drivers', 'mime_drivers_map'), 'luxor');
+            $mime_drivers = Horde_Array::array_merge_recursive_overwrite($mime_drivers, $result['mime_drivers']);
+            $mime_drivers_map = Horde_Array::array_merge_recursive_overwrite($mime_drivers_map, $result['mime_drivers_map']);
+
+            $contents = file_get_contents($filename);
+
+            $mime_part = new Horde_Mime_Part('text/plain', $contents);
+            $mime_part->setName('README');
+            $viewer = Horde_Mime_Viewer::factory($mime_part);
+            return $table_head . $viewer->render() . $table_foot;
+        }
+    }
+
+    /**
+     * Smaller version of the markupFile() function meant for marking up
+     * the descriptions in source directory listings.
+     *
+     * @see markupFile()
+     *
+     * @todo most of this can be done by Horde_Text::toHtml()
+     */
+    function markupString($string, $virtp)
+    {
+        $string = htmlspecialchars($string);
+
+        // HTMLify email addresses and urls.
+        $string = preg_replace('#((ftp|http|nntp|snews|news)://(\w|\w\.\w|\~|\-|\/|\#)+(?!\.\b))#',
+                               '<a href="$1">$1</a>', $string);
+
+        // HTMLify file names, assuming file is in the current directory.
+        $string = preg_replace('#\b(([\w\-_\/]+\.(c|h|cc|cp|hpp|cpp|java))|README)\b#e',
+                               '"<a href=\" . Luxor::url("' . $virtp . '$1") . "$1</a>"', $string);
+
+        return $string;
+    }
+
+    function whereMenu()
+    {
+        global $pathname;
+
+        $res = '';
+        $wherePath = '';
+        foreach (explode('/', $pathname) as $dir) {
+            $wherePath .= $dir ? "/$dir" : '';
+            if (!empty($dir)) {
+                $res .= ' :: ' . Horde::link(Luxor::url($wherePath)) .
+                    htmlspecialchars($dir) . '</a>';
+            }
+        }
+        return $res;
+    }
+
+    function fileRef($desc, $css, $path, $line = 0, $args = array())
+    {
+        if ($line > 0 && strlen($line) < 3) {
+            $line = str_repeat('0', (3 - strlen($line))) . $line;
+        }
+
+        return '<a href="' . Luxor::url($path, $args, $line > 0 ? 'l' . $line : '') . '" class="' . htmlspecialchars($css) . '">' .
+            htmlspecialchars($desc) . '</a>';
+    }
+
+    function incRef($name, $css, $file, $paths = array())
+    {
+        global $files;
+
+        foreach ($paths as $dir) {
+            $dir = preg_replace('|/+$|', '', $dir);
+            $path = $dir . '/' . $file;
+            if ($files->isFile($path)) {
+                return Luxor::fileRef($name, $css, $path);
+            }
+        }
+
+        return htmlspecialchars($name);
+    }
+
+    /**
+     * Check if the given item is restricted from being shown.
+     *
+     * @param string $filename  The filename to check
+     *
+     * @return boolean  Whether or not the item is allowed to be displayed
+     */
+    function isRestricted($filename)
+    {
+        global $source;
+
+        if (Horde_Auth::isAdmin()) {
+            return false;
+        }
+
+        if (isset($source['restrictions']) && is_array($source['restrictions'])) {
+            foreach ($source['restrictions'] as $restriction) {
+                if (preg_match('|' . str_replace('|', '\|', $restriction) . '|', $filename)) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Check if the given directory is filtered out.
+     *
+     * @param string $dir  The path to check.
+     *
+     * @return boolean  True if the directory should be shown/parsed, false otherwise.
+     */
+    function isDirParsed($dir)
+    {
+        global $source;
+
+        if (isset($source['dirFilter']) && is_array($source['dirFilter'])) {
+            foreach ($source['dirFilter'] as $filter) {
+                if (preg_match('/' . str_replace('/', '\/', substr($filter, 1)) . '/', $dir)) {
+                    return (substr($filter, 0, 1) == '+');
+                }
+            }
+        }
+
+        if (isset($source['dirUnmatched'])) {
+            return $source['dirUnmatched'];
+        }
+        return true;
+    }
+
+    /**
+     * Check if the given file should be parsed an/or displayed.
+     *
+     * @param string $file  The filename to check.
+     *
+     * @return boolean  True if the file should be shown/parsed, false otherwise.
+     */
+    function isFileParsed($file)
+    {
+        global $source;
+
+        if (isset($source['fileFilter']) && is_array($source['fileFilter'])) {
+            foreach ($source['fileFilter'] as $filter) {
+                if (preg_match('/' . str_replace('/', '\/', substr($filter, 1)) . '/', $file, $matches)) {
+                    return (substr($filter, 0, 1) == '+');
+                }
+            }
+        }
+
+        if (isset($source['fileUnmatched'])) {
+            return $source['fileUnmatched'];
+        }
+        return true;
+    }
+
+    /**
+     * Pre- and post-fix every line of a string with strings.
+     */
+    function fixString($string, $pre = '', $post = '')
+    {
+        $lines = preg_split('(\r\n|\n|\r)', $string);
+        $res = '';
+        foreach ($lines as $line) {
+            $res .= !empty($res) ? "\n" : '';
+            $res .= $pre . Horde_Text_Filter::filter($line, 'space2html', array('charset' => Horde_Nls::getCharset(), 'encode' => true, 'encode_all' => true)) . $post;
+        }
+        return $res;
+    }
+
+    /**
+     */
+    function markupfile($pathname, $fileh, $ann = array())
+    {
+        global $files, $conf;
+
+        preg_match_all('|^(.*/)|', $pathname, $dir);
+        $dir = $dir[0];
+
+        /* Determine the file's language and create a Luxor_Lang
+         * instance. */
+        $lang = &Luxor_Lang::builder($files, $pathname);
+        if (is_a($lang, 'PEAR_Error')) {
+            return $lang;
+        }
+
+        $html = '<table cellspacing="0" width="100%" class="text">';
+
+        // A source code file.
+        if (!$lang) {
+            return false;
+        }
+
+        $parser = new Luxor_SimpleParse($fileh, 1, $lang->_langmap['spec']);
+        $linenum = 1;
+
+        list($btype, $frag) = $parser->nextFrag();
+        $ofrag = '';
+        while ($frag) {
+            $frag = preg_replace('/([&<>])/', chr(0) . '$1', $frag);
+            switch ($btype) {
+            case 'comment':
+                // Comment
+                // Convert mail adresses to mailto:
+                // &freetextmarkup($frag);
+                // $lang->processComment(\$frag);
+                $frag = Luxor::fixString($frag, '<span class="comment">', '</span>');
+                break;
+
+            case 'string':
+                $frag = Luxor::fixString($frag, '<span class="string">', '</span>');
+                break;
+
+            case 'include':
+                // Include directive
+                $frag = $lang->processInclude($frag, $dir);
+                break;
+
+            case 'variable':
+                if (!empty($conf['options']['use_show_var'])) {
+                    $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));
+                    $frag = Luxor::fixString($frag, $pre, '</span></span>');
+                } else {
+                    $frag = Luxor::fixString($frag, '<span class="variable">', '</span>');
+                }
+                break;
+
+            default:
+                // Code
+                // somehow get $source['may_reference'] into the second parameter here.
+                $frag = $lang->processCode($frag);
+            }
+
+            $frag = preg_replace('/\0([&<>])/', '$1', $frag);
+
+            $ofrag .= $frag;
+            list($btype, $frag) = $parser->nextFrag();
+        }
+
+        $lines = preg_split('(\r\n|\n|\r)', $ofrag);
+        foreach ($lines as $line) {
+            $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";
+        }
+        return $html . '</table>';
+    }
+
+    /**
+     * Build Luxor's list of menu items.
+     */
+    function getMenu($returnType = 'object')
+    {
+        global $registry;
+
+        $menu = new Horde_Menu(Horde_Menu::MASK_ALL);
+        $menu->add(Horde::applicationUrl('source.php'), _("_Browse"), 'luxor.png');
+
+        if ($returnType == 'object') {
+            return $menu;
+        } else {
+            return $menu->render();
+        }
+    }
+}
diff --git a/luxor/lib/SimpleParse.php b/luxor/lib/SimpleParse.php
new file mode 100644 (file)
index 0000000..53318b7
--- /dev/null
@@ -0,0 +1,178 @@
+<?php
+/**
+ * $Horde: luxor/lib/SimpleParse.php,v 1.10 2005/06/13 03:20:27 selsky Exp $
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @since   Luxor 0.1
+ * @package Luxor
+ */
+class Luxor_SimpleParse {
+
+    /** File handle. */
+    var $_fileh;
+
+    /** Current linenumber. */
+    var $_line = 0;
+
+    /** Fragments in queue. */
+    var $_frags = array();
+
+    /** Array of body type ids. */
+    var $_bodyid = array();
+
+    /** Fragment closing delimiters. */
+    var $_term = array();
+
+    /** Fragmentation regexp. */
+    var $_split = '';
+
+    /** Fragment opening regexp. */
+    var $_open = '';
+
+    /** Tab width. */
+    var $_tabwidth = 8;
+
+    /**
+     * Constructor for the source code parser.
+     *
+     * @param ressource $file     The file handler of the file to parse.
+     *
+     * @param int       $tabhint  (Unused?)
+     *
+     * @param array     $blksep   An array containing block seperators for
+     *                            this file's type.
+     *                            Essentially a 'spec' entry from the
+     *                            $languages array.
+     */
+    function Luxor_SimpleParse(&$fileh, $tabhint, $blksep)
+    {
+        $this->_fileh = $fileh;
+
+        /* Get possible block opening and closing delimiters and their meaning. */
+        $open_a = array();
+        while ($splice = array_splice($blksep, 0, 3)) {
+            $this->_bodyid[] = $splice[0];
+            $open_a[]        = $splice[1];
+            $this->_term[]   = $splice[2];
+        }
+
+        /* Build regexps for opening and delimiters and fragment splitting. */
+        foreach ($open_a as $open_s) {
+            $this->_open  .= "($open_s)|";
+            $this->_split .= "$open_s|";
+        }
+        $this->_open = substr($this->_open, 0, -1);
+        $this->_open = str_replace('/', '\\/', $this->_open);
+
+        foreach ($this->_term as $term) {
+            if (empty($term)) {
+                continue;
+            }
+            $this->_split .= "$term|";
+        }
+        $this->_split = substr($this->_split, 0, -1);
+        $this->_split = str_replace('/', '\\/', $this->_split);
+    }
+
+    /**
+     * Returns the content and type of the next code fragment.
+     */
+    function nextFrag()
+    {
+        $btype = null;
+        $frag  = null;
+        $line  = '';
+
+        while (true) {
+            // read one more line if we have processed
+            // all of the previously read line
+            if (!count($this->_frags)) {
+                $line = fgets($this->_fileh);
+                $this->_line++;
+
+                if ($this->_line <= 2 &&
+                    preg_match('/^.*-[*]-.*?[ \t;]tab-width:[ \t]*([0-9]+).*-[*]-/',
+                               $line, $match)) {
+                    $this->_tabwidth = $match[1];
+                }
+
+                // Optimize for common case.
+                if (!empty($line)) {
+                    $line = preg_replace('/^(\t+)/e', "str_repeat(' ', $this->_tabwidth * strlen('\\1'))", $line);
+                    if (preg_match('/([^\t]*)\t/e', $line, $match)) {
+                        $tabs = str_repeat(' ', $this->_tabwidth - (strlen($match[1]) % $this->_tabwidth));
+                        $line = preg_replace('/([^\t]*)\t/', '\1' . $tabs, $line);
+                    }
+
+                    // split the line into fragments
+                    $this->_frags = preg_split('/(' . $this->_split . ')/', $line, -1, PREG_SPLIT_DELIM_CAPTURE);
+                }
+            }
+
+            if (!count($this->_frags)) {
+                break;
+            }
+
+            // skip empty fragments
+            if (empty($this->_frags[0])) {
+                array_shift($this->_frags);
+                continue;
+            }
+
+            if (!empty($frag)) {
+                // Check if we are inside a fragment
+                if (!is_null($btype)) {
+                    $next = array_shift($this->_frags);
+
+                    // Some ugly special casing for escaped quotes.
+                    if (substr($frag, -1, 1) == '\\' && substr($frag, -2, 2) != '\\\\' &&
+                            (substr($next, 0, 1) == '"' || substr($next, 0, 1) == "'")) {
+                        $frag .= $next;
+                        $next = substr($next, 1);
+                    } else {
+                        // Add to the fragment
+                        $frag .= $next;
+                    }
+
+                    // We are done if this was the terminator
+                    if (preg_match('/^' . str_replace('/', '\\/', $this->_term[$btype]) . '$/', $next)) {
+                        // Return what we have
+                        break;
+                    }
+                } else {
+                    // Is the start of a frag?
+                    if (preg_match('/^' . $this->_open . '$/', $this->_frags[0])) {
+                        // Return what we have
+                        break;
+                    } else {
+                        // Add to the fragment and keep looking
+                        $frag .= array_shift($this->_frags);
+                    }
+                }
+            } else {
+                // Find the blocktype of the current block
+                $frag = array_shift($this->_frags);
+                if (preg_match_all('/^' . $this->_open . '$/', $frag, $match)) {
+                    array_shift($match);
+                    foreach ($match as $id => $matched) {
+                        if ($matched[0] == $frag) {
+                            $btype = $id;
+                            break;
+                        }
+                    }
+                    if (is_null($btype)) {
+                        //return the fragment as unknown.
+                        break;
+                    }
+                }
+            }
+        }
+
+        // Clear text block type
+        if (!is_null($btype)) {
+            $btype = $this->_bodyid[$btype];
+        }
+        return array($btype, $frag);
+    }
+
+}
diff --git a/luxor/lib/Tagger.php b/luxor/lib/Tagger.php
new file mode 100644 (file)
index 0000000..f4d6cf4
--- /dev/null
@@ -0,0 +1,104 @@
+<?php
+/**
+ * $Horde: luxor/lib/Tagger.php,v 1.9 2008/08/01 21:09:31 chuck Exp $
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @since   Luxor 0.1
+ * @package Luxor
+ */
+class Luxor_Tagger {
+
+    /**
+     * Indexes a file.
+     * Parses the files contents for symbols and creates indexes in the
+     * storage backend for the file itself and the symbols it defines.
+     *
+     * @param Luxor_Driver $files   An instance of a storage backend driver.
+     * @param string $pathname      The (relative) pathname of the file to
+     *                              be processed.
+     * @param Luxor_Lang $lang      The language object for $pathname.
+     *
+     * @return mixed                A PEAR_Error if an error occured.
+     */
+    function processFile($files, $pathname, $lang)
+    {
+        global $index;
+
+        /* Get the unique ID for this file. */
+        $fileId = $index->fileId($pathname);
+        if ($fileId === false) {
+            $fileId = $index->createFileId($pathname, '', $files->getFiletime($pathname));
+        } elseif (is_a($fileId, 'PEAR_Error')) {
+            return $fileId;
+        }
+
+        /* Update the file's status. */
+        $result = $index->toIndex($fileId);
+        if ($result === false) {
+            return PEAR::raiseError(sprintf(_("%s was already indexed."), $pathname));
+        } elseif (is_a($result, 'PEAR_Error')) {
+            return $result;
+        }
+
+        /* Empty symbol cache. */
+        $index->clearCache();
+
+        /* Find symbols defined by this file. */
+        $path = $files->tmpFile($pathname);
+        if (!$path) {
+            return PEAR::raiseError(sprintf(_("Can't create copy of file %s."), $pathname));
+        }
+        $result = $lang->indexFile($path, $fileId);
+        if (is_a($result, 'PEAR_Error')) {
+            return $result;
+        }
+    }
+
+    /**
+     * References a file.
+     * Parses the files contents for symbols and creates references to the
+     * files where these symbols are defined.
+     *
+     * @param Luxor_Driver $files   An instance of a storage backend driver.
+     * @param string $pathname      The (relative) pathname of the file to
+     *                              be referenced.
+     * @param Luxor_Lang $lang      The language object for $pathname.
+     *
+     * @return mixed                A PEAR_Error if an error occured.
+     */
+    function processRefs($files, $pathname, $lang)
+    {
+        global $index;
+
+        /* Get the unique ID for this file. */
+        $fileId = $index->fileId($pathname);
+        if ($fileId === false) {
+            $fileId = $index->createFileId($pathname, '', $files->getFiletime($pathname));
+        }
+        if (is_a($fileId, 'PEAR_Error')) {
+            return $fileId;
+        }
+
+        /* Update the file's status. */
+        $result = $index->toReference($fileId);
+        if ($result === false) {
+            return PEAR::raiseError(sprintf(_("%s was already indexed."), $pathname));
+        } elseif (is_a($result, 'PEAR_Error')) {
+            return $result;
+        }
+
+        /* Empty symbol cache. */
+        $index->clearCache();
+
+        /* Create references to symbol definitions. */
+        $path = $files->tmpFile($pathname);
+        if (!$path) {
+            return PEAR::raiseError(sprintf(_("Can't create copy of file %s."), $pathname));
+        }
+        $result = $lang->referenceFile($path, $fileId);
+        if (is_a($result, 'PEAR_Error')) {
+            return $result;
+        }
+    }
+
+}
diff --git a/luxor/locale/de_DE/LC_MESSAGES/luxor.mo b/luxor/locale/de_DE/LC_MESSAGES/luxor.mo
new file mode 100644 (file)
index 0000000..ca6a29c
Binary files /dev/null and b/luxor/locale/de_DE/LC_MESSAGES/luxor.mo differ
diff --git a/luxor/locale/es_ES/LC_MESSAGES/luxor.mo b/luxor/locale/es_ES/LC_MESSAGES/luxor.mo
new file mode 100644 (file)
index 0000000..91fea88
Binary files /dev/null and b/luxor/locale/es_ES/LC_MESSAGES/luxor.mo differ
diff --git a/luxor/locale/ro_RO/LC_MESSAGES/luxor.mo b/luxor/locale/ro_RO/LC_MESSAGES/luxor.mo
new file mode 100644 (file)
index 0000000..474bd42
Binary files /dev/null and b/luxor/locale/ro_RO/LC_MESSAGES/luxor.mo differ
diff --git a/luxor/po/.htaccess b/luxor/po/.htaccess
new file mode 100644 (file)
index 0000000..3a42882
--- /dev/null
@@ -0,0 +1 @@
+Deny from all
diff --git a/luxor/po/README b/luxor/po/README
new file mode 100644 (file)
index 0000000..a985e94
--- /dev/null
@@ -0,0 +1 @@
+see horde/po/README
diff --git a/luxor/po/de_DE.po b/luxor/po/de_DE.po
new file mode 100644 (file)
index 0000000..3b2824d
--- /dev/null
@@ -0,0 +1,181 @@
+# German translations for Luxor.
+# Copyright 2003-2009 The Horde Project
+# This file is distributed under the same license as the Luxor package.
+# Jan Schneider <jan@horde.org>, 2003-2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Luxor 0.1-cvs\n"
+"Report-Msgid-Bugs-To: dev@lists.horde.org\n"
+"POT-Creation-Date: 2008-09-18 11:24+0200\n"
+"PO-Revision-Date: 2008-09-18 12:08+0200\n"
+"Last-Translator: Jan Schneider <jan@horde.org>\n"
+"Language-Team: i18n@lists.horde.org\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: symbol.php:74
+#, php-format
+msgid "%s :: Symbol \"%s\""
+msgstr "%s :: Symbol \"%s\""
+
+#: lib/Tagger.php:38 lib/Tagger.php:85
+#, php-format
+msgid "%s was already indexed."
+msgstr "%s wurde bereits indiziert."
+
+#: scripts/indexer.php:47
+msgid "Can't be both verbose and quiet"
+msgstr "Ausführlich und Leise ist nicht gleichzeitig möglich"
+
+#: lib/Tagger.php:49 lib/Tagger.php:96
+#, php-format
+msgid "Can't create copy of file %s."
+msgstr "Kopie von %s konnte nicht erstellt werden."
+
+#: lib/Files/plain.php:85
+#, php-format
+msgid "Can't open directory %s"
+msgstr "Verzeichnis %s konnte nicht geöffnet werden"
+
+#: lib/Lang/Generic.php:117
+#, php-format
+msgid "Can't open file %s."
+msgstr "Datei %s konnte nicht geöffnet werden."
+
+#: lib/Lang/Generic.php:75
+msgid "Can't run ectags."
+msgstr "ectags konnte nicht ausgeführt werden."
+
+#: source.php:90
+#, php-format
+msgid "Could not markup file %s."
+msgstr "Die Datei %s konnte nicht ausgezeichnet werden."
+
+#: scripts/indexer.php:88
+msgid "DONE"
+msgstr "FERTIG"
+
+#: templates/directory.html.php:6
+msgid "Date (GMT)"
+msgstr "Datum (GMT)"
+
+#: templates/symbol.html.php:8
+msgid "Declarations"
+msgstr "Definitionen"
+
+#: search.php:57
+msgid "Declared as "
+msgstr "Definiert als "
+
+#: symbol.php:38
+#, php-format
+msgid "Declared as a %s"
+msgstr "Definiert als ein(e) %s"
+
+#: templates/directory.html.php:7
+msgid "Description"
+msgstr "Beschreibung"
+
+#: source.php:143
+#, php-format
+msgid "Directory Listing :: %s"
+msgstr "Verzeichnis :: %s"
+
+#: lib/Lang/Generic.php:65
+#, php-format
+msgid "Exuberant ctags version 5 or above required, found version %s"
+msgstr "Exuberant ctags Version 5 oder höher wird benötigt, %s wurde gefunden"
+
+#: scripts/indexer.php:69
+#, php-format
+msgid "Indexing %s"
+msgstr "Indiziere %s"
+
+#: symbol.php:44 symbol.php:68
+#, php-format
+msgid "Line %s"
+msgstr "Zeile %s"
+
+#: templates/headerbar.inc:3
+msgid "Location:"
+msgstr "Position:"
+
+#: source.php:146
+#, php-format
+msgid "Markup of %s"
+msgstr "Auszeichnung von %s"
+
+#: templates/directory.html.php:4
+msgid "Name"
+msgstr "Name"
+
+#: lib/Luxor.php:60
+msgid "Other Sources"
+msgstr "Andere Quellen"
+
+#: lib/Luxor.php:138
+msgid "Parent Directory"
+msgstr "Verzeichnis hoch"
+
+#: templates/symbol.html.php:20
+msgid "Referenced in"
+msgstr "Referenziert in"
+
+#: scripts/indexer.php:74
+#, php-format
+msgid "Referencing %s"
+msgstr "Referenziere %s"
+
+#: templates/directory.html.php:5
+msgid "Size"
+msgstr "Größe"
+
+#: scripts/indexer.php:81
+msgid "Skipped files:"
+msgstr "Übersprungene Dateien:"
+
+#: templates/menu.inc:13
+msgid "Symbol Search"
+msgstr "Symbolsuche"
+
+#: search.php:32
+#, php-format
+msgid "Symbol Search for \"%s\""
+msgstr "Symbolsuche nach \"%s\""
+
+#: symbol.php:21
+msgid "Symbol not found"
+msgstr "Symbol nicht gefunden"
+
+#: source.php:84
+#, php-format
+msgid "The file %s can't be opened or doesn't exist."
+msgstr "Die Datei %s konnte nicht geöffnet werden oder existiert nicht."
+
+#: templates/headerbar.inc:10
+msgid "Tracking Branch"
+msgstr "Branch beobachten"
+
+#: lib/Luxor.php:137
+msgid "Up to parent"
+msgstr "Ein Verzeichnis höher"
+
+#: source.php:34
+#, php-format
+msgid "You do not have permission to view %s."
+msgstr "Sie haben nicht genügend Rechte, um %s anzuzeigen."
+
+#: lib/Luxor.php:448
+msgid "_Browse"
+msgstr "_Liste"
+
+#: lib/Luxor.php:149
+msgid "bytes"
+msgstr "Bytes"
+
+#: lib/Luxor.php:151
+msgid "kbytes"
+msgstr "kBytes"
diff --git a/luxor/po/es_ES.po b/luxor/po/es_ES.po
new file mode 100644 (file)
index 0000000..a841462
--- /dev/null
@@ -0,0 +1,169 @@
+# Spanish translations for luxor package
+# Traducciones al español para el paquete luxor.
+# Copyright 2008-2009 The Horde Project
+# This file is distributed under the same license as the luxor package.
+# Automatically generated, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Luxor 1.0-cvs\n"
+"Report-Msgid-Bugs-To: dev@lists.horde.org\n"
+"POT-Creation-Date: 2007-11-22 17:11+0100\n"
+"PO-Revision-Date: 2008-03-18 20:18+0100\n"
+"Last-Translator: Manuel P. Ayala <mayala@unex.es>\n"
+"Language-Team: i18n@lists.horde.org\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ident.php:73
+#, php-format
+msgid "%s :: Symbol \"%s\""
+msgstr "%s :: Símbolo \"%s\""
+
+#: lib/Tagger.php:46 lib/Tagger.php:101
+#, php-format
+msgid "%s was already indexed."
+msgstr "%s ya estaba indexado."
+
+#: lib/Tagger.php:30 lib/Tagger.php:84
+#, php-format
+msgid "Can't build language class for file %s."
+msgstr "No se puede contruir la clase idioma del archivo %s."
+
+#: lib/Tagger.php:57 lib/Tagger.php:112
+#, php-format
+msgid "Can't create copy of file %s."
+msgstr "No se puede crear una copia del archivo %s."
+
+#: lib/Files/plain.php:85
+#, php-format
+msgid "Can't open directory %s"
+msgstr "No se puede abrir el directorio %s"
+
+#: lib/Lang/Generic.php:117
+#, php-format
+msgid "Can't open file %s."
+msgstr "No se puede abrir el archivo %s."
+
+#: lib/Lang/Generic.php:75
+msgid "Can't run ectags."
+msgstr "No se puede ejecutar ectags."
+
+#: source.php:95
+#, php-format
+msgid "Could not markup file %s."
+msgstr "No se puede marcar el archivo %s."
+
+#: source.php:18
+msgid "Date (GMT)"
+msgstr "Fecha (GMT)"
+
+#: templates/ident/ident.html:7
+msgid "Declarations"
+msgstr "Declaraciones"
+
+#: search.php:60
+msgid "Declared as "
+msgstr "Declarada como "
+
+#: ident.php:40
+#, php-format
+msgid "Declared as a %s"
+msgstr "Declarada como una %s"
+
+#: source.php:19
+msgid "Description"
+msgstr "Descripción"
+
+#: source.php:150
+#, php-format
+msgid "Directory Listing :: %s"
+msgstr "Listado del directorio :: %s"
+
+#: lib/Lang/Generic.php:65
+#, php-format
+msgid "Exuberant ctags version 5 or above required, found version %s"
+msgstr ""
+"Se necesita exuberant ctags versión 5 o superior, se ha encontrado la "
+"versión %s"
+
+#: scripts/genxref.php:60
+#, php-format
+msgid "Indexing %s"
+msgstr "Indexando %s"
+
+#: ident.php:46 ident.php:69
+#, php-format
+msgid "Line %s"
+msgstr "Línea %s"
+
+#: templates/headerbar.inc:2
+msgid "Location:"
+msgstr "Ubicación:"
+
+#: source.php:153
+#, php-format
+msgid "Markup of %s"
+msgstr "Marcador de %s"
+
+#: source.php:16
+msgid "Name"
+msgstr "Nombre"
+
+#: lib/Luxor.php:60
+msgid "Other Sources"
+msgstr "Otros orígenes"
+
+#: lib/Luxor.php:138
+msgid "Parent Directory"
+msgstr "Directorio anterior"
+
+#: templates/ident/ident.html:8
+msgid "Referenced in"
+msgstr "Referenciado en"
+
+#: scripts/genxref.php:65
+#, php-format
+msgid "Referencing %s"
+msgstr "Remitiendo a %s"
+
+#: source.php:17
+msgid "Size"
+msgstr "Tamaño"
+
+#: search.php:35
+#, php-format
+msgid "Symbol Search for \"%s\""
+msgstr "Búsqueda simbólica de \"%s\""
+
+#: source.php:89
+#, php-format
+msgid "The file %s can't be opened or doesn't exist."
+msgstr "No se puede abrir el archivo %s o no existe."
+
+#: templates/headerbar.inc:9
+msgid "Tracking Branch"
+msgstr "Rama de seguimiento"
+
+#: lib/Luxor.php:137
+msgid "Up to parent"
+msgstr "Nivel anterior"
+
+#: source.php:39
+#, php-format
+msgid "You do not have permission to view %s."
+msgstr "No dispone de privilegios para ver %s."
+
+#: lib/Luxor.php:448
+msgid "_Browse"
+msgstr "_Examinar"
+
+#: lib/Luxor.php:149
+msgid "bytes"
+msgstr "bytes"
+
+#: lib/Luxor.php:151
+msgid "kbytes"
+msgstr "kbytes"
diff --git a/luxor/po/luxor.pot b/luxor/po/luxor.pot
new file mode 100644 (file)
index 0000000..585b289
--- /dev/null
@@ -0,0 +1,170 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright YEAR Horde Project
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: dev@lists.horde.org\n"
+"POT-Creation-Date: 2008-08-01 10:44+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ident.php:79
+#, php-format
+msgid "%s :: Symbol \"%s\""
+msgstr ""
+
+#: lib/Tagger.php:46 lib/Tagger.php:101
+#, php-format
+msgid "%s was already indexed."
+msgstr ""
+
+#: lib/Tagger.php:30 lib/Tagger.php:84
+#, php-format
+msgid "Can't build language class for file %s."
+msgstr ""
+
+#: lib/Tagger.php:57 lib/Tagger.php:112
+#, php-format
+msgid "Can't create copy of file %s."
+msgstr ""
+
+#: lib/Files/plain.php:85
+#, php-format
+msgid "Can't open directory %s"
+msgstr ""
+
+#: lib/Lang/Generic.php:117
+#, php-format
+msgid "Can't open file %s."
+msgstr ""
+
+#: lib/Lang/Generic.php:75
+msgid "Can't run ectags."
+msgstr ""
+
+#: source.php:95
+#, php-format
+msgid "Could not markup file %s."
+msgstr ""
+
+#: source.php:18
+msgid "Date (GMT)"
+msgstr ""
+
+#: templates/ident/ident.html:7
+msgid "Declarations"
+msgstr ""
+
+#: search.php:60
+msgid "Declared as "
+msgstr ""
+
+#: ident.php:43
+#, php-format
+msgid "Declared as a %s"
+msgstr ""
+
+#: source.php:19
+msgid "Description"
+msgstr ""
+
+#: source.php:150
+#, php-format
+msgid "Directory Listing :: %s"
+msgstr ""
+
+#: lib/Lang/Generic.php:65
+#, php-format
+msgid "Exuberant ctags version 5 or above required, found version %s"
+msgstr ""
+
+#: scripts/genxref.php:56
+#, php-format
+msgid "Indexing %s"
+msgstr ""
+
+#: ident.php:49 ident.php:73
+#, php-format
+msgid "Line %s"
+msgstr ""
+
+#: templates/headerbar.inc:2
+msgid "Location:"
+msgstr ""
+
+#: source.php:153
+#, php-format
+msgid "Markup of %s"
+msgstr ""
+
+#: source.php:16
+msgid "Name"
+msgstr ""
+
+#: lib/Luxor.php:60
+msgid "Other Sources"
+msgstr ""
+
+#: lib/Luxor.php:138
+msgid "Parent Directory"
+msgstr ""
+
+#: templates/ident/ident.html:8
+msgid "Referenced in"
+msgstr ""
+
+#: scripts/genxref.php:61
+#, php-format
+msgid "Referencing %s"
+msgstr ""
+
+#: source.php:17
+msgid "Size"
+msgstr ""
+
+#: search.php:35
+#, php-format
+msgid "Symbol Search for \"%s\""
+msgstr ""
+
+#: ident.php:26
+msgid "Symbol not found"
+msgstr ""
+
+#: source.php:89
+#, php-format
+msgid "The file %s can't be opened or doesn't exist."
+msgstr ""
+
+#: templates/headerbar.inc:9
+msgid "Tracking Branch"
+msgstr ""
+
+#: lib/Luxor.php:137
+msgid "Up to parent"
+msgstr ""
+
+#: source.php:39
+#, php-format
+msgid "You do not have permission to view %s."
+msgstr ""
+
+#: lib/Luxor.php:448
+msgid "_Browse"
+msgstr ""
+
+#: lib/Luxor.php:149
+msgid "bytes"
+msgstr ""
+
+#: lib/Luxor.php:151
+msgid "kbytes"
+msgstr ""
diff --git a/luxor/po/ro_RO.po b/luxor/po/ro_RO.po
new file mode 100644 (file)
index 0000000..0e14186
--- /dev/null
@@ -0,0 +1,215 @@
+# Romanian translations for luxor package.
+# Copyright 2003-2009 The Horde Project
+# This file is distributed under the same license as the luxor package.
+# Eugen Hoanca <eugenh@urban-grafx.ro>, 2003.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Luxor 0.1\n"
+"POT-Creation-Date: 2003-03-04 13:46+0100\n"
+"PO-Revision-Date: 2003-03-25 11:29+0200\n"
+"Last-Translator: Eugen Hoanca <eugenh@urban-grafx.ro>\n"
+"Language-Team: Romanian <i18n@lists.horde.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: lib/Tagger.php:48 lib/Tagger.php:103
+msgid "%s was already indexed."
+msgstr "%s a fost deja indexat."
+
+#: lib/Tagger.php:31 lib/Tagger.php:86
+msgid "Can't build language class for file %s."
+msgstr "Imposibil de cladit o clasa de limba pentru fisierul %s."
+
+#: lib/Tagger.php:59 lib/Tagger.php:115
+msgid "Can't create copy of file %s."
+msgstr "Imposibil de creat copie a fisierului %s."
+
+#: lib/Files/plain.php:82
+msgid "Can't open directory %s"
+msgstr "Nu se poate deschide directorul %s"
+
+#: lib/Lang/Generic.php:125
+msgid "Can't open file %s."
+msgstr "Nu se poate deschite fisierul %s."
+
+#: lib/Lang/Generic.php:83
+msgid "Can't run ectags."
+msgstr "Nu se poate rula ectags."
+
+#: source.php:78
+msgid "Could not markup file %s."
+msgstr "Nu se poate marca fisierul %s."
+
+#: source.php:130
+msgid "Cross Reference"
+msgstr "Referinta in cruce"
+
+#: source.php:18
+msgid "Date (GMT)"
+msgstr "Data (GMT)"
+
+#: ident.php:49
+msgid "Declared as "
+msgstr "Declarat ca"
+
+#: source.php:19
+msgid "Description"
+msgstr "Descriere"
+
+#: lib/Lang/Generic.php:50
+msgid "Exuberant ctags version 5 or above required, found %s"
+msgstr "Ctags versiunea 5 sau mai mare necesara, s-a gasit %s"
+
+#: templates/menu/menu.inc:17
+msgid "Help"
+msgstr "Ajutor"
+
+#: templates/menu/menu.inc:6
+msgid "Home"
+msgstr "Acasa"
+
+#: ident.php:29
+msgid "Identifier"
+msgstr "Identificator"
+
+#: genxref.php:110
+msgid "Indexing %s"
+msgstr "Indexare %s"
+
+#: templates/genxref/genxref.inc:13
+msgid "Just build the symbol index"
+msgstr "Cladire index simboluri"
+
+#: templates/genxref/genxref.inc:14
+msgid "Just build the symbol references"
+msgstr "Cladire referinte simboluri"
+
+#: templates/headerbar.inc:26
+msgid "Location:"
+msgstr "Locatie:"
+
+#: templates/genxref/genxref.inc:4
+msgid "Luxor Backend"
+msgstr "Suport Luxor"
+
+#: templates/headerbar.inc:11
+msgid "Luxor Homepage"
+msgstr "Pagina Luxor"
+
+#: templates/index/notconfigured.inc:4
+msgid "Luxor is not properly configured"
+msgstr "Luxor nu este corect configurat"
+
+#: source.php:16
+msgid "Name"
+msgstr "Nume"
+
+#: lib/Driver/sql.php:477
+msgid "No configuration information specified for SQL Tasks."
+msgstr "Nici o configurare specificata pentru sarcinile SQL."
+
+#: lib/Luxor.php:85
+msgid "Other Sources"
+msgstr "Alte surse"
+
+#: lib/Luxor.php:156
+msgid "Parent Directory"
+msgstr "Director parinte"
+
+#: ident.php:57
+msgid "Referenced in"
+msgstr "Referinta in"
+
+#: genxref.php:128
+msgid "Referencing %s"
+msgstr "Referinta %s"
+
+#: lib/Driver/sql.php:495
+msgid "Required 'charset' not specified in tasks configuration."
+msgstr "'charset' nespecificat in configurarea taskurilor."
+
+#: lib/Driver/sql.php:492
+msgid "Required 'database' not specified in tasks configuration."
+msgstr "'database' nespecificat in configurarea taskurilor."
+
+#: lib/Driver/sql.php:483
+msgid "Required 'hostspec' not specified in tasks configuration."
+msgstr "'hostspec' nespecificat in configurarea taskurilor."
+
+#: lib/Driver/sql.php:489
+msgid "Required 'password' not specified in tasks configuration."
+msgstr "'password' nespecificat in configurarea taskurilor."
+
+#: lib/Driver/sql.php:480
+msgid "Required 'phptype' not specified in tasks configuration."
+msgstr "'phptype' nespecificat in configurarea taskurilor."
+
+#: lib/Driver/sql.php:486
+msgid "Required 'username' not specified in tasks configuration."
+msgstr "'username' nespecificat in configurarea taskurilor."
+
+#: source.php:17
+msgid "Size"
+msgstr "Marime"
+
+#: templates/index/notconfigured.inc:39
+msgid "Some of Luxor's configuration files are missing:"
+msgstr "Anumite fisiere de configurare Luxor lipsesc:"
+
+#: ident.php:36
+msgid "Source"
+msgstr "Sursa"
+
+#: source.php:55
+msgid "The file %s can't be opened or doesn't exist."
+msgstr "Fisierul %s nu poate fi deschis sau nu exista."
+
+#: templates/index/notconfigured.inc:51
+msgid "This file contains preferences for Luxor."
+msgstr "Acest fisier contine preferintele Luxor."
+
+#: templates/index/notconfigured.inc:58
+msgid ""
+"This file controls the stylesheet that is used to set colors and fonts in "
+"addition to or overriding Horde defaults."
+msgstr ""
+"Acest fisier controleaza schema de culori si fonturi diferite de cele " 
+"implicite Horde."
+
+#: templates/index/notconfigured.inc:44
+msgid ""
+"This is the main Luxor configuration file. It contains options for all Luxor "
+"scripts."
+msgstr ""
+"Acesta este principalul fisier de configurare Luxor. Contine optiuni pentru "
+"toate scripturile Luxor."
+
+#: templates/headerbar.inc:30
+msgid "Tracking Branch"
+msgstr "Ramura de urmarire"
+
+#: lib/Luxor.php:145 lib/Luxor.php:155
+msgid "Up to parent"
+msgstr "Inapoi la parinte"
+
+#: templates/menu/menu.inc:9
+msgid "Update"
+msgstr "Improspatare"
+
+#: templates/genxref/genxref.inc:10
+msgid "Update the Cross Reference"
+msgstr "Improspatare referinta in cruce"
+
+#: source.php:49
+msgid "You do not have permission to view file %s."
+msgstr "Nu aveti permisiunea sa vizualizati fisierul %s."
+
+#: lib/Luxor.php:176
+msgid "bytes"
+msgstr "octeti"
+
+#: lib/Luxor.php:178
+msgid "kbytes"
+msgstr "kocteti"
diff --git a/luxor/scripts/.htaccess b/luxor/scripts/.htaccess
new file mode 100644 (file)
index 0000000..3a42882
--- /dev/null
@@ -0,0 +1 @@
+Deny from all
diff --git a/luxor/scripts/sql/luxor.sql b/luxor/scripts/sql/luxor.sql
new file mode 100644 (file)
index 0000000..9b876f3
--- /dev/null
@@ -0,0 +1,57 @@
+-- $Horde: luxor/scripts/sql/luxor.sql,v 1.4 2006/03/21 01:57:37 selsky Exp $
+
+CREATE TABLE luxor_declarations (
+    declid SMALLINT NOT NULL,
+    langid SMALLINT DEFAULT 0 NOT NULL,
+    declaration char(255) DEFAULT '' NOT NULL,
+    PRIMARY KEY (declid)
+);
+
+CREATE TABLE luxor_files (
+    fileid INT NOT NULL,
+    source VARCHAR(255) DEFAULT '' NOT NULL,
+    filename VARCHAR(255) DEFAULT '' NOT NULL,
+    tag VARCHAR(255) DEFAULT '' NOT NULL,
+    lastmodified INT DEFAULT 0 NOT NULL,
+    PRIMARY KEY (fileid)
+);
+
+CREATE INDEX luxor_files_source ON luxor_files (source);
+CREATE INDEX luxor_files_tag ON luxor_files (tag);
+CREATE INDEX luxor_files_filename ON luxor_files (filename);
+
+CREATE TABLE luxor_indexes (
+    symid INT DEFAULT 0 NOT NULL,
+    fileid INT DEFAULT 0 NOT NULL,
+    line INT DEFAULT 0 NOT NULL,
+    declid SMALLINT DEFAULT 0 NOT NULL
+);
+
+CREATE INDEX luxor_indexes_symid ON luxor_indexes (symid);
+CREATE INDEX luxor_indexes_fileid ON luxor_indexes (fileid);
+CREATE INDEX luxor_indexes_declid ON luxor_indexes (declid);
+
+CREATE TABLE luxor_status (
+    fileid INT DEFAULT 0 NOT NULL,
+    status SMALLINT DEFAULT 0 NOT NULL,
+    PRIMARY KEY (fileid)
+);
+
+CREATE TABLE luxor_symbols (
+    symid INT NOT NULL,
+    symname VARCHAR(255) DEFAULT '' NOT NULL,
+    source VARCHAR(255) DEFAULT '' NOT NULL,
+    PRIMARY KEY (symid)
+);
+
+CREATE INDEX luxor_symbols_symname ON luxor_symbols (symname);
+CREATE INDEX luxor_symbols_source ON luxor_symbols (source);
+
+CREATE TABLE luxor_usage (
+    symid INT DEFAULT 0 NOT NULL,
+    fileid INT DEFAULT 0 NOT NULL,
+    line INT DEFAULT 0 NOT NULL
+);
+
+CREATE INDEX luxor_usage_symid ON luxor_usage (symid);
+CREATE INDEX luxor_usage_fileid ON luxor_usage (fileid);
diff --git a/luxor/search.php b/luxor/search.php
new file mode 100644 (file)
index 0000000..707e53b
--- /dev/null
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.horde.org/licenses/gpl.php.
+ *
+ * @author Jan Schneider <jan@horde.org>
+ * @author Mike Cochrane <mike@graftonhall.co.nz>
+ */
+
+require_once dirname(__FILE__) . '/lib/Application.php';
+Horde_Registry::appInit('luxor');
+
+$symbol = Horde_Util::getFormData('s');
+if (!$symbol) {
+    header('Location: ' . Horde::applicationUrl('source.php', true));
+    exit;
+}
+
+$ids = $index->searchSymbols($symbol);
+if (count($ids) == 1) {
+    $id = current($ids);
+    header('Location: ' . Horde::applicationUrl('symbol.php?i=' . $id, true));
+    exit;
+}
+
+// If there are multiple search results, display some info for all of them.
+
+$title = sprintf(_("Symbol Search for \"%s\""), $symbol);
+require LUXOR_TEMPLATES . '/common-header.inc';
+require LUXOR_TEMPLATES . '/menu.inc';
+
+echo '<h1 class="header">' . htmlspecialchars($title) . '</h1>';
+
+foreach ($ids as $ident) {
+    // Change source if the symbol isn't from the current source.
+    $symbolSource = $index->getSourceBySymbol($ident);
+    if ($symbolSource != $sourceid) {
+        $source = $sources[$symbolSource];
+        $index = Luxor_Driver::factory($symbolSource);
+    }
+
+    $name = $index->symname($ident);
+    echo '<br /><span class="header">' . Horde::link(Horde::applicationUrl('symbol.php?i=' . $ident), $name, 'header') . $name . '</a></span><br />';
+
+    $references = $index->getIndex($ident);
+    $sorted = array();
+    foreach ($references as $ref) {
+        $sorted[$ref['declaration']][] = array('filename' => $ref['filename'],
+                                               'line' => $ref['line']);
+    }
+
+    foreach ($sorted as $type => $locations) {
+        echo _("Declared as ") . $type . "\n";
+        foreach ($locations as $loc) {
+            $href = Luxor::url($loc['filename'], array(), 'l' . $loc['line']);
+            echo '    <a href="' . $href . '">' . $loc['filename'] . ' Line: ' . $loc['line'] . '</a><br />';
+        }
+        echo '<br />';
+    }
+}
+
+require $registry->get('templates', 'horde') . '/common-footer.inc';
diff --git a/luxor/source.php b/luxor/source.php
new file mode 100644 (file)
index 0000000..c81516c
--- /dev/null
@@ -0,0 +1,157 @@
+<?php
+/**
+ * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.horde.org/licenses/gpl.php.
+ *
+ * @author Jan Schneider <jan@horde.org>
+ */
+
+require_once dirname(__FILE__) . '/lib/Application.php';
+Horde_Registry::appInit('luxor');
+
+function printdir($dir)
+{
+    $view = new Horde_View(array('templatePath' => LUXOR_TEMPLATES));
+    $view->addBuiltinHelpers();
+    $dirlist = Luxor::dirExpand($dir);
+    if (is_a($dirlist, 'PEAR_Error')) {
+        $GLOBALS['notification']->push($dirlist, 'horde.error');
+        return;
+    }
+    $view->files = $dirlist;
+
+    return $view->render('directory.html.php')
+        . Luxor::dirDesc($GLOBALS['files'], $dir);
+}
+
+function printfile($pathname, $raw = false)
+{
+    if (substr($pathname, -1) == '/') {
+        return printdir($pathname);
+    }
+
+    if (Luxor::isRestricted($pathname)) {
+        $GLOBALS['notification']->push(sprintf(_("You do not have permission to view %s."), $pathname), 'horde.error');
+        return '';
+    }
+
+    $cache = $GLOBALS['injector']->getInstance('Horde_Cache');
+    $lastmod = $GLOBALS['index']->getLastModified($pathname);
+    $key = 'luxor_' . $pathname;
+    if ($raw) {
+        $key .= '_raw';
+    }
+    $output = $cache->get($key, time() - $lastmod);
+    if (true || !$output) {
+        $output = $raw ? printfile_raw($pathname) : printfile_markup($pathname);
+        if (!empty($output)) {
+            $cache->set($key, $output);
+        }
+    }
+
+    return $output;
+}
+
+function printfile_markup($pathname)
+{
+    $ann = $GLOBALS['files']->getAnnotations($pathname);
+    /*  Commented out until we have a driver that supports annotations.
+        this formatting should probably be done in markupFile();
+        if (is_array($ann)) {
+            $b = null;
+            for ($i = 0; $i < count($ann); $i++) {
+                if ($ann[$i] == $b) {
+                    $ann[$i] = str_repeat(' ', 16);
+                    continue;
+                }
+                $b = $ann[$i];
+                $ann[$i] .= str_repeat(' ', 6 - strlen($ann[$i])) . $files->getAuthor($pathname);
+                $ann[$i] .= str_repeat(' ', 16 - strlen($ann[$i]));
+            }
+        }
+    */
+
+    $fileh = $GLOBALS['files']->getFileHandle($pathname);
+    if (!$fileh) {
+        $GLOBALS['notification']->push(sprintf(_("The file %s can't be opened or doesn't exist."), $pathname), 'horde.error');
+        return;
+    }
+
+    $output = Luxor::markupFile($pathname, $fileh, $ann);
+    if ($output === false) {
+        $GLOBALS['notification']->push(sprintf(_("Could not markup file %s."), $pathname), 'horde.warning');
+        return printfile_raw($pathname);
+    }
+
+    return $output;
+}
+
+function printfile_raw($pathname)
+{
+    global $mime_drivers, $mime_drivers_map;
+
+    $result = Horde::loadConfiguration('mime_drivers.php', array('mime_drivers', 'mime_drivers_map'), 'horde');
+    extract($result);
+    $result = Horde::loadConfiguration('mime_drivers.php', array('mime_drivers', 'mime_drivers_map'), 'luxor');
+    if (isset($result['mime_drivers'])) {
+        $mime_drivers = Horde_Array::array_merge_recursive_overwrite(
+            $mime_drivers, $result['mime_drivers']);
+    }
+    if (isset($result['mime_drivers_map'])) {
+        $mime_drivers_map = Horde_Array::array_merge_recursive_overwrite(
+            $mime_drivers_map, $result['mime_drivers_map']);
+    }
+
+    $filename = $GLOBALS['files']->toReal($pathname);
+    $data = file_get_contents($filename);
+
+    $mime_part = new Horde_Mime_Part(Horde_Mime_Magic::filenameToMime($pathname), $data);
+    $mime_part->setName($pathname);
+    $viewer = Horde_Mime_Viewer::factory($mime_part);
+
+    if ($viewer->getType() == 'text/plain') {
+        return '<pre class="fixed">' . htmlspecialchars($viewer->render()) . '</pre>';
+    } else {
+        return $viewer->render();
+    }
+}
+
+if (substr($pathname, -5) == '.html' ||
+    substr($pathname, -4) == '.htm' ||
+    Horde_Util::getFormData('raw')) {
+    echo printfile($pathname, true);
+    exit;
+}
+
+$content = printfile($pathname);
+
+if (substr($pathname, -1) == '/') {
+    $title = sprintf(_("Directory Listing :: %s"), $pathname);
+    Horde::addScriptFile('tables.js', 'horde', true);
+} else {
+    $title = sprintf(_("Markup of %s"), $pathname);
+    $lastmod = $index->getLastModified($pathname);
+    if ($lastmod) {
+        $mod_gmt = gmdate('D, d M Y H:i:s', $lastmod) . ' GMT';
+        header('Last-Modified: ' . $mod_gmt);
+        header('Cache-Control: public, max-age=86400');
+    }
+
+    if (!empty($conf['options']['use_show_var'])) {
+        Horde::addScriptFile('show_var.js', 'luxor', true);
+    }
+}
+
+if (is_a($content, 'PEAR_Error')) {
+    $notification->push($content->getMessage(), 'horde.error');
+}
+
+require LUXOR_TEMPLATES . '/common-header.inc';
+require LUXOR_TEMPLATES . '/menu.inc';
+require LUXOR_TEMPLATES . '/headerbar.inc';
+if (!is_a($content, 'PEAR_Error')) {
+    echo $content;
+}
+require $registry->get('templates', 'horde') . '/common-footer.inc';
diff --git a/luxor/symbol.php b/luxor/symbol.php
new file mode 100644 (file)
index 0000000..a25c09e
--- /dev/null
@@ -0,0 +1,86 @@
+<?php
+/**
+ * $Horde: luxor/symbol.php,v 1.6 2009/06/10 19:54:42 chuck Exp $
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.horde.org/licenses/gpl.php.
+ *
+ * @author Jan Schneider <jan@horde.org>
+ * @author Mike Cochrane <mike@graftonhall.co.nz>
+ */
+
+require_once dirname(__FILE__) . '/lib/Application.php';
+Horde_Registry::appInit('luxor');
+
+$ident = Horde_Util::getFormData('i');
+
+// Change source if the symbol isn't from the current source.
+$symbolSource = $index->getSourceBySymbol($ident);
+if (!$symbolSource) {
+    Horde::fatal(_("Symbol not found"), __FILE__, __LINE__);
+}
+if ($symbolSource != $sourceid) {
+    $source = $sources[$symbolSource];
+    $index = Luxor_Driver::factory($symbolSource);
+}
+
+$declarations = $index->getIndex($ident);
+$sorted = array();
+foreach ($declarations as $decl) {
+    $sorted[$decl['declaration']][] = array('filename' => $decl['filename'],
+                                            'line' => $decl['line']);
+}
+
+$ds = array();
+foreach ($sorted as $type => $locations) {
+    $d = array();
+    $d['title'] = sprintf(_("Declared as a %s"), $type);
+    $d['files'] = array();
+
+    Horde_Array::arraySort($locations, 'filename', 0, false);
+    foreach ($locations as $loc) {
+        $href = Luxor::url($loc['filename'], array(), 'l' . $loc['line']);
+        $d['files'][] = '<a href="' . $href . '">' . $loc['filename'] . ' ' . sprintf(_("Line %s"), $loc['line']) . '</a>';
+    }
+    $ds[] = $d;
+}
+
+$references = $index->getReference($ident);
+Horde_Array::arraySort($references, 'filename', 0, false);
+
+$curfile = '';
+$rs = array();
+$r = array();
+foreach ($references as $info) {
+    if ($curfile != $info['filename']) {
+        if ($r) {
+            $rs[] = $r;
+        }
+
+        $curfile = $info['filename'];
+
+        $r = array();
+        $r['file'] = '<a href="' . Luxor::url($info['filename']) . '">' . htmlspecialchars($info['filename']) . '</a>';
+        $r['lines'] = array();
+    }
+
+    $r['lines'][] = '<a href="' . Luxor::url($info['filename'], array(), 'l' . $info['line']) . '">' . sprintf(_("Line %s"), $info['line']) . '</a>';
+}
+if ($r) {
+    $rs[] = $r;
+}
+
+$title = sprintf(_("%s :: Symbol \"%s\""), $source['name'], $index->symname($ident));
+require LUXOR_TEMPLATES . '/common-header.inc';
+require LUXOR_TEMPLATES . '/menu.inc';
+
+$view = new Horde_View(array('templatePath' => LUXOR_TEMPLATES));
+$view->addBuiltinHelpers();
+$view->title = $title;
+$view->declarations = $ds;
+$view->references = $rs;
+echo $view->render('symbol.html.php');
+
+require $registry->get('templates', 'horde') . '/common-footer.inc';
diff --git a/luxor/templates/.htaccess b/luxor/templates/.htaccess
new file mode 100644 (file)
index 0000000..3a42882
--- /dev/null
@@ -0,0 +1 @@
+Deny from all
diff --git a/luxor/templates/common-header.inc b/luxor/templates/common-header.inc
new file mode 100644 (file)
index 0000000..e74d555
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+if (isset($language)) {
+    header('Content-type: text/html; charset=' . Horde_Nls::getCharset());
+    header('Vary: Accept-Language');
+}
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-transitional.dtd">
+<!--  Luxor: Copyright 2003-2009 The Horde Project.  Luxor is under the GPL.   -->
+<!-- Horde Project: http://www.horde.org/ | Luxor: http://www.horde.org/luxor/ -->
+<!--             Horde Licenses: http://www.horde.org/licenses/                -->
+<?php echo !empty($language) ? '<html lang="' . strtr($language, '_', '-') . '">' : '<html>' ?>
+<head>
+<?php
+
+$page_title = $registry->get('name');
+if (!empty($title)) $page_title .= ' :: ' . $title;
+if (!empty($refresh_time) && ($refresh_time > 0) && !empty($refresh_url)) {
+    echo "<meta http-equiv=\"refresh\" content=\"$refresh_time;url=$refresh_url\">\n";
+}
+
+Horde::includeScriptFiles();
+
+?>
+<title><?php echo htmlspecialchars($page_title) ?></title>
+<link href="<?php echo Horde_Themes::img('favicon.ico') ?>" rel="SHORTCUT ICON" />
+<?php Horde_Themes::includeStylesheetFiles() ?>
+</head>
+
+<body<?php if ($bc = Horde_Util::nonInputVar('bodyClass')) echo ' class="' . $bc . '"' ?><?php if ($bi = Horde_Util::nonInputVar('bodyId')) echo ' id="' . $bi . '"'; ?>>
diff --git a/luxor/templates/directory.html.php b/luxor/templates/directory.html.php
new file mode 100644 (file)
index 0000000..7ad47ec
--- /dev/null
@@ -0,0 +1,20 @@
+<table id="filelist" class="striped sortable horde-table" cellspacing="0">
+<thead>
+ <tr>
+  <th class="sortdown" width="20%"><?= _("Name") ?></th>
+  <th width="10%"><?= _("Size") ?></th>
+  <th width="10%"><?= _("Date (GMT)") ?></th>
+  <th width="60%"><?= _("Description") ?></th>
+ </tr>
+</thead>
+<tbody>
+ <? foreach ($this->files as $file): ?>
+ <tr>
+  <td><a href="<?= $file['link'] ?>"><?= $file['icon'] ?> <?= $this->escape($file['name']) ?></a></td>
+  <td><?= $this->escape($file['filesize']) ?> <?= $this->escape($file['bytes']) ?></td>
+  <td><?= $this->escape($file['modtime']) ?></td>
+  <td><?= $file['description'] ?></td>
+ </tr>
+ <? endforeach ?>
+</tbody>
+</table>
diff --git a/luxor/templates/headerbar.inc b/luxor/templates/headerbar.inc
new file mode 100644 (file)
index 0000000..d514030
--- /dev/null
@@ -0,0 +1,23 @@
+<div id="headerbar">
+<div class="header">
+<?php echo _("Location:") ?><small>
+[ <?php echo Horde::link(Luxor::url()) . htmlspecialchars($source['name']) ?></a> ]
+<?php
+
+echo Luxor::whereMenu() . '</small>';
+
+if (!empty($onb)): ?>
+&nbsp; &nbsp; <em>(<?php echo _("Tracking Branch") ?> <strong><?php echo $fl->branches[$onb] ?></strong>)</em>
+<?php endif;
+
+if ($pathname == '/' && count($sources) > 1) {
+    echo '&nbsp; &nbsp;';
+    echo Luxor::sources();
+} ?>
+</div>
+<?php if ($pathname == '/' && @is_file($conf['paths']['introText'])): ?>
+<div class="box">
+<?php @readfile($conf['paths']['introText']) ?>
+</div>
+<?php endif ?>
+</div>
diff --git a/luxor/templates/menu.inc b/luxor/templates/menu.inc
new file mode 100644 (file)
index 0000000..7cad233
--- /dev/null
@@ -0,0 +1,20 @@
+<script type="text/javascript">
+function jump()
+{
+    return document.getElementById('symbol-search-string').value;
+}
+</script>
+
+<form method="get" action="<?php echo Horde::applicationUrl('search.php') ?>">
+<?php Horde_Util::pformInput() ?>
+<div id="menu">
+ <div class="rightFloat">
+  <input type="text" size="10" name="s" id="symbol-search-string" value="<?php echo Horde_Util::getFormData('s') ?>" />
+  <input type="submit" onclick="return jump();" class="button" value="<?php echo _("Symbol Search") ?>" />
+ </div>
+ <?php echo Luxor::getMenu('string') ?>
+ <br class="clear" />
+</div>
+</form>
+
+<?php $GLOBALS['notification']->notify(array('listeners' => 'status')) ?>
diff --git a/luxor/templates/symbol.html.php b/luxor/templates/symbol.html.php
new file mode 100644 (file)
index 0000000..87afb98
--- /dev/null
@@ -0,0 +1,29 @@
+<div id="headerbar">
+<h1 class="header">
+ <?= $this->escape($this->title) ?>
+</h1>
+</div>
+
+<div id="symbol-declarations">
+<h2><?= _("Declarations") ?></h2>
+<? foreach ($this->declarations as $declaration): ?>
+ <dl class="box">
+  <dt><?= $this->escape($declaration['title']) ?></dt>
+  <? foreach ($declaration['files'] as $file): ?>
+   <dd><?= $file ?></dd>
+  <? endforeach ?>
+ </dl>
+<? endforeach ?>
+</div>
+
+<div id="symbol-references">
+<h2><?= _("Referenced in") ?></h2>
+<? foreach ($this->references as $reference): ?>
+ <dl class="box">
+  <dt><?= $reference['file'] ?></dt>
+   <? foreach ($reference['lines'] as $line): ?>
+   <dd><?= $line ?></dd>
+   <? endforeach ?>
+ </dl>
+<? endforeach ?>
+</div>
diff --git a/luxor/themes/graphics/favicon.ico b/luxor/themes/graphics/favicon.ico
new file mode 100644 (file)
index 0000000..94ff92d
Binary files /dev/null and b/luxor/themes/graphics/favicon.ico differ
diff --git a/luxor/themes/graphics/folder.png b/luxor/themes/graphics/folder.png
new file mode 100644 (file)
index 0000000..323c51b
Binary files /dev/null and b/luxor/themes/graphics/folder.png differ
diff --git a/luxor/themes/graphics/luxor.png b/luxor/themes/graphics/luxor.png
new file mode 100644 (file)
index 0000000..33d9dc4
Binary files /dev/null and b/luxor/themes/graphics/luxor.png differ
diff --git a/luxor/themes/graphics/parent.png b/luxor/themes/graphics/parent.png
new file mode 100644 (file)
index 0000000..6ee2d98
Binary files /dev/null and b/luxor/themes/graphics/parent.png differ
diff --git a/luxor/themes/screen.css b/luxor/themes/screen.css
new file mode 100644 (file)
index 0000000..8ea099a
--- /dev/null
@@ -0,0 +1,60 @@
+/**
+ * $Horde: luxor/themes/screen.css,v 1.7 2008/08/06 16:10:00 chuck Exp $
+ */
+
+th {
+    border-bottom: 1px solid #999;
+}
+.title {
+    font-size: 120%;
+    font-weight: bold;
+}
+.comment {
+    color: #008000;
+}
+.string {
+    color: #d00;
+}
+.variable {
+    color: #ff8000;
+}
+.variable-highlight {
+    background: yellow;
+}
+.reserved {
+    color: #007f7f;
+}
+.symbol {
+    color: #00b;
+}
+
+dl {
+    margin: 5px;
+}
+dt {
+    font-weight: bold;
+}
+dd {
+    margin-left: 10px;
+}
+
+#headerbar {
+    margin-bottom: .5em;
+}
+
+#filelist {
+    text-align: left;
+    white-space: nowrap;
+}
+#filelist td, #filelist tr {
+    padding: 1px 4px;
+}
+
+#symbol-declarations, #symbol-references {
+    width: 48%;
+    float: left;
+}
+#symbol-declarations h2, #symbol-references h2 {
+    margin-left: .3em;
+    font-size: 1.2em;
+}