+sub output_with_http_headers($$$$;$) {
+ my ( $query, $cookie, $data, $content_type, $status ) = @_;
+ $status ||= '200 OK';
+
+ my %content_type_map = (
+ 'html' => 'text/html',
+ 'js' => 'text/javascript',
+ 'json' => 'application/json',
+ 'xml' => 'text/xml',
+ # NOTE: not using application/atom+xml or application/rss+xml because of
+ # Internet Explorer 6; see bug 2078.
+ 'rss' => 'text/xml',
+ 'atom' => 'text/xml'
+ );
+
+ die "Unknown content type '$content_type'" if ( !defined( $content_type_map{$content_type} ) );
+ my $options = {
+ type => $content_type_map{$content_type},
+ status => $status,
+ charset => 'UTF-8',
+ Pragma => 'no-cache',
+ 'Cache-Control' => 'no-cache',
+ };
+ $options->{cookie} = $cookie if $cookie;
+ if ($content_type eq 'html') { # guaranteed to be one of the content_type_map keys, else we'd have died
+ $options->{'Content-Style-Type' } = 'text/css';
+ $options->{'Content-Script-Type'} = 'text/javascript';
+ }
+
+# We can't encode here, that will double encode our templates, and xslt
+# We need to fix the encoding as it comes out of the database, or when we pass the variables to templates
+
+# utf8::encode($data) if utf8::is_utf8($data);
+
+ $data =~ s/\&\;amp\; /\&\; /g;
+ print $query->header($options), $data;
+}
+
+sub output_html_with_http_headers ($$$;$) {
+ my ( $query, $cookie, $data, $status ) = @_;
+ output_with_http_headers( $query, $cookie, $data, 'html', $status );
+}
+
+sub is_ajax () {
+ my $x_req = $ENV{HTTP_X_REQUESTED_WITH};
+ return ( $x_req and $x_req =~ /XMLHttpRequest/i ) ? 1 : 0;