From 378a912bf79e1e5b6384b02b14919371ac0c4785 Mon Sep 17 00:00:00 2001 From: Arne Georg Gleditsch Date: Thu, 7 Feb 2008 20:31:11 +0100 Subject: Provisions for mod_perl use, take one. --- cgi-bin/.htaccess | 8 - cgi-bin/css/lxrng.css | 367 ----------------------- cgi-bin/gfx/Makefile | 10 - cgi-bin/gfx/close.png | Bin 802 -> 0 bytes cgi-bin/gfx/close.svg | 102 ------- cgi-bin/gfx/diff.png | Bin 605 -> 0 bytes cgi-bin/gfx/diff.svg | 129 -------- cgi-bin/gfx/left.png | Bin 585 -> 0 bytes cgi-bin/gfx/left.svg | 102 ------- cgi-bin/gfx/print.png | Bin 355 -> 0 bytes cgi-bin/gfx/print.svg | 149 ---------- cgi-bin/gfx/right.png | Bin 586 -> 0 bytes cgi-bin/gfx/right.svg | 102 ------- cgi-bin/gfx/rolldown.png | Bin 536 -> 0 bytes cgi-bin/gfx/rolldown.svg | 102 ------- cgi-bin/js/lxrng-funcs.js | 354 ---------------------- cgi-bin/lxr | 735 ---------------------------------------------- 17 files changed, 2160 deletions(-) delete mode 100644 cgi-bin/.htaccess delete mode 100644 cgi-bin/css/lxrng.css delete mode 100644 cgi-bin/gfx/Makefile delete mode 100644 cgi-bin/gfx/close.png delete mode 100644 cgi-bin/gfx/close.svg delete mode 100644 cgi-bin/gfx/diff.png delete mode 100644 cgi-bin/gfx/diff.svg delete mode 100644 cgi-bin/gfx/left.png delete mode 100644 cgi-bin/gfx/left.svg delete mode 100644 cgi-bin/gfx/print.png delete mode 100644 cgi-bin/gfx/print.svg delete mode 100644 cgi-bin/gfx/right.png delete mode 100644 cgi-bin/gfx/right.svg delete mode 100644 cgi-bin/gfx/rolldown.png delete mode 100644 cgi-bin/gfx/rolldown.svg delete mode 100644 cgi-bin/js/lxrng-funcs.js delete mode 100755 cgi-bin/lxr (limited to 'cgi-bin') diff --git a/cgi-bin/.htaccess b/cgi-bin/.htaccess deleted file mode 100644 index 06615a1..0000000 --- a/cgi-bin/.htaccess +++ /dev/null @@ -1,8 +0,0 @@ -Options ExecCGI - -SetHandler cgi-script - - - -SetHandler cgi-script - diff --git a/cgi-bin/css/lxrng.css b/cgi-bin/css/lxrng.css deleted file mode 100644 index f5d84c0..0000000 --- a/cgi-bin/css/lxrng.css +++ /dev/null @@ -1,367 +0,0 @@ -/* -*- mode: fundamental -*- */ - -body { - font-family: sans-serif; - margin-top: 3px; - margin-left: 3px; - margin-right: 3px; -} - -span.lxr_title { - float: left; - vertical-align: middle; -} - -span.lxr_l { - text-transform: uppercase; - margin-left: 5px; - font-weight: normal; -} - -span.lxr_x { - text-transform: uppercase; - font-weight: normal; -} - -span.lxr_r { - text-transform: uppercase; - font-weight: normal; - padding-right: 5px; - border-right: solid; - border-width: 1px; -} - -span.lxr_logo { - text-transform: uppercase; - font-weight: normal; - margin-left: 5px; - padding-right: 5px; - border-right: solid; - border-width: 1px; -} - -div.prose { - margin-left: 20px; - margin-right: 20px; - max-width: 40em; -} -span.section { - font-weight: bold; - display: block; - margin-top: 10px; -} - -span.lxr_menu { -/* float: right; */ -} - -div.lxr_menu { - float: right; -} - -span.lxr_search { - font-weight: normal; - margin-left: 5px; - padding-left: 5px; - margin-right: 5px; - border-left: solid; - border-width: 1px; -} - -span.lxr_search input#search { - width: 8em; -} - -span.lxr_search button { - border: solid 1px; -} - -span.lxr_prefs { - font-weight: normal; - margin-left: 5px; - padding-left: 5px; - margin-right: 5px; - border-left: solid; - border-width: 1px; -} - -span.lxr_version { - font-weight: normal; - padding-left: 5px; -/* border-left: solid; - border-width: 1px; */ -} - -body.full div.search_results { - background: #F0F0F0; - z-index: 3; -/* position: absolute; */ - position: fixed; - right: 3px; - top: 35px; - width: 35%; - height: 70%; - border: solid; - border-width: 1px; - display: none; - overflow: auto; - padding: 3px; -} - -body.popup div.search_results { - background: #F0F0F0; - border: solid; - border-width: 1px; - padding: 3px; - margin: 1px; -} - -span.identtype { - display: block; -/* font-weight: bold; */ - font-style: italic; - margin-top: 10px; - margin-left: 1em; -} - -span.resultline { - display: block; - margin-left: 2em; -} - -span.resultdetails { - font-size: 75%; -/* font-style: italic; */ -} - -div.query_desc { - font-weight: bold; - margin-top: 10px; - margin-bottom: 5px; -} - -span.close-button { - float: right; - margin-top: 3px; - margin-right: 3px; -} - -/* a.line:before { - content: attr(id); -} */ - -a.line { - position: absolute; - top: auto; - left: 0px; - height: 2ex; - width: 3em; - text-align: right; - - border: solid; - border-width: 1px; - border-color: #000000; - margin-left: 3px; -} - -a.line span { - position: absolute; - top: auto; - height: 2ex; - left: 0px; - background: #6c6c6c; - filter: alpha(opacity=10); - moz-opacity: .10; - opacity: .10; - width: 3em; -} - - -pre#file_contents li { - color: blue; -} - -span.line { - position: absolute; - left: 4em; - color: black; - white-space: pre; -} - -pre { - margin-left: 0.7em; -} - -a img { - border: 0px; -} - -div.headingtop { -} - -div.headingbottom { - clear: both; -} - -div.heading { - background: #F0F0F0; - margin-right: 0px; - margin-left: 0px; - font-weight: bold; - font-size: 120%; - border: solid; - border-width: 1px; - text-align: right; -} - -div.heading img { - vertical-align: middle; -} - -div.searchbox { - background: #F0F0F0; - border: solid; - margin-top: 3px; - border-width: 1px; - margin-right: 0px; - margin-left: 0px; - width: 30ex; - float: right; -} - - -button.print { - border: 0; - background: #F0F0F0; -} - -table.directory td.name { - width: 30ex; -} - -table.directory td.size { - width: 10ex; - text-align: right; - padding-right: 1ex; -} - -table.directory td.time { - width: 30ex; -} - -div.footerbox { - left: 3px; - right: 3px; - bottom: 3px; - border: solid; - border-width: 1px; - background: #F0F0F0; -} - -div.footerfill { - height: 3px; -} - -div.content { - background: white; -} - - -span.comment { - font-weight: bold; - font-style: italic; -} - -span.string { - font-style: italic; - color: green; -} - -div.find { - padding: 3px; -} - -div.find div.find_input { - width: 100%; -} - -div.find div.find_code { - width: 33%; - float: left; - text-align: left; -} - -div.find div.find_text { - width: 33%; - float: left; - text-align: center; -} - -div.find div.find_file { - width: 33%; - float: right; - text-align: right; -} - -div.vars { - clear: both; - padding: 3px; -} - -div.vars div.var_title { - clear: both; - width: 50%; - float: left; - text-align: left; -} - -div.vars div.var_select { - width: 50%; - float: right; - text-align: right; -} - -div.vars div.do_update { - clear: both; - width: 50%; - float: left; - text-align: left; -} - -div.vars div.do_hide { - width: 50%; - float: right; - text-align: right; -} - -div.progress { - font-weight: bold; - font-style: italic; -} - -div.error { - font-weight: bold; - font-style: italic; - color: #E04040; -} - -form { - display: inline; -} - -div.footer { - margin-top: 30px; - border-top: solid; - border-width: 1px; - padding-top: 10px; - font-style: italic; - text-align: center; - font-size: 80%; -} - -div.subfooter { - font-style: italic; - text-align: center; - font-size: 80%; -} - diff --git a/cgi-bin/gfx/Makefile b/cgi-bin/gfx/Makefile deleted file mode 100644 index bef9f65..0000000 --- a/cgi-bin/gfx/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -SVGFILES=$(wildcard *.svg) -PNGFILES=$(subst svg,png,${SVGFILES}) - -all: ${PNGFILES} - -clean: - rm -f ${PNGFILES} - -%.png: %.svg - inkscape -e $@ -w 16 -h 16 $< diff --git a/cgi-bin/gfx/close.png b/cgi-bin/gfx/close.png deleted file mode 100644 index cd4178f..0000000 Binary files a/cgi-bin/gfx/close.png and /dev/null differ diff --git a/cgi-bin/gfx/close.svg b/cgi-bin/gfx/close.svg deleted file mode 100644 index 2207f0f..0000000 --- a/cgi-bin/gfx/close.svg +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - diff --git a/cgi-bin/gfx/diff.png b/cgi-bin/gfx/diff.png deleted file mode 100644 index 73edeca..0000000 Binary files a/cgi-bin/gfx/diff.png and /dev/null differ diff --git a/cgi-bin/gfx/diff.svg b/cgi-bin/gfx/diff.svg deleted file mode 100644 index 46290d3..0000000 --- a/cgi-bin/gfx/diff.svg +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/cgi-bin/gfx/left.png b/cgi-bin/gfx/left.png deleted file mode 100644 index b01b78c..0000000 Binary files a/cgi-bin/gfx/left.png and /dev/null differ diff --git a/cgi-bin/gfx/left.svg b/cgi-bin/gfx/left.svg deleted file mode 100644 index 4a3b1df..0000000 --- a/cgi-bin/gfx/left.svg +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - diff --git a/cgi-bin/gfx/print.png b/cgi-bin/gfx/print.png deleted file mode 100644 index 4e56c0e..0000000 Binary files a/cgi-bin/gfx/print.png and /dev/null differ diff --git a/cgi-bin/gfx/print.svg b/cgi-bin/gfx/print.svg deleted file mode 100644 index b981609..0000000 --- a/cgi-bin/gfx/print.svg +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - diff --git a/cgi-bin/gfx/right.png b/cgi-bin/gfx/right.png deleted file mode 100644 index 439fe13..0000000 Binary files a/cgi-bin/gfx/right.png and /dev/null differ diff --git a/cgi-bin/gfx/right.svg b/cgi-bin/gfx/right.svg deleted file mode 100644 index 07e8941..0000000 --- a/cgi-bin/gfx/right.svg +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - diff --git a/cgi-bin/gfx/rolldown.png b/cgi-bin/gfx/rolldown.png deleted file mode 100644 index a2a15ca..0000000 Binary files a/cgi-bin/gfx/rolldown.png and /dev/null differ diff --git a/cgi-bin/gfx/rolldown.svg b/cgi-bin/gfx/rolldown.svg deleted file mode 100644 index 85697fb..0000000 --- a/cgi-bin/gfx/rolldown.svg +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - diff --git a/cgi-bin/js/lxrng-funcs.js b/cgi-bin/js/lxrng-funcs.js deleted file mode 100644 index fdd9b43..0000000 --- a/cgi-bin/js/lxrng-funcs.js +++ /dev/null @@ -1,354 +0,0 @@ -function popup_search(searchform) { - searchform = document.getElementById(searchform); - searchform.target = 'popup_' + window.name; - searchform.navtarget.value = window.name; - window.open('about:blank', 'popup_' + window.name, - 'resizable,width=400,height=600,menubar=yes,status=yes,scrollbars=yes'); - return true; -} - -function popup_anchor() { - var anchor = this; - window.open('about:blank', 'popup_' + window.name, - 'resizable,width=400,height=600,location=no,menubar=yes,scrollbars=yes'); - - anchor.target = 'popup_' + window.name; - - if (anchor.href.indexOf("navtarget=") >= 0) - return true; - - if (anchor.href.indexOf("?") >= 0) { - anchor.href = anchor.href + ';navtarget=' + window.name; - } - else { - anchor.href = anchor.href + '?navtarget=' + window.name; - } - return true; -} - -function navigate_here(searchform) { - searchform = document.getElementById(searchform); - searchform.target = window.name; - return true; -} - -function window_unique(serial) { - if (!window.name) - window.name = 'lxr_source_' + serial; -} - -function do_search(form) { - if (use_ajax_navigation) { - var res = document.getElementById('search_results'); - res.style.display = 'block'; - res.innerHTML = '
Searching...
'; - - pjx_search(['type__search', - 'search', 'v', 'tree__' + loaded_tree, 'NO_CACHE'], - ['search_results']); - return false; - } - else if (use_popup_navigation) { - form.target = 'popup_' + window.name; - form.navtarget.value = window.name; - reswin = window.open('about:blank', 'popup_' + window.name, - 'resizable,width=400,height=600,location=no,menubar=yes,scrollbars=yes'); - } - return true; -} - -function hide_search() { - var res = document.getElementById('search_results'); - res.style.display = 'none'; - return false; -} - -var loaded_hash; -var loaded_tree; -var loaded_file; -var loaded_ver; -var loaded_line; - -var pending_tree; -var pending_file; -var pending_ver; -var pending_line; - -function ajax_nav() { - var file = this.href.replace(/^(http:.*?\/.*?[+][*]\/|)/, ''); - load_file(loaded_tree, file, loaded_ver, ''); - return false; -} - -function ajax_jumpto_line() { - location.hash = location.hash.replace(/\#L\d+$/, '') + - this.href.replace(/.*(\#L\d+)$/, '$1'); - check_hash_navigation(); - return false; -} - -function ajax_prefs() { - if (use_ajax_navigation) { - var full_path = location.href.split(/#/)[0]; - full_path = full_path + '/' + loaded_tree; - if (loaded_ver) { - full_path = full_path + '+' + loaded_ver; - } - full_path = full_path + '/+prefs?return=' + loaded_file.replace(/^\/?$/, '.'); - location = full_path; - return false; - } - else { - return true; - } -} - -var hash_check; -function check_hash_navigation() { - if (location.hash != loaded_hash) { - if (location.hash.replace(/\#L\d+$/, '') == - loaded_hash.replace(/\#L\d+$/, '')) - { - var l = location.hash.replace(/.*#(L\d+)$/, '$1'); - var a = document.getElementById(l); - if (l && a) { - a.name = location.hash.replace(/^\#/, ''); - location.hash = a.name; - loaded_hash = location.hash; - } - hash_check = setTimeout('check_hash_navigation()', 50); - } - else { - load_content(); - } - } - else { - hash_check = setTimeout('check_hash_navigation()', 50); - } -} - -function load_file(tree, file, ver, line) { - if (!use_ajax_navigation) { - return true; - } - - if (hash_check) { - clearTimeout(hash_check); - } - - if ((pending_tree == tree) && - (pending_file == file) && - (pending_ver == ver)) - { - if (line > 0) - line = '#L' + line; - location.hash = location.hash.replace(/\#L\d+$/, '') + line; - check_hash_navigation(); - return false; - } - - - var res = document.getElementById('content'); - - res.innerHTML = '
Loading...
'; - pending_line = line; - pending_tree = tree; - pending_file = file; - if (ver) { - pending_ver = ver; - } - else { - pending_ver = ''; - } - - if (!file) - file = '/'; - if (line < 1) - line = 1; - pjx_load_file(['tree__' + tree, 'file__' + file, 'v__' + ver, - 'line__' + line, 'NO_CACHE'], - [load_file_finalize]); - return false; -} - -function load_file_finalize(content) { - var res = document.getElementById('content'); - res.innerHTML = 'Done'; - res.innerHTML = content; - var head = document.getElementById('current_path'); - head.innerHTML = '' + pending_tree + ''; - var path_walked = ''; - var elems = pending_file.split(/\//); - for (var i=0; i' + elems[i] + ''; - path_walked = path_walked + elems[i] + '/'; - } - } - document.title = 'LXR ' + pending_tree + '/' + pending_file; - - var full_tree = pending_tree; - if (pending_ver) { - full_tree = full_tree + '+' + pending_ver; - } - var full_path = full_tree + '/' + pending_file.replace(/^\/?/, ''); - - var pre = document.getElementById('file_contents'); - if (pre && pre.className == 'partial') { - pjx_load_file(['tree__' + pending_tree, 'file__' + pending_file, - 'v__' + pending_ver, 'full__1', 'NO_CACHE'], - [load_file_finalize]); - } - - var print = document.getElementById('lxr_print'); - var dirlist = document.getElementById('content_dir'); - if (dirlist) { - print.style.display = 'none'; - } - else { - var pform = document.getElementById('print_form'); - pform.action = '../' + full_tree + '/+print=' + - pending_file.replace(/^\/?/, ''); - print.style.display = 'inline'; - } - - if (hash_check) { - clearTimeout(hash_check); - } - if (pending_line) { - var anchor = document.getElementById('L' + pending_line); - if (anchor) { - anchor.name = full_path + '#L' + pending_line; - location.hash = full_path + '#L' + pending_line; - } - else { - location.hash = full_path; - } - loaded_line = pending_line; - } - else { - location.hash = full_path; - loaded_line = 0; - } - loaded_hash = location.hash; - loaded_tree = pending_tree; - loaded_file = pending_file; - loaded_ver = pending_ver; - hash_check = setTimeout('check_hash_navigation()', 50); - -// TODO: This really takes oodles of time. Consider coding into html. - var i; - for (i = 0; i < document.links.length; i++) { - if (document.links[i].className == 'fref') { - document.links[i].onclick = ajax_nav; - } - else if (document.links[i].className == 'line') { - document.links[i].onclick = ajax_jumpto_line; - } - else if (document.links[i].className == 'sref' || - document.links[i].className == 'falt') - { - document.links[i].onclick = ajax_lookup_anchor; - } - - } -} - -function load_content() { - if (!use_ajax_navigation) { - return false; - } - var tree = location.hash.split('/', 1); - tree = tree[0].split(/[+]/); - var ver = tree[1] || ''; - tree = tree[0].replace(/^#/, ''); - var file = location.hash.replace(/^[^\/]*\/?/, ''); - var line = file.replace(/.*\#L(\d+)/, '$1'); - file = file.replace(/\#L\d+$/, ''); - load_file(tree, file, ver, line); - - pjx_releases(['tree__' + tree, 'NO_CACHE'], - [load_content_finalize]); -} - -function load_content_finalize(content) { - var res = document.getElementById('ver_select'); - res.innerHTML = content; - var verlist = document.getElementById('v'); - verlist.value = pending_ver; -} - -function update_version(verlist, base_url, tree, defversion, path) { - if (use_ajax_navigation) { - var file = location.hash.replace(/^[^\/]*\//, ''); - var line = file.replace(/.*\#L(\d+)/, '$1'); - file = file.replace(/\#L\d*$/, ''); - - load_file(loaded_tree, file, verlist.value, line); - return false; - } - else { - var newurl = base_url.replace(/[^\/]*\/?$/, ''); - if (verlist.value == defversion) { - newurl = newurl + tree; - } - else { - newurl = newurl + tree + '+' + verlist.value; - } - newurl = newurl + '/' + path.replace(/^\//, ''); - document.location = newurl; - } -} - -function next_version() { - var verlist = document.getElementById('v'); - if (verlist.selectedIndex > 0) { - verlist.selectedIndex = verlist.selectedIndex - 1; - update_version(verlist, '', '', '', ''); - } - return false; -} - -function previous_version() { - var verlist = document.getElementById('v'); - if (verlist.selectedIndex < verlist.length - 1) { - verlist.selectedIndex = verlist.selectedIndex + 1; - update_version(verlist, '', '', '', ''); - } - return false; -} - -function popup_prepare(serial) { - window_unique(serial); - var i; - for (i = 0; i < document.links.length; i++) { - if (document.links[i].className == 'sref' || - document.links[i].className == 'falt') - { - document.links[i].onclick = popup_anchor; - } - } -} - -function ajax_lookup_anchor(event, anchor) { - if (!use_ajax_navigation) - return true; - - if (!anchor) - anchor = this; - - lookup = anchor.href.replace(/^(http:.*?\/.*?[+][*]\/|)/, ''); - - var lvar = document.getElementById('ajax_lookup'); - lvar.value = lookup; - - var res = document.getElementById('search_results'); - res.style.display = 'block'; - res.innerHTML = '
Searching...
'; - - pjx_search(['ajax_lookup', 'v', 'tree__' + loaded_tree, 'NO_CACHE'], - ['search_results']); - return false; -} diff --git a/cgi-bin/lxr b/cgi-bin/lxr deleted file mode 100755 index b134738..0000000 --- a/cgi-bin/lxr +++ /dev/null @@ -1,735 +0,0 @@ -#!/usr/bin/perl - -use strict; - -use FindBin; -use lib "$FindBin::Bin/../lib"; - -use CGI::Carp qw(fatalsToBrowser); -use IO::Handle; - -use LXRng ROOT => "$FindBin::Bin/.."; -use LXRng::Context; -use LXRng::Lang; -use LXRng::Parse::Simple; -use LXRng::Markup::File; -use LXRng::Markup::Dir; -use Subst::Complex; - -use Template; -use Digest::SHA1 qw(sha1_hex); -use CGI::Ajax; -use CGI::Simple qw(-newstyle_urls); -use File::Temp qw(tempdir tempfile); -use POSIX qw(waitpid); - -use constant PDF_LINELEN => 95; -use constant PDF_CHARPTS => 6.6; - -use vars qw($has_gzip_io); -eval { require PerlIO::gzip; $has_gzip_io = 1; }; - - -# Return 1 if gzip compression of html is desired. - -sub do_compress_response { - my ($query) = @_; - - my @enc = split(",", $query->http('Accept-Encoding')); - return $has_gzip_io && grep { $_ eq 'gzip' } @enc; -} - - -# Progressive output of marked-up file. If the file in question -# exists in cache, and this is the initial load of an ajax-requested -# file, return only the lines the user wants to see (with a minimum of -# context) as a first approximation. - -sub print_markedup_file { - my ($context, $template, $node) = @_; - - autoflush STDOUT 1; - - unless ($node) { - print('
File not found.
'); - return; - } - - if ($node->isa('LXRng::Repo::Directory')) { - my $markup = LXRng::Markup::Dir->new('context' => $context, - 'node' => $node); - $template->process('content_dir.tt2', - {'context' => $context, - 'dir_listing' => $markup->listing}) - or die $template->error(); - } - else { - # Grmble. We assume the identifiers to markup are identical - # from one version to another, but if the same revision of a - # file exists both in an indexed and un-indexed release, one - # of them will have its identifiers highlighted and the other - # not. So we can't share a cache slot across releases without - # adding some extra logic here. Bummer. - # TODO: Resolve by caching only accesses to releases that are - # is_indexed. - my $shaid = sha1_hex(join("\0", $node->name, $node->revision, - $context->release)); - my $cfile; - $cfile = $context->config->{'cache'}.'/'.$shaid - if exists $context->config->{'cache'}; - - if ($cfile and -e $cfile) { - open(my $cache, '<', $cfile); - - my $focus = $context->param('line') || 0; - $focus = 0 if $context->param('full'); - my $class = $focus ? 'partial' : 'full'; - my $start = $focus > 5 ? " start=".($focus - 5) : ""; - print("
");
-	    while (<$cache>) {
-		next if $focus and $. < $focus - 5;
-		print($_);
-		last if $focus and $. > $focus + 70;
-	    }
-	    print("
"); - close($cache); - } - else { - my $cache; - open($cache, '>', $cfile) if $cfile; - my $handle = $node->handle(); - LXRng::Lang->init($context); - my $lang = LXRng::Lang->new($node); - my $parse = LXRng::Parse::Simple->new($handle, 8, - @{$lang->parsespec}); - my $markup = LXRng::Markup::File->new('context' => $context); - my $subst = $lang->markuphandlers($context, $node, $markup); - - # Possible optimization: store cached file also as .gz, - # and pass that on if the client accepts gzip-encoded - # data. Saves us from compressing the cached file each - # time it's needed, but requires a bit of fiddling with - # perlio and the streams to get right. Also messes up - # partial transfers. - print("
    "); - while (1) { - my @frags = $markup->markupfile($subst, $parse); - last unless @frags; - print(@frags); - print($cache @frags) if $cache; - } - print("
\n"); - } - } -} - -sub print_tree_list { - my ($context, $template) = @_; - - $template->process('tree_list.tt2', - {'context' => $context}) - or die $template->error(); -} - -sub print_release_list { - my ($context, $template) = @_; - - $template->process('release_select.tt2', - {'context' => $context}) - or die $template->error(); -} - -sub source { - my ($context, $template, $query, $template_extra_args) = @_; - - my $pjx = CGI::Ajax->new('pjx_search' => '', - 'pjx_load_file' => '', - 'pjx_releases' => ''); - $pjx->js_encode_function('escape'); - - if ($context->prefs and $context->prefs->{'navmethod'} eq 'ajax') { - if ($context->tree ne '') { - my $base = $context->base_url(1); - my $path = $context->vtree.'/'.$context->path; - print($query->redirect($base.'#'.$path)); - } - else { - print($query->header(-type => 'text/html', - -charset => 'utf-8')); - - if ($context->release eq 'trees') { - print_tree_list($context, $template); - } - else { - my $base = $context->base_url(1); - $base =~ s,/*$,/ajax+*/,; - - $template->process('main.tt2', - {'context' => $context, - 'base_url' => $base, - 'javascript' => $pjx->show_javascript(), - 'is_ajax' => 1}) - or die $template->error(); - } - } - return; - } - - if ($context->tree eq '') { - print($query->header(-type => 'text/html', - -charset => 'utf-8')); - print_tree_list($context, $template); - return; - } - - - my $ver = $context->release; - my $rep = $context->config->{'repository'}; - die "No tree given" unless $rep; - - my $node = $rep->node($context->path, $ver); - die "Node not found: ".$context->path." ($ver)" unless $node; - - my $gzip = do_compress_response($query); - - my @history = $query->cookie('lxr_history_'.$context->tree); - if ($node->isa('LXRng::Repo::File')) { - my $h = $context->path.'+'.$ver; - @history = ($h, grep { $_ ne $h } @history); - splice(@history, 15) if @history > 15; - } - - my $lxr_hist = $query->cookie(-name => 'lxr_history_'.$context->tree, - -values => \@history, - -expires => '+1y'); - - print($query->header(-type => 'text/html', - -charset => 'utf-8', - -cookie => $lxr_hist, - $gzip ? (-content_encoding => 'gzip') : ())); - - binmode(\*STDOUT, ":gzip") if $gzip; - - my @rels = @{$context->all_releases()}; - unshift(@rels, $rels[0]); - while (@rels > 2 and $rels[1] ne $context->release) { - shift(@rels); - } - - my $ver_next = @rels > 1 ? $rels[0] : $context->release; - my $ver_prev = @rels > 2 ? $rels[2] : $context->release; - - my %template_args = (%{$template_extra_args || {}}, - 'context' => $context, - 'tree' => $context->tree, - 'node' => $node, - 'ver_prev' => $ver_prev, - 'ver_next' => $ver_next, - 'base_url' => $context->base_url, - 'javascript' => $pjx->show_javascript()); - - - if ($context->prefs and $context->prefs->{'navmethod'} eq 'popup') { - $template_args{'is_popup'} = 1; - $template_args{'popup_serial'} = int(rand(1000000)); - } - - if ($node->isa('LXRng::Repo::Directory')) { - my $markup = LXRng::Markup::Dir->new('context' => $context, - 'node' => $node); - $template->process('main.tt2', - {%template_args, - 'dir_listing' => $markup->listing, - 'is_dir' => 1}) - or die $template->error(); - } - else { - my $html = ''; - $template->process('main.tt2', - {%template_args, - 'file_content' => '', - 'is_dir' => 0}, - \$html) - or die $template->error(); - - # Template directives in processed template. Sigh. TT2 sadly - # can't do progressive rendering of its templates, so we cheat... - my ($pre, $post) = split('', $html); - print($pre); - print_markedup_file($context, $template, $node); - print($post); - } - - # TODO: This is potentially useful, in that it resets the stream - # to uncompressed mode. However, under Perl 5.8.8+PerlIO::gzip - # 0.18, this seems to truncate the stream. Not strictly needed - # for CGI, reexamine when adapting to mod_perl. - ## binmode(\*STDOUT, ":pop") if $gzip; -} - -#sub ident { -# my ($self) = @_; - -# my $index = $self->context->config->{'index'}; -# my $view = LXRng::View->new('context' => $self->context);; - -# my $ident = $self->context->value('ident'); -# my $target = $self->context->value('navtarget'); -# $target ||= 'source'; - -# my $rel_id = $index->release_id($self->tree, $self->context->value('v')); -# my ($symname, $symid, $ident, $refs) = -# $index->get_identifier_info($ident, $rel_id); - -# $$ident[1] = $LXRng::Lang::deftypes{$$ident[1]}; -# $$ident[5] &&= $LXRng::Lang::deftypes{$$ident[5]}; - -# return $view->identifier_info($symname, $symid, $ident, $refs, $target); -#} - - -# Perform various search operations. Return results as html suitable -# both as a response to an ajax request and inclusion in a more -# general html document. - -sub search { - my ($context, $template, $type, $find) = @_; - - my $ver = $context->release; - $find ||= $context->param('search'); - - my $index = $context->config->{'index'}; - my $rel_id = $index->release_id($context->tree, $ver); - my %template_args = ('context' => $context); - - $template_args{'navtarget'} = 'target='.$context->param('navtarget') - if $context->param('navtarget'); - - - if ($find =~ /\S/) { - if ($find =~ /^(ident|code):(.*)/) { - $type = 'code'; - $find = $2; - } - elsif ($find =~ /^(file|path):(.*)/) { - $type = 'file'; - $find = $2; - } - elsif ($find =~ /^(text):(.*)/) { - $type = 'text'; - $find = $2; - } - - if ($type eq 'file' or $type eq 'search') { - my $files = $index->files_by_wildcard($context->tree, - $ver, $find); - $template_args{'file_res'} = {'query' => $find, - 'files' => $files,} - } - if ($type eq 'text' or $type eq 'search') { - my $hash = $context->config->{'search'}; - my ($total, $res) = $hash->search($rel_id, $find); - - $template_args{'text_res'} = {'query' => $find, - 'total' => $total, - 'files' => $res}; - } - if ($type eq 'code' or $type eq 'search') { - my $result = $index->identifiers_by_name($context->tree, - $ver, $find); - my @cooked = (map { $$_[1] = ucfirst($LXRng::Lang::deftypes{$$_[1]}); - $_ } - sort { $LXRng::Lang::defweight{$$b[1]} cmp - $LXRng::Lang::defweight{$$a[1]} || - $$a[2] cmp $$b[2] || - $$a[3] <=> $$b[3] } - @$result); - $template_args{'code_res'} = {'query' => $find, - 'idents' => \@cooked}; - } - if ($type eq 'ident') { - my $usage = $context->config->{'usage'}; - my ($symname, $symid, $ident, $refs) = - $index->get_identifier_info($usage, $find, $rel_id); - - $$ident[1] = ucfirst($LXRng::Lang::deftypes{$$ident[1]}); - $$ident[5] &&= $LXRng::Lang::deftypes{$$ident[5]}; - - $template_args{'ident_res'} = {'query' => $symname, - 'ident' => $ident, - 'refs' => $refs}; - } - if ($type eq 'ambig') { - my $rep = $context->config->{'repository'}; - my @args = grep { - $rep->node($_, $context->release) - } split(/\|/, $find); - $template_args{'ambig_res'} = {'query' => $find, - 'files' => \@args,} - } - } - else { - die "No query string given"; - } - my $html = ''; - $template_args{'tree'} = $context->tree; - $template_args{'search_type'} = $type if - $type =~ /^(search|file|text|code|ident|ambig)$/; - $template->process('search_result.tt2', - \%template_args, - \$html) - or die $template->error(); - return $html; -} - - -# Display search results for plain and popup navigation methods. -# (Ajax methods call "search" directly.) - -sub search_result { - my ($context, $template, $query, $result) = @_; - - my %template_args = ('context' => $context, - 'tree' => $context->tree, - 'search_res' => $result, - 'base_url' => $context->base_url); - - if ($context->prefs and $context->prefs->{'navmethod'} eq 'popup') { - my $gzip = do_compress_response($query); - - print($query->header(-type => 'text/html', - -charset => 'utf-8', - $gzip ? (-content_encoding => 'gzip') : ())); - - binmode(\*STDOUT, ":gzip") if $gzip; - - $template->process('popup_main.tt2', - {%template_args, - 'is_popup' => 1}) - or die $template->error(); - } - else { - $context->path(''); - source($context, $template, $query, \%template_args); - } -} - - -# Callback to perform the ajax-available functions. - -sub handle_ajax_request { - my ($query, $context, $template) = @_; - my $gzip = do_compress_response($query); - - $query->no_cache(1); - print($query->header(-type => 'text/html', - -charset => 'utf-8', - -cache-control => 'no-store, no-cache, must-revalidate', - $gzip ? (-content_encoding => 'gzip') : ())); - - binmode(\*STDOUT, ":gzip") if $gzip; - - if ($context->param('fname') eq 'pjx_load_file') { - my $rep = $context->config->{'repository'}; - my $node = $rep->node($context->param('file'), $context->release); - print_markedup_file($context, $template, $node); - - } - elsif ($context->param('fname') eq 'pjx_search') { - if ($context->param('ajax_lookup') =~ - /^[+ ](code|ident|file|text|ambig)=(.*)/) - { - print(search($context, $template, $1, $2)); - } - else { - print(search($context, $template, 'search', - $context->param('search'))); - } - } - elsif ($context->param('fname') eq 'pjx_releases') { - print_release_list($context, $template); - } - - # binmode(\*STDOUT, ":pop") if $gzip; -} - - -# Stuff user preferences in cookie. - -sub handle_preferences { - my ($query, $context, $template) = @_; - - if ($context->param('resultloc')) { - my @prefs; - if ($context->param('resultloc') =~ /^(replace|popup|ajax)$/) { - push(@prefs, 'navmethod='.$1); - } - my $lxr_prefs = $query->cookie(-name => 'lxr_prefs', - -values => \@prefs, - -expires => '+1y'); - print($query->header(-type => 'text/html', - -charset => 'utf-8', - -cookie => $lxr_prefs)); - - my %template_args; - if (defined($context->param('return')) and $context->config) { - $template_args{'return'} = - $context->base_url.$query->param('return'); - } - else { - my $url = $query->url(-full => 1, -path => 1); - $url =~ s,/[+ ]prefs\b.*,/,; - $template_args{'return'} = $url; - } - - $template->process('prefs_set.tt2', - \%template_args) - or die $template->error(); - } - else { - print($query->header(-type => 'text/html', - -charset => 'utf-8')); - - my $nav = 'is_replace'; - $nav = 'is_'.$context->prefs->{'navmethod'} if - $context->prefs and $context->prefs->{'navmethod'} ne ''; - - $template->process('prefs.tt2', - {'return' => $query->param('return'), - $nav => 1}) - or die $template->error(); - } -} - - -# Generate pdf listing of given file. Much if the following lifted -# from the script "texify". Proof of concept, code quality could be -# better. - -sub generate_pdf { - my ($query, $context, $template, $path) = @_; - - my $tempdir = tempdir(CLEANUP => 1); - - my %tspecials = ( - '$' => '\$', '*' => "\$\\ast\$", - '&' => '\&', '%' => '\%', - '#' => '\#', '_' => '\_', - '^' => '\^{}', '{' => '\{', - '}' => '\}', '|' => "\$|\$", - '[' => '{[}', ']' => '{]}', - "'" => "{'}", "\"" => "\\string\"", - '~' => '\~{}', '<' => "\$<\$", - '>' => "\$>\$", "\\" => "\$\\backslash\$", - '-' => '\dash{}', -# These are latin1-replacements, and interact badly with utf8... - "\242" => '?', "\244" => '?', - "\245" => '?', "\246" => '?', - "\252" => "\$\252\$", "\254" => "\$\254\$", - "\255" => "\\dash{}", "\260" => "\$\260\$", - "\261" => "\$\261\$", "\262" => "\$\262\$", - "\263" => "\$\263\$", "\265" => "\$\265\$", - "\271" => "\$\271\$", "\272" => "\$\272\$", - "\327" => "\$\327\$", "\367" => "\$\367\$", - ); - - my $tspecials = join('', map { quotemeta($_) } keys(%tspecials)); - - my $ver = $context->release; - my $rep = $context->config->{'repository'}; - my $node = $rep->node($path, $ver); - - die "No such file" unless $node; - - my $handle = $node->handle(); - LXRng::Lang->init($context); - my $lang = LXRng::Lang->new($node); - my $parse = LXRng::Parse::Simple->new($handle, 8, - @{$lang->parsespec}); - my $res = $lang->reserved(); - my $resre; - if (%$res) { - $resre = '(?:(?<=[\s\W])|^)('. - join('|', map { my $c = $_; $c =~ s/\#/\\\#/g; quotemeta($c) } - sort { length($b) <=> length($a) } - keys %$res).')(?=$|[\s\W])'; - } - - my @lines; - my $row = 1; - my $col = 0; - my $line = '\\lxrln{1}'; - - while (1) { - my ($btype, $frag) = $parse->nextfrag; - - last unless defined $frag; - - $btype ||= 'code'; - my @parts = split(/(\n)/, $frag); - - while (@parts) { - my $part = shift(@parts); - my $align = 0; - my $cont = 0; - - if ($part eq "\n") { - push(@lines, $line); - - $col = 0; - $row++; - if ($row % 5 == 0) { - $line = "\\lxrln{$row}"; - } - else { - $line = ''; - } - next; - } - - if ($part =~ /^(.*? +)(.*)/) { - unshift(@parts, $2); - $part = $1; - $align = 1; - } - - $col += length($part); - - if ($col > PDF_LINELEN) { - unshift(@parts, - substr($part, PDF_LINELEN - $col, length($part), '')); - if ($part =~ s/([^\s_,\(\)\{\}\/\=\-\+\*\<\>\[\]\.]+)$//) { - if (length($1) < 20) { - unshift(@parts, $1); - } - else { - $part .= $1; - } - } - $align = 0; - $cont = 1; - } - - $part =~ s(([$tspecials\0-\010\013\014\016-\037\200-\240])) - (exists $tspecials{$1} ? $tspecials{$1} : '?')ge; - - if ($btype eq 'code') { - $part =~ s/$resre/\\textbf{$1}/g if $resre; - } - elsif ($btype eq 'include') { - $part =~ s/$resre/\\textbf{$1}/ if $resre; - } - elsif ($btype eq 'comment') { - $part = '\textit{'.$part.'}'; - } - elsif ($btype eq 'string') { - $part = '\texttt{'.$part.'}'; - } - - # Common fixed-width "ascii-art" characters. - $part =~ s/(\$\\ast\$|=)/'\\makebox['.PDF_CHARPTS."pt][c]{$1}"/ge; - $line .= $part; - if ($align) { - $line = '\\makebox['.int($col * PDF_CHARPTS). - 'pt][l]{'.$line.'}'; - } - if ($cont) { - push(@lines, "$line\\raisebox{-2pt}{\\ArrowBoldRightStrobe}"); - $line = '\\raisebox{-2pt}{\\ArrowBoldDownRight} '; - $col = 3; - } - } - } - - if ($line ne '') { - push(@lines, $line); - } - else { - $row--; - } - - if (@lines and $row % 5 != 0) { - $lines[$#lines] =~ s/^/\\lxrln{$row}/; - } - - my $pathdesc = $context->tree."/$path ($ver)"; - $pathdesc =~ s/([$tspecials])/$tspecials{$1}/ge; - - my ($texh, $texname) = tempfile(DIR => $tempdir, SUFFIX => '.tex'); - - $template->process('print_pdf.tt2', - {'pathdesc' => $pathdesc, - 'lines' => \@lines}, - $texh) - or die $template->error(); - my $pid = fork(); - die $! unless defined($pid); - if ($pid == 0) { - close(STDOUT); - open(STDOUT, "> $texname.output"); - close(STDERR); - open(STDERR, ">&STDOUT"); - chdir($tempdir); - exec("pdflatex", "$texname"); - kill(9, $$); - } - waitpid($pid, 0); - my $pdfname = $texname; - $pdfname =~ s/[.]tex$/.pdf/; - if (-e $pdfname) { - open(my $pdfh, "< $pdfname") or die $!; - - print($query->header(-type => 'application/pdf', - -content_disposition => - "inline; filename=$path.pdf")); - my $buf = ''; - while (sysread($pdfh, $buf, 65536) > 0) { - print($buf); - } - close($pdfh); - } - elsif (-e "$texname.output") { - open(my $errh, "< $texname.output") or die $!; - my @err = <$errh>; - close($errh); - @err = splice(@err, -15) if @err > 15; - die "PDF generation failed: ".join("\n", @err); - } - else { - die "PDF generation failed"; - } -} - - -# Initial request dispatch. - -my $query = CGI::Simple->new(); -my $context = LXRng::Context->new('query' => $query); -my $template = Template->new({'INCLUDE_PATH' => $LXRng::ROOT.'/tmpl/'}); - - -if ($context->param('fname')) { - handle_ajax_request($query, $context, $template); -} -else { - if ($context->path =~ /^[+ ]prefs$/) { - handle_preferences($query, $context, $template); - } - elsif ($context->path =~ /^[+ ]print=(.*)/) { - generate_pdf($query, $context, $template, $1); - } - else { - if ($context->path =~ - /^[+ ](search|code|ident|file|text|ambig)(?:=(.*)|)/) - { - search_result($context, $template, $query, - search($context, $template, $1, $2)); - $context->path(''); - } - else { - source($context, $template, $query); - } - } -} - -1; -- cgit v1.2.3