3 use Squirrel::Template;
4 use Carp qw(confess cluck);
7 our $VERSION = "1.007";
10 my ($class, $cfg, $rsets) = @_;
12 my @conf_dirs = $class->template_dirs($cfg);
14 if ($rsets && @$rsets) {
15 for my $set (@$rsets) {
16 push @dirs, map "$_/$set", @conf_dirs;
18 push @dirs, @conf_dirs;
26 template_dir => \@dirs,
28 charset => $cfg->charset,
32 require BSE::Util::HTML;
33 return BSE::Util::HTML::escape_html($_[0]);
36 require BSE::Util::HTML;
37 return BSE::Util::HTML::escape_uri($_[0]);
41 if ($cfg->entry("basic", "cache_templates")) {
43 $opts{cache} = BSE::Cache->load($cfg);
46 $opts{preload} = $cfg->entry("basic", "preload_template");
48 return Squirrel::Template->new(%opts);
52 my ($class, $cfg, $template) = @_;
54 my $file = $cfg->entry('templates', $template) || $template;
55 $file =~ /\.\w+$/ or $file .= ".tmpl";
61 my ($class, $template, $cfg, $acts, $base_template, $rsets, $vars) = @_;
63 my $file = $class->_get_filename($cfg, $template);
64 my $obj = $class->templater($cfg, $rsets);
68 unless ($class->find_source($template, $cfg)) {
69 $template = $base_template;
70 $file = $class->_get_filename($cfg, $template);
74 return $obj->show_page(undef, $file, $acts, undef, undef, $vars);
78 my ($class, $source, $cfg, $acts, $vars) = @_;
80 my $obj = $class->templater($cfg);
82 $obj->replace_template($source, $acts, undef, undef, $vars);
86 my ($class, $cfg) = @_;
92 my ($class, $cfg) = @_;
98 my ($class, $cfg) = @_;
100 my $type = "text/html";
101 my $charset = $class->charset($cfg);
102 return $type . "; charset=$charset";
106 my ($class, $cfg, $template) = @_;
108 return $cfg->entry("template types", $template)
109 || $class->html_type($cfg);
113 my ($class, $template, $cfg, $acts, $base_template) = @_;
115 $class->show_literal($class->get_page($template, $cfg, $acts, $base_template), $cfg);
119 my ($class, $source, $cfg, $acts) = @_;
121 $class->show_literal($class->replace($source, $cfg, $acts), $cfg);
125 my ($class, $text, $cfg) = @_;
127 my $type = $class->html_type($cfg);
129 print "Content-Type: $type\n\n";
134 my ($class, $template, $cfg, $acts, $base_template, $rsets, $vars) = @_;
136 my $content = $class->get_page($template, $cfg, $acts,
137 $base_template, $rsets, $vars);
139 return $class->make_response($content, $class->get_type($cfg, $template));
143 my ($class, $content, $type) = @_;
145 if ($type =~ /\bcharset=([\w-]+)/) {
150 my $cfg = BSE::Cfg->single;
151 my $check = $cfg->entry("utf8", "check", Encode::FB_DEFAULT());
152 $check = oct($check) if $check =~ /^0/;
154 $content = Encode::encode($charset, $content, $check);
162 push @{$result->{headers}}, "Content-Length: ".length($result->{content});
168 my ($class, $url, $cfg) = @_;
181 my ($class, $url, $cfg) = @_;
194 my ($class, $cfg) = @_;
196 ref($cfg) eq 'BSE::Cfg'
197 or confess "Invalid cfg $cfg supplied\n";
199 my $path_sep = $Config::Config{path_sep};
201 my $base = $cfg->entryVar('paths', 'templates');
202 my @dirs = split /\Q$path_sep/, $base;
203 my $local = $cfg->entry('paths', 'local_templates');
205 unshift @dirs, split /\Q$path_sep/,
206 $cfg->entryVar('paths', 'local_templates');
213 my ($class, $template, $cfg) = @_;
215 my @dirs = $class->template_dirs($cfg);
217 my $file = $cfg->entry('templates', $template) || $template;
218 $file =~ /\.\w+$/ or $file .= ".tmpl";
220 for my $dir (@dirs) {
221 return "$dir/$file" if -f "$dir/$file";
228 my ($class, $template, $cfg) = @_;
230 my $path = $class->find_source($template, $cfg)
231 or confess "Cannot find template $template";
232 open my $source, "< $path"
233 or confess "Cannot open template $path: $!";
236 my $charset = $cfg->charset;
237 binmode $source, ":encoding($charset)";
239 my $html = do { local $/; <$source> };
246 my ($class, $req, $result) = @_;
248 $class->output_resultc($req->cfg, $result);
252 my ($class, $cfg, $result) = @_;
259 push @{$result->{headers}}, "Content-Type: $result->{type}"
261 my $add_cache_control = $cfg->entry('basic', 'no_cache_dynamic', 1);
262 if (defined $result->{no_cache_dynamic}) {
263 $add_cache_control = $result->{no_cache_dynamic};
265 if ($add_cache_control) {
266 for my $header (@{$result->{headers}}) {
267 if ($header =~ /^cache-control:/i) {
268 $add_cache_control = 0;
272 if ($add_cache_control) {
273 push @{$result->{headers}}, "Cache-Control: no-cache";
277 if ($result->{content_filename}) {
278 # at some point, if we have a FEP like perlbal of nginx we might
279 # get it to serve the file instead
280 if (open my $fh, "<", $result->{content_filename}) {
282 $result->{content_fh} = $fh;
285 print STDERR "$ENV{SCRIPT_NAME}: ** cannot open file $result->{content_filename}: $!\n";
286 $result->{content} = "* Internal error";
290 if (!grep /^content-length:/i, @{$result->{headers}}) {
292 if (defined $result->{content}) {
293 $length = length $result->{content};
295 if (defined $result->{content_fh}) {
296 # this may need to change if we support byte ranges
297 $length += -s $result->{content_fh};
300 if (defined $length) {
301 push @{$result->{headers}}, "Content-Length: $length";
304 if (exists $ENV{GATEWAY_INTERFACE}
305 && $ENV{GATEWAY_INTERFACE} =~ /^CGI-Perl\//) {
307 my $r = Apache->request or die;
308 $r->send_cgi_header(join("\n", @{$result->{headers}})."\n\n");
311 print "$_\n" for @{$result->{headers}};
314 if (defined $result->{content}) {
315 if ($result->{content} =~ /([^\x00-\xff])/) {
316 cluck "Wide character in content (\\x{", sprintf("%X", ord $1), "})";
318 print $result->{content};
320 elsif ($result->{content_fh}) {
321 # in the future this could be updated to support byte ranges
323 my $fh = $result->{content_fh};
325 while (my $data = <$fh>) {
330 print STDERR "$ENV{SCRIPT_NAME}: ** No content supplied\n";
331 print "** Internal error\n";
334 if ($result->{content}
335 && $result->{type} =~ m(text/html|application/xhtml\+xml)
336 && $cfg->entry("html", "validate", 0)) {
337 require BSE::Util::ValidateHTML;
338 BSE::Util::ValidateHTML->validate($cfg, $result);