o Made several changes in response to suggestions in Wiki.
[project-aon.git] / scripts / gbtoxhtml.pl
1 #!/usr/bin/perl -w
2 #
3 # gbtoxhtml.pl
4 #
5 # Creates XHTML gamebook from XML source.
6 #
7 # $Id$
8 #
9 # $Log$
10 # Revision 2.1  2006/03/04 01:07:43  jonathan.blake
11 # Added parameter to pass the language of the document to the transformation.
12 #
13 # Revision 2.0  2006/02/28 23:50:54  jonathan.blake
14 # Extensive overhaul and changed command line interface
15 #
16 # Revision 1.2  2005/10/13 00:48:47  angantyr
17 # Put Paul Bonner as illustrator of the GS books.
18 #
19 # Revision 1.1.1.1  2005/04/26 04:47:33  jonathan.blake
20 # Imported scripts
21 #
22 # Revision 1.8  2003/07/14 17:20:09  jblake
23 # Modified for Xalan 2.5.1, added support for AONPATH
24 # environment variable, commented out RXP validation.
25 #
26 # Revision 1.7  2002/11/10 07:52:15  jblake
27 # Added more books.
28 #
29 # Revision 1.6  2002/11/10 03:57:50  jblake
30 # Added some missing semicolons.
31 #
32 # Revision 1.5  2002/11/07 18:43:14  jblake
33 # Added books (02fotw, 13tplor, and 15tdc) and added an illustrator to the list.
34 #
35 # Revision 1.4  2002/10/23 18:58:34  jblake
36 # Added Flight from the Dark to the valid book list, and made
37 # a change to the working directory in order to work with
38 # Xalan-J 2.4.0.
39 #
40 # Revision 1.3  2002/10/20 05:47:50  jblake
41 # Added Highway Holocaust to the book list.
42 #
43 # Revision 1.2  2002/10/18 15:42:25  jblake
44 # Added Grey Star the Wizard to the book list.
45 #
46 # Revision 1.1  2002/10/18 15:38:41  jblake
47 # Initial revision
48 #
49 # ///// To Do
50 # * make the transformation more generic by using an xslt-params rule
51
52 #####
53
54 use strict;
55
56 delete @ENV{qw(PATH IFS CDPATH ENV BASH_ENV)}; # clean house for taint mode
57
58 my $PROGRAM_NAME    = 'gbtoxhtml';
59 my $USAGE           = "$PROGRAM_NAME [options]\n\t--book=[book code]\n\t--meta=[metadata file]\n\t--xml=[book XML]\n\t--xsl=[XSL transformation]\n";
60
61 my $FILENAME_SEPARATOR = '/';
62
63 my $RXP        = '/home/projectaon/bin/rxp';
64 my $CP         = '/bin/cp';
65 my $MV         = '/bin/mv';
66 my $TAR        = '/bin/tar';
67 my $ZIP        = '/usr/bin/zip';
68 my $BZIP2      = '/usr/bin/bzip2';
69 my $JAVA       = '/usr/bin/java';
70 my $XALAN_JAR  = '/home/projectaon/bin/xalan.jar';
71 my $RM         = '/bin/rm';
72 my $CHMOD      = '/bin/chmod';
73
74 ###
75
76 my $bookCode     = '';
77 my $metaFile     = '';
78 my $bookXML      = '';
79 my $xhtmlXSL     = '';
80
81 my $verbose = 0;
82
83 while( $#ARGV > -1 ) {
84     my $cmdLineItem = shift @ARGV;
85     if( $cmdLineItem =~ /^--book=(.+)$/ ) {
86         $bookCode = $1;
87     }
88     elsif( $cmdLineItem =~ /^--meta=(.+)$/ ) {
89         $metaFile = $1;
90     }
91     elsif( $cmdLineItem =~ /^--xml=(.+)$/ ) {
92         $bookXML = $1;
93     }
94     elsif( $cmdLineItem =~ /^--xsl=(.+)$/ ) {
95         $xhtmlXSL = $1;
96     }
97     elsif( $cmdLineItem =~ /^--verbose/ ) {
98         $verbose = 1;
99     }
100     else { die $USAGE; }
101 }
102
103 if( $bookCode eq '' ) { die "Unspecified book code\n$USAGE"; }
104 if( $metaFile eq '' ) { die "Unspecified metadata file\n$USAGE"; }
105 if( $bookXML eq '' ) { die "Unspecified book XML file\n$USAGE"; }
106 if( $xhtmlXSL eq '' ) { die "Unspecified XSL transformation file\n$USAGE"; }
107
108 if( -e $metaFile && -f $metaFile && -r $metaFile ) {
109     open( META, '<', $metaFile ) or die qq{Unable to open metadata file ($metaFile): $!\n};
110 }
111 else { die qq{Improper metadata file ($metaFile)\n}; }
112
113 my $meta = '';
114 while( my $line = <META> ) {
115     $meta .= $line if $line !~ /^[[:space:]]*#/;
116 }
117 close META;
118
119 my $rulesString = '';
120 if( $meta =~ /^[[:space:]]*$bookCode[[:space:]]*{([^}]*)}/sm ) {
121     $rulesString = $1;
122 }
123 else {
124     die "Book code ($bookCode) not found in metadata file or invalid file syntax\n";
125 }
126
127 my @rules = split( /[[:space:]\n]*;[[:space:]\n]*/, $rulesString );
128 my %rulesHash;
129 foreach my $rule (@rules) {
130     if( $rule =~ /[[:space:]]*([^:]+)[[:space:]]*:[[:space:]]*(.+)$/s ) {
131         $rulesHash{ $1 } = $2;
132     }
133     else {
134         die "Unrecognized rule syntax:\n$rule\n";
135     }
136 }
137
138 if( $bookXML =~ m{^([-\w\@./]+)$} ) {
139     $bookXML = $1;
140     if( -e $bookXML && -f $bookXML && -r $bookXML ) {
141         system( $RXP, '-Vs', $bookXML ) == 0 or die( "XML validation failed\n" );
142     }
143     unless( defined $rulesHash{'book-path'} ) { die "Metadata file leaves output path unspecified\n"; }
144     unless( -e $rulesHash{'book-path'} && -d $rulesHash{'book-path'} ) {
145         my @dirs = split ( /$FILENAME_SEPARATOR/, $rulesHash{'book-path'} );
146         my $dirPath = '';
147         for( my $i = 0; $i <= $#dirs; ++$i ) {
148             $dirPath .= $dirs[$i] . $FILENAME_SEPARATOR;
149             if( -e $dirPath && ! -d $dirPath ) { die "Output directory name exists and is not a directory\n"; }
150             unless( -e $dirPath ) {
151                 mkdir $dirPath or die( "Unable to create output directory ($rulesHash{'book-path'}): $!\n" );
152             }
153         }
154     }
155     unless( -e $rulesHash{'book-path'} && -d $rulesHash{'book-path'} ) {
156         die "Unknown error creating output directory\n";
157     }
158
159     print qx{$RM $rulesHash{'book-path'}$FILENAME_SEPARATOR*};
160     print qx{$JAVA -classpath "$XALAN_JAR" org.apache.xalan.xslt.Process -IN "$bookXML" -XSL "$xhtmlXSL" -OUT "$rulesHash{'book-path'}${FILENAME_SEPARATOR}foo.xml" -PARAM background-color "$rulesHash{'background-color'}" -PARAM text-color "$rulesHash{'text-color'}" -PARAM link-color "$rulesHash{'link-color'}" -PARAM use-illustrators "$rulesHash{'use-illustrators'}" -PARAM language "$rulesHash{'language'}"};
161     print qx{$RM $rulesHash{'book-path'}${FILENAME_SEPARATOR}foo.xml};
162
163     foreach my $cssTemplate (split( /:/, $rulesHash{'csst'} )) {
164         $cssTemplate =~ m/([^${FILENAME_SEPARATOR}]+)t$/;
165         my $templateFilename = $1;
166         open( TEMPLATE, '<', $cssTemplate ) or die "Unable to open CSS template file ($cssTemplate): $!\n";
167         open( STYLESHEET, '>', "$rulesHash{'book-path'}${FILENAME_SEPARATOR}${templateFilename}" ) or die "Unable to open stylesheet file ($rulesHash{'book-path'}${FILENAME_SEPARATOR}${templateFilename}) for writing: $!\n";
168         while( my $templateLine = <TEMPLATE> ) {
169             while( $templateLine =~ /%%([^%[:space:]]+)%%/ ) {
170                 my $name = $1;
171                 $templateLine =~ s/%%${name}%%/$rulesHash{$name}/g;
172             }
173             print STYLESHEET $templateLine;
174         }
175     }
176     close TEMPLATE;
177     close STYLESHEET;
178
179     foreach my $imagePath (split( /:/, $rulesHash{'images'} )) {
180         unless( -e $imagePath && -d $imagePath ) {
181             die "Image path ($imagePath) does not exist or is not a directory\n";
182         }
183         print qx{$CP $imagePath${FILENAME_SEPARATOR}* $rulesHash{'book-path'}};
184     }
185
186     print qx{$TAR cf ${bookCode}.tar $rulesHash{'book-path'}${FILENAME_SEPARATOR}*};
187     print qx{$ZIP -8 -q ${bookCode}.zip $rulesHash{'book-path'}${FILENAME_SEPARATOR}*};
188     print qx{$BZIP2 -9 ${bookCode}.tar};
189     print qx{$MV ${bookCode}* $rulesHash{'book-path'}${FILENAME_SEPARATOR}};
190 }
191
192 print "Success\n" if $verbose;