Tadashi Okoshi
slash****@users*****
2005年 10月 25日 (火) 04:20:52 JST
Index: affelio_farm/admin/skelton/affelio/extlib/XML/RSS.pm diff -u affelio_farm/admin/skelton/affelio/extlib/XML/RSS.pm:1.1.1.1 affelio_farm/admin/skelton/affelio/extlib/XML/RSS.pm:removed --- affelio_farm/admin/skelton/affelio/extlib/XML/RSS.pm:1.1.1.1 Tue Oct 25 04:14:40 2005 +++ affelio_farm/admin/skelton/affelio/extlib/XML/RSS.pm Tue Oct 25 04:20:52 2005 @@ -1,2223 +0,0 @@ -# $Id: RSS.pm,v 1.1.1.1 2005/10/24 19:14:40 slash5234 Exp $ -package XML::RSS; - -use strict; -use Carp; -use XML::Parser; -use vars qw($VERSION $AUTOLOAD @ISA $modules $AUTO_ADD); - -$VERSION = '1.05'; - @ ISA = qw(XML::Parser); - -$AUTO_ADD = 0; - -my %v0_9_ok_fields = ( - channel => { - title => '', - description => '', - link => '', - }, - image => { - title => '', - url => '', - link => '' - }, - textinput => { - title => '', - description => '', - name => '', - link => '' - }, - items => [], - num_items => 0, - version => '', - encoding => '' -); - -my %v0_9_1_ok_fields = ( - channel => { - title => '', - copyright => '', - description => '', - docs => '', - language => '', - lastBuildDate => '', - 'link' => '', - managingEditor => '', - pubDate => '', - rating => '', - webMaster => '' - }, - image => { - title => '', - url => '', - 'link' => '', - width => '', - height => '', - description => '' - }, - skipDays => { - day => '' - }, - skipHours => { - hour => '' - }, - textinput => { - title => '', - description => '', - name => '', - 'link' => '' - }, - items => [], - num_items => 0, - version => '', - encoding => '', - category => '' -); - -my %v1_0_ok_fields = ( - channel => { - title => '', - description => '', - link => '', - }, - image => { - title => '', - url => '', - link => '' - }, - textinput => { - title => '', - description => '', - name => '', - link => '' - }, - skipDays => { - day => '' - }, - skipHours => { - hour => '' - }, - items => [], - num_items => 0, - version => '', - encoding => '', - output => '', -); - -my %v2_0_ok_fields = ( - channel => { - title => '', - 'link' => '', - description => '', - language => '', - copyright => '', - managingEditor => '', - webMaster => '', - pubDate => '', - lastBuildDate => '', - category => '', - generator => '', - docs => '', - cloud => '', - ttl => '', - image => '', - textinput => '', - skipHours => '', - skipDays => '', - }, - image => { - title => '', - url => '', - 'link' => '', - width => '', - height => '', - description => '' - }, - skipDays => { - day => '' - }, - skipHours => { - hour => '' - }, - textinput => { - title => '', - description => '', - name => '', - 'link' => '' - }, - items => [], - num_items => 0, - version => '', - encoding => '', - category => '', - cloud => '', - ttl => '' -); - -my %languages = ( - 'af' => 'Afrikaans', - 'sq' => 'Albanian', - 'eu' => 'Basque', - 'be' => 'Belarusian', - 'bg' => 'Bulgarian', - 'ca' => 'Catalan', - 'zh-cn' => 'Chinese (Simplified)', - 'zh-tw' => 'Chinese (Traditional)', - 'hr' => 'Croatian', - 'cs' => 'Czech', - 'da' => 'Danish', - 'nl' => 'Dutch', - 'nl-be' => 'Dutch (Belgium)', - 'nl-nl' => 'Dutch (Netherlands)', - 'en' => 'English', - 'en-au' => 'English (Australia)', - 'en-bz' => 'English (Belize)', - 'en-ca' => 'English (Canada)', - 'en-ie' => 'English (Ireland)', - 'en-jm' => 'English (Jamaica)', - 'en-nz' => 'English (New Zealand)', - 'en-ph' => 'English (Phillipines)', - 'en-za' => 'English (South Africa)', - 'en-tt' => 'English (Trinidad)', - 'en-gb' => 'English (United Kingdom)', - 'en-us' => 'English (United States)', - 'en-zw' => 'English (Zimbabwe)', - 'fo' => 'Faeroese', - 'fi' => 'Finnish', - 'fr' => 'French', - 'fr-be' => 'French (Belgium)', - 'fr-ca' => 'French (Canada)', - 'fr-fr' => 'French (France)', - 'fr-lu' => 'French (Luxembourg)', - 'fr-mc' => 'French (Monaco)', - 'fr-ch' => 'French (Switzerland)', - 'gl' => 'Galician', - 'gd' => 'Gaelic', - 'de' => 'German', - 'de-at' => 'German (Austria)', - 'de-de' => 'German (Germany)', - 'de-li' => 'German (Liechtenstein)', - 'de-lu' => 'German (Luxembourg)', - 'el' => 'Greek', - 'hu' => 'Hungarian', - 'is' => 'Icelandic', - 'in' => 'Indonesian', - 'ga' => 'Irish', - 'it' => 'Italian', - 'it-it' => 'Italian (Italy)', - 'it-ch' => 'Italian (Switzerland)', - 'ja' => 'Japanese', - 'ko' => 'Korean', - 'mk' => 'Macedonian', - 'no' => 'Norwegian', - 'pl' => 'Polish', - 'pt' => 'Portuguese', - 'pt-br' => 'Portuguese (Brazil)', - 'pt-pt' => 'Portuguese (Portugal)', - 'ro' => 'Romanian', - 'ro-mo' => 'Romanian (Moldova)', - 'ro-ro' => 'Romanian (Romania)', - 'ru' => 'Russian', - 'ru-mo' => 'Russian (Moldova)', - 'ru-ru' => 'Russian (Russia)', - 'sr' => 'Serbian', - 'sk' => 'Slovak', - 'sl' => 'Slovenian', - 'es' => 'Spanish', - 'es-ar' => 'Spanish (Argentina)', - 'es-bo' => 'Spanish (Bolivia)', - 'es-cl' => 'Spanish (Chile)', - 'es-co' => 'Spanish (Colombia)', - 'es-cr' => 'Spanish (Costa Rica)', - 'es-do' => 'Spanish (Dominican Republic)', - 'es-ec' => 'Spanish (Ecuador)', - 'es-sv' => 'Spanish (El Salvador)', - 'es-gt' => 'Spanish (Guatemala)', - 'es-hn' => 'Spanish (Honduras)', - 'es-mx' => 'Spanish (Mexico)', - 'es-ni' => 'Spanish (Nicaragua)', - 'es-pa' => 'Spanish (Panama)', - 'es-py' => 'Spanish (Paraguay)', - 'es-pe' => 'Spanish (Peru)', - 'es-pr' => 'Spanish (Puerto Rico)', - 'es-es' => 'Spanish (Spain)', - 'es-uy' => 'Spanish (Uruguay)', - 'es-ve' => 'Spanish (Venezuela)', - 'sv' => 'Swedish', - 'sv-fi' => 'Swedish (Finland)', - 'sv-se' => 'Swedish (Sweden)', - 'tr' => 'Turkish', - 'uk' => 'Ukranian' - ); - -# define required elements for RSS 0.9 -my $_REQ_v0_9 = { - channel => { - "title" => [1,40], - "description" => [1,500], - "link" => [1,500] - }, - image => { - "title" => [1,40], - "url" => [1,500], - "link" => [1,500] - }, - item => { - "title" => [1,100], - "link" => [1,500] - }, - textinput => { - "title" => [1,40], - "description" => [1,100], - "name" => [1,500], - "link" => [1,500] - } -}; - -# define required elements for RSS 0.91 -my $_REQ_v0_9_1 = { - channel => { - "title" => [1,100], - "description" => [1,500], - "link" => [1,500], - "language" => [1,5], - "rating" => [0,500], - "copyright" => [0,100], - "pubDate" => [0,100], - "lastBuildDate" => [0,100], - "docs" => [0,500], - "managingEditor" => [0,100], - "webMaster" => [0,100], - }, - image => { - "title" => [1,100], - "url" => [1,500], - "link" => [0,500], - "width" => [0,144], - "height" => [0,400], - "description" => [0,500] - }, - item => { - "title" => [1,100], - "link" => [1,500], - "description" => [0,500] - }, - textinput => { - "title" => [1,100], - "description" => [1,500], - "name" => [1,20], - "link" => [1,500] - }, - skipHours => { - "hour" => [1,23] - }, - skipDays => { - "day" => [1,10] - } -}; - -# define required elements for RSS 2.0 -my $_REQ_v2_0 = { - channel => { - "title" => [1,100], - "description" => [1,500], - "link" => [1,500], - "language" => [0,5], - "rating" => [0,500], - "copyright" => [0,100], - "pubDate" => [0,100], - "lastBuildDate" => [0,100], - "docs" => [0,500], - "managingEditor" => [0,100], - "webMaster" => [0,100], - }, - image => { - "title" => [1,100], - "url" => [1,500], - "link" => [0,500], - "width" => [0,144], - "height" => [0,400], - "description" => [0,500] - }, - item => { - "title" => [1,100], - "link" => [1,500], - "description" => [0,500] - }, - textinput => { - "title" => [1,100], - "description" => [1,500], - "name" => [1,20], - "link" => [1,500] - }, - skipHours => { - "hour" => [1,23] - }, - skipDays => { - "day" => [1,10] - } -}; - -my $namespace_map = { - rss10 => 'http://purl.org/rss/1.0/', - rss09 => 'http://my.netscape.com/rdf/simple/0.9/', -# rss091 => 'http://purl.org/rss/1.0/modules/rss091/', - rss20 => 'http://backend.userland.com/blogChannelModule', -}; - -my $modules = { - 'http://purl.org/rss/1.0/modules/syndication/' => 'syn', - 'http://purl.org/dc/elements/1.1/' => 'dc', - 'http://purl.org/rss/1.0/modules/taxonomy/' => 'taxo', - 'http://webns.net/mvcb/' => 'admin' -}; - -my %syn_ok_fields = ( - 'updateBase' => '', - 'updateFrequency' => '', - 'updatePeriod' => '', -); - -my %dc_ok_fields = ( - 'title' => '', - 'creator' => '', - 'subject' => '', - 'description' => '', - 'publisher' => '', - 'contributor' => '', - 'date' => '', - 'type' => '', - 'format' => '', - 'identifier' => '', - 'source' => '', - 'language' => '', - 'relation' => '', - 'coverage' => '', - 'rights' => '', -); - -my %rdf_resource_fields = ( - 'http://webns.net/mvcb/' => { - 'generatorAgent' => 1, - 'errorReportsTo' => 1 - }, - 'http://purl.org/rss/1.0/modules/annotate/' => { - 'reference' => 1 - }, - 'http://my.theinfo.org/changed/1.0/rss/' => { - 'server' => 1 - } -); - -sub new { - my $class = shift; - - my $self = $class->SUPER::new( - Namespaces => 1, - NoExpand => 1, - ParseParamEnt => 0, - Handlers => { - Char => \&handle_char, - XMLDecl => \&handle_dec, - Start => \&handle_start - }); - - bless $self, $class; - - $self->_initialize(@_); - - return $self; -} - -sub _initialize { - my $self = shift; - my %hash = @_; - - # internal hash - $self->{_internal} = {}; - - # init num of items to 0 - $self->{num_items} = 0; - - # adhere to Netscape limits; no by default - $self->{'strict'} = 0; - - # initialize items - $self->{items} = []; - - # namespaces - $self->{namespaces} = {}; - $self->{rss_namespace} = ''; - - # modules - $self->{modules} = $modules; - - # encode output from as_string? - (exists($hash{encode_output})) - ? ($self->{encode_output} = $hash{encode_output}) - : ($self->{encode_output} = 1); - - #get version info - (exists($hash{version})) - ? ($self->{version} = $hash{version}) - : ($self->{version} = '1.0'); - - # set default output - (exists($hash{output})) - ? ($self->{output} = $hash{output}) - : ($self->{output} = ""); - - # encoding - (exists($hash{encoding})) - ? ($self->{encoding} = $hash{encoding}) - : ($self->{encoding} = 'UTF-8'); - - # initialize RSS data structure - # RSS version 0.9 - if ($self->{version} eq '0.9') { - # Copy the hashes instead of using them directly to avoid - # problems with multiple XML::RSS objects being used concurrently - foreach my $i (qw(channel image textinput)) { - my %template=%{$v0_9_ok_fields{$i}}; - $self->{$i} = \%template; - } - - # RSS version 0.91 - } elsif ($self->{version} eq '0.91') { - foreach my $i (qw(channel image textinput skipDays skipHours)) { - my %template=%{$v0_9_1_ok_fields{$i}}; - $self->{$i} = \%template; - } - - # RSS version 2.0 - } elsif ($self->{version} eq '2.0') { - $self->{namespaces}->{'blogChannel'} = "http://backend.userland.com/blogChannelModule"; - foreach my $i (qw(channel image textinput skipDays skipHours)) { - my %template=%{ $v2_0_ok_fields{$i} }; - $self->{$i} = \%template; - } - - # RSS version 1.0 - #} elsif ($self->{version} eq '1.0') { - } else { - foreach my $i (qw(channel image textinput)) { - #foreach my $i (keys(%v1_0_ok_fields)) { - my %template=%{$v1_0_ok_fields{$i}}; - $self->{$i} = \%template; - } - } -} - -sub add_module { - my $self = shift; - my $hash = {@_}; - - $hash->{prefix} =~ /^[a-z_][a-z0-9.-_]*$/ or - croak "a namespace prefix should look like [a-z_][a-z0-9.-_]*"; - - $hash->{uri} or - croak "a URI must be provided in a namespace declaration"; - - $self->{modules}->{$hash->{uri}} = $hash->{prefix}; -} - -sub add_item { - my $self = shift; - my $hash = {@_}; - - # strict Netscape Netcenter length checks - if ($self->{'strict'}) { - # make sure we have a title and link - croak "title and link elements are required" - unless ($hash->{title} && $hash->{'link'}); - - # check string lengths - croak "title cannot exceed 100 characters in length" - if (length($hash->{title}) > 100); - croak "link cannot exceed 500 characters in length" - if (length($hash->{'link'}) > 500); - croak "description cannot exceed 500 characters in length" - if (exists($hash->{description}) - && length($hash->{description}) > 500); - - # make sure there aren't already 15 items - croak "total items cannot exceed 15 " if (@{$self->{items}} >= 15); - } - - # add the item to the list - if (defined($hash->{mode}) && $hash->{mode} eq 'insert') { - unshift (@{$self->{items}}, $hash); - } else { - push (@{$self->{items}}, $hash); - } - - # return reference to the list of items - return $self->{items}; -} - -sub as_rss_0_9 { - my $self = shift; - my $output; - - # XML declaration - my $encoding = exists $$self{encoding} ? qq| encoding="$$self{encoding}"| : ''; - $output .= qq|<?xml version="1.0"$encoding?>\n\n|; - - # RDF root element - $output .= '<rdf:RDF'."\n".'xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"'."\n"; - $output .= 'xmlns="http://my.netscape.com/rdf/simple/0.9/">'."\n\n"; - - ################### - # Channel Element # - ################### - $output .= '<channel>'."\n"; - $output .= '<title>'. $self->encode($self->{channel}->{title}) .'</title>'."\n"; - $output .= '<link>'. $self->encode($self->{channel}->{'link'}) .'</link>'."\n"; - $output .= '<description>'. $self->encode($self->{channel}->{description}) .'</description>'."\n"; - $output .= '</channel>'."\n\n"; - - ################# - # image element # - ################# - if ($self->{image}->{url}) { - $output .= '<image>'."\n"; - - # title - $output .= '<title>'. $self->encode($self->{image}->{title}) .'</title>'."\n"; - - # url - $output .= '<url>'. $self->encode($self->{image}->{url}) .'</url>'."\n"; - - # link - $output .= '<link>'. $self->encode($self->{image}->{'link'}) .'</link>'."\n" - if $self->{image}->{link}; - - # end image element - $output .= '</image>'."\n\n"; - } - - ################ - # item element # - ################ - foreach my $item (@{$self->{items}}) { - if ($item->{title}) { - $output .= '<item>'."\n"; - $output .= '<title>'. $self->encode($item->{title}) .'</title>'."\n"; - $output .= '<link>'. $self->encode($item->{'link'}) .'</link>'."\n"; - - # end image element - $output .= '</item>'."\n\n"; - } - } - - ##################### - # textinput element # - ##################### - if ($self->{textinput}->{'link'}) { - $output .= '<textinput>'."\n"; - $output .= '<title>'. $self->encode($self->{textinput}->{title}) .'</title>'."\n"; - $output .= '<description>'. $self->encode($self->{textinput}->{description}) .'</description>'."\n"; - $output .= '<name>'. $self->encode($self->{textinput}->{name}) .'</name>'."\n"; - $output .= '<link>'. $self->encode($self->{textinput}->{'link'}) .'</link>'."\n"; - $output .= '</textinput>'."\n\n"; - } - - $output .= '</rdf:RDF>'; - - return $output; -} - -sub as_rss_0_9_1 { - my $self = shift; - my $output; - - # XML declaration - $output .= '<?xml version="1.0" encoding="'.$self->{encoding}.'"?>'."\n\n"; - - # DOCTYPE - $output .= '<!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN"'."\n"; - $output .= ' "http://my.netscape.com/publish/formats/rss-0.91.dtd">'."\n\n"; - - # RSS root element - $output .= '<rss version="0.91">'."\n\n"; - - ################### - # Channel Element # - ################### - $output .= '<channel>'."\n"; - $output .= '<title>'. $self->encode($self->{channel}->{title}) .'</title>'."\n"; - $output .= '<link>'. $self->encode($self->{channel}->{'link'}) .'</link>'."\n"; - $output .= '<description>'. $self->encode($self->{channel}->{description}) .'</description>'."\n"; - - # language - if ($self->{channel}->{'dc'}->{'language'}) { - $output .= '<language>'. $self->encode($self->{channel}->{'dc'}->{'language'}) .'</language>'."\n"; - } elsif ($self->{channel}->{language}) { - $output .= '<language>'. $self->encode($self->{channel}->{language}).'</language>'."\n"; - } - - # PICS rating - $output .= '<rating>'. $self->encode($self->{channel}->{rating}) .'</rating>'."\n" - if $self->{channel}->{rating}; - - # copyright - if ($self->{channel}->{'dc'}->{'rights'}) { - $output .= '<copyright>'. $self->encode($self->{channel}->{'dc'}->{'rights'}) .'</copyright>'."\n"; - } elsif ($self->{channel}->{copyright}) { - $output .= '<copyright>'. $self->encode($self->{channel}->{copyright}) .'</copyright>'."\n"; - } - - # publication date - if ($self->{channel}->{pubDate}) { - $output .= '<pubDate>'. $self->encode($self->{channel}->{pubDate}) .'</pubDate>'."\n"; - } elsif ($self->{channel}->{'dc'}->{'date'}) { - $output .= '<pubDate>'. $self->encode($self->{channel}->{'dc'}->{'date'}) .'</pubDate>'."\n"; - } - - # last build date - if ($self->{channel}->{lastBuildDate}) { - $output .= '<lastBuildDate>'. $self->encode($self->{channel}->{lastBuildDate}) .'</lastBuildDate>'."\n"; - } elsif ($self->{channel}->{'dc'}->{'date'}) { - $output .= '<lastBuildDate>'. $self->encode($self->{channel}->{'dc'}->{'date'}) .'</lastBuildDate>'."\n"; - } - - # external CDF URL - $output .= '<docs>'. $self->encode($self->{channel}->{docs}) .'</docs>'."\n" - if $self->{channel}->{docs}; - - # managing editor - if ($self->{channel}->{'dc'}->{'publisher'}) { - $output .= '<managingEditor>'. $self->encode($self->{channel}->{'dc'}->{'publisher'}) .'</managingEditor>'."\n"; - } elsif ($self->{channel}->{managingEditor}) { - $output .= '<managingEditor>'. $self->encode($self->{channel}->{managingEditor}) .'</managingEditor>'."\n"; - } - - # webmaster - if ($self->{channel}->{'dc'}->{'creator'}) { - $output .= '<webMaster>'. $self->encode($self->{channel}->{'dc'}->{'creator'}) .'</webMaster>'."\n"; - } elsif ($self->{channel}->{webMaster}) { - $output .= '<webMaster>'. $self->encode($self->{channel}->{webMaster}) .'</webMaster>'."\n"; - } - - $output .= "\n"; - - ################# - # image element # - ################# - if ($self->{image}->{url}) { - $output .= '<image>'."\n"; - - # title - $output .= '<title>'. $self->encode($self->{image}->{title}) .'</title>'."\n"; - - # url - $output .= '<url>'. $self->encode($self->{image}->{url}) .'</url>'."\n"; - - # link - $output .= '<link>'. $self->encode($self->{image}->{'link'}) .'</link>'."\n" - if $self->{image}->{link}; - - # image width - $output .= '<width>'. $self->encode($self->{image}->{width}) .'</width>'."\n" - if $self->{image}->{width}; - - # image height - $output .= '<height>'. $self->encode($self->{image}->{height}) .'</height>'."\n" - if $self->{image}->{height}; - - # description - $output .= '<description>'. $self->encode($self->{image}->{description}) .'</description>'."\n" - if $self->{image}->{description}; - - # end image element - $output .= '</image>'."\n\n"; - } - - ################ - # item element # - ################ - foreach my $item (@{$self->{items}}) { - if ($item->{title}) { - $output .= '<item>'."\n"; - $output .= '<title>'. $self->encode($item->{title}) .'</title>'."\n"; - $output .= '<link>'. $self->encode($item->{'link'}) .'</link>'."\n"; - - $output .= '<description>'. $self->encode($item->{description}) .'</description>'."\n" - if $item->{description}; - - # end image element - $output .= '</item>'."\n\n"; - } - } - - ##################### - # textinput element # - ##################### - if ($self->{textinput}->{'link'}) { - $output .= '<textinput>'."\n"; - $output .= '<title>'. $self->encode($self->{textinput}->{title}) .'</title>'."\n"; - $output .= '<description>'. $self->encode($self->{textinput}->{description}) .'</description>'."\n"; - $output .= '<name>'. $self->encode($self->{textinput}->{name}) .'</name>'."\n"; - $output .= '<link>'. $self->encode($self->{textinput}->{'link'}) .'</link>'."\n"; - $output .= '</textinput>'."\n\n"; - } - - ##################### - # skipHours element # - ##################### - if ($self->{skipHours}->{hour}) { - $output .= '<skipHours>'."\n"; - $output .= '<hour>'. $self->encode($self->{skipHours}->{hour}) .'</hour>'."\n"; - $output .= '</skipHours>'."\n\n"; - } - - #################### - # skipDays element # - #################### - if ($self->{skipDays}->{day}) { - $output .= '<skipDays>'."\n"; - $output .= '<day>'. $self->encode($self->{skipDays}->{day}) .'</day>'."\n"; - $output .= '</skipDays>'."\n\n"; - } - - # end channel element - $output .= '</channel>'."\n"; - $output .= '</rss>'; - - return $output; -} - -sub as_rss_1_0 { - my $self = shift; - my $output; - - # XML declaration - $output .= '<?xml version="1.0" encoding="'.$self->{encoding}.'"?>'."\n\n"; - - # RDF namespaces declaration - $output .="<rdf:RDF"."\n"; - $output .=' xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"'."\n"; - $output .=' xmlns="http://purl.org/rss/1.0/"'."\n"; - - # print all imported namespaces - while (my($k, $v) = each %{$self->{modules}}) { - $output.=" xmlns:$v=\"$k\"\n"; - } - - $output .=">"."\n\n"; - - ################### - # Channel Element # - ################### - unless ( defined($self->{channel}->{'about'}) ) { - $output .= '<channel rdf:about="'. $self->encode($self->{channel}->{'link'}) .'">'."\n"; - } else { - $output .= '<channel rdf:about="'. $self->encode($self->{channel}->{'about'}) .'">'."\n"; - } - # title - $output .= '<title>'. $self->encode($self->{channel}->{title}) .'</title>'."\n"; - - # link - $output .= '<link>'. $self->encode($self->{channel}->{'link'}) .'</link>'."\n"; - - # description - $output .= '<description>'. $self->encode($self->{channel}->{description}) .'</description>'."\n"; - - # additional elements for RSS 0.91 - # language - if ($self->{channel}->{'dc'}->{'language'}) { - $output .= '<dc:language>'. $self->encode($self->{channel}->{'dc'}->{'language'}) .'</dc:language>'."\n"; - } elsif ($self->{channel}->{language}) { - $output .= '<dc:language>'. $self->encode($self->{channel}->{language}) .'</dc:language>'."\n"; - } - - # PICS rating - Dublin Core has not decided how to incorporate PICS ratings yet - #$$output .= '<rss091:rating>'.$self->{channel}->{rating}.'</rss091:rating>'."\n" - #$if $self->{channel}->{rating}; - - # copyright - if ($self->{channel}->{'dc'}->{'rights'}) { - $output .= '<dc:rights>'. $self->encode($self->{channel}->{'dc'}->{'rights'}) .'</dc:rights>'."\n"; - } elsif ($self->{channel}->{copyright}) { - $output .= '<dc:rights>'. $self->encode($self->{channel}->{copyright}) .'</dc:rights>'."\n"; - } - - # publication date - if ($self->{channel}->{'dc'}->{'date'}) { - $output .= '<dc:date>'. $self->encode($self->{channel}->{'dc'}->{'date'}) .'</dc:date>'."\n"; - } elsif ($self->{channel}->{pubDate}) { - $output .= '<dc:date>'. $self->encode($self->{channel}->{pubDate}) .'</dc:date>'."\n"; - } elsif ($self->{channel}->{lastBuildDate}) { - $output .= '<dc:date>'. $self->encode($self->{channel}->{lastBuildDate}) .'</dc:date>'."\n"; - } - - # external CDF URL - #$output .= '<rss091:docs>'.$self->{channel}->{docs}.'</rss091:docs>'."\n" - #if $self->{channel}->{docs}; - - # managing editor - if ($self->{channel}->{'dc'}->{'publisher'}) { - $output .= '<dc:publisher>'. $self->encode($self->{channel}->{'dc'}->{'publisher'}) .'</dc:publisher>'."\n"; - } elsif ($self->{channel}->{managingEditor}) { - $output .= '<dc:publisher>'. $self->encode($self->{channel}->{managingEditor}) .'</dc:publisher>'."\n"; - } - - # webmaster - if ($self->{channel}->{'dc'}->{'creator'}) { - $output .= '<dc:creator>'. $self->encode($self->{channel}->{'dc'}->{'creator'}) .'</dc:creator>'."\n"; - } elsif ($self->{channel}->{webMaster}) { - $output .= '<dc:creator>'. $self->encode($self->{channel}->{webMaster}) .'</dc:creator>'."\n"; - } - - # Dublin Core module - foreach my $dc ( keys %dc_ok_fields ) { - next if ($dc eq 'language' - || $dc eq 'creator' - || $dc eq 'publisher' - || $dc eq 'rights' - || $dc eq 'date'); - $self->{channel}->{dc}->{$dc} and $output .= "<dc:$dc>". $self->encode($self->{channel}->{dc}->{$dc}) ."</dc:$dc>\n"; - } - - # Syndication module - foreach my $syn ( keys %syn_ok_fields ) { - $self->{channel}->{syn}->{$syn} and $output .= "<syn:$syn>". $self->encode($self->{channel}->{syn}->{$syn}) ."</syn:$syn>\n"; - } - - # Taxonomy module - if (exists($self->{'channel'}->{'taxo'}) && $self->{'channel'}->{'taxo'}) { - $output .= "<taxo:topics>\n <rdf:Bag>\n"; - foreach my $taxo (@{$self->{'channel'}->{'taxo'}}) { - $output.= " <rdf:li resource=\"" . $self->encode($taxo) . "\" />\n"; - } - $output .= " </rdf:Bag>\n</taxo:topics>\n"; - } - - # Ad-hoc modules - while ( my($url, $prefix) = each %{$self->{modules}} ) { - next if $prefix =~ /^(dc|syn|taxo)$/; - while ( my($el, $value) = each %{$self->{channel}->{$prefix}} ) { - if ( exists( $rdf_resource_fields{ $url } ) and - exists( $rdf_resource_fields{ $url }{ $el }) ) - { - $output .= qq!<$prefix:$el rdf:resource="! . - $self->encode($value) . - qq!" />\n!; - } - else { - $output .= "<$prefix:$el>". $self->encode($value) ."</$prefix:$el>\n"; - } - } - } - - # Seq items - $output .= "<items>\n <rdf:Seq>\n"; - - foreach my $item (@{$self->{items}}) { - my $about = ( defined($item->{'about'}) ) ? $item->{'about'} : $item->{'link'}; - $output .= ' <rdf:li rdf:resource="'. $self->encode($about) .'" />'."\n"; - } - - $output .= " </rdf:Seq>\n</items>\n"; - - $self->{image}->{url} and - $output .= '<image rdf:resource="'. $self->encode($self->{image}->{url}) .'" />'."\n"; - - $self->{textinput}->{'link'} and - $output .= '<textinput rdf:resource="'. $self->encode($self->{textinput}->{'link'}) .'" />'."\n"; - - # end channel element - $output .= '</channel>'."\n\n"; - - ################# - # image element # - ################# - if ($self->{image}->{url}) { - $output .= '<image rdf:about="'. $self->encode($self->{image}->{url}) .'">'."\n"; - - # title - $output .= '<title>'. $self->encode($self->{image}->{title}) .'</title>'."\n"; - - # url - $output .= '<url>'. $self->encode($self->{image}->{url}) .'</url>'."\n"; - - # link - $output .= '<link>'. $self->encode($self->{image}->{'link'}) .'</link>'."\n" - if $self->{image}->{link}; - - # image width - #$output .= '<rss091:width>'.$self->{image}->{width}.'</rss091:width>'."\n" - # if $self->{image}->{width}; - - # image height - #$output .= '<rss091:height>'.$self->{image}->{height}.'</rss091:height>'."\n" - # if $self->{image}->{height}; - - # description - #$output .= '<rss091:description>'.$self->{image}->{description}.'</rss091:description>'."\n" - # if $self->{image}->{description}; - - # Dublin Core Modules - foreach my $dc ( keys %dc_ok_fields ) { - $self->{image}->{dc}->{$dc} and - $output .= "<dc:$dc>". $self->encode($self->{image}->{dc}->{$dc}) ."</dc:$dc>\n"; - } - - # Ad-hoc modules for images - while ( my($url, $prefix) = each %{$self->{modules}} ) { - next if $prefix =~ /^(dc|syn|taxo)$/; - while ( my($el, $value) = each %{$self->{image}->{$prefix}} ) { - if ( exists( $rdf_resource_fields{ $url } ) and - exists( $rdf_resource_fields{ $url }{ $el }) ) - { - $output .= qq!<$prefix:$el rdf:resource="! . - $self->encode($value) . - qq!" />\n!; - } - else { - $output .= "<$prefix:$el>". $self->encode($value) ."</$prefix:$el>\n"; - } - } - } - # end image element - $output .= '</image>'."\n\n"; - } # end if ($self->{image}->{url}) { - - ################ - # item element # - ################ - foreach my $item (@{$self->{items}}) { - if ($item->{title}) { - my $about = ( defined($item->{'about'}) ) ? $item->{'about'} : $item->{'link'}; - $output .= '<item rdf:about="'. $self->encode($about) .'"'; - $output .= ">\n"; - $output .= '<title>'. $self->encode($item->{title}) .'</title>'."\n"; - $output .= '<link>'. $self->encode($item->{'link'}) .'</link>'."\n"; - $item->{description} and $output .= '<description>'. $self->encode($item->{description}) .'</description>'."\n"; - - # Dublin Core module - foreach my $dc ( keys %dc_ok_fields ) { - $item->{dc}->{$dc} and $output .= "<dc:$dc>". $self->encode($item->{dc}->{$dc}) ."</dc:$dc>\n"; - } - - # Taxonomy module - if (exists($item->{'taxo'}) && $item->{'taxo'}) { - $output .= "<taxo:topics>\n <rdf:Bag>\n"; - foreach my $taxo (@{$item->{'taxo'}}) { - $output.= " <rdf:li resource=\"$taxo\" />\n"; - } - $output .= " </rdf:Bag>\n</taxo:topics>\n"; - } - - # Ad-hoc modules - while ( my($url, $prefix) = each %{$self->{modules}} ) { - next if $prefix =~ /^(dc|syn|taxo)$/; - while ( my($el, $value) = each %{$item->{$prefix}} ) { - if ( exists( $rdf_resource_fields{ $url } ) and - exists( $rdf_resource_fields{ $url }{ $el }) ) - { - $output .= qq!<$prefix:$el rdf:resource="! . - $self->encode($value) . - qq!" />\n!; - } - else { - $output .= "<$prefix:$el>". $self->encode($value) ."</$prefix:$el>\n"; - } - } - } - # end item element - $output .= '</item>'."\n\n"; - } - } # end foreach my $item (@{$self->{items}}) { - - ##################### - # textinput element # - ##################### - if ($self->{textinput}->{'link'}) { - $output .= '<textinput rdf:about="'. $self->encode($self->{textinput}->{'link'}) .'">'."\n"; - $output .= '<title>'. $self->encode($self->{textinput}->{title}) .'</title>'."\n"; - $output .= '<description>'. $self->encode($self->{textinput}->{description}) .'</description>'."\n"; - $output .= '<name>'. $self->encode($self->{textinput}->{name}) .'</name>'."\n"; - $output .= '<link>'. $self->encode($self->{textinput}->{'link'}) .'</link>'."\n"; - - # Dublin Core module - foreach my $dc ( keys %dc_ok_fields ) { - $self->{textinput}->{dc}->{$dc} - and $output .= "<dc:$dc>". $self->encode($self->{textinput}->{dc}->{$dc}) ."</dc:$dc>\n"; - } - - # Ad-hoc modules - while ( my($url, $prefix) = each %{$self->{modules}} ) { - next if $prefix =~ /^(dc|syn|taxo)$/; - while ( my($el, $value) = each %{$self->{textinput}->{$prefix}} ) { - $output .= "<$prefix:$el>". $self->encode($value) ."</$prefix:$el>\n"; - } - } - - $output .= '</textinput>'."\n\n"; - } - - $output .= '</rdf:RDF>'; -} - -sub as_rss_2_0 { - my $self = shift; - my $output; - - # XML declaration - $output .= '<?xml version="1.0" encoding="'.$self->{encoding}.'"?>'."\n\n"; - - # DOCTYPE - # $output .= '<!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN"'."\n"; - # $output .= ' "http://my.netscape.com/publish/formats/rss-0.91.dtd">'."\n\n"; - - # RSS root element - # $output .= '<rss version="0.91">'."\n\n"; - $output .= '<rss version="2.0" xmlns:blogChannel="http://backend.userland.com/blogChannelModule">' . "\n\n"; - - ################### - # Channel Element # - ################### - $output .= '<channel>'."\n"; - $output .= '<title>'.$self->encode($self->{channel}->{title}).'</title>'."\n"; - $output .= '<link>'.$self->encode($self->{channel}->{'link'}).'</link>'."\n"; - $output .= '<description>'.$self->encode($self->{channel}->{description}).'</description>'."\n"; - - # language - if ($self->{channel}->{'dc'}->{'language'}) { - $output .= '<language>'.$self->encode($self->{channel}->{'dc'}->{'language'}).'</language>'."\n"; - } elsif ($self->{channel}->{language}) { - $output .= '<language>'.$self->encode($self->{channel}->{language}).'</language>'."\n"; - } - - # PICS rating - # Not supported by RSS 2.0 - # $output .= '<rating>'.$self->{channel}->{rating}.'</rating>'."\n" - # if $self->{channel}->{rating}; - - # copyright - if ($self->{channel}->{'dc'}->{'rights'}) { - $output .= '<copyright>'.$self->encode($self->{channel}->{'dc'}->{'rights'}).'</copyright>'."\n"; - } elsif ($self->{channel}->{copyright}) { - $output .= '<copyright>'.$self->encode($self->{channel}->{copyright}).'</copyright>'."\n"; - } - - # publication date - if ($self->{channel}->{pubDate}) { - $output .= '<pubDate>'.$self->encode($self->{channel}->{pubDate}).'</pubDate>'."\n"; - } elsif ($self->{channel}->{'dc'}->{'date'}) { - $output .= '<pubDate>'.$self->encode($self->{channel}->{'dc'}->{'date'}).'</pubDate>'."\n"; - } - - # last build date - if ($self->{channel}->{'dc'}->{'date'}) { - $output .= '<lastBuildDate>'.$self->encode($self->{channel}->{'dc'}->{lastBuildDate}).'</lastBuildDate>'."\n"; - } elsif ($self->{channel}->{lastBuildDate}) { - $output .= '<lastBuildDate>'.$self->encode($self->{channel}->{lastBuildDate}).'</lastBuildDate>'."\n"; - } - - # external CDF URL - $output .= '<docs>'.$self->encode($self->{channel}->{docs}).'</docs>'."\n" - if $self->{channel}->{docs}; - - # managing editor - if ($self->{channel}->{'dc'}->{'publisher'}) { - $output .= '<managingEditor>'.$self->encode($self->{channel}->{'dc'}->{'publisher'}).'</managingEditor>'."\n"; - } elsif ($self->{channel}->{managingEditor}) { - $output .= '<managingEditor>'.$self->encode($self->{channel}->{managingEditor}).'</managingEditor>'."\n"; - } - - # webmaster - if ($self->{channel}->{'dc'}->{'creator'}) { - $output .= '<webMaster>'.$self->encode($self->{channel}->{'dc'}->{'creator'}).'</webMaster>'."\n"; - } elsif ($self->{channel}->{webMaster}) { - $output .= '<webMaster>'.$self->encode($self->{channel}->{webMaster}).'</webMaster>'."\n"; - } - - # category - if ($self->{channel}->{'dc'}->{'category'}) { - $output .= '<category>'.$self->encode($self->{channel}->{'dc'}->{'category'}).'</category>'."\n"; - } elsif ($self->{channel}->{category}) { - $output .= '<category>'.$self->encode($self->{channel}->{generator}).'</category>'."\n"; - } - - # generator - if ($self->{channel}->{'dc'}->{'generator'}) { - $output .= '<generator>'.$self->encode($self->{channel}->{'dc'}->{'generator'}).'</generator>'."\n"; - } elsif ($self->{channel}->{generator}) { - $output .= '<generator>'.$self->encode($self->{channel}->{generator}).'</generator>'."\n"; - } - - # Insert cloud support here - - # ttl - if ($self->{channel}->{'dc'}->{'ttl'}) { - $output .= '<ttl>'.$self->encode($self->{channel}->{'dc'}->{'ttl'}).'</ttl>'."\n"; - } elsif ($self->{channel}->{ttl}) { - $output .= '<ttl>'.$self->encode($self->{channel}->{ttl}).'</ttl>'."\n"; - } - - - - $output .= "\n"; - - ################# - # image element # - ################# - if ($self->{image}->{url}) { - $output .= '<image>'."\n"; - - # title - $output .= '<title>'.$self->encode($self->{image}->{title}).'</title>'."\n"; - - # url - $output .= '<url>'.$self->encode($self->{image}->{url}).'</url>'."\n"; - - # link - $output .= '<link>'.$self->encode($self->{image}->{'link'}).'</link>'."\n" - if $self->{image}->{link}; - - # image width - $output .= '<width>'.$self->encode($self->{image}->{width}).'</width>'."\n" - if $self->{image}->{width}; - - # image height - $output .= '<height>'.$self->encode($self->{image}->{height}).'</height>'."\n" - if $self->{image}->{height}; - - # description - $output .= '<description>'.$self->encode($self->{image}->{description}).'</description>'."\n" - if $self->{image}->{description}; - - # end image element - $output .= '</image>'."\n\n"; - } - - ################ - # item element # - ################ - foreach my $item (@{$self->{items}}) { - if ($item->{title}) { - $output .= '<item>'."\n"; - $output .= '<title>'.$self->encode($item->{title}).'</title>'."\n" - if $item->{title}; - $output .= '<link>'.$self->encode($item->{'link'}).'</link>'."\n" - if $item->{link}; - $output .= '<description>'.$self->encode($item->{description}).'</description>'."\n" - if $item->{description}; - - $output .= '<author>'.$self->encode($item->{author}).'</author>'."\n" - if $item->{author}; - - $output .= '<category>'.$self->encode($item->{category}).'</category>'."\n" - if $item->{category}; - - $output .= '<comments>'.$self->encode($item->{comments}).'</comments>'."\n" - if $item->{comments}; - - # The unique identifier. Use 'permaLink' for an external - # identifier, or 'guid' for a internal string. - # (I call it permaLink in the hash for purposes of clarity.) - if ($item->{permaLink}) - { - $output .= '<guid isPermaLink="true">'.$self->encode($item->{permaLink}).'</guid>'."\n"; - } - elsif ($item->{guid}) - { - $output .= '<guid isPermaLink="false">'.$self->encode($item->{guid}).'</guid>'."\n"; - } - - $output .= '<pubDate>'.$self->encode($item->{pubDate}).'</pubDate>'."\n" - if $item->{pubDate}; - - $output .= '<source url="'.$self->encode($item->{sourceUrl}).'">'.$item->{source}.'</source>'."\n" - if $item->{source} && $item->{sourceUrl}; - - if (my $e = $item->{enclosure}) - { - $output .= "<enclosure " - . join(' ', map {qq!$_="! . $self->encode($e->{$_}) . qq!"!} keys(%$e)) - . ' />' . "\n"; - } - - # end image element - $output .= '</item>'."\n\n"; - } - } - - ##################### - # textinput element # - ##################### - if ($self->{textinput}->{'link'}) { - $output .= '<textInput>'."\n"; - $output .= '<title>'.$self->encode($self->{textinput}->{title}).'</title>'."\n"; - $output .= '<description>'.$self->encode($self->{textinput}->{description}).'</description>'."\n"; - $output .= '<name>'.$self->encode($self->{textinput}->{name}).'</name>'."\n"; - $output .= '<link>'.$self->encode($self->{textinput}->{'link'}).'</link>'."\n"; - $output .= '</textInput>'."\n\n"; - } - - ##################### - # skipHours element # - ##################### - if ($self->{skipHours}->{hour}) { - $output .= '<skipHours>'."\n"; - $output .= '<hour>'.$self->encode($self->{skipHours}->{hour}).'</hour>'."\n"; - $output .= '</skipHours>'."\n\n"; - } - - #################### - # skipDays element # - #################### - if ($self->{skipDays}->{day}) { - $output .= '<skipDays>'."\n"; - $output .= '<day>'.$self->encode($self->{skipDays}->{day}).'</day>'."\n"; - $output .= '</skipDays>'."\n\n"; - } - - # end channel element - $output .= '</channel>'."\n"; - $output .= '</rss>'; - - return $output; -} - -sub as_string { - my $self = shift; - my $version = ($self->{output} =~ /\d/) ? $self->{output} : $self->{version}; - my $output; - - ########### - # RSS 0.9 # - ########### - if ($version eq '0.9') { - $output = &as_rss_0_9($self); - - ############ - # RSS 0.91 # - ############ - } elsif ($version eq '0.91') { - $output = &as_rss_0_9_1($self); - - ########### - # RSS 2.0 # - ########### - } elsif ($version eq '2.0') { - $output = &as_rss_2_0($self); - - ########### - # RSS 1.0 # - ########### - } else { - $output = &as_rss_1_0($self); - } - - return $output; -} - -sub handle_char { - # removed assumption that RSS is the default namespace - kellan, 11/5/02 - - my ($self,$cdata) = (@_); - - # image element - if ( - $self->within_element("image") || - $self->within_element($self->generate_ns_name("image",$self->{rss_namespace})) - ) { - my $ns = $self->namespace($self->current_element); - # If it's in the default namespace - if ( - (!$ns && !$self->{rss_namespace}) || - ($ns eq $self->{rss_namespace}) - ) { - $self->{'image'}->{$self->current_element} .= $cdata; - } - else { - # If it's in another namespace - $self->{'image'}->{$ns}->{$self->current_element} .= $cdata; - - # If it's in a module namespace, provide a friendlier prefix duplicate - $modules->{$ns} and $self->{'image'}->{$modules->{$ns}}->{$self->current_element} .= $cdata; - } - - # item element - } - elsif ( - $self->within_element("item") - || $self->within_element($self->generate_ns_name("item",$self->{rss_namespace})) - - ) { - return if $self->within_element($self->generate_ns_name("topics",'http://purl.org/rss/1.0/modules/taxonomy/')); - - my $ns = $self->namespace($self->current_element); - - # If it's in the default RSS 1.0 namespace - if ( - (!$ns && !$self->{rss_namespace}) || - ($ns eq $self->{rss_namespace}) - ) { - $self->{'items'}->[$self->{num_items}-1]->{$self->current_element} .= $cdata; - } else { - # If it's in another namespace - $self->{'items'}->[$self->{num_items}-1]->{$ns}->{$self->current_element} .= $cdata; - - # If it's in a module namespace, provide a friendlier prefix duplicate - $modules->{$ns} and - $self->{'items'}->[$self->{num_items}-1]->{$modules->{$ns}}->{$self->current_element} .= $cdata; - } - - # textinput element - } elsif ( - $self->within_element("textinput") - || $self->within_element($self->generate_ns_name("textinput",$self->{rss_namespace})) - ) { - my $ns = $self->namespace($self->current_element); - - # If it's in the default namespace - if ( - (!$ns && !$self->{rss_namespace}) || - ($ns eq $self->{rss_namespace}) - ) { - $self->{'textinput'}->{$self->current_element} .= $cdata; - } - else { - # If it's in another namespace - $self->{'textinput'}->{$ns}->{$self->current_element} .= $cdata; - - # If it's in a module namespace, provide a friendlier prefix duplicate - $modules->{$ns} and $self->{'textinput'}->{$modules->{$ns}}->{$self->current_element} .= $cdata; - } - - # skipHours element - } elsif ( - $self->within_element("skipHours") || - $self->within_element($self->generate_ns_name("skipHours",$self->{rss_namespace})) - ) { - $self->{'skipHours'}->{$self->current_element} .= $cdata; - - # skipDays element - } elsif ( - $self->within_element("skipDays") || - $self->within_element($self->generate_ns_name("skipDays",$self->{rss_namespace})) - ) { - $self->{'skipDays'}->{$self->current_element} .= $cdata; - - # channel element - } elsif ( - $self->within_element("channel") || - $self->within_element($self->generate_ns_name("channel",$self->{rss_namespace})) - ) { - return if $self->within_element($self->generate_ns_name("topics",'http://purl.org/rss/1.0/modules/taxonomy/')); - - my $ns = $self->namespace($self->current_element); - - # If it's in the default namespace - if ( - (!$ns && !$self->{rss_namespace}) || - ($ns eq $self->{rss_namespace}) - ) { - $self->{'channel'}->{$self->current_element} .= $cdata; - } else { - # If it's in another namespace - $self->{'channel'}->{$ns}->{$self->current_element} .= $cdata; - - # If it's in a module namespace, provide a friendlier prefix duplicate - $modules->{$ns} and $self->{'channel'}->{$modules->{$ns}}->{$self->current_element} .= $cdata; - } - } -} - -sub handle_dec { - my ($self,$version,$encoding,$standalone) = (@_); - $self->{encoding} = $encoding; - #print "ENCODING: $encoding\n"; -} - -sub handle_start { - my $self = shift; - my $el = shift; - my %attribs = @_; - - # beginning of RSS 0.91 - if ($el eq 'rss') { - if (exists($attribs{version})) { - $self->{_internal}->{version} = $attribs{version}; - } else { - croak "Malformed RSS: invalid version\n"; - } - - # beginning of RSS 1.0 or RSS 0.9 - } elsif ($el eq 'RDF') { - my @prefixes = $self->new_ns_prefixes; - foreach my $prefix (@prefixes) { - my $uri = $self->expand_ns_prefix($prefix); - $self->{namespaces}->{$prefix} = $uri; - #print "$prefix = $uri\n"; - } - - # removed assumption that RSS is the default namespace - kellan, 11/5/02 - # - foreach my $uri ( values %{ $self->{namespaces} } ) { - if ( $namespace_map->{'rss10'} eq $uri ) { - $self->{_internal}->{version} = '1.0'; - $self->{rss_namespace} = $uri; - last; - } - elsif ( $namespace_map->{'rss09'} eq $uri ) { - $self->{_internal}->{version} = '0.9'; - $self->{rss_namespace} = $uri; - last; - } - } - - # failed to match a namespace - if ( !defined($self->{_internal}->{version}) ) { - croak "Malformed RSS: invalid version\n" - } - #if ($self->expand_ns_prefix('#default') =~ /\/1.0\//) { - # $self->{_internal}->{version} = '1.0'; - #} elsif ($self->expand_ns_prefix('#default') =~ /\/0.9\//) { - # $self->{_internal}->{version} = '0.9'; - #} else { - # croak "Malformed RSS: invalid version\n"; - #} - - # beginning of item element - } elsif ($el eq 'item') { - # deal with trouble makers who use mod_content :) - my $ns = $self->namespace( $el ); - - if ( - (!$ns && !$self->{rss_namespace}) || - ($ns eq $self->{rss_namespace}) - ) { - # increment item count - $self->{num_items}++; - } - # beginning of taxo li element in item element - #'http://purl.org/rss/1.0/modules/taxonomy/' => 'taxo' - } elsif ($self->within_element($self->generate_ns_name("topics",'http://purl.org/rss/1.0/modules/taxonomy/')) - && $self->within_element($self->generate_ns_name("item",$self->{namespace_map}->{'rss10'})) - && $self->current_element eq 'Bag' - && $el eq 'li') { - #print "taxo: ", $attribs{'resource'},"\n"; - push(@{$self->{'items'}->[$self->{num_items}-1]->{'taxo'}},$attribs{'resource'}); - $self->{'modules'}->{'http://purl.org/rss/1.0/modules/taxonomy/'} = 'taxo'; - - # beginning of taxo li in channel element - } elsif ($self->within_element($self->generate_ns_name("topics",'http://purl.org/rss/1.0/modules/taxonomy/')) - && $self->within_element($self->generate_ns_name("channel",$self->{namespace_map}->{'rss10'})) - && $self->current_element eq 'Bag' - && $el eq 'li') { - push(@{$self->{'channel'}->{'taxo'}},$attribs{'resource'}); - $self->{'modules'}->{'http://purl.org/rss/1.0/modules/taxonomy/'} = 'taxo'; - } - # beginning of a channel element that stores its info in rdf:resource - elsif ( $self->namespace($el) and - exists( $rdf_resource_fields{ $self->namespace($el) } ) and - exists( $rdf_resource_fields{ $self->namespace($el) }{ $el } ) and - $self->current_element eq 'channel' ) - { - my $ns = $self->namespace( $el ); - - if ( $ns eq $self->{rss_namespace} ) { - $self->{channel}->{$el} = $attribs{resource}; - } - else { - $self->{channel}->{$ns}->{$el} = $attribs{resource}; - # add short cut - # - if ( exists( $modules->{ $ns } ) ) { - $ns = $modules->{ $ns }; - $self->{channel}->{$ns}->{$el} = $attribs{resource}; - } - } - } - # beginning of an item element that stores its info in rdf:resource - elsif ( $self->namespace($el) and - exists( $rdf_resource_fields{ $self->namespace($el) } ) and - exists( $rdf_resource_fields{ $self->namespace($el) }{ $el } ) and - $self->current_element eq 'item' ) - { - my $ns = $self->namespace( $el ); - - if ( $ns eq $self->{rss_namespace} ) { - $self->{'items'}->[$self->{num_items}-1]->{ $el } = $attribs{resource}; - } else { - $self->{'items'}->[$self->{num_items}-1]->{$ns}->{ $el } = $attribs{resource}; - - # add short cut - # - if ( exists( $modules->{ $ns } ) ) { - $ns = $modules->{ $ns }; - $self->{'items'}->[$self->{num_items}-1]->{$ns}->{ $el } = $attribs{resource}; - } - } - } -} - -sub append { - my($self, $inside, $cdata) = @_; - - my $ns = $self->namespace($self->current_element); - - # If it's in the default RSS 1.0 namespace - if ($ns eq 'http://purl.org/rss/1.0/') { - #$self->{'items'}->[$self->{num_items}-1]->{$self->current_element} .= $cdata; - $inside->{$self->current_element} .= $cdata; - } - - # If it's in another namespace - #$self->{'items'}->[$self->{num_items}-1]->{$ns}->{$self->current_element} .= $cdata; - $inside->{$ns}->{$self->current_element} .= $cdata; - - # If it's in a module namespace, provide a friendlier prefix duplicate - #$modules->{$ns} and $self->{'items'}->[$self->{num_items}-1]->{$modules->{$ns}}->{$self->current_element} .= $cdata; - $modules->{$ns} and $inside->{$modules->{$ns}}->{$self->current_element} .= $cdata; - - return $inside; -} - -sub _auto_add_modules { - my $self = shift; - - for my $ns (keys %{$self->{namespaces}}) { - # skip default namespaces - next if $ns eq "rdf" || $ns eq "#default" - || exists $self->{modules}{ $self->{namespaces}{$ns} }; - $self->add_module(prefix => $ns, uri => $self->{namespaces}{$ns}) - } - - $self; -} - -sub parse { - my $self = shift; - $self->_initialize((%$self)); - $self->SUPER::parse(shift); - $self->_auto_add_modules if $AUTO_ADD; - $self->{version} = $self->{_internal}->{version}; -} - -sub parsefile { - my $self = shift; - $self->_initialize((%$self)); - $self->SUPER::parsefile(shift); - $self->_auto_add_modules if $AUTO_ADD; - $self->{version} = $self->{_internal}->{version}; -} - -sub save { - my ($self,$file) = @_; - open(OUT,">$file") || croak "Cannot open file $file for write: $!"; - print OUT $self->as_string; - close OUT; -} - -sub strict { - my ($self,$value) = @_; - $self->{'strict'} = $value; -} - -sub AUTOLOAD { - my $self = shift; - my $type = ref($self) || croak "$self is not an object\n"; - my $name = $AUTOLOAD; - $name =~ s/.*://; - return if $name eq 'DESTROY'; - - croak "Unregistered entity: Can't access $name field in object of class $type" - unless (exists $self->{$name}); - - # return reference to RSS structure - if (@_ == 1) { - return $self->{$name}->{$_[0]} if defined $self->{$name}->{$_[0]}; - - # we're going to set values here - } elsif (@_ > 1) { - my %hash = @_; - my $_REQ; - - # make sure we have required elements and correct lengths - if ($self->{'strict'}) { - ($self->{version} eq '0.9') - ? ($_REQ = $_REQ_v0_9) - : ($_REQ = $_REQ_v0_9_1); - } - - # store data in object - foreach my $key (keys(%hash)) { - if ($self->{'strict'}) { - my $req_element = $_REQ->{$name}->{$key}; - confess "$key cannot exceed " . $req_element->[1] . " characters in length" - if defined $req_element->[1] && length($hash{$key}) > $req_element->[1]; - } - $self->{$name}->{$key} = $hash{$key}; - } - - # return value - return $self->{$name}; - - # otherwise, just return a reference to the whole thing - } else { - return $self->{$name}; - } - return 0; - - # make sure we have all required elements - #foreach my $key (keys(%{$_REQ->{$name}})) { - #my $element = $_REQ->{$name}->{$key}; - #croak "$key is required in $name" - #if ($element->[0] == 1) && (!defined($hash{$key})); - #croak "$key cannot exceed ".$element->[1]." characters in length" - #unless length($hash{$key}) <= $element->[1]; - #} -} - -# the code here is a minorly tweaked version of code from -# Matts' rssmirror.pl script -# -my %entity = ( - nbsp => " ", - iexcl => "¡", - cent => "¢", - pound => "£", - curren => "¤", - yen => "¥", - brvbar => "¦", - sect => "§", - uml => "¨", - copy => "©", - ordf => "ª", - laquo => "«", - not => "¬", - shy => "­", - reg => "®", - macr => "¯", - deg => "°", - plusmn => "±", - sup2 => "²", - sup3 => "³", - acute => "´", - micro => "µ", - para => "¶", - middot => "·", - cedil => "¸", - sup1 => "¹", - ordm => "º", - raquo => "»", - frac14 => "¼", - frac12 => "½", - frac34 => "¾", - iquest => "¿", - Agrave => "À", - Aacute => "Á", - Acirc => "Â", - Atilde => "Ã", - Auml => "Ä", - Aring => "Å", - AElig => "Æ", - Ccedil => "Ç", - Egrave => "È", - Eacute => "É", - Ecirc => "Ê", - Euml => "Ë", - Igrave => "Ì", - Iacute => "Í", - Icirc => "Î", - Iuml => "Ï", - ETH => "Ð", - Ntilde => "Ñ", - Ograve => "Ò", - Oacute => "Ó", - Ocirc => "Ô", - Otilde => "Õ", - Ouml => "Ö", - times => "×", - Oslash => "Ø", - Ugrave => "Ù", - Uacute => "Ú", - Ucirc => "Û", - Uuml => "Ü", - Yacute => "Ý", - THORN => "Þ", - szlig => "ß", - agrave => "à", - aacute => "á", - acirc => "â", - atilde => "ã", - auml => "ä", - aring => "å", - aelig => "æ", - ccedil => "ç", - egrave => "è", - eacute => "é", - ecirc => "ê", - euml => "ë", - igrave => "ì", - iacute => "í", - icirc => "î", - iuml => "ï", - eth => "ð", - ntilde => "ñ", - ograve => "ò", - oacute => "ó", - ocirc => "ô", - otilde => "õ", - ouml => "ö", - divide => "÷", - oslash => "ø", - ugrave => "ù", - uacute => "ú", - ucirc => "û", - uuml => "ü", - yacute => "ý", - thorn => "þ", - yuml => "ÿ", - ); - -my $entities = join('|', keys %entity); - -sub encode { - my ($self, $text) = @_; - return $text unless $self->{'encode_output'}; - - my $encoded_text = ''; - - while ( $text =~ s/(.*?)(\<\!\[CDATA\[.*?\]\]\>)//s ) { - $encoded_text .= encode_text($1) . $2; - } - $encoded_text .= encode_text($text); - - return $encoded_text; -} - -sub encode_text { - my $text = shift; - - $text =~ s/&(?!(#[0-9]+|#x[0-9a-fA-F]+|\w+);)/&/g; - $text =~ s/&($entities);/$entity{$1}/g; - $text =~ s/</</g; - - return $text; -} - -1; -__END__ - -=head1 NAME - -XML::RSS - creates and updates RSS files - -=head1 SYNOPSIS - - # create an RSS 1.0 file (http://purl.org/rss/1.0/) - use XML::RSS; - my $rss = new XML::RSS (version => '1.0'); - $rss->channel( - title => "freshmeat.net", - link => "http://freshmeat.net", - description => "the one-stop-shop for all your Linux software needs", - dc => { - date => '2000-08-23T07:00+00:00', - subject => "Linux Software", - creator => 'scoop****@fresh*****', - publisher => 'scoop****@fresh*****', - rights => 'Copyright 1999, Freshmeat.net', - language => 'en-us', - }, - syn => { - updatePeriod => "hourly", - updateFrequency => "1", - updateBase => "1901-01-01T00:00+00:00", - }, - taxo => [ - 'http://dmoz.org/Computers/Internet', - 'http://dmoz.org/Computers/PC' - ] - ); - - $rss->image( - title => "freshmeat.net", - url => "http://freshmeat.net/images/fm.mini.jpg", - link => "http://freshmeat.net", - dc => { - creator => "G. Raphics (graph****@fresh*****)", - }, - ); - - $rss->add_item( - title => "GTKeyboard 0.85", - link => "http://freshmeat.net/news/1999/06/21/930003829.html", - description => "GTKeyboard is a graphical keyboard that ...", - dc => { - subject => "X11/Utilities", - creator => "David Allen (s2mda****@titan*****)", - }, - taxo => [ - 'http://dmoz.org/Computers/Internet', - 'http://dmoz.org/Computers/PC' - ] - ); - - $rss->textinput( - title => "quick finder", - description => "Use the text input below to search freshmeat", - name => "query", - link => "http://core.freshmeat.net/search.php3", - ); - - # Optionally mixing in elements of a non-standard module/namespace - - $rss->add_module(prefix=>'my', uri=>'http://purl.org/my/rss/module/'); - - $rss->add_item( - title => "xIrc 2.4pre2", - link => "http://freshmeat.net/projects/xirc/", - description => "xIrc is an X11-based IRC client which ...", - my => { - rating => "A+", - category => "X11/IRC", - }, - ); - - $rss->add_item (title=>$title, link=>$link, slash=>{ topic=>$topic }); - - # create an RSS 2.0 file - use XML::RSS; - my $rss = new XML::RSS (version => '2.0'); - $rss->channel(title => 'freshmeat.net', - link => 'http://freshmeat.net', - language => 'en', - description => 'the one-stop-shop for all your Linux software needs', - rating => '(PICS-1.1 "http://www.classify.org/safesurf/" 1 r (SS~~000 1))', - copyright => 'Copyright 1999, Freshmeat.net', - pubDate => 'Thu, 23 Aug 1999 07:00:00 GMT', - lastBuildDate => 'Thu, 23 Aug 1999 16:20:26 GMT', - docs => 'http://www.blahblah.org/fm.cdf', - managingEditor => 'scoop****@fresh*****', - webMaster => 'scoop****@fresh*****' - ); - - $rss->image(title => 'freshmeat.net', - url => 'http://freshmeat.net/images/fm.mini.jpg', - link => 'http://freshmeat.net', - width => 88, - height => 31, - description => 'This is the Freshmeat image stupid' - ); - - $rss->add_item(title => "GTKeyboard 0.85", - # creates a guid field with permaLink=true - permaLink => "http://freshmeat.net/news/1999/06/21/930003829.html", - # alternately creates a guid field with permaLink=false - # guid => "gtkeyboard-0.85 - enclosure => { url=>$url, type=>"application/x-bittorrent" }, - description => 'blah blah' -); - - $rss->textinput(title => "quick finder", - description => "Use the text input below to search freshmeat", - name => "query", - link => "http://core.freshmeat.net/search.php3" - ); - - # create an RSS 0.9 file - use XML::RSS; - my $rss = new XML::RSS (version => '0.9'); - $rss->channel(title => "freshmeat.net", - link => "http://freshmeat.net", - description => "the one-stop-shop for all your Linux software needs", - ); - - $rss->image(title => "freshmeat.net", - url => "http://freshmeat.net/images/fm.mini.jpg", - link => "http://freshmeat.net" - ); - - $rss->add_item(title => "GTKeyboard 0.85", - link => "http://freshmeat.net/news/1999/06/21/930003829.html" - ); - - $rss->textinput(title => "quick finder", - description => "Use the text input below to search freshmeat", - name => "query", - link => "http://core.freshmeat.net/search.php3" - ); - - # print the RSS as a string - print $rss->as_string; - - # or save it to a file - $rss->save("fm.rdf"); - - # insert an item into an RSS file and removes the oldest item if - # there are already 15 items - my $rss = new XML::RSS; - $rss->parsefile("fm.rdf"); - pop(@{$rss->{'items'}}) if (@{$rss->{'items'}} == 15); - $rss->add_item(title => "MpegTV Player (mtv) 1.0.9.7", - link => "http://freshmeat.net/news/1999/06/21/930003958.html", - mode => 'insert' - ); - - # parse a string instead of a file - $rss->parse($string); - - # print the title and link of each RSS item - foreach my $item (@{$rss->{'items'}}) { - print "title: $item->{'title'}\n"; - print "link: $item->{'link'}\n\n"; - } - - # output the RSS 0.9 or 0.91 file as RSS 1.0 - $rss->{output} = '1.0'; - print $rss->as_string; - -=head1 DESCRIPTION - -This module provides a basic framework for creating and maintaining -RDF Site Summary (RSS) files. This distribution also contains many -examples that allow you to generate HTML from an RSS, convert between -0.9, 0.91, and 1.0 version, and other nifty things. -This might be helpful if you want to include news feeds on your Web -site from sources like Slashot and Freshmeat or if you want to syndicate -your own content. - -XML::RSS currently supports 0.9, 0.91, and 1.0 versions of RSS. -See http://my.netscape.com/publish/help/mnn20/quickstart.html -for information on RSS 0.91. See http://my.netscape.com/publish/help/ -for RSS 0.9. See http://purl.org/rss/1.0/ for RSS 1.0. - -RSS was originally developed by Netscape as the format for -Netscape Netcenter channels, however, many Web sites have since -adopted it as a simple syndication format. With the advent of RSS 1.0, -users are now able to syndication many different kinds of content -including news headlines, threaded measages, products catalogs, etc. - -=head1 METHODS - -=over 4 - -=item new XML::RSS (version=>$version, encoding=>$encoding, -output=>$output) - -Constructor for XML::RSS. It returns a reference to an XML::RSS object. -You may also pass the RSS version and the XML encoding to use. The default -B<version> is 1.0. The default B<encoding> is UTF-8. You may also specify -the B<output> format regarless of the input version. This comes in handy -when you want to convert RSS between versions. The XML::RSS modules -will convert between any of the formats. If you set <encode_output> XML::RSS -will make sure to encode any entities in generated RSS. This is now on by default. - -=item add_item (title=>$title, link=>$link, description=>$desc, mode=>$mode) - -Adds an item to the XML::RSS object. B<mode> and B<description> are optional. -The default B<mode> -is append, which adds the item to the end of the list. To insert an item, set the mode -to B<insert>. - -The items are stored in the array @{$obj->{'items'}} where -B<$obj> is a reference to an XML::RSS object. - -=item as_string; - -Returns a string containing the RSS for the XML::RSS object. This -method will also encode special characters along the way. - -=item channel (title=>$title, link=>$link, description=>$desc, -language=>$language, rating=>$rating, copyright=>$copyright, -pubDate=>$pubDate, lastBuildDate=>$lastBuild, docs=>$docs, -managingEditor=>$editor, webMaster=>$webMaster) - - -Channel information is required in RSS. The B<title> cannot -be more the 40 characters, the B<link> 500, and the B<description> -500 when outputting RSS 0.9. B<title>, B<link>, and B<description>, -are required for RSS 1.0. B<language> is required for RSS 0.91. -The other parameters are optional for RSS 0.91 and 1.0. - -To retreive the values of the channel, pass the name of the value -(title, link, or description) as the first and only argument -like so: - -$title = channel('title'); - -=item image (title=>$title, url=>$url, link=>$link, width=>$width, -height=>$height, description=>$desc) - -Adding an image is not required. B<url> is the URL of the -image, B<link> is the URL the image is linked to. B<title>, B<url>, -and B<link> parameters are required if you are going to -use an image in your RSS file. The remaining image elements are used -in RSS 0.91 or optionally imported into RSS 1.0 via the rss091 namespace. - -The method for retrieving the values for the image is the same as it -is for B<channel()>. - -=item parse ($string) - -Parses an RDF Site Summary which is passed into B<parse()> as the first parameter. - -See the add_module() method for instructions on automatically adding -modules as a string is parsed. - -=item parsefile ($file) - -Same as B<parse()> except it parses a file rather than a string. - -See the add_module() method for instructions on automatically adding -modules as a string is parsed. - -=item save ($file) - -Saves the RSS to a specified file. - -=item strict ($boolean) - -If it's set to 1, it will adhere to the lengths as specified -by Netscape Netcenter requirements. It's set to 0 by default. -Use it if the RSS file you're generating is for Netcenter. -strict will only work for RSS 0.9 and 0.91. Do not use it for -RSS 1.0. - -=item textinput (title=>$title, description=>$desc, name=>$name, link=>$link); - -This RSS element is also optional. Using it allows users to submit a Query -to a program on a Web server via an HTML form. B<name> is the HTML form name -and B<link> is the URL to the program. Content is submitted using the GET -method. - -Access to the B<textinput> values is the the same as B<channel()> and -B<image()>. - -=item add_module(prefix=>$prefix, uri=>$uri) - -Adds a module namespace declaration to the XML::RSS object, allowing you -to add modularity outside of the the standard RSS 1.0 modules. At present, -the standard modules Dublin Core (dc) and Syndication (syn) are predefined -for your convenience. The Taxonomy (taxo) module is also internally supported. - -The modules are stored in the hash %{$obj->{'modules'}} where -B<$obj> is a reference to an XML::RSS object. - -If you want to automatically add modules that the parser finds in -namespaces, set the $XML::RSS::AUTO_ADD variable to a true value. By -default the value is false. (N.B. AUTO_ADD only updates the -%{$obj->{'modules'}} hash. It does not provide the other benefits -of using add_module.) - - - -=back - -=head2 RSS 1.0 MODULES - -XML-Namespace-based modularization affords RSS 1.0 compartmentalized -extensibility. The only modules that ship "in the box" with RSS 1.0 -are Dublin Core (http://purl.org/rss/1.0/modules/dc/), Syndication -(http://purl.org/rss/1.0/modules/syndication/), and Taxonomy -(http://purl.org/rss/1.0/modules/taxonomy/). Consult the appropriate -module's documentation for further information. - -Adding items from these modules in XML::RSS is as simple as adding other -attributes such as title, link, and description. The only difference -is the compartmentalization of their key/value paris in a second-level -hash. - - $rss->add_item (title=>$title, link=>$link, dc=>{ subject=>$subject, creator=>$creator }); - -For elements of the Dublin Core module, use the key 'dc'. For elements -of the Syndication module, 'syn'. For elements of the Taxonomy module, -'taxo'. These are the prefixes used in the RSS XML document itself. -They are associated with appropriate URI-based namespaces: - - syn: http://purl.org/rss/1.0/modules/syndication/ - dc: http://purl.org/dc/elements/1.1/ - taxo: http://purl.org/rss/1.0/modules/taxonomy/ - -Dublin Core elements may occur in channel, image, item(s), and textinput --- albeit uncomming to find them under image and textinput. Syndication -elements are limited to the channel element. Taxonomy elements can occur -in the channel or item elements. - -Access to module elements after parsing an RSS 1.0 document using -XML::RSS is via either the prefix or namespace URI for your convenience. - - print $rss->{items}->[0]->{dc}->{subject}; - - or - - print $rss->{items}->[0]->{'http://purl.org/dc/elements/1.1/'}->{subject}; - -XML::RSS also has support for "non-standard" RSS 1.0 modularization at -the channel, image, item, and textinput levels. Parsing an RSS document -grabs any elements of other namespaces which might appear. XML::RSS -also allows the inclusion of arbitrary namespaces and associated elements -when building RSS documents. - -For example, to add elements of a made-up "My" module, first declare the -namespace by associating a prefix with a URI: - - $rss->add_module(prefix=>'my', uri=>'http://purl.org/my/rss/module/'); - -Then proceed as usual: - - $rss->add_item (title=>$title, link=>$link, my=>{ rating=>$rating }); - -Non-standard namespaces are not, however, currently accessible via a simple -prefix; access them via their namespace URL like so: - - print $rss->{items}->[0]->{'http://purl.org/my/rss/module/'}->{rating}; - -XML::RSS will continue to provide built-in support for standard RSS 1.0 -modules as they appear. - -=head1 SOURCE AVAILABILITY - -This source is part of a SourceForge project which always has the -latest sources in CVS, as well as all of the previous releases. - - https://sourceforge.net/projects/perl-rss/ - http://perl-rss.sourceforge.net - -If, for some reason, I disappear from the world, one of the other -members of the project can shepherd this module appropriately. - -=head1 AUTHOR - - Original code: Jonathan Eisenzopf <eisen****@pobox*****> - Further changes: Rael Dornfest <rael****@oreil*****> - - Currently: perl-rss project (http://perl-rss.sourceforge.net) - - -=head1 COPYRIGHT - -Copyright (c) 2001 Jonathan Eisenzopf <eisen****@pobox*****> -and Rael Dornfest <rael****@oreil*****> - -XML::RSS is free software. You can redistribute it and/or -modify it under the same terms as Perl itself. - -=head1 CREDITS - - Wojciech Zwiefka <wojte****@cnt*****> - Chris Nandor <pudge****@pobox*****> - Jim Hebert <jim****@cosou*****> - Randal Schwartz <merly****@stone*****> - rjp****@brows***** - Kellan <kella****@prote*****> - Rafe Colburn <rafe****@rafe*****> - Adam Trickett <adam.****@btint*****> - Aaron Straup Cope <asc****@viney*****> - Ian Davis <iand****@inter*****> - rayg****@varch***** - -=head1 SEE ALSO - -perl(1), XML::Parser(3). - -=cut