source: main/tags/stable/greenstone2/perllib/gsprintf.pm@ 25632

Last change on this file since 25632 was 25499, checked in by ak19, 12 years ago

Dr Bainbridge modified gsprintf code to print text containing ampersand, less than and greater then with their entity values instead so that printing to STDERR from BEGIN statements (so far used only in PDFBoxConverter of the PDFBox extension) will play nicely with the XML generated for Pluginfo.pl. Pluginfo.pl has also been modified to use the correct gsprintf printing methods.

  • Property svn:keywords set to Author Date Id Revision
File size: 10.0 KB
Line 
1###########################################################################
2#
3# gsprintf.pm --
4# A component of the Greenstone digital library software
5# from the New Zealand Digital Library Project at the
6# University of Waikato, New Zealand.
7#
8# Copyright (C) 1999 New Zealand Digital Library Project
9#
10# This program is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation; either version 2 of the License, or
13# (at your option) any later version.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program; if not, write to the Free Software
22# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23#
24###########################################################################
25use strict;
26no strict 'refs';
27
28package gsprintf;
29require Exporter;
30@gsprintf::ISA=qw(Exporter);
31
32use unicode;
33use util;
34
35@gsprintf::EXPORT_OK = qw(gsprintf); # functions we can export into namespace
36
37
38# Language-specific resource bundle
39my %specialresourcebundle = ();
40our $specialoutputencoding; # our, so that it can be changed outside.
41
42# Default resource bundle
43my %defaultresourcebundle;
44my $defaultoutputencoding;
45
46# English resource bundle
47my %englishresourcebundle;
48my $englishoutputencoding;
49
50# Ignore the OutputEncoding strings in the resource bundles and output all text in UTF-8
51my $outputstringsinUTF8 = 0;
52my $freetext_xml_mode = 0;
53
54
55sub make_freetext_xml_safe
56{
57 my ($text) = @_;
58
59 $text =~ s/\&/&/g;
60 $text =~ s/\"/"/g;
61 $text =~ s/\</&lt;/g;
62 $text =~ s/\>/&gt;/g;
63
64 return $text;
65}
66
67
68sub gsprintf
69{
70 my ($handle, $text_string, @text_arguments) = @_;
71
72 # Return unless the required arguments were supplied
73 return unless (defined($handle) && defined($text_string));
74
75 # Look up all the strings in the dictionary
76 $text_string =~ s/(\{[^\}]+\})/&lookup_string($1)/eg;
77
78 # Resolve the string arguments using sprintf, then write out to the handle
79 my $text_string_resolved = sprintf($text_string, @text_arguments);
80
81 if ($freetext_xml_mode) {
82 $text_string_resolved = make_freetext_xml_safe($text_string_resolved);
83 }
84
85 print $handle $text_string_resolved;
86}
87
88
89sub lookup_string
90{
91 my ($stringkey) = @_;
92 return "" unless defined $stringkey;
93 # Try the language-specific resource bundle first
94 my $utf8string = $specialresourcebundle{$stringkey};
95 my $outputencoding = $specialoutputencoding;
96
97 # Try the default resource bundle next
98 if (!defined($utf8string)) {
99 # Load the default resource bundle if it is not already loaded
100 &load_default_resource_bundle() if (!%defaultresourcebundle);
101
102 $utf8string = $defaultresourcebundle{$stringkey};
103 $outputencoding = $defaultoutputencoding;
104 }
105
106 # Try the English resource bundle last
107 if (!defined($utf8string)) {
108 # Load the English resource bundle if it is not already loaded
109 &load_english_resource_bundle() if (!%englishresourcebundle);
110
111 $utf8string = $englishresourcebundle{$stringkey};
112 $outputencoding = $englishoutputencoding;
113 }
114
115 # No matching string was found, so just return the key
116 if (!defined($utf8string)) {
117 return $stringkey;
118 }
119
120 # Return the string matching the key
121 return $utf8string if (!defined($outputencoding) || $outputstringsinUTF8
122 || $outputencoding eq "utf8");
123
124 # If an 8-bit output encoding has been defined, encode the string appropriately
125 my $encoded=unicode::unicode2singlebyte(&unicode::utf82unicode($utf8string), $outputencoding);
126
127 # If we successfully encoded it, return it
128 if ($encoded) { return $encoded }
129
130 # Otherwise, we can't convert to the requested encoding. return the utf8?
131 $specialoutputencoding='utf8';
132 return $utf8string;
133}
134
135
136sub load_language_specific_resource_bundle
137{
138 my $language = shift(@_);
139
140 # Read the specified resource bundle
141 my $resourcebundlename = "strings_" . $language . ".properties";
142
143 %specialresourcebundle
144 = &read_resource_bundle_and_extensions($ENV{'GSDLHOME'},"perllib",$resourcebundlename);
145 return if (!%specialresourcebundle);
146
147 # Read the output encoding to use from the resource bundle
148 if ($ENV{'GSDLOS'} =~ /windows/) {
149 $specialoutputencoding = $specialresourcebundle{"{OutputEncoding.windows}"};
150 }
151 else {
152 # see if there is an encoding set in the appropriate locale env var
153
154 foreach my $envvar ('LC_ALL', 'LANG') {
155 if (!exists $ENV{$envvar}) { next }
156 my $locale=$ENV{$envvar};
157 if ($locale !~ /^\w+\.(.+)$/) { next }
158 my $enc=lc($1);
159 $enc =~ s/-/_/g;
160 if ($enc eq 'utf_8') { $enc='utf8' } # normalise to this name
161 $specialoutputencoding = $enc;
162 return;
163 }
164 $specialoutputencoding = $specialresourcebundle{"{OutputEncoding.unix}"};
165 }
166}
167
168
169sub load_default_resource_bundle
170{
171 # Read the default resource bundle
172 my $resourcebundlename = "strings.properties";
173
174 %defaultresourcebundle
175 = &read_resource_bundle_and_extensions($ENV{'GSDLHOME'},"perllib",$resourcebundlename);
176 if (!%defaultresourcebundle) {
177 # $! will still have the error value for the last failed syscall
178
179 my $error_message = "$! $resourcebundlename\n";
180
181 if ($freetext_xml_mode) {
182 $error_message = make_freetext_xml_safe($error_message);
183 }
184
185 print STDERR $error_message;
186
187 # set something so we don't bother trying to load it again
188 $defaultresourcebundle{0}=undef;
189 return;
190 }
191
192 # Read the output encoding to use from the resource bundle
193 if ($ENV{'GSDLOS'} =~ /windows/) {
194 $defaultoutputencoding = $defaultresourcebundle{"{OutputEncoding.windows}"};
195 }
196 else {
197 $defaultoutputencoding = $defaultresourcebundle{"{OutputEncoding.unix}"};
198 }
199}
200
201
202sub load_english_resource_bundle
203{
204 # Ensure the English resource bundle hasn't already been loaded
205 if (%specialresourcebundle && $specialresourcebundle{"{Language.code}"} eq "en") {
206 %englishresourcebundle = %specialresourcebundle;
207 $englishoutputencoding = $specialoutputencoding;
208 }
209
210 if ($defaultresourcebundle{"{Language.code}"} &&
211 $defaultresourcebundle{"{Language.code}"} eq "en") {
212 %englishresourcebundle = %defaultresourcebundle;
213 $englishoutputencoding = $defaultoutputencoding;
214 }
215
216 # Read the English resource bundle
217 my $resourcebundlename = "strings_en.properties";
218
219 %englishresourcebundle
220 = &read_resource_bundle_and_extensions($ENV{'GSDLHOME'},"perllib",$resourcebundlename);
221 return if (!%englishresourcebundle);
222
223 # Read the output encoding to use from the resource bundle
224 if ($ENV{'GSDLOS'} =~ /windows/) {
225 $englishoutputencoding = $englishresourcebundle{"{OutputEncoding.windows}"};
226 }
227 else {
228 $englishoutputencoding = $englishresourcebundle{"{OutputEncoding.unix}"};
229 }
230}
231
232
233sub read_resource_bundle_and_extensions
234{
235 my ($bundle_base,$primary_dir,$resourcename) = @_;
236
237 my $primary_resourcebundlefile
238 = &util::filename_cat($bundle_base,$primary_dir,$resourcename);
239
240 my $resourcebundle = read_resource_bundle($primary_resourcebundlefile);
241 return if (!defined $resourcebundle);
242
243 if (defined $ENV{'GSDLEXTS'}) {
244 my @extensions = split(/:/,$ENV{'GSDLEXTS'});
245 foreach my $e (@extensions) {
246 my $ext_base
247 = &util::filename_cat($bundle_base,"ext",$e);
248
249 my $ext_resourcebundlefile
250 = &util::filename_cat($ext_base,$primary_dir,$resourcename);
251
252 # can ignore return value (will be same reference to $resourcebundle)
253 read_resource_bundle($ext_resourcebundlefile,$resourcebundle);
254 }
255 }
256 if (defined $ENV{'GSDL3EXTS'}) {
257 my @extensions = split(/:/,$ENV{'GSDL3EXTS'});
258 foreach my $e (@extensions) {
259 my $ext_base
260 = &util::filename_cat($ENV{'GSDL3SRCHOME'},"ext",$e);
261
262 my $ext_resourcebundlefile
263 = &util::filename_cat($ext_base,$primary_dir,$resourcename);
264
265 # can ignore return value (will be same reference to $resourcebundle)
266 read_resource_bundle($ext_resourcebundlefile,$resourcebundle);
267 }
268 }
269
270 return %$resourcebundle;
271}
272
273
274sub read_resource_bundle
275{
276 my ($resourcebundlefilepath,$resourcebundle) = @_;
277
278 if (!open(RESOURCE_BUNDLE, "<$resourcebundlefilepath")) {
279 # When called for the first time (primary resource), $resourcebundle
280 # is not defined (=undef). If the file does not exist, then we return
281 # this 'undef' to signal it was not found
282 # For an extension resource bundle, if it does not exist this
283 # is not so serious (in fact quite likely) => return what we
284 # have built up so far
285
286 return $resourcebundle;
287 }
288
289 if (!defined $resourcebundle) {
290 # resource files exists, so exect some content to be stored
291 $resourcebundle = {};
292 }
293
294 # Load this resource bundle
295 my @resourcebundlelines = <RESOURCE_BUNDLE>;
296 close(RESOURCE_BUNDLE);
297
298 # Parse the resource bundle
299
300 foreach my $line (@resourcebundlelines) {
301 # Remove any trailing whitespace
302 $line =~ s/(\s*)$//;
303
304 # Ignore comments and empty lines
305 if ($line !~ /^\#/ && $line ne "") {
306 # Parse key (everything up to the first colon)
307 if ($line =~ m/^([^:]+):(.+)$/) {
308 my $linekey = "{" . $1 . "}";
309 my $linetext = $2;
310 $linetext =~ s/(\s*)\#\s+Updated\s+(\d?\d-\D\D\D-\d\d\d\d).*$//i;
311
312 # Map key to text
313 $resourcebundle->{$linekey} = $linetext;
314 }
315 }
316 }
317
318 return $resourcebundle;
319}
320
321
322sub set_print_freetext_for_xml
323{
324 $freetext_xml_mode = 1;
325}
326
327sub set_print_xml_tags
328{
329 $freetext_xml_mode = 0;
330}
331
332sub output_strings_in_UTF8
333{
334 $outputstringsinUTF8 = 1;
335}
336
337
338sub debug_unicode_string
339{
340 join("",
341 map { $_ > 255 ? # if wide character...
342 sprintf("\\x{%04X}", $_) : # \x{...}
343 chr($_)
344 } unpack("U*", $_[0])); # unpack Unicode characters
345}
346
347
3481;
Note: See TracBrowser for help on using the repository browser.