--- /dev/null
+<IfModule mod_rewrite.c>
+ RewriteEngine On
+ RewriteCond %{REQUEST_FILENAME} !-d
+ RewriteCond %{REQUEST_FILENAME} !-f
+ RewriteRule ^(.*)$ source.php?f=$1 [QSA]
+</IfModule>
--- /dev/null
+ 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
--- /dev/null
+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.
--- /dev/null
+Deny from all
--- /dev/null
+#!/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()
+{
+}
--- /dev/null
+Deny from all
--- /dev/null
+<?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 "pretty" 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>
--- /dev/null
+<?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',
+ ),
+ )
+);
--- /dev/null
+<?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.
+ */
--- /dev/null
+<?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/'
+);
--- /dev/null
+----
+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.
--- /dev/null
+============================
+|| 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 $
--- /dev/null
+==========================
+|| 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 $
--- /dev/null
+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
--- /dev/null
+<?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';
--- /dev/null
+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);
+ }
+}
--- /dev/null
+Deny from all
--- /dev/null
+<?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();
+ }
+}
--- /dev/null
+<?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;
+ }
+}
--- /dev/null
+<?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;
+ }
+
+}
--- /dev/null
+<?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;
+ }
+ }
+}
--- /dev/null
+<?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();
+ }
+
+}
--- /dev/null
+<?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);
+ }
+}
--- /dev/null
+<?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;
+ }
+}
--- /dev/null
+<?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]) ? ' ' : $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();
+ }
+ }
+}
--- /dev/null
+<?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);
+ }
+
+}
--- /dev/null
+<?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;
+ }
+ }
+
+}
--- /dev/null
+Deny from all
--- /dev/null
+see horde/po/README
--- /dev/null
+# 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"
--- /dev/null
+# 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"
--- /dev/null
+# 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 ""
--- /dev/null
+# 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"
--- /dev/null
+Deny from all
--- /dev/null
+-- $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);
--- /dev/null
+<?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';
--- /dev/null
+<?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';
--- /dev/null
+<?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';
--- /dev/null
+Deny from all
--- /dev/null
+<?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 . '"'; ?>>
--- /dev/null
+<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>
--- /dev/null
+<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)): ?>
+ <em>(<?php echo _("Tracking Branch") ?> <strong><?php echo $fl->branches[$onb] ?></strong>)</em>
+<?php endif;
+
+if ($pathname == '/' && count($sources) > 1) {
+ echo ' ';
+ echo Luxor::sources();
+} ?>
+</div>
+<?php if ($pathname == '/' && @is_file($conf['paths']['introText'])): ?>
+<div class="box">
+<?php @readfile($conf['paths']['introText']) ?>
+</div>
+<?php endif ?>
+</div>
--- /dev/null
+<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')) ?>
--- /dev/null
+<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>
--- /dev/null
+/**
+ * $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;
+}