File Coverage

blib/lib/OpenOffice/OOBuilder.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             package OpenOffice::OOBuilder;
2              
3             # Copyright 2004, 2007 Stefan Loones
4             # More info can be found at http://www.maygill.com/oobuilder
5             #
6             # This library is free software; you can redistribute it and/or
7             # modify it under the same terms as Perl itself.
8              
9 2     2   26016 use 5.008; # lower versions not tested
  2         8  
  2         68  
10 2     2   8 use strict;
  2         4  
  2         54  
11 2     2   8 use warnings;
  2         7  
  2         66  
12 2     2   8 no warnings 'uninitialized'; # don't want this, because we use strict
  2         4  
  2         67  
13 2     2   851 use Archive::Zip;
  0            
  0            
14              
15             my ($VERSION, %COLORS, $MINFONTSIZE, $MAXFONTSIZE);
16             $VERSION=sprintf("%d.%02d", q$Revision: 0.9 $ =~ /(\d+)\.(\d+)/);
17             %COLORS=('red' => 'ff0000', 'green' => '00ff00', 'blue' => '0000ff',
18             'white' => 'ffffff', 'black' => '000000');
19             $MINFONTSIZE=6;
20             $MAXFONTSIZE=96;
21              
22             # - Object constructor
23             #
24             sub new {
25             my ($proto, $class, $self, $doctype);
26             $proto=shift;
27             $class=ref($proto) || $proto;
28             $doctype=shift;
29             $doctype='sxw' if (! $doctype);
30             $self={};
31             $self->{oooType} = $doctype;
32             $self->{contentxml} = undef;
33             $self->{builddir} = '.';
34             $self->{tgt_file} = 'oo_doc';
35             $self->{meta} = undef;
36             $self->{log} = 0;
37              
38             # - Init available fonts
39             $self->{availfonts}{Arial}=q{};
40             $self->{availfonts}{'Bitstream Vera Sans'}=q{};
41             $self->{availfonts}{'Bitstream Vera Serif'}=q{};
42             $self->{availfonts}{Bookman}=q{};
43             $self->{availfonts}{Courier}=q{};
44             $self->{availfonts}{'Courier 10 Pitch'}=q{};
45             $self->{availfonts}{Helvetica}=q{};
46             $self->{availfonts}{Lucidabright}=q{};
47             $self->{availfonts}{Lucidasans}=q{};
48             $self->{availfonts}{'Lucida Sans Unicode'}=q{};
49             $self->{availfonts}{Lucidatypewriter}=q{};
50             $self->{availfonts}{'Luxi Mono'}=q{};
51             $self->{availfonts}{'Luxi Sans'}=q{};
52             $self->{availfonts}{'Luxi Serif'}=q{};
53             $self->{availfonts}{Symbol}=q{};
54             $self->{availfonts}{Tahoma}=q{};
55             $self->{availfonts}{Times}=q{};
56             $self->{availfonts}{'Times New Roman'}=q{};
57             $self->{availfonts}{Utopia}=q{};
58             $self->{availfonts}{'Zapf Chancery'}=q{};
59             $self->{availfonts}{'Zapf Dingbats'}=q{};
60              
61             $self->{style}{bold} = 0;
62             $self->{style}{italic} = 0;
63             $self->{style}{underline}= 0;
64             $self->{style}{align} = 'left';
65             $self->{style}{txtcolor} = '000000';
66             $self->{style}{bgcolor} = 'ffffff';
67             $self->{style}{font} = 'Luxi Sans';
68             $self->{style}{size} = '10';
69              
70             $self->{actstyle}=join('#',($self->{style}{bold}, $self->{style}{italic},
71             $self->{style}{underline},$self->{style}{align},
72             $self->{style}{txtcolor},$self->{style}{bgcolor},
73             $self->{style}{font},$self->{style}{size}));
74             $self->{defstyle}=$self->{actstyle};
75              
76             bless ($self, $class);
77             return $self;
78             } # - - End new (Object constructor)
79              
80             # - * - Setters/Getters Meta.xml data
81              
82             sub set_title {
83             my $self=shift;
84             $self->{meta}{title}=$self->encode_data (shift);
85             1;
86             }
87              
88             sub get_title {
89             my $self=shift;
90             return $self->{meta}{title};
91             }
92              
93             sub set_author {
94             my $self=shift;
95             $self->{meta}{author}=$self->encode_data (shift);
96             1;
97             }
98              
99             sub get_author {
100             my $self=shift;
101             return $self->{meta}{author};
102             }
103              
104             sub set_subject {
105             my $self=shift;
106             $self->{meta}{subject}=$self->encode_data (shift);
107             1;
108             }
109              
110             sub get_subject {
111             my $self=shift;
112             return $self->{meta}{subject};
113             }
114              
115             sub set_comments {
116             my $self=shift;
117             $self->{meta}{comments}=$self->encode_data (shift);
118             1;
119             }
120              
121             sub get_comments {
122             my $self=shift;
123             return $self->{meta}{comments};
124             }
125              
126             sub set_keywords {
127             my ($self, @keywords)=@_;
128             @{$self->{meta}{keywords}}=map $self->encode_data($_), @keywords;
129             1;
130             }
131              
132             sub push_keywords {
133             my ($self, @keywords)=@_;
134             push @{$self->{meta}{keywords}}, map $self->encode_data($_), @keywords;
135             1;
136             }
137              
138             sub get_keywords {
139             my $self=shift;
140             return @{$self->{meta}{keywords}};
141             }
142              
143             sub set_meta {
144             my ($self, $nb, $name, $value)=@_;
145             if ($nb < 1 || $nb > 4 || ! $name) {
146             return 0;
147             } else {
148             delete $self->{meta}{"data$nb"} if (exists ($self->{meta}{"data$nb"}));
149             $name=$self->encode_data ($name);
150             $name="meta$nb" if (! $name);
151             $self->{meta}{"data$nb"}{$name}=$self->encode_data($value);
152             1;
153             }
154             }
155              
156             # ** TODO get_meta : best way to return it: array, hash or ?
157              
158             # - Setters for active style
159              
160             # ** TODO getters for active style
161             # not yet implemented because in the future we will probably add
162             # ways to get the style of a specifique cell or location
163             # maybe we also add the possibility to read an existing document, and make
164             # changes to it. This all makes that we have to be careful about this.
165              
166             sub set_bold {
167             my ($self, $bold)=@_;
168             if (! $bold) {
169             $self->{style}{bold}=0;
170             } else {
171             $self->{style}{bold}=1;
172             }
173             $self->_set_active_style;
174             1;
175             }
176              
177             sub set_italic {
178             my ($self, $italic)=@_;
179             if (! $italic) {
180             $self->{style}{italic}=0;
181             } else {
182             $self->{style}{italic}=1;
183             }
184             $self->_set_active_style;
185             1;
186             }
187              
188             sub set_underline {
189             my ($self, $underline)=@_;
190             if (! $underline) {
191             $self->{style}{underline}=0;
192             } else {
193             $self->{style}{underline}=1;
194             }
195             $self->_set_active_style;
196             1;
197             }
198              
199             sub set_align {
200             my ($self, $align)=@_;
201             $align=lc($align);
202             if ($align eq 'right' || $align eq 'center' || $align eq 'justify' ||
203             $align eq 'left') {
204             $self->{style}{align}=$align;
205             $self->_set_active_style;
206             return 1;
207             } else {
208             return 0;
209             }
210             }
211              
212             sub set_txtcolor {
213             my ($self, $txtcolor)=@_;
214             $txtcolor=$self->_check_color($txtcolor);
215             return 0 unless ($txtcolor);
216             $self->{style}{txtcolor}=$txtcolor;
217             $self->_set_active_style;
218             1;
219             }
220              
221             sub set_bgcolor {
222             my ($self, $bgcolor)=@_;
223             $bgcolor=$self->_check_color($bgcolor);
224             return 0 unless ($bgcolor);
225             $self->{style}{bgcolor}=$bgcolor;
226             $self->_set_active_style;
227             1;
228             }
229              
230             sub set_font {
231             my ($self, $font)=@_;
232             return 0 unless (exists($self->{availfonts}{$font}));
233             $self->{style}{font}=$font;
234             $self->_set_active_style;
235             1;
236             }
237              
238             sub set_fontsize {
239             my ($self, $size)=@_;
240             $size=~ s/[^0-9]//g;
241             return 0 if ($size<$MINFONTSIZE || $size>$MAXFONTSIZE);
242             $self->{style}{size}=$size;
243             $self->_set_active_style;
244             1;
245             }
246              
247             # - * - Build-directory
248              
249             sub set_builddir {
250             my ($self, $builddir)=@_;
251             if (-d $builddir) {
252             $self->{builddir}=$builddir;
253             return 1;
254             } else {
255             return 0;
256             }
257             }
258              
259             sub get_builddir {
260             my $self=shift;
261             return $self->{builddir};
262             }
263              
264             # - * - PrivateMethods
265             sub generate {
266             my ($self, $tgtfile)=@_;
267              
268             # - check workdirectory & filename
269             $self->{builddir}='.' unless (-d $self->{builddir});
270             $tgtfile='oo_doc' unless ($tgtfile);
271             $tgtfile.=qq{.$self->{oooType}};
272              
273             # - Available Document types and their mime types
274             my (%mimetype);
275             # Text - oowriter - sxw - OOWBuilder
276             $mimetype{sxw}='application/vnd.sun.xml.writer';
277             # Spreadsheet - oocalc - sxc - OOCBuilder
278             $mimetype{sxc}='application/vnd.sun.xml.calc';
279             # Drawing - oodraw - sxd - OODBuilder
280             $mimetype{sxd}='application/vnd.sun.xml.draw';
281             # Presentation - ooimpress - sxi - OOIBuilder
282             $mimetype{sxi}='application/vnd.sun.xml.impress';
283             # Formula - oomath - OOMBuilder
284             $mimetype{sxm}='application/vnd.sun.xml.math';
285             # ** TODO
286             # Chart application/vnd.sun.xml.chart
287             # Master Document application/vnd.sun.xml.writer.global
288              
289             # - Generate mimetype.xml
290             open TGT, qq{>$self->{builddir}/mimetype};
291             print TGT $mimetype{$self->{oooType}};
292             close TGT;
293              
294             # - Generate content.xml
295             # (must be build by the derived class and put into $self->{contentxml})
296             open TGT, qq{>$self->{builddir}/content.xml};
297             print TGT $self->{contentxml};
298             close TGT;
299              
300             # - Generate meta.xml, styles.xml, settings.xml
301             $self->_generate_meta;
302             $self->_generate_styles;
303             $self->_generate_settings;
304              
305             # - Generate Manifest
306             mkdir(qq{$self->{builddir}/META-INF}) unless (-d qq{$self->{builddir}/META-INF});
307             open TGT, qq{>$self->{builddir}/META-INF/manifest.xml};
308             print TGT qq{
309            
310            
311            
312            
313            
314            
315            
316            
317             };
318             close (TGT);
319              
320             # - Build compressed target file
321             # windows support added by using Archive::Zip
322             # thanks to Magnus Nufer
323             my $zip = Archive::Zip->new();
324             $zip->addFile(qq{$self->{builddir}/mimetype}, 'mimetype');
325             $zip->addFile(qq{$self->{builddir}/content.xml}, 'content.xml');
326             $zip->addFile(qq{$self->{builddir}/styles.xml}, 'styles.xml');
327             $zip->addFile(qq{$self->{builddir}/meta.xml}, 'meta.xml');
328             $zip->addFile(qq{$self->{builddir}/settings.xml}, 'settings.xml');
329             $zip->addFile(qq{$self->{builddir}/META-INF/manifest.xml}, 'META-INF/manifest.xml');
330             my $status = $zip->overwriteAs($tgtfile);
331             # if you are on a Linux system with zip available and you don't want to
332             # use Archive::Zip, you could use the following 6 lines, and comment out the
333             # above 8 lines and of course the 'use Archive::Zip' statement at the top
334             # system("cd $self->{builddir}; zip -r '$tgtfile' mimetype &> /dev/null");
335             # system("cd $self->{builddir}; zip -r '$tgtfile' content.xml &> /dev/null");
336             # system("cd $self->{builddir}; zip -r '$tgtfile' styles.xml &> /dev/null");
337             # system("cd $self->{builddir}; zip -r '$tgtfile' meta.xml &> /dev/null");
338             # system("cd $self->{builddir}; zip -r '$tgtfile' settings.xml &> /dev/null");
339             # system("cd $self->{builddir}; zip -r '$tgtfile' META-INF/manifest.xml &> /dev/null");
340              
341             # - remove workfiles & directory
342             unlink("$self->{builddir}/mimetype");
343             unlink("$self->{builddir}/content.xml");
344             unlink("$self->{builddir}/styles.xml");
345             unlink("$self->{builddir}/meta.xml");
346             unlink("$self->{builddir}/settings.xml");
347             unlink("$self->{builddir}/META-INF/manifest.xml");
348             rmdir("$self->{builddir}/META-INF");
349              
350             1;
351             }
352              
353             sub _generate_meta {
354             my ($self);
355             $self=shift;
356              
357             # - prepare data
358             my ($timestamp, $keywords);
359             $timestamp=$self->_oo_timestamp;
360             $keywords=join('',map qq{$_}, @{$self->{meta}{keywords}});
361              
362             # - user defined vars
363             my ($meta, $name, $value, @tmp);
364             for (1 .. 4) {
365             if ($self->{meta}{"data$_"}) {
366             @tmp=keys(%{$self->{meta}{"data$_"}});
367             $name=shift @tmp;
368             } else {
369             $name="meta$_";
370             }
371             $value=$self->{meta}{"data$_"}{$name};
372             if ($value) {
373             $meta.=qq{$value};
374             } else {
375             $meta.=qq{};
376             }
377             }
378              
379             open (TGT, qq{>$self->{builddir}/meta.xml});
380             print TGT
381             qq{
382            
383            
384            
385             oooBuilder $VERSION
386             $self->{meta}{title}
387             $self->{meta}{comments}
388             $self->{meta}{subject}
389             $self->{meta}{author}
390             $timestamp
391             $self->{meta}{author}
392             $timestamp
393             $keywords
394             en-US
395             1
396             PT0S
397             $meta
398            
399            
400             };
401             1;
402             } # - - End _generate_meta
403              
404              
405             sub _generate_styles {
406             my ($self);
407             $self=shift;
408              
409             # ** TODO
410              
411             1;
412             } # - - End _generate_styles
413              
414              
415             sub _generate_settings {
416             my ($self);
417             $self=shift;
418              
419             # ** TODO
420              
421             1;
422             } # - - End _generate_settings
423              
424              
425             sub _set_active_style {
426             my ($self);
427             $self=shift;
428             $self->{actstyle}=join('#',($self->{style}{bold}, $self->{style}{italic},
429             $self->{style}{underline},$self->{style}{align},
430             $self->{style}{txtcolor},$self->{style}{bgcolor},
431             $self->{style}{font},$self->{style}{size}));
432             1;
433             }
434              
435             sub _check_color {
436             my ($self, $color)=@_;
437             $color=lc($color);
438             $color=$COLORS{$color} if (! ($color =~ /^[0-9a-f]{6}$/));
439             return $color
440             }
441              
442             # OpenOffice TimeStamp (form = yyyy-mm-ddThh:mm:ss)
443             sub _oo_timestamp {
444             my ($self);
445             $self=shift;
446             my ($sec,$min,$hour,$mday,$mon,$year,@rest) = gmtime(time);
447             return (sprintf("%04d-%02d-%02dT%02d:%02d:%02d",
448             $year+1900,$mon+1,$mday,$hour,$min,$sec));
449             }
450              
451             sub encode_data {
452             my ($self, $data)=@_;
453             $data=~ s/\&/\&/g;
454             $data=~ s/
455             $data=~ s/>/\>/g;
456             $data=~ s/'/\'/g;
457             $data=~ s/"/\"/g;
458             $data=~ s/\t//g;
459             return $data;
460             }
461              
462             1;
463             __END__