File Coverage

blib/lib/Toader/Entry.pm
Criterion Covered Total %
statement 27 595 4.5
branch 0 224 0.0
condition 0 15 0.0
subroutine 9 44 20.4
pod 35 35 100.0
total 71 913 7.7


line stmt bran cond sub pod time code
1             package Toader::Entry;
2              
3 7     7   43090 use warnings;
  7         16  
  7         205  
4 7     7   34 use strict;
  7         25  
  7         149  
5 7     7   6383 use Email::MIME;
  7         503131  
  7         219  
6 7     7   5598 use File::MimeInfo;
  7         36391  
  7         440  
7 7     7   1259 use Toader::Entry::Helper;
  7         21  
  7         201  
8 7     7   51 use File::Path qw(make_path);
  7         14  
  7         444  
9 7     7   41 use base 'Error::Helper';
  7         14  
  7         701  
10 7     7   41 use Toader::pathHelper;
  7         15  
  7         163  
11 7     7   5707 use Text::Tags::Parser;
  7         5824  
  7         38030  
12              
13             =head1 NAME
14              
15             Toader::Entry - This holds a blog/article/whatever entry.
16              
17             =head1 VERSION
18              
19             Version 1.0.0
20              
21             =cut
22              
23             our $VERSION = '1.0.0';
24              
25             =head1 SYNOPSIS
26              
27             For information on the storage and rendering of entries,
28             please see 'Documentation/Entry.pod'.
29              
30             =head1 NEW METHODS
31              
32             If any of the new methods error, the error is permanent.
33              
34             =head2 new
35              
36             This creates the a object that represents a entry.
37              
38             One argument is taken and it s a hash reference.
39              
40             =head3 args hash
41              
42             =head4 renderer
43              
44             This is the rendering engine the body should use.
45              
46             If not defined, html will be used.
47              
48             =head4 body
49              
50             This is the body.
51              
52             =head4 title
53              
54             This is the title of the entry.
55              
56             =head4 from
57              
58             This is the from address to use.
59              
60             =head4 publish
61              
62             If it should be published or not.
63              
64             The default value is '1'.
65              
66             =head4 summary
67              
68             This is a summary of the entry.
69              
70             =head4 tags
71              
72             This is a L parsable string for the tags.
73              
74             =head4 files
75              
76             This is a list of files that will be made available with this entry.
77              
78             =head4 toader
79              
80             This is a L object.
81              
82             my $foo = Toader::Entry->new(\%args);
83             if ($foo->error){
84             warn('Error:'.$foo->error.': '.$foo->errorString);
85             }
86              
87             =cut
88              
89             sub new{
90 0     0 1   my %args;
91 0 0         if(defined($_[1])){
92 0           %args= %{$_[1]};
  0            
93             };
94              
95 0           my $self={
96             error=>undef,
97             errorString=>'',
98             perror=>undef,
99             dir=>undef,
100             entryName=>undef,
101             errorExtra=>{
102             flags=>{
103             1=>'noNameSpecified',
104             2=>'emailMIMEerror',
105             3=>'notAnArray',
106             4=>'fileDoesNotExist',
107             5=>'MIMEinfoError',
108             6=>'unableToOpenFile',
109             7=>'emailMIMEerror',
110             8=>'noBody',
111             9=>'invalidEntryName',
112             10=>'notAtoaderDir',
113             11=>'noDirSpecified',
114             12=>'noDirSet',
115             13=>'noLongerAtoaderDir',
116             14=>'noEntryDir',
117             15=>'noSummarySpecified',
118             16=>'noEntryNameSet',
119             17=>'dirDNEorNAD',
120             18=>'noFileSpecified',
121             19=>'publishValError',
122             20=>'getVCSerrored',
123             21=>'VCSusableErrored',
124             22=>'underVCSerrored',
125             23=>'VCSaddErrored',
126             24=>'notAtoaderObj',
127             25=>'noToaderObj',
128             },
129             },
130             VCSusable=>0,
131             };
132 0           bless $self;
133              
134 0 0         if (!defined($args{renderer})) {
135 0           $args{renderer}='html';
136             }
137              
138 0 0         if (!defined($args{title})) {
139 0           $self->{error}=1;
140 0           $self->{perror}=1;
141 0           $self->{errorString}='No title specified';
142 0           $self->warn;
143 0           return $self;
144             }
145              
146 0 0         if (!defined($args{from})) {
147 0           $self->{error}=9;
148 0           $self->{perror}=1;
149 0           $self->{errorString}='No from specified';
150 0           $self->warn;
151 0           return $self;
152             }
153              
154 0 0         if (!defined($args{body})) {
155 0           $args{body}='';
156             }
157              
158 0 0         if (!defined($args{publish})) {
159 0           $args{publish}='1';
160             }
161              
162             #makes sure the publish value is
163 0 0 0       if (
164             ( $args{publish} ne "0" ) &&
165             ( $args{publish} ne "1" )
166             ){
167 0           $self->{perror}=1;
168 0           $self->{error}=19;
169 0           $self->{errorString}='"'.$args{publish}.'" is not a recognized boolean value';
170 0           $self->warn;
171 0           return $self;
172             }
173              
174 0 0         if ( !defined( $args{summary} ) ){
175 0           $args{summary}='';
176             }
177              
178             #this will hold the various parts
179 0           my @parts;
180 0           my $int=0;
181 0 0         if (defined($args{files})) {
182 0 0         if ( ref( $args{files} ne "ARRAY" ) ) {
183 0           $self->{perror}=1;
184 0           $self->{error}=3;
185 0           $self->{errorString}="Has files specified, but the passed object is not a array";
186 0           $self->warn;
187 0           return $self;
188             }
189              
190             #puts all the parts together
191 0           while (defined( $args{files}[$int] )) {
192 0 0         if (! -f $args{files}[$int] ) {
193 0           $self->{error}=4;
194 0           $self->{perror}=1;
195 0           $self->{errorString}="'".$args{files}[$int]."' is not a file or does not exist";
196 0           $self->warn;
197 0           return $self;
198             }
199              
200             #gets the MIME type
201 0           my $mimetype=mimetype( $args{files}[$int] );
202              
203             #makes sure it is a mimetype
204 0 0         if ( !defined( $mimetype ) ) {
205 0           $self->{error}=5;
206 0           $self->{perror}=1;
207 0           $self->{errorString}="'".$args{files}[$int]."' could not be read or does not exist";
208 0           $self->warn;
209 0           return $self;
210             }
211              
212             #open and read the file
213 0           my $fh;
214 0 0         if ( ! open( $fh, '<', $args{files}[$int] ) ) {
215 0           $self->{error}=6;
216 0           $self->{perror}=1;
217 0           $self->{errorString}="unable to open '".$args{files}[$int]."'";
218 0           $self->warn;
219 0           return $self;
220             }
221 0           my $file=join('',<$fh>);
222 0           close $fh;
223              
224             #create a short name for it... removing the path
225 0           my $filename=$args{files}[$int];
226 0           $filename=~s/.*\///g;
227            
228 0           my $part=Email::MIME->create(attributes=>{
229             filename=>$filename,
230             content_type=>$mimetype,
231             encode=>"base64",
232             },
233             body=>$file,
234             );
235              
236 0 0         if (!defined( $part )) {
237 0           $self->{error}=7;
238 0           $self->{perror}=1;
239 0           $self->{errorString}='Unable to create a MIME object for one of the files';
240 0           $self->warn;
241 0           return $self;
242             }
243              
244 0           push(@parts, $part);
245              
246 0           $int++;
247             }
248              
249             }
250              
251             #blank the tags value if not defined
252 0 0         if ( ! defined( $args{tags} ) ){
253 0           $args{tags}='';
254             }
255             #clean the tag string
256 0           my @tags=Text::Tags::Parser->new->parse_tags( $args{tags} );
257 0           $args{tags}=Text::Tags::Parser->new->join_tags( @tags );
258            
259              
260             #creates it
261             my $mime=Email::MIME->create(
262             header=>[
263             renderer=>$args{renderer},
264             title=>$args{title},
265             summary=>$args{summary},
266             From=>$args{from},
267             publish=>$args{publish},
268             tags=>$args{tags},
269             ],
270             body=>$args{body},
271 0           );
272             #this sets the parts if needed
273 0 0         if ( defined( $parts[0] ) ){
274 0           $mime->set_parts( \@parts );
275             }
276            
277 0 0         if (!defined($mime)) {
278 0           $self->{error}=2;
279 0           $self->{perror}=1;
280 0           $self->{errorString}='Unable to create Email::MIME object';
281 0           $self->warn;
282 0           return $self;
283             }
284              
285 0           $self->{mime}=$mime;
286              
287             #if we have a Toader object, reel it in
288 0 0         if ( ! defined( $args{toader} ) ){
289 0           $self->{perror}=1;
290 0           $self->{error}=25;
291 0           $self->{errorString}='No Toader object specified';
292 0           $self->warn;
293 0           return $self;
294             }
295 0 0         if ( ref( $args{toader} ) ne "Toader" ){
296 0           $self->{perror}=1;
297 0           $self->{error}=24;
298 0           $self->{errorString}='The object specified is a "'.ref($args{toader}).'"';
299 0           $self->warn;
300 0           return $self;
301             }
302 0           $self->{toader}=$args{toader};
303              
304             #gets the Toader::VCS object
305 0           $self->{vcs}=$self->{toader}->getVCS;
306 0 0         if ( $self->{toader}->error ){
307 0           $self->{perror}=1;
308 0           $self->{error}=20;
309             $self->{errorString}='Toader->getVCS errored. error="'.
310 0           $self->{toader}->error.'" errorString="'.$self->{toader}->errorString.'"';
311 0           $self->warn;
312 0           return $self;
313             }
314            
315             #checks if VCS is usable
316 0           $self->{VCSusable}=$self->{vcs}->usable;
317 0 0         if ( $self->{vcs}->error ){
318 0           $self->{perror}=1;
319 0           $self->{error}=21;
320             $self->{errorString}='Toader::VCS->usable errored. error="'.
321 0           $self->{toader}->error.'" errorString="'.$self->{toader}->errorString.'"';
322 0           $self->warn;
323 0           return $self;
324             }
325              
326 0           return $self;
327             }
328              
329             =head2 newFromString
330              
331             This creates a new entry from a string.
332              
333             Two argument are accepted. The first is the entry string and the second
334             is a L object.
335              
336             my $foo=Toader::Entry->newFromString($entryString, $toader);
337             if($foo->error){
338             warn('Error:'.$foo->error.': '.$foo->errorString);
339             }
340              
341             =cut
342              
343             sub newFromString{
344 0     0 1   my $string=$_[1];
345 0           my $toader=$_[2];
346              
347 0           my $self={
348             error=>undef,
349             errorString=>'',
350             module=>'Toader-Entry',
351             perror=>undef,
352             dir=>undef,
353             entryName=>undef,
354             toader=>undef,
355             errorExtra=>{
356             flags=>{
357             1=>'noNameSpecified',
358             2=>'emailMIMEerror',
359             3=>'notAnArray',
360             4=>'fileDoesNotExist',
361             5=>'MIMEinfoError',
362             6=>'unableToOpenFile',
363             7=>'emailMIMEerror',
364             8=>'noBody',
365             9=>'invalidEntryName',
366             10=>'notAtoaderDir',
367             11=>'noDirSpecified',
368             12=>'noDirSet',
369             13=>'noLongerAtoaderDir',
370             14=>'noEntryDir',
371             15=>'noSummarySpecified',
372             16=>'noEntryNameSet',
373             17=>'dirDNEorNAD',
374             18=>'noFileSpecified',
375             19=>'publishValError',
376             20=>'getVCSfailed',
377             21=>'VCSusableFailed',
378             22=>'underVCSerrored',
379             23=>'VCSaddErrored',
380             24=>'notAtoaderObj',
381             25=>'noToaderObj',
382             },
383             },
384             VCSusable=>0,
385             };
386 0           bless $self;
387              
388             #Email::MIME will exit if we pass it a null value
389 0 0         if (!defined($string)) {
390 0           $self->{error}=8;
391 0           $self->{perror}=1;
392 0           $self->{errorString}='The string is null';
393 0           $self->warn;
394 0           return $self;
395             }
396              
397             #creates the MIME object
398 0           my $mime=Email::MIME->new($string);
399 0 0         if (!defined($mime)) {
400 0           $self->{error}=2;
401 0           $self->{perror}=1;
402 0           $self->{errorString}='Unable to create Email::MIME object';
403 0           $self->warn;
404 0           return $self;
405             }
406              
407             #make sure we have a title
408 0 0         if (!defined( $mime->header( "title" ) )) {
409 0           $self->{error}=1;
410 0           $self->{perror}=1;
411 0           $self->{errorString}='No title specified';
412 0           $self->warn;
413 0           return $self;
414             }
415              
416             #make sure we have a from
417 0 0         if (!defined( $mime->header( "from" ) )) {
418 0           $self->{error}=9;
419 0           $self->{perror}=1;
420 0           $self->{errorString}='No from specified';
421 0           $self->warn;
422 0           return $self;
423             }
424              
425             #set the summary to blank if one is not specified
426 0 0         if (!defined( $mime->header( "summary" ) )) {
427 0           $mime->header_set(summary=>'');
428             }
429              
430             #if there are no tags, make sure it is blank
431 0 0         if (!defined( $mime->header( "tags" ) )) {
432 0           $mime->header_set(tags=>'');
433             }
434             #clean the tags
435 0           my @tags=Text::Tags::Parser->new->parse_tags( $mime->header("tags") );
436 0           $mime->header_set( tags=>Text::Tags::Parser->new->join_tags( @tags ) );
437              
438             #make sure we have a renderer type
439 0 0         if (!defined( $mime->header( "renderer" ) )) {
440 0           $mime->header_set(renderer=>'html')
441             }
442              
443             #make sure we have publish set
444 0 0         if (!defined( $mime->header( "publish" ) )) {
445 0           $mime->header_set(publish=>'1');
446             }
447              
448             #makes sure it is a recognized boolean value
449 0 0 0       if (
450             ( $mime->header( "publish" ) ne "0" ) &&
451             ( $mime->header( "publish" ) ne "1" )
452             ){
453 0           $self->{perror}=1;
454 0           $self->{error}=19;
455 0           $self->{errorstring}='"'.$mime->header( "publish" ).
456             '" is not a recognized boolean value';
457 0           $self->warn;
458 0           return $self;
459             }
460            
461 0           $self->{mime}=$mime;
462              
463             #if we have a Toader object, reel it in
464 0 0         if ( ! defined( $toader ) ){
465 0           $self->{perror}=1;
466 0           $self->{error}=25;
467 0           $self->{errorString}='No Toader object specified';
468 0           $self->warn;
469 0           return $self;
470             }
471 0 0         if ( ref( $toader ) ne "Toader" ){
472 0           $self->{perror}=1;
473 0           $self->{error}=24;
474 0           $self->{errorString}='The object specified is a "'.ref($toader).'"';
475 0           $self->warn;
476 0           return $self;
477             }
478 0           $self->{toader}=$toader;
479              
480             #gets the Toader::VCS object
481 0           $self->{vcs}=$self->{toader}->getVCS;
482 0 0         if ( $toader->error ){
483 0           $self->{perror}=1;
484 0           $self->{error}=20;
485             $self->{errorString}='Toader->getVCS errored. error="'.
486 0           $self->{toader}->error.'" errorString="'.$self->{toader}->errorString.'"';
487 0           $self->warn;
488 0           return $self;
489             }
490            
491             #checks if VCS is usable
492 0           $self->{VCSusable}=$self->{vcs}->usable;
493 0 0         if ( $self->{vcs}->error ){
494 0           $self->{perror}=1;
495 0           $self->{error}=21;
496             $self->{errorString}='Toader::VCS->usable errored. error="'.
497 0           $self->{toader}->error.'" errorString="'.$self->{toader}->errorString.'"';
498 0           $self->warn;
499 0           return $self;
500             }
501              
502 0           return $self;
503             }
504              
505             =head1 GENERAL METHODS
506              
507             =head2 as_string
508              
509             This returns the entry as a string.
510              
511             my $mimeString=$foo->as_string;
512             if($foo->error)
513             warn('Error:'.$foo->error.': '.$foo->errorString);
514             }
515              
516             =cut
517              
518             sub as_string{
519 0     0 1   my $self=$_[0];
520              
521 0 0         if (!$self->errorblank){
522 0           return undef;
523             }
524              
525 0           return $self->{mime}->as_string;
526             }
527              
528             =head2 bodyGet
529              
530             This gets body.
531              
532             my $body=$foo->bodyGet;
533             if($foo->error){
534             warn('Error:'.$foo->error.': '.$foo->errorString);
535             }
536              
537             =cut
538              
539             sub bodyGet{
540 0     0 1   my $self=$_[0];
541              
542 0 0         if (!$self->errorblank){
543 0           return undef;
544             }
545              
546 0           my @parts=$self->{mime}->subparts;
547            
548 0           my $int=0;
549 0           while ( defined( $parts[$int] ) ){
550 0 0         if ( ! defined( $parts[$int]->filename ) ){
551 0           return $parts[$int]->body;
552             }
553              
554 0           $int++;
555             }
556              
557 0           return $self->{mime}->body;
558             }
559              
560             =head2 bodySet
561              
562             This sets the body.
563              
564             One argument is required and it is the body.
565              
566             $foo->bodySet($body);
567             if($foo->error){
568             warn('Error:'.$foo->error.': '.$foo->errorString);
569             }
570              
571             =cut
572              
573             sub bodySet{
574 0     0 1   my $self=$_[0];
575 0           my $body=$_[1];
576              
577 0 0         if (!$self->errorblank){
578 0           return undef;
579             }
580              
581 0 0         if (!defined($body)) {
582 0           $self->{error}=8;
583 0           $self->{errorString}='No body defined';
584 0           $self->warn;
585 0           return undef;
586             }
587              
588              
589 0           my @parts=$self->{mime}->subparts;
590            
591 0 0         if ( defined( $parts[1] ) ){
592 0           my $int=0;
593 0           while ( defined( $parts[$int] ) ){
594 0 0         if ( ! defined( $parts[$int]->filename ) ){
595 0           $parts[$int]->body_set($body);
596             }
597              
598 0           $int++;
599             }
600              
601 0           $self->{mime}->parts_set( \@parts );
602              
603 0           return 1;
604             }
605              
606 0           $self->{mime}->body_set($body);
607              
608 0           return 1;
609             }
610              
611             =head2 dirGet
612              
613             This gets L directory this entry is associated with.
614              
615             This will only error if a permanent error is set.
616              
617             This will return undef if no directory has been set.
618              
619             my $dir=$foo->dirGet;
620             if($foo->error){
621             warn('Error:'.$foo->error.': '.$foo->errorString);
622             }
623              
624             =cut
625              
626             sub dirGet{
627 0     0 1   my $self=$_[0];
628              
629 0 0         if (!$self->errorblank){
630 0           return undef;
631             }
632              
633 0           return $self->{dir};
634             }
635              
636             =head2 dirSet
637              
638             This sets L directory this entry is associated with.
639              
640             One argument is taken and it is the L directory to set it to.
641              
642             my $dir=$foo->dirSet($toaderDirectory);
643             if($foo->error){
644             warn('Error:'.$foo->error.': '.$foo->errorString);
645             }
646              
647             =cut
648              
649             sub dirSet{
650 0     0 1   my $self=$_[0];
651 0           my $dir=$_[1];
652              
653 0 0         if (!$self->errorblank){
654 0           return undef;
655             }
656              
657             #make sure a directory has been specified
658 0 0         if (!defined($dir)) {
659 0           $self->{error}=11;
660 0           $self->{errorString}='No directory specified.';
661 0           $self->warn;
662 0           return undef;
663             }
664              
665             #cleans up the naming
666 0           my $pathHelper=Toader::pathHelper->new($dir);
667 0           $dir=$pathHelper->cleanup($dir);
668              
669             #checks if the directory is Toader directory or not
670 0           my $isatd=Toader::isaToaderDir->new;
671 0           my $returned=$isatd->isaToaderDir($dir);
672 0 0         if (! $returned ) {
673 0           $self->{error}=10;
674 0           $self->{errorString}='"'.$dir.'" is not a Toader directory.';
675 0           $self->warn;
676 0           return undef;
677             }
678              
679 0           $self->{dir}=$dir;
680              
681 0           return 1;
682             }
683              
684             =head2 entryNameGet
685              
686             This gets L directory this entry is associated with.
687              
688             This will only error if a permanent error is set.
689              
690             This will return undef if no entry name has been set.
691              
692             my $entryName=$foo->entryNameGet;
693             if($foo->error){
694             warn('Error:'.$foo->error.': '.$foo->errorString);
695             }
696              
697             =cut
698              
699             sub entryNameGet{
700 0     0 1   my $self=$_[0];
701              
702 0 0         if (!$self->errorblank){
703 0           $self->warn;
704 0           return undef;
705             }
706              
707 0           return $self->{entryName};
708             }
709              
710             =head2 entryNameSet
711              
712             This sets L directory this entry is associated with.
713              
714             One argument is taken and it is the Toader directory to set it to.
715             If none is specified it will be generated.
716              
717             $foo->entryNameSet($entryName);
718             if($foo->error){
719             warn('Error:'.$foo->error.': '.$foo->errorString);
720             }
721              
722             =cut
723              
724             sub entryNameSet{
725 0     0 1   my $self=$_[0];
726 0           my $entryName=$_[1];
727              
728 0 0         if (!$self->errorblank){
729 0           return undef;
730             }
731              
732             #generate a entry name if one has not been
733 0           my $ehelper=Toader::Entry::Helper->new( $self->{toader} ) ;
734 0 0         if (!defined($entryName)) {
735 0           $entryName=$ehelper->generateEntryName;
736             }
737              
738             #makes sure the entry name is valid
739 0           my $returned=$ehelper->validEntryName($entryName);
740 0 0         if ( ! $returned ) {
741 0           $self->{error}=9;
742 0 0         if ( defined( $entryName ) ){
743 0           $self->{errorString}='"'.$entryName.'" is not a valid entry name';
744             }else{
745 0           $self->{errorString}='undef is not a valid entry name';
746             }
747 0           $self->warn;
748 0           return undef;
749             }
750              
751 0           $self->{entryName}=$entryName;
752              
753 0           return 1;
754             }
755              
756             =head2 fromGet
757              
758             This returns the from.
759              
760             my $from=$foo->fromGet;
761             if($foo->error){
762             warn('error: '.$foo->error.":".$foo->errorString);
763             }
764              
765             =cut
766              
767             sub fromGet{
768 0     0 1   my $self=$_[0];
769              
770 0 0         if (!$self->errorblank){
771 0           return undef;
772             }
773              
774 0           return $self->{mime}->header('From');
775             }
776              
777             =head2 fromSet
778              
779             This sets the from.
780              
781             One argument is taken and it is the name.
782              
783             $foo->fromSet($name);
784             if($foo->error){
785             warn('error: '.$foo->error.":".$foo->errorString);
786             }
787              
788             =cut
789              
790             sub fromSet{
791 0     0 1   my $self=$_[0];
792 0           my $from=$_[1];
793              
794 0 0         if (!$self->errorblank){
795 0           return undef;
796             }
797              
798 0 0         if (!defined( $from )) {
799 0           $self->{error}=9;
800 0           $self->{errorString}='No short name specified';
801 0           $self->warn;
802 0           return $self;
803             }
804              
805 0           $self->{mime}->header_set('From'=>$from);
806              
807 0           return 1;
808             }
809              
810             =head2 publishGet
811              
812             This returns the publish value.
813              
814             my $publish=$foo->publishGet;
815             if($foo->error){
816             warn('error: '.$foo->error.":".$foo->errorString);
817             }
818              
819             =cut
820              
821             sub publishGet{
822 0     0 1   my $self=$_[0];
823              
824 0 0         if (!$self->errorblank){
825 0           return undef;
826             }
827              
828 0           my $publish=$self->{mime}->header('publish');
829            
830             #return the default if none is specified
831 0 0         if ( ! defined( $publish ) ){
832 0           return "1";
833             }
834              
835 0 0 0       if (
836             ( $publish ne "0" ) &&
837             ( $publish ne "1" )
838             ){
839 0           $self->{error}=19;
840 0           $self->{errorString}='"'.$publish.'" is not a recognized boolean value';
841 0           $self->warn;
842 0           return undef;
843             }
844              
845 0           return $publish;
846             }
847              
848             =head2 publishSet
849              
850             This sets the publish value.
851              
852             One argument is taken and it is the publish value.
853              
854             $foo->publishSet($publish);
855             if($foo->error){
856             warn('error: '.$foo->error.":".$foo->errorString);
857             }
858              
859             =cut
860              
861             sub publishSet{
862 0     0 1   my $self=$_[0];
863 0           my $publish=$_[1];
864              
865 0 0         if (!$self->errorblank){
866 0           return undef;
867             }
868              
869 0 0         if (!defined( $publish )) {
870 0           $publish='0';
871             }
872              
873 0 0 0       if (
874             ( $publish ne '0' ) &&
875             ( $publish ne '1' )
876             ){
877 0           $self->error=19;
878 0           $self->errorString='The publish value is not "0" or "1", but "'.$publish.'"';
879 0           $self->warn;
880 0           return undef;
881             }
882            
883              
884 0           $self->{mime}->header_set('publish'=>$publish);
885              
886 0           return 1;
887             }
888              
889             =head2 summaryGet
890              
891             This returns the summary.
892              
893             my $summary=$foo->summaryGet;
894             if($foo->error){
895             warn('error: '.$foo->error.":".$foo->errorString);
896             }
897              
898             =cut
899              
900             sub summaryGet{
901 0     0 1   my $self=$_[0];
902              
903 0 0         if (!$self->errorblank){
904 0           return undef;
905             }
906              
907 0           my $summary=$self->{mime}->header('summary');
908              
909 0 0         if ( ! defined( $summary ) ){
910 0           $summary='';
911             }
912              
913 0           return $summary;
914             }
915              
916             =head2 summarySet
917              
918             This sets the summary.
919              
920             One argument is taken and it is the summary.
921              
922             $foo->summarySet($summary);
923             if($foo->error){
924             warn('error: '.$foo->error.":".$foo->errorString);
925             }
926              
927             =cut
928              
929             sub summarySet{
930 0     0 1   my $self=$_[0];
931 0           my $summary=$_[1];
932              
933 0 0         if (!$self->errorblank){
934 0           return undef;
935             }
936              
937 0 0         if (!defined( $summary )) {
938 0           $self->{error}=15;
939 0           $self->{errorString}='No summary specified';
940 0           $self->warn;
941 0           return $self;
942             }
943              
944 0           $self->{mime}->header_set('summary'=>$summary);
945              
946 0           return 1;
947             }
948              
949             =head2 titleGet
950              
951             This returns the title.
952              
953             my $name=$foo->titleGet;
954             if($foo->error){
955             warn('error: '.$foo->error.":".$foo->errorString);
956             }
957              
958             =cut
959              
960             sub titleGet{
961 0     0 1   my $self=$_[0];
962              
963 0 0         if (!$self->errorblank){
964 0           return undef;
965             }
966              
967 0           return $self->{mime}->header('title');
968             }
969              
970             =head2 titleSet
971              
972             This sets the title.
973              
974             One argument is taken and it is the title.
975              
976             $foo->titleSet($title);
977             if($foo->error){
978             warn('error: '.$foo->error.":".$foo->errorString);
979             }
980              
981             =cut
982              
983             sub titleSet{
984 0     0 1   my $self=$_[0];
985 0           my $title=$_[1];
986              
987 0 0         if (!$self->errorblank){
988 0           return undef;
989             }
990              
991 0 0         if (!defined( $title )) {
992 0           $self->{error}=1;
993 0           $self->{errorString}='No title specified';
994 0           $self->warn;
995 0           return $self;
996             }
997              
998 0           $self->{mime}->header_set('title'=>$title);
999              
1000 0           return 1;
1001             }
1002              
1003             =head2 rendererGet
1004              
1005             This returns the renderer type.
1006              
1007             my $renderer=$foo->rendererGet;
1008             if($foo->error){
1009             warn('error: '.$foo->error.":".$foo->errorString);
1010             }
1011              
1012             =cut
1013              
1014             sub rendererGet{
1015 0     0 1   my $self=$_[0];
1016              
1017 0 0         if (!$self->errorblank){
1018 0           return undef;
1019             }
1020              
1021 0           return $self->{mime}->header('renderer');
1022             }
1023              
1024             =head2 rendererSet
1025              
1026             This sets the renderer type.
1027              
1028             One argument is taken and it is the render type.
1029              
1030             A value of undef sets it to the default, 'html'.
1031              
1032             my $renderer=$foo->rendererGet;
1033             if($foo->error){
1034             warn('error: '.$foo->error.":".$foo->errorString);
1035             }
1036              
1037             =cut
1038              
1039             sub rendererSet{
1040 0     0 1   my $self=$_[0];
1041 0           my $renderer=$_[1];
1042              
1043 0 0         if (!$self->errorblank){
1044 0           return undef;
1045             }
1046              
1047 0 0         if (!defined( $renderer )) {
1048 0           $renderer='html';
1049             }
1050              
1051 0           $self->{mime}->header_set('renderer'=>$renderer);
1052              
1053 0           return 1;
1054             }
1055              
1056             =head2 subpartsAdd
1057              
1058             This adds a new file as a subpart.
1059              
1060             One argument is required and it is the path to the file.
1061              
1062             $foo->subpartsAdd( $file );
1063             if ( $foo->error ){
1064             warn('Error:'.$foo->error.': '.$foo->errorString);
1065             }
1066              
1067             =cut
1068              
1069             sub subpartsAdd{
1070 0     0 1   my $self=$_[0];
1071 0           my $file=$_[1];
1072              
1073 0 0         if (!$self->errorblank){
1074 0           return undef;
1075             }
1076              
1077             #makes sure a file is specified
1078 0 0         if ( ! defined( $file ) ){
1079 0           $self->{error}=18;
1080 0           $self->{errorstring}='No file specified';
1081 0           $self->warn;
1082 0           return undef;
1083             }
1084              
1085             #makes sure the file exists and is a file
1086 0 0         if ( ! -f $file ){
1087 0           $self->{error}=4;
1088 0           $self->{errorString}='The file, "'.$file.'", does not exist or is not a file';
1089 0           $self->warn;
1090 0           return undef;
1091             }
1092              
1093             #gets the MIME type
1094 0           my $mimetype=mimetype( $file );
1095            
1096             #makes sure it is a mimetype
1097 0 0         if ( !defined( $mimetype ) ) {
1098 0           $self->{error}=5;
1099 0           $self->{errorString}="'".$file."' could not be read or does not exist";
1100 0           $self->warn;
1101 0           return $self;
1102             }
1103              
1104             #create a short name for it... removing the path
1105 0           my $filename=$file;
1106 0           $filename=~s/.*\///g;
1107              
1108             #open and read the file
1109 0           my $fh;
1110 0 0         if ( ! open( $fh, '<', $file ) ) {
1111 0           $self->{error}=6;
1112 0           $self->{errorString}="Unable to open '".$file."'";
1113 0           $self->warn;
1114 0           return undef;
1115             }
1116 0           my $body=join('',<$fh>);
1117 0           close $fh;
1118              
1119              
1120             #creates the part
1121 0           my $part=Email::MIME->create(attributes=>{
1122             filename=>$filename,
1123             content_type=>$mimetype,
1124             encode=>"base64",
1125             },
1126             body=>$body,
1127             );
1128 0           my @parts;
1129 0           push( @parts, $part );
1130 0           $self->{mime}->parts_add( \@parts );
1131              
1132 0           return 1;
1133             }
1134              
1135             =head2 subpartsExtract
1136              
1137             This extracts the subparts of a entry.
1138              
1139             One argument is extracted, it is the directory
1140             to extract the files to.
1141              
1142             $foo->subpartsExtract( $dir );
1143             if ( $foo->error ){
1144             warn('Error:'.$foo->error.': '.$foo->errorString);
1145             }
1146              
1147             =cut
1148              
1149             sub subpartsExtract{
1150 0     0 1   my $self=$_[0];
1151 0           my $dir=$_[1];
1152              
1153 0 0         if (!$self->errorblank){
1154 0           return undef;
1155             }
1156              
1157 0 0         if ( ! defined( $dir ) ){
1158 0           $self->{error}=11;
1159 0           $self->{errorString}='No directory specified';
1160 0           $self->warn;
1161 0           return undef;
1162             }
1163              
1164             #make sure it exists and is a directory
1165 0 0         if ( ! -d $dir ){
1166 0           $self->{error}=17;
1167 0           $self->{errorString}='"'.$dir.'" is not a directory or does not exist';
1168 0           $self->warn;
1169 0           return undef;
1170             }
1171              
1172 0           my @subparts=$self->subpartsGet;
1173 0 0         if ( $self->error ){
1174 0           $self->warnString('Failed to get the subparts');
1175 0           return undef;
1176             }
1177              
1178             # no subparts to write to the FS
1179 0 0         if ( ! defined( $subparts[0] ) ){
1180 0           return 1;
1181             }
1182              
1183 0           my $int=0;
1184 0           while ( defined( $subparts[$int] ) ){
1185 0           my $file=$subparts[$int]->filename;
1186 0 0         if( defined( $file ) ){
1187 0           my $file=$dir.'/'.$file;
1188            
1189 0           my $fh;
1190 0 0         if ( ! open( $fh, '>', $file ) ){
1191 0           $self->{error}=18;
1192 0           $self->{errorString}='"Failed to open "'.$file.
1193             '" for writing the body of a subpart out to';
1194 0           $self->warn;
1195 0           return undef;
1196             }
1197 0           print $fh $subparts[$int]->body;
1198 0           close( $fh );
1199             }
1200              
1201 0           $int++;
1202             }
1203              
1204 0           return 1;
1205             }
1206              
1207             =head2 subpartsGet
1208              
1209             This returns the results from the subparts
1210             methods from the internal L object.
1211              
1212             my @parts=$foo->subpartsGet;
1213             if ( $foo->error ){
1214             warn('Error:'.$foo->error.': '.$foo->errorString);
1215             }
1216              
1217             =cut
1218              
1219             sub subpartsGet{
1220 0     0 1   my $self=$_[0];
1221              
1222 0 0         if (!$self->errorblank){
1223 0           return undef;
1224             }
1225              
1226 0           return $self->{mime}->subparts;
1227             }
1228              
1229             =head2 subpartsList
1230              
1231             This returns a list filenames for the subparts.
1232              
1233             my @files=$foo->subpartsList;
1234             if ( $foo->error ){
1235             warn('Error:'.$foo->error.': '.$foo->errorString);
1236             }
1237              
1238             =cut
1239              
1240             sub subpartsList{
1241 0     0 1   my $self=$_[0];
1242              
1243 0 0         if (!$self->errorblank){
1244 0           return undef;
1245             }
1246              
1247 0           my @subparts=$self->subpartsGet;
1248 0 0         if ( $self->error ){
1249 0           $self->warnString('Failed to get the subparts');
1250 0           return undef;
1251             }
1252              
1253 0           my @files;
1254 0           my $int=0;
1255 0           while( defined( $subparts[$int] ) ){
1256 0 0         if ( defined( $subparts[$int]->filename ) ){
1257 0           push( @files, $subparts[$int]->filename );
1258             }
1259              
1260 0           $int++;
1261             }
1262              
1263 0           return @files;
1264             }
1265              
1266             =head2 subpartsRemove
1267              
1268             This removes the specified subpart.
1269              
1270             One argument is required and it is the name of the
1271             file to remove.
1272              
1273             $foo->subpartsRemove( $filename );
1274             if ( $foo->error ){
1275             warn('Error:'.$foo->error.': '.$foo->errorString);
1276             }
1277              
1278             =cut
1279              
1280             sub subpartsRemove{
1281 0     0 1   my $self=$_[0];
1282 0           my $file=$_[1];
1283              
1284 0 0         if (!$self->errorblank){
1285 0           return undef;
1286             }
1287              
1288             #makes sure a file is specified
1289 0 0         if ( ! defined( $file ) ){
1290 0           $self->{error}=18;
1291 0           $self->{errorstring}='No file specified';
1292 0           $self->warn;
1293 0           return undef;
1294             }
1295              
1296 0           my @parts=$self->{mime}->parts;
1297 0           my @newparts;
1298 0           my $int=0;
1299 0           while ( defined( $parts[$int] ) ){
1300 0           my $partFilename=$parts[$int]->filename;
1301 0 0 0       if ( ( ! defined( $partFilename ) ) ||
1302             ( $file ne $partFilename ) ){
1303 0           push( @newparts, $parts[$int] );
1304             }
1305              
1306 0           $int++;
1307             }
1308              
1309 0           $self->{mime}->parts_set( \@newparts );
1310              
1311 0           return 1;
1312             }
1313              
1314             =head2 tagsGet
1315              
1316             Returns a array of tags tags.
1317              
1318             The returned value is an array.
1319              
1320             my @tags=$foo->tagsGet;
1321             if ( $foo->error ){
1322             warn('Error:'.$foo->error.': '.$foo->errorString);
1323             }
1324              
1325             =cut
1326              
1327             sub tagsGet{
1328 0     0 1   my $self=$_[0];
1329              
1330 0 0         if (!$self->errorblank){
1331 0           return undef;
1332             }
1333            
1334             #if there are no tags, make sure it is blank
1335 0 0         if (!defined( $self->{mime}->header( "tags" ) )) {
1336 0           $self->{mime}->header_set(tags=>'');
1337             }
1338             #clean the tags
1339 0           my @tags=Text::Tags::Parser->new->parse_tags( $self->{mime}->header("tags") );
1340              
1341 0           return @tags;
1342             }
1343              
1344             =head2 tagsGetAsString
1345              
1346             This returns the tags as a string.
1347              
1348             As long as this object has initiated with
1349             out issue, then there is no need to do error
1350             checking for this method.
1351              
1352             my $tagsString=$foo->tagsGetAsString;
1353              
1354             =cut
1355              
1356             sub tagsGetAsString{
1357 0     0 1   my $self=$_[0];
1358              
1359 0 0         if (!$self->errorblank){
1360 0           return undef;
1361             }
1362              
1363 0           my $tags=$self->{mime}->header( "tags" );
1364              
1365 0 0         if ( ! defined( $tags ) ){
1366 0           $tags='';
1367             }
1368              
1369 0           return $tags;
1370             }
1371              
1372             =head2 tagsSet
1373              
1374             This sets the tags.
1375              
1376             One value is taken and that is the a array reference.
1377              
1378             $foo->tagsSet( \@tags );
1379             if ( $foo->error ){
1380             warn('Error:'.$foo->error.': '.$foo->errorString);
1381             }
1382              
1383             =cut
1384              
1385             sub tagsSet{
1386 0     0 1   my $self=$_[0];
1387 0           my @tags;
1388 0 0         if ( defined( $_[1] ) ){
1389 0           @tags=@{ $_[1] };
  0            
1390             }
1391              
1392 0 0         if (!$self->errorblank){
1393 0           return undef;
1394             }
1395              
1396 0           $self->{mime}->header_set( Text::Tags::Parser->new->join_tags( @tags ) );
1397            
1398 0           return @tags;
1399             }
1400              
1401             =head2 tagsSetFromString
1402              
1403             This sets the tags.
1404              
1405             One value is taken and that is a L parsable
1406             string. A value of undef will blank the tags.
1407              
1408             $foo->tagsSetFromString( $tagsString );
1409             if ( $foo->error ){
1410             warn('Error:'.$foo->error.': '.$foo->errorString);
1411             }
1412              
1413             =cut
1414              
1415             sub tagsSetFromString{
1416 0     0 1   my $self=$_[0];
1417 0           my $tagsString=$_[1];
1418              
1419 0 0         if (!$self->errorblank){
1420 0           return undef;
1421             }
1422              
1423 0 0         if ( ! defined( $tagsString ) ){
1424 0           $tagsString='';
1425             }
1426              
1427 0           my @tags=Text::Tags::Parser->new->parse_tags( $tagsString );
1428 0           $self->{mime}->header_set( tags=>Text::Tags::Parser->new->join_tags( @tags ) );
1429            
1430 0           return @tags;
1431             }
1432              
1433             =head2 write
1434              
1435             This writes the entry out to a file.
1436              
1437             This requires a L directory to have been specified.
1438              
1439             $foo->write;
1440             if($foo->error){
1441             warn('error: '.$foo->error.":".$foo->errorString);
1442             }
1443              
1444             =cut
1445              
1446             sub write{
1447 0     0 1   my $self=$_[0];
1448              
1449 0 0         if (!$self->errorblank){
1450 0           return undef;
1451             }
1452              
1453             #makes so a directory has been specified
1454 0 0         if (!defined( $self->{dir} )) {
1455 0           $self->{error}=12;
1456 0           $self->{errorString}='No directory has been specified yet';
1457 0           $self->warn;
1458 0           return undef;
1459             }
1460              
1461             #makes sure it is still a toader directory...
1462 0 0         if (! -d $self->{dir}.'/.toader/' ) {
1463 0           $self->{error}=13;
1464 0           $self->{errorString}='No directory has been specified yet';
1465 0           $self->warn;
1466 0           return undef;
1467             }
1468              
1469             #if we don't have a entry title, generate one
1470 0 0         if (!defined( $self->{entryName} )) {
1471 0           $self->entryNameSet;
1472             }
1473              
1474             #if there is no entry directory, generate one...
1475 0 0         if (! -d $self->{dir}.'/.toader/entries/' ) {
1476 0 0         if (! make_path( $self->{dir}.'/.toader/entries/' ) ) {
1477 0           $self->{error}=14;
1478 0           $self->{errorString}='The entries directory did not exist and was not able to create it';
1479 0           $self->warn;
1480 0           return undef;
1481             }
1482             }
1483              
1484             #the file that will be writen
1485 0           my $file=$self->{dir}.'/.toader/entries/'.$self->{entryName};
1486              
1487             #dump the entry to a string
1488 0           my $entry=$self->as_string;
1489              
1490             #writes the file
1491 0           my $fh;
1492 0 0         if ( ! open($fh, '>', $file) ){
1493 0           $self->{error}=15;
1494 0           $self->{errorString}='Unable to open "'.$file.'" for writing';
1495 0           $self->warn;
1496 0           return undef;
1497             }
1498 0           print $fh $entry;
1499 0           close($fh);
1500              
1501             #if VCS is not usable, stop here
1502 0 0         if ( ! $self->{VCSusable} ){
1503 0           return 1;
1504             }
1505              
1506             #if it is under VCS, we have nothing to do
1507 0           my $underVCS=$self->{vcs}->underVCS($file);
1508 0 0         if ( $self->{vcs}->error ){
1509 0           $self->{error}=22;
1510             $self->{errorString}='Toader::VCS->underVCS errored. error="'.
1511 0           $self->{vcs}->error.'" errorString="'.$self->{vcs}->errorString.'"';
1512 0           $self->warn;
1513 0           return undef;
1514             }
1515 0 0         if ( $underVCS ){
1516 0           return 1;
1517             }
1518              
1519             #add it as if we reach here it is not under VCS and VCS is being used
1520 0           $self->{vcs}->add( $file );
1521 0 0         if ( $self->{vcs}->error ){
1522 0           $self->{error}=23;
1523             $self->{errorString}='Toader::VCS->add errored. error="'.
1524 0           $self->{vcs}->error.'" errorString="'.$self->{vcs}->errorString.'"';
1525 0           $self->warn;
1526 0           return undef;
1527             }
1528              
1529 0           return 1;
1530             }
1531              
1532             =head1 REQUIRED RENDERING METHODS
1533              
1534             =head2 filesDir
1535              
1536             This returns the file directory for the object.
1537              
1538             This is not a full path, but a partial path that should
1539             be appended the directory current directory being outputted to.
1540              
1541             =cut
1542              
1543             sub filesDir{
1544 0     0 1   my $self=$_[0];
1545              
1546 0 0         if (!$self->errorblank){
1547 0           return undef;
1548             }
1549              
1550 0 0         if ( ! defined( $self->{entryName} ) ){
1551 0           $self->{error}=16;
1552 0           $self->{errorString}='No entry name has been set';
1553 0           $self->warn;
1554 0           return undef;
1555             }
1556              
1557 0           return $self->renderDir.'/'.$self->{entryName}.'/.files';
1558             }
1559              
1560             =head2 locationID
1561              
1562             This returns the location ID.
1563              
1564             This one requires the object to be initialized.
1565              
1566             =cut
1567              
1568             sub locationID{
1569 0     0 1   my $self=$_[0];
1570              
1571 0 0         if (!$self->errorblank){
1572 0           return undef;
1573             }
1574              
1575 0           return 'Entry='.$self->entryNameGet;
1576             }
1577              
1578             =head2 renderDir
1579              
1580             This is the directory that it will be rendered to.
1581              
1582             The base directory that will be used for rendering.
1583              
1584             =cut
1585              
1586             sub renderDir{
1587 0     0 1   return '.entries';
1588             }
1589              
1590             =head2 renderUsing
1591              
1592             This returns the module to use for rendering.
1593              
1594             my $module=$foo->renderUsing;
1595              
1596             =cut
1597              
1598             sub renderUsing{
1599 0     0 1   return 'Toader::Render::Entry';
1600             }
1601              
1602             =head2 toaderRenderable
1603              
1604             This method returns true and marks it as being L
1605             renderable.
1606              
1607             =cut
1608              
1609             sub toaderRenderable{
1610 0     0 1   return 1;
1611             }
1612              
1613             =head2 toDir
1614              
1615             This returns the directory that will return the directory
1616             that contains where this object should be rendered to.
1617              
1618             This is not a full path, but a partial path that should
1619             be appended the directory current directory being outputted to.
1620              
1621             =cut
1622              
1623             sub toDir{
1624 0     0 1   my $self=$_[0];
1625              
1626 0 0         if (!$self->errorblank){
1627 0           return undef;
1628             }
1629              
1630 0 0         if ( ! defined( $self->{entryName} ) ){
1631 0           $self->{error}=16;
1632 0           $self->{errorString}='No entry name has been set';
1633 0           $self->warn;
1634 0           return undef;
1635             }
1636              
1637 0           return $self->renderDir.'/'.$self->{entryName};
1638             }
1639              
1640              
1641             =head1 ERROR CODES
1642              
1643             =head2 1, noNameSpecified
1644              
1645             No name specified.
1646              
1647             =head2 2, emailMIMEerror
1648              
1649             Unable to create L object.
1650              
1651             =head2 3, notAnArray
1652              
1653             Has files specified, but the passed object is not a array.
1654              
1655             =head2 4, fileDoesNotExist
1656              
1657             The file does not exist or is not a file.
1658              
1659             =head2 5, MIMEinfoError
1660              
1661             File::MimeInfo->mimetype returned undef, meaning the file does not exist or is not readable.
1662              
1663             =head2 6, unableToOpenFile
1664              
1665             Unable to open the file.
1666              
1667             =head2 7, emailMIMEerror
1668              
1669             Unable to create a L object for one of the parts/files.
1670              
1671             =head2 8, noBody
1672              
1673             No body defined.
1674              
1675             =head2 9, invalidEntryName
1676              
1677             Not a valid entry name.
1678              
1679             =head2 10. notAtoaderDir
1680              
1681             The specified directory is not a Toader directory.
1682              
1683             =head2 11, noDirSpecified
1684              
1685             No directory specified.
1686              
1687             =head2 12, noDirSet
1688              
1689             No directory has been set yet.
1690              
1691             =head2 13, noLongerAtoaderDir
1692              
1693             The directory is no longer a L directory. It looks like
1694             it has been removed.
1695              
1696             =head2 14, noEntryDir
1697              
1698             The entries directory did not exist and was not able to create it.
1699              
1700             =head2 15, noSummarySpecified
1701              
1702             No summary specified.
1703              
1704             =head2 16, noEntryNameSet
1705              
1706             No entry name has been set.
1707              
1708             =head2 17, dirDNEorNAD
1709              
1710             The directory does not exist or is a not a directory.
1711              
1712             =head2 18, noFileSpecified
1713              
1714             No file specified.
1715              
1716             =head2 19, publishValError
1717              
1718             Invalid publish value. It is not a recognized boolean value of
1719             either "0" or "1".
1720              
1721             =head2 20, getVCSerrored
1722              
1723             L->getVCS errored.
1724              
1725             =head2 21, VCSusableErrored
1726              
1727             L->usable errored.
1728              
1729             =head2 22, underVCSerrored
1730              
1731             L->underVCS errored.
1732              
1733             =head2 23, VCSaddErrored
1734              
1735             L->add errored.
1736              
1737             =head2 24, notAtoaderObj
1738              
1739             The specified object is not a L object.
1740              
1741             =head2 25, noToaderObj
1742              
1743             Nothing passed for a L object.
1744              
1745             =head1 AUTHOR
1746              
1747             Zane C. Bowers-Hadley, C<< >>
1748              
1749              
1750             =head1 BUGS
1751              
1752             Please report any bugs or feature requests to C, or through
1753             the web interface at L. I will be notified, and then you'll
1754             automatically be notified of progress on your bug as I make changes.
1755              
1756             =head1 SUPPORT
1757              
1758             You can find documentation for this module with the perldoc command.
1759              
1760             perldoc Toader::Entry
1761              
1762              
1763             You can also look for information at:
1764              
1765             =over 4
1766              
1767             =item * RT: CPAN's request tracker
1768              
1769             L
1770              
1771             =item * AnnoCPAN: Annotated CPAN documentation
1772              
1773             L
1774              
1775             =item * CPAN Ratings
1776              
1777             L
1778              
1779             =item * Search CPAN
1780              
1781             L
1782              
1783             =back
1784              
1785              
1786             =head1 ACKNOWLEDGEMENTS
1787              
1788              
1789             =head1 LICENSE AND COPYRIGHT
1790              
1791             Copyright 2013 Zane C. Bowers-Hadley.
1792              
1793             This program is free software; you can redistribute it and/or modify it
1794             under the terms of either: the GNU General Public License as published
1795             by the Free Software Foundation; or the Artistic License.
1796              
1797             See http://dev.perl.org/licenses/ for more information.
1798              
1799              
1800             =cut
1801              
1802             1; # End of Toader