XML-RSS-1.65000755001750001750 014756547744 13066 5ustar00shlomifshlomif000000000000TODO100644001750001750 155014756547744 13640 0ustar00shlomifshlomif000000000000XML-RSS-1.65http://rt.cpan.org/Public/Dist/Display.html?Name=XML-RSS --- before the next release-ish - wrong handling enclosure subelement of item http://rt.cpan.org/Ticket/Display.html?id=21740 --- soon-ish - Make all the date/time interfaces accept and emit DateTime dates (maybe unix timestamps too?) instead of strings --- eventually - use a better / more liberal XML parser - fix skipHour and skipDay methods (bdf: what's wrong with them?) - rewrite for extendability (base class with a derived one for each version) - auto encode text? - Investigate parsing multiple dc:items into an array reference when inside other elements besides an : - http://rt.cpan.org/Public/Bug/Display.html?id=6000 - Add a way (and an option) to parse module items with duplicate keys into an array reference. - check more edge cases with other than elements. README100644001750001750 131714756547744 14031 0ustar00shlomifshlomif000000000000XML-RSS-1.65Copyright (c) 2001 Jonathan Eisenzopf and Rael Dornfest. Copyright (c) 2006-2007 Ask Bjoern Hansen, Develooper LLC. All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. This module was created to help those who need to manage RDF Site Summary (RSS) files. It makes quick work of creating, updating, and saving RSS files. perldoc lib/XML/RSS.pm https://metacpan.org/pod/XML::RSS for more details. REQUIREMENTS This module requires version 2.23 or greater of the XML::Parser module. The latest version is available at any CPAN archive. INSTALLATION perl Makefile.PL make make test # (optional) make install Changes100644001750001750 3565014756547744 14473 0ustar00shlomifshlomif000000000000XML-RSS-1.65Revision history for Perl module XML::RSS 1.65 2025-02-23 - Fix <*:guid> outside a feed's item element - https://github.com/shlomif/perl-XML-RSS/issues/24 - Thanks to @steve-piner 1.64 2024-10-16 - Avoid double $VERSION - https://github.com/shlomif/perl-XML-RSS/pull/23 - https://github.com/shlomif/perl-XML-RSS/issues/18 - Thanks to @yoshikazusawa - Thanks to @hvds 1.63 2023-12-26 - Add allow_empty . - https://github.com/shlomif/perl-XML-RSS/issues/20 - Thanks to @johnhorner . 1.62 2020-10-15 - dist.ini / weaver.ini / .tidyallrc / etc. cleanup - Move to @SHLOMIF - Inspired by Lady_Aleena. - Sympotamtic fix for item/link nested inside custom tags: - https://github.com/shlomif/perl-XML-RSS/issues/7 - Thanks to @jkramer for the bug report and a test case. 1.61 2019-08-24 - Clarified the docs regarding DateTime objects. - Thanks to shtrb - Add 2.0 to the version list, fix broken links to versions - Thanks to E. Choroba - Changed to explicit imports in "use" statements. 1.60 2018-04-03 - Convert to Dist-Zilla. - Add Travis-CI support. 1.59 2016-03-01 - Merge a pull request to add subcategory support. - https://github.com/shlomif/perl-XML-RSS/pull/4 - https://rt.cpan.org/Public/Bug/Display.html?id=48426 - Thanks to @ozcoder for the changes. 1.58 2016-02-08 - Merge a pull-request regarding the handling of isPermaLink: - https://github.com/shlomif/perl-XML-RSS/pull/2 - Thanks to @dwmc15873 for the changes. 1.57 2015-12-13 - Update an old E-mail address for Shlomi Fish. 1.56 2014-12-04 - Fix https://rt.cpan.org/Ticket/Display.html?id=100660 - XML External Entities Exploit, as reported here: - http://mikeknoop.com/lxml-xxe-exploit/ - Security. 1.55 2014-04-15 - Fix the tests for DateTime-Format-Mail-0.400. 1.54 2013-06-05 - Apply a patch from Debian for correcting a typo. - https://rt.cpan.org/Public/Bug/Display.html?id=85962 - Thanks to Gregor Herrmann 1.53 2013-06-04 - Implement a more user-friendly error with XML::RSS->new(version=>1.0) and a missing "link" and/or "title" field. - Thanks to Gabor Szabo for reporting it. 1.52 2013-05-21 - Add t/style-trailing-space.t. - Got rid of trailing space. - Convert to t/cpan-changes.t . 1.51 2013-05-11 - Sort the XML namespaces before outputting. - became broken in perl-5.18.0-RC1. 1.50 2013-04-07 - Update the repository URL to its new location on GitHub. 1.49 2011-04-07 - Some correctness and Modern Perl changes to the rss2html.pl script (it still appears to be very hairy.) - Add support for parsing rssCloud: - https://rt.cpan.org/Ticket/Display.html?id=67241 - Thanks to STUIFZAND for the patch. 1.48 2010-04-23 - Fix the $rss->parse($string)->other_method() display (had to add spaces between the << and >>). See: - https://rt.cpan.org/Public/Bug/Display.html?id=56848 - Thanks to Slaven_Rezic for the report. 1.47 2009-12-08 - Made sure XML::RSS::save() can do its thing when in taint mode: - http://rt.cpan.org/Public/Bug/Display.html?id=52334 1.46 2009-10-08 - Updated the E-mail address of Adam Trickett. - Removed the perl-5.6.x-specific workarounds and made perl-5.8.x as a requirement. This was done in order to: - avoid a workaround that also caused an incomplete test coverage. - avoid various test failures due to a problem with XML-Parser on 5.6.x . - encourage people using ancient versions of perl in production. - Convert all occurences of "new XML::RSS" to "XML::RSS->new()" everywhere. - a best practice. 1.45 2009-08-05 - Removed some unused module requirements statements from lib/**.pm. - Added a note about date parsing/generation (thanks to an email correspondent). - Applied a patch by "David White" to have uppercase letter in namespace/module identifiers. - https://rt.cpan.org/Ticket/Display.html?id=48405 - Added "resources" and "keywords" to the Build.PL. 1.44 2009-04-01 - Applied a patch from Simon Wistow (after some modifications) to add support for multiple enclosures. - Added the t/xml-base.t test file from Simon Wistow to test for xml:base. Corrected for style. 1.43 2009-01-12 - Fixed the date on the last entry on this changelog, to say "2009" instead of "2008". - http://rt.cpan.org/Ticket/Display.html?id=42304 1.42 2009-01-03 - When transforming elements with attributes into hash-refs - make sure they are placed in the correct namespace. Previously over-rided the plain . (as in Flickr). 1.41 2008-12-04 - Made the default keys for the channel link, description and title undef instead of ''. They become '' once they are opened. - http://rt.cpan.org/Public/Bug/Display.html?id=40686 - Now keeping track of rdf:resource of in RSS 1.0: - http://rt.cpan.org/Ticket/Display.html?id=3978 - Made sure that channel/{link,description,title} are localized to the empty string before rendering, to allow for better backwards compatibility. - http://rt.cpan.org/Public/Bug/Display.html?id=40686 1.40 2008-12-01 - Now outputting an arrayref of /'s and / properly. - http://rt.cpan.org/Public/Bug/Display.html?id=40978 - Now parsing multiple 'ies inside an into an array-reference. - http://rt.cpan.org/Ticket/Display.html?id=38296 - Now outputting an arayref of / prpoerly. - http://rt.cpan.org/Ticket/Display.html?id=38296 - Parsing multiple / into arrays. - http://rt.cpan.org/Public/Bug/Display.html?id=9729 - Rendering multiple / elements from array refs. - http://rt.cpan.org/Public/Bug/Display.html?id=9729 - Now parsing multiple dc:items into an array reference (at least inside an ): - http://rt.cpan.org/Public/Bug/Display.html?id=6000 - Added the modules_as_arrays option to parse repeatable module elements into an array ref. 1.38 2008-11-27 - Added support for duplicate items of RSS modules. - http://rt.cpan.org/Public/Bug/Display.html?id=4495 - Added support for multiple Dublin Core elements. One can point the field to an array and it will create multiple elements: - http://rt.cpan.org/Public/Bug/Display.html?id=6000 - Now parsing several /s and /s into an array reference instead of concatenating them together. - http://rt.cpan.org/Public/Bug/Display.html?id=40978 1.37 2008-11-18 - Extracted the common parts of parse() and parsefile() into one method (Refactoring - Shlomi Fish) - Incorporated a modified version of a patch from Simon Wistow to add support for the "xml:base" attribute. - Renamed t/items-are-0.t into the more descriptive t/test-generated-items.t , to highlight its significance and make it easier to notice. - Enabled backwards-compatibility mode for the "description" item to not become a hash-ref by default if xml:base is specified. 1.36 2008-10-07 - ->parse() now explicitly returns $self. - http://rt.cpan.org/Public/Bug/Display.html?id=34914 - ->parsefile() now explicitly returns $self. - http://rt.cpan.org/Public/Bug/Display.html?id=34914 - Applied a patch to change the RSS-0.91 DTD URL from my.netscape.com to rssboard.org: - http://rt.cpan.org/Ticket/Display.html?id=39780 - Reformatted the Changes file to standardize on 4-space-indents. - Small documentation patch: (add_item with dc:date) - http://rt.cpan.org/Ticket/Display.html?id=39780 1.35 2008-09-13 - Added a Module::Build-based Build.PL so we'll have an easier time with the META.yml and the Kwalitee. - Kwalitee - added "use warnings" to all Perl files. - now depending on at least perl-5.6.0. - Kwalitee - fixed the "use" statement of "Test::Run::CmdLine::Iface" to a runtime require. 1.34 2008-09-12 - fixed a typo in the documentation of lib/XML/RSS.pm - "regardless" instead of "regarless". - http://rt.cpan.org/Public/Bug/Display.html?id=37916 - (Reported by Reuben Thomas, Fixed by Shlomif). - fixed a code fragment - pop() instead of shift() for older items, and while() instead of if(): - http://rt.cpan.org/Public/Bug/Display.html?id=39231 - (Reported by Dave, Fixed by Shlomif). 1.33 2008-06-08 - Allowed the end-user to customise the _encode() routine in XML::RSS::Private::Output::Base from XML::RSS using the encode_cb key. 1.32 2008-02-08 - Fixed http://rt.cpan.org/Public/Bug/Display.html?id=25336 : - made sure the namespace specified elements can have a hash as a value in which case they'll be outputted as a standalone tag with attributes. - Fixed http://rt.cpan.org/Ticket/Display.html?id=25368 : - changed pop() to shift() to remove the oldest item in the example in lib/XML/RSS.pm, per the comments in the bug report. - Fixed http://rt.cpan.org/Ticket/Display.html?id=24329#txn-296761 : - updated the URLs for information about RSS mentioned under "=head1 DESCRIPTION", based on a Google search. - (Shlomi Fish) - Fixed http://rt.cpan.org/Ticket/Display.html?id=33001 : - made sure that isPermalink is true if and only if the isPermalink attribute is "true". Not if it is non-existent, etc. - this modified the behaviour of the module. 1.31 2007-06-29 - Fixed the save() function to handle perl-5.6.x (and possibly below) where the ":encoding(...)" filehandle are not available (Shlomi Fish) 1.30 2007-06-18 - Same as 1.29_02 (from February 23, 2007) - Removed some methods that were not used. - Added more tests to increase the test coverage. - Fixed a bug where prefixes could be specified with invalid characters because there was a range (.-_) instead of three individual characters (.\-_). - Many files were left in the distribution or Subversion repository that were executable but need not be. Made them non-executable. - Clean up examples/ directory and move generated files out of t/ - isPerCould not parse Line '1.04 - Web Mar 03 20:49:43 2004' at /home/shlomif/bin/upgrade-to-CPAN-Changes line 40, line 271. maLink / guid fixes (RT#23983, Shlomi) - increased the test coverage of XML::RSS up to 100%. (Shlomif) - SECURITY BUG FIX: eliminated a markup injection vulnerability in the taxo:topics output of RSS 1.0. (Shlomif) - Moved the append function, which is unused and cannot be effectively used, out of the main module and into the rejects directory inside the repository (but outside the module). (Shlomif) - Added POD for full POD coverage. (Shlomif) - Several other bug fixes. (Shlomif) - Heavy refactoring of the code. (Shlomif) - perltidy configuration file; run perltidy on XML::RSS (and intentionally not on the tests) (ABH). - Removed the remaining tab characters. (Shlomif) - Fixed a bug in one of the tests. (Shlomif) - Converted the rendering processes of the various RSS versions to one class per RSS version and applied the "Convert Conditionals to Polymorphism" refactoring. (Shlomif) - Removed the languages hash which was completely unused. (Shlomif) - Converted the parsing routines to be methods of XML::RSS to increase modularity. XML::RSS no longer inherits from XML::Parser. (Shlomif) - Extracted several methods from the parsing stage. (Shlomif) - Added a regression test to https://rt.cpan.org/Ticket/Display.html?id=24742 (Shlomif) - Tweaked the Makefile.PL Test::Run integration according to: http://www.nntp.perl.org/group/perl.qa/2006/11/msg7400.html (Shlomif) 1.22 2006-12-17 - Fix XML::Feed compatability. Make sure $item->{content} is always setup (broke in 1.20, RT#23822, Shlomi, Andreas J. Koenig) - Fix the tests to work on Win32 (RT#23752, Shlomi, Kenichi Ishigaki) - make add_module work for both RSS 1.0 and 2.0 (RT#16191, RT#18907, RT#13209, Ben Trott, Ivan Willis) - Fixed the problem with a version => "2.0" RSS not parsing correctly the namespaced elements in a RSS 1.0 feed (in RT#23822, Shlomi) - Channel->{link | textInput} (sic) property mapping in RSS 2.0 (RT#9862, Shlomi / chatiman) - Don't fail the tests if Test::Pod::Coverage is missing (reported by Andreas J. Koenig) 1.21 2006-12-05 - Support inserting a XSL stylesheet URL into the XML output (RT#11569, Jason A. Smith, Shlomi Fish) - Remove empty lines in the test_manifest - some versions of Test::Manifest doesn't do the right thing with those. (RT#23678, Hugo van der Sanden) - Add Pod::Coverage tests - More Date Conversion (Shlomi) - Fix for a Markup Injection Vulnerability (RT#23435, Shlomi) 1.20 2006-11-10 - Value for $XML::RSS::modules gets destroyed (RT#18755, Shlomi) - Note that YOU CAN NO LONGER USE $XML::RSS::modules, you have to use the add_modules call as documented! - encode generates warnings for undefined text (RT#13523, Mark Stosberg) - Missing last build date value in RSS 2.0 (RT#19417) - renamed the internal encode method to _encode - RSS 2.0 spec allows omission of title from entry (RT#18817, test from Shlomi) - Can't create "0" values in optional items (RT#11415, based on patch from Shlomi - thanks!) - Remove the executable bit from Makefile.PL - Add test to test regression of CPAN RT#5438 (Shlomi) - More tests... 1.12 2006-10-25 - Add more tests - make sure META.yml is correctly generated - Fix enclosure parsing (RT#7920, Tatsuhiko Miyagawa) - Incorrect entity encoding in XML output (RT#22467, reported by Stephen Hall) 1.11 2006-10-19 - use HTML::Entities instead of the "homegrown" entity encoding code - Minor doc fix (David Steinbrunner) - Fix encoding of the > char, added tests (RT#19420, Shlomi Fish) - XML::RSS ignores output encoding (RT#11124, RT#7343, test failures on win32, Vaclav Haisman, Steve Peters) - encoding of source element (RT#2285) - use base instead of @ISA - Thanks to Shlomi Fish for helping sorting through the RT queue! 1.10 2006-03-11 - Module (for now) maintained by Ask Bjoern Hansen - Fixed category output in RSS 2.0 (RT#17303, Yasuhiro Onishi) - Update documentation with new Subversion server and bug tracking - Clean up distribution (tests, Makefile.PL, file locations, ...) 1.05 2004-08-12 - fixed version number - improved RSS 2.0 generation support - typo and documentation fixes LICENSE100644001750001750 5013114756547744 14174 0ustar00shlomifshlomif000000000000XML-RSS-1.65Terms of Perl itself a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or b) the "Artistic License" ---------------------------------------------------------------------------- GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS ---------------------------------------------------------------------------- The Artistic License Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: - "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. - "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder. - "Copyright Holder" is whoever is named in the copyright or copyrights for the package. - "You" is you, if you're thinking about copying or distributing this Package. - "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) - "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as ftp.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) accompany any non-standard executables with their corresponding Standard Version executables, giving the non-standard executables non-standard names, and clearly documenting the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this Package. 7. C or perl subroutines supplied by you and linked into this Package shall not be considered part of this Package. 8. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End dist.ini100644001750001750 67014756547744 14576 0ustar00shlomifshlomif000000000000XML-RSS-1.65name = XML-RSS author = Shlomi Fish license = Perl_5 copyright_holder = Various copyright_year = 2001 version = 1.65 [@Filter] -bundle = @SHLOMIF -remove = License -remove = Readme dist = XML-RSS github_name = perl-XML-RSS [Keywords] keyword = feed keyword = feeds keyword = generate keyword = generating keyword = parse keyword = parsing keyword = rss keyword = RSS keyword = web-feed keyword = web-feeds keyword = xml t000755001750001750 014756547744 13252 5ustar00shlomifshlomif000000000000XML-RSS-1.65load.t100644001750001750 73114756547744 14477 0ustar00shlomifshlomif000000000000XML-RSS-1.65/tBEGIN { use File::Find; @files = (); my $lib = 'lib'; $lib = 'blib/lib' if -e 'blib/lib'; find(sub { push @files, $File::Find::name if $_ =~ m/\.pm$/;}, ($lib)); @classes = map { my $x = $_; $x =~ s|^blib/lib/||; $x =~ s|/|::|g; $x =~ s|\.pm$||; $x; } @files; } use Test::More tests => scalar @classes; foreach my $class ( @classes ){ print "bail out! $class did not compile" unless use_ok( $class ); } guid.t100644001750001750 341714756547744 14534 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t# This is to test the following bug: # https://rt.cpan.org/Ticket/Display.html?id=24742 use strict; use warnings; use Test::More tests => 1; use XML::RSS; { my $rss_text = qq( Example 2.0 Channel http://example.com/ To lead by example en-us All content Public Domain, except comments which remains copyright the author editor\@example.com webmaster\@example.com http://backend.userland.com/rss Reference/Libraries/Library_and_Information_Science/Technical_Services/Cataloguing/Metadata/RDF/Applications/RSS/ The Superest Dooperest RSS Generator Mon, 02 Sep 2002 03:19:17 GMT 60 News for September the Second http://example.com/2002/09/02 other things happened today http://example.com/2002/09/02/comments.html joeuser\@example.com Mon, 02 Sep 2002 03:19:00 GMT http://example.com/2002/09/02 ); my $xml = XML::RSS->new(); $xml->parse($rss_text); # TEST ok ( (index($xml->as_string(), q{http://example.com/2002/09/02}) >= 0), "Checking for correct guid" ); } META.yml100644001750001750 3045714756547744 14451 0ustar00shlomifshlomif000000000000XML-RSS-1.65--- abstract: 'creates and updates RSS files' author: - 'Shlomi Fish ' build_requires: File::Find: '0' File::Spec: '0' IO::Handle: '0' IPC::Open3: '0' Module::Build: '0.28' POSIX: '0' Test::More: '0.88' constant: '0' configure_requires: ExtUtils::MakeMaker: '0' Module::Build: '0.28' dynamic_config: 0 generated_by: 'Dist::Zilla version 6.032, CPAN::Meta::Converter version 2.150010' keywords: - feed - feeds - generate - generating - parse - parsing - rss - RSS - web-feed - web-feeds - xml license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: XML-RSS provides: XML::RSS: file: lib/XML/RSS.pm version: '1.65' XML::RSS::Private::Output::Base: file: lib/XML/RSS/Private/Output/Base.pm version: '1.65' XML::RSS::Private::Output::Roles::ImageDims: file: lib/XML/RSS/Private/Output/Roles/ImageDims.pm version: '1.65' XML::RSS::Private::Output::Roles::ModulesElems: file: lib/XML/RSS/Private/Output/Roles/ModulesElems.pm version: '1.65' XML::RSS::Private::Output::V0_9: file: lib/XML/RSS/Private/Output/V0_9.pm version: '1.65' XML::RSS::Private::Output::V0_91: file: lib/XML/RSS/Private/Output/V0_91.pm version: '1.65' XML::RSS::Private::Output::V1_0: file: lib/XML/RSS/Private/Output/V1_0.pm version: '1.65' XML::RSS::Private::Output::V2_0: file: lib/XML/RSS/Private/Output/V2_0.pm version: '1.65' requires: Carp: '0' DateTime::Format::Mail: '0' DateTime::Format::W3CDTF: '0' HTML::Entities: '0' XML::Parser: '0' perl: '5.008' strict: '0' vars: '0' warnings: '0' resources: bugtracker: https://github.com/shlomif/perl-XML-RSS/issues homepage: http://metacpan.org/release/XML-RSS repository: git://github.com/shlomif/perl-XML-RSS.git version: '1.65' x_Dist_Zilla: perl: version: '5.040001' plugins: - class: Dist::Zilla::Plugin::Prereqs config: Dist::Zilla::Plugin::Prereqs: phase: test type: requires name: '@Filter/TestMoreDoneTesting' version: '6.032' - class: Dist::Zilla::Plugin::AutoPrereqs name: '@Filter/AutoPrereqs' version: '6.032' - class: Dist::Zilla::Plugin::ExecDir name: '@Filter/ExecDir' version: '6.032' - class: Dist::Zilla::Plugin::GatherDir config: Dist::Zilla::Plugin::GatherDir: exclude_filename: [] exclude_match: [] follow_symlinks: 0 include_dotfiles: 0 prefix: '' prune_directory: [] root: . name: '@Filter/GatherDir' version: '6.032' - class: Dist::Zilla::Plugin::ManifestSkip name: '@Filter/ManifestSkip' version: '6.032' - class: Dist::Zilla::Plugin::MetaYAML name: '@Filter/MetaYAML' version: '6.032' - class: Dist::Zilla::Plugin::PruneCruft name: '@Filter/PruneCruft' version: '6.032' - class: Dist::Zilla::Plugin::RunExtraTests config: Dist::Zilla::Role::TestRunner: default_jobs: 1 name: '@Filter/RunExtraTests' version: '0.029' - class: Dist::Zilla::Plugin::ShareDir name: '@Filter/ShareDir' version: '6.032' - class: Dist::Zilla::Plugin::MakeMaker config: Dist::Zilla::Role::TestRunner: default_jobs: 1 name: '@Filter/MakeMaker' version: '6.032' - class: Dist::Zilla::Plugin::CheckChangesHasContent name: '@Filter/CheckChangesHasContent' version: '0.011' - class: Dist::Zilla::Plugin::ConfirmRelease name: '@Filter/ConfirmRelease' version: '6.032' - class: Dist::Zilla::Plugin::Manifest name: '@Filter/Manifest' version: '6.032' - class: Dist::Zilla::Plugin::MetaConfig name: '@Filter/MetaConfig' version: '6.032' - class: Dist::Zilla::Plugin::MetaJSON name: '@Filter/MetaJSON' version: '6.032' - class: Dist::Zilla::Plugin::MetaProvides::Package config: Dist::Zilla::Plugin::MetaProvides::Package: finder_objects: - class: Dist::Zilla::Plugin::FinderCode name: '@Filter/MetaProvides::Package/AUTOVIV/:InstallModulesPM' version: '6.032' include_underscores: 0 Dist::Zilla::Role::MetaProvider::Provider: $Dist::Zilla::Role::MetaProvider::Provider::VERSION: '2.002004' inherit_missing: 1 inherit_version: 1 meta_noindex: 1 Dist::Zilla::Role::ModuleMetadata: Module::Metadata: '1.000038' version: '0.006' name: '@Filter/MetaProvides::Package' version: '2.004003' - class: Dist::Zilla::Plugin::MetaResources name: '@Filter/MetaResources' version: '6.032' - class: Dist::Zilla::Plugin::ModuleBuild config: Dist::Zilla::Role::TestRunner: default_jobs: 1 name: '@Filter/ModuleBuild' version: '6.032' - class: Dist::Zilla::Plugin::PkgVersion name: '@Filter/PkgVersion' version: '6.032' - class: Dist::Zilla::Plugin::PodCoverageTests name: '@Filter/PodCoverageTests' version: '6.032' - class: Dist::Zilla::Plugin::PodSyntaxTests name: '@Filter/PodSyntaxTests' version: '6.032' - class: Dist::Zilla::Plugin::Test::Compile config: Dist::Zilla::Plugin::Test::Compile: bail_out_on_fail: 0 fail_on_warning: author fake_home: 0 filename: t/00-compile.t module_finder: - ':InstallModules' needs_display: 0 phase: test script_finder: - ':PerlExecFiles' skips: [] switch: [] name: '@Filter/Test::Compile' version: '2.058' - class: Dist::Zilla::Plugin::Test::CPAN::Changes config: Dist::Zilla::Plugin::Test::CPAN::Changes: changelog: Changes filename: xt/release/cpan-changes.t name: '@Filter/Test::CPAN::Changes' version: '0.013' - class: Dist::Zilla::Plugin::Test::EOL config: Dist::Zilla::Plugin::Test::EOL: filename: xt/author/eol.t finder: - ':ExecFiles' - ':InstallModules' - ':TestFiles' trailing_whitespace: 1 name: '@Filter/Test::EOL' version: '0.19' - class: Dist::Zilla::Plugin::Test::NoTabs config: Dist::Zilla::Plugin::Test::NoTabs: filename: xt/author/no-tabs.t finder: - ':InstallModules' - ':ExecFiles' - ':TestFiles' name: '@Filter/Test::NoTabs' version: '0.15' - class: Dist::Zilla::Plugin::Test::TrailingSpace name: '@Filter/Test::TrailingSpace' version: ~ - class: Dist::Zilla::Plugin::TestRelease name: '@Filter/TestRelease' version: '6.032' - class: Dist::Zilla::Plugin::PodWeaver config: Dist::Zilla::Plugin::PodWeaver: finder: - ':InstallModules' - ':PerlExecFiles' plugins: - class: Pod::Weaver::Plugin::SingleEncoding name: '@SHLOMIF/SingleEncoding' version: '4.020' - class: Pod::Weaver::Plugin::WikiDoc name: '@SHLOMIF/WikiDoc' version: '0.093004' - class: Pod::Weaver::Plugin::EnsurePod5 name: '@CorePrep/EnsurePod5' version: '4.020' - class: Pod::Weaver::Plugin::H1Nester name: '@CorePrep/H1Nester' version: '4.020' - class: Pod::Weaver::Section::Generic name: '@SHLOMIF/Name' version: '4.020' - class: Pod::Weaver::Section::Version name: '@SHLOMIF/Version' version: '4.020' - class: Pod::Weaver::Section::Region name: '@SHLOMIF/Prelude' version: '4.020' - class: Pod::Weaver::Section::Generic name: '@SHLOMIF/Synopsis' version: '4.020' - class: Pod::Weaver::Section::Generic name: '@SHLOMIF/Description' version: '4.020' - class: Pod::Weaver::Section::Generic name: '@SHLOMIF/Usage' version: '4.020' - class: Pod::Weaver::Section::Generic name: '@SHLOMIF/Overview' version: '4.020' - class: Pod::Weaver::Section::Generic name: '@SHLOMIF/Stability' version: '4.020' - class: Pod::Weaver::Section::Collect name: Requirements version: '4.020' - class: Pod::Weaver::Section::Collect name: Attributes version: '4.020' - class: Pod::Weaver::Section::Collect name: Constructors version: '4.020' - class: Pod::Weaver::Section::Collect name: Methods version: '4.020' - class: Pod::Weaver::Section::Collect name: Functions version: '4.020' - class: Pod::Weaver::Section::Leftovers name: '@SHLOMIF/Leftovers' version: '4.020' - class: Pod::Weaver::Section::Region name: '@SHLOMIF/postlude' version: '4.020' - class: Pod::Weaver::Section::Support name: '@SHLOMIF/Support' version: '1.014' - class: Pod::Weaver::Section::Authors name: '@SHLOMIF/Authors' version: '4.020' - class: Pod::Weaver::Section::Bugs name: '@SHLOMIF/Bugs' version: '4.020' - class: Pod::Weaver::Section::Contributors name: '@SHLOMIF/Contributors' version: '0.009' - class: Pod::Weaver::Section::Legal name: '@SHLOMIF/Legal' version: '4.020' - class: Pod::Weaver::Plugin::Transformer name: '@SHLOMIF/List' version: '4.020' name: '@Filter/PodWeaver' version: '4.010' - class: Dist::Zilla::Plugin::UploadToCPAN name: '@Filter/UploadToCPAN' version: '6.032' - class: Dist::Zilla::Plugin::Keywords config: Dist::Zilla::Plugin::Keywords: keywords: - feed - feeds - generate - generating - parse - parsing - rss - RSS - web-feed - web-feeds - xml name: Keywords version: '0.007' - class: Dist::Zilla::Plugin::FinderCode name: ':InstallModules' version: '6.032' - class: Dist::Zilla::Plugin::FinderCode name: ':IncModules' version: '6.032' - class: Dist::Zilla::Plugin::FinderCode name: ':TestFiles' version: '6.032' - class: Dist::Zilla::Plugin::FinderCode name: ':ExtraTestFiles' version: '6.032' - class: Dist::Zilla::Plugin::FinderCode name: ':ExecFiles' version: '6.032' - class: Dist::Zilla::Plugin::FinderCode name: ':PerlExecFiles' version: '6.032' - class: Dist::Zilla::Plugin::FinderCode name: ':ShareFiles' version: '6.032' - class: Dist::Zilla::Plugin::FinderCode name: ':MainModule' version: '6.032' - class: Dist::Zilla::Plugin::FinderCode name: ':AllFiles' version: '6.032' - class: Dist::Zilla::Plugin::FinderCode name: ':NoFiles' version: '6.032' - class: Dist::Zilla::Plugin::FinderCode name: '@Filter/MetaProvides::Package/AUTOVIV/:InstallModulesPM' version: '6.032' zilla: class: Dist::Zilla::Dist::Builder config: is_trial: 0 version: '6.032' x_generated_by_perl: v5.40.1 x_serialization_backend: 'YAML::Tiny version 1.74' x_spdx_expression: 'Artistic-1.0-Perl OR GPL-1.0-or-later' MANIFEST100644001750001750 461014756547744 14301 0ustar00shlomifshlomif000000000000XML-RSS-1.65# This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.032. Build.PL Changes LICENSE MANIFEST MANIFEST.SKIP META.json META.yml Makefile.PL README TODO dist.ini examples/0.9/create_rss.pl examples/0.9/linuxtoday.rdf examples/0.9/rss-0.9.dtd examples/0.9/slashdot.rdf examples/0.91/create_rss_0.91.pl examples/0.91/create_rss_0.91_full.pl examples/0.91/fm.rdf examples/0.91/fm0.91.rdf examples/0.91/fm0.91_full.rdf examples/0.91/rss-0.91.dtd examples/0.91/xmlnews.rdf examples/1.0/create_rss_1.0.pl examples/1.0/rss1.0.rdf examples/1.0/slash.rdf examples/1.0/update_rss_1.0.pl examples/2.0/flickr-rss-with-both-desc-and-media-desc.xml examples/2.0/rss-2.0-sample-from-rssboard-multiple-skip-days-and-hours.xml examples/README examples/convert.pl examples/create_rss_multiple.pl examples/rss2html.pl examples/rss_info.pl examples/update_rss.pl keep-out/rejects/append.pl keep-out/rejects/languages.pm keep-out/rejects/old_rss_versions_ok_fields.pm keep-out/scripts/code-gen/gen-pod-for-as_rss.pl lib/XML/RSS.pm lib/XML/RSS/Private/Output/Base.pm lib/XML/RSS/Private/Output/Roles/ImageDims.pm lib/XML/RSS/Private/Output/Roles/ModulesElems.pm lib/XML/RSS/Private/Output/V0_9.pm lib/XML/RSS/Private/Output/V0_91.pm lib/XML/RSS/Private/Output/V1_0.pm lib/XML/RSS/Private/Output/V2_0.pm t/0.9-generate.t t/0.9-parse.t t/0.9-strict.t t/0.91-parse.t t/00-compile.t t/1.0-gen-errors-on-missing-fields.t t/1.0-generate.t t/1.0-parse-2.t t/1.0-parse-exotic.t t/1.0-parse.t t/1.0-to-2.0.t t/2.0-generate.t t/2.0-modules.t t/2.0-parse-2.t t/2.0-parse-cloud.t t/2.0-parse-self.t t/2.0-parse.t t/2.0-permalink.t t/2.0-wo-title.t t/add-item-insert-vs-append.t t/auto_add_modules.t t/charset1.t t/data/1.0/rss1.0.exotic.rdf t/data/1.0/with_content.rdf t/data/2.0/empty-desc.rss t/data/2.0/no-desc.rss t/data/2.0/sf-hs-with-lastBuildDate.rss t/data/2.0/sf-hs-with-pubDate.rss t/data/freshmeat.rdf t/data/merlyn1.rss t/data/rss-permalink.xml t/empty-elements.t t/enclosures-multi.t t/enclosures.t t/enclosures2.t t/encode-output.t t/encoding.t t/generated/placeholder.txt t/guid-outside-item.t t/guid.t t/load.t t/render-upon-init.t t/rss2-gt-encoding.t t/rss2-nested-custom-tag.t t/save-while-in-taint-mode.t t/subcategory.t t/test-generated-items.t t/version.t t/xml-base.t t/xml-header.t weaver.ini xt/author/eol.t xt/author/no-tabs.t xt/author/pod-coverage.t xt/author/pod-syntax.t xt/release/cpan-changes.t xt/release/trailing-space.t Build.PL100644001750001750 267414756547744 14454 0ustar00shlomifshlomif000000000000XML-RSS-1.65 # This file was automatically generated by Dist::Zilla::Plugin::ModuleBuild v6.032. use strict; use warnings; use Module::Build 0.28; my %module_build_args = ( "build_requires" => { "Module::Build" => "0.28" }, "configure_requires" => { "ExtUtils::MakeMaker" => 0, "Module::Build" => "0.28" }, "dist_abstract" => "creates and updates RSS files", "dist_author" => [ "Shlomi Fish " ], "dist_name" => "XML-RSS", "dist_version" => "1.65", "license" => "perl", "module_name" => "XML::RSS", "recursive_test_files" => 1, "requires" => { "Carp" => 0, "DateTime::Format::Mail" => 0, "DateTime::Format::W3CDTF" => 0, "HTML::Entities" => 0, "XML::Parser" => 0, "perl" => "5.008", "strict" => 0, "vars" => 0, "warnings" => 0 }, "test_requires" => { "File::Find" => 0, "File::Spec" => 0, "IO::Handle" => 0, "IPC::Open3" => 0, "POSIX" => 0, "Test::More" => "0.88", "constant" => 0 } ); my %fallback_build_requires = ( "File::Find" => 0, "File::Spec" => 0, "IO::Handle" => 0, "IPC::Open3" => 0, "Module::Build" => "0.28", "POSIX" => 0, "Test::More" => "0.88", "constant" => 0 ); unless ( eval { Module::Build->VERSION(0.4004) } ) { delete $module_build_args{test_requires}; $module_build_args{build_requires} = \%fallback_build_requires; } my $build = Module::Build->new(%module_build_args); $build->create_build_script; META.json100644001750001750 4655514756547744 14627 0ustar00shlomifshlomif000000000000XML-RSS-1.65{ "abstract" : "creates and updates RSS files", "author" : [ "Shlomi Fish " ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 6.032, CPAN::Meta::Converter version 2.150010", "keywords" : [ "feed", "feeds", "generate", "generating", "parse", "parsing", "rss", "RSS", "web-feed", "web-feeds", "xml" ], "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "XML-RSS", "prereqs" : { "build" : { "requires" : { "Module::Build" : "0.28" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0", "Module::Build" : "0.28" } }, "develop" : { "requires" : { "Pod::Coverage::TrustPod" : "0", "Test::CPAN::Changes" : "0.19", "Test::EOL" : "0", "Test::More" : "0.96", "Test::NoTabs" : "0", "Test::Pod" : "1.41", "Test::Pod::Coverage" : "1.08", "Test::TrailingSpace" : "0.0203" } }, "runtime" : { "requires" : { "Carp" : "0", "DateTime::Format::Mail" : "0", "DateTime::Format::W3CDTF" : "0", "HTML::Entities" : "0", "XML::Parser" : "0", "perl" : "5.008", "strict" : "0", "vars" : "0", "warnings" : "0" } }, "test" : { "requires" : { "File::Find" : "0", "File::Spec" : "0", "IO::Handle" : "0", "IPC::Open3" : "0", "POSIX" : "0", "Test::More" : "0.88", "constant" : "0" } } }, "provides" : { "XML::RSS" : { "file" : "lib/XML/RSS.pm", "version" : "1.65" }, "XML::RSS::Private::Output::Base" : { "file" : "lib/XML/RSS/Private/Output/Base.pm", "version" : "1.65" }, "XML::RSS::Private::Output::Roles::ImageDims" : { "file" : "lib/XML/RSS/Private/Output/Roles/ImageDims.pm", "version" : "1.65" }, "XML::RSS::Private::Output::Roles::ModulesElems" : { "file" : "lib/XML/RSS/Private/Output/Roles/ModulesElems.pm", "version" : "1.65" }, "XML::RSS::Private::Output::V0_9" : { "file" : "lib/XML/RSS/Private/Output/V0_9.pm", "version" : "1.65" }, "XML::RSS::Private::Output::V0_91" : { "file" : "lib/XML/RSS/Private/Output/V0_91.pm", "version" : "1.65" }, "XML::RSS::Private::Output::V1_0" : { "file" : "lib/XML/RSS/Private/Output/V1_0.pm", "version" : "1.65" }, "XML::RSS::Private::Output::V2_0" : { "file" : "lib/XML/RSS/Private/Output/V2_0.pm", "version" : "1.65" } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/shlomif/perl-XML-RSS/issues" }, "homepage" : "http://metacpan.org/release/XML-RSS", "repository" : { "type" : "git", "url" : "git://github.com/shlomif/perl-XML-RSS.git", "web" : "https://github.com/shlomif/perl-XML-RSS" } }, "version" : "1.65", "x_Dist_Zilla" : { "perl" : { "version" : "5.040001" }, "plugins" : [ { "class" : "Dist::Zilla::Plugin::Prereqs", "config" : { "Dist::Zilla::Plugin::Prereqs" : { "phase" : "test", "type" : "requires" } }, "name" : "@Filter/TestMoreDoneTesting", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::AutoPrereqs", "name" : "@Filter/AutoPrereqs", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::ExecDir", "name" : "@Filter/ExecDir", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::GatherDir", "config" : { "Dist::Zilla::Plugin::GatherDir" : { "exclude_filename" : [], "exclude_match" : [], "follow_symlinks" : 0, "include_dotfiles" : 0, "prefix" : "", "prune_directory" : [], "root" : "." } }, "name" : "@Filter/GatherDir", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::ManifestSkip", "name" : "@Filter/ManifestSkip", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::MetaYAML", "name" : "@Filter/MetaYAML", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::PruneCruft", "name" : "@Filter/PruneCruft", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::RunExtraTests", "config" : { "Dist::Zilla::Role::TestRunner" : { "default_jobs" : 1 } }, "name" : "@Filter/RunExtraTests", "version" : "0.029" }, { "class" : "Dist::Zilla::Plugin::ShareDir", "name" : "@Filter/ShareDir", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::MakeMaker", "config" : { "Dist::Zilla::Role::TestRunner" : { "default_jobs" : 1 } }, "name" : "@Filter/MakeMaker", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::CheckChangesHasContent", "name" : "@Filter/CheckChangesHasContent", "version" : "0.011" }, { "class" : "Dist::Zilla::Plugin::ConfirmRelease", "name" : "@Filter/ConfirmRelease", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::Manifest", "name" : "@Filter/Manifest", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::MetaConfig", "name" : "@Filter/MetaConfig", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::MetaJSON", "name" : "@Filter/MetaJSON", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::MetaProvides::Package", "config" : { "Dist::Zilla::Plugin::MetaProvides::Package" : { "finder_objects" : [ { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : "@Filter/MetaProvides::Package/AUTOVIV/:InstallModulesPM", "version" : "6.032" } ], "include_underscores" : 0 }, "Dist::Zilla::Role::MetaProvider::Provider" : { "$Dist::Zilla::Role::MetaProvider::Provider::VERSION" : "2.002004", "inherit_missing" : 1, "inherit_version" : 1, "meta_noindex" : 1 }, "Dist::Zilla::Role::ModuleMetadata" : { "Module::Metadata" : "1.000038", "version" : "0.006" } }, "name" : "@Filter/MetaProvides::Package", "version" : "2.004003" }, { "class" : "Dist::Zilla::Plugin::MetaResources", "name" : "@Filter/MetaResources", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::ModuleBuild", "config" : { "Dist::Zilla::Role::TestRunner" : { "default_jobs" : 1 } }, "name" : "@Filter/ModuleBuild", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::PkgVersion", "name" : "@Filter/PkgVersion", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::PodCoverageTests", "name" : "@Filter/PodCoverageTests", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::PodSyntaxTests", "name" : "@Filter/PodSyntaxTests", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::Test::Compile", "config" : { "Dist::Zilla::Plugin::Test::Compile" : { "bail_out_on_fail" : 0, "fail_on_warning" : "author", "fake_home" : 0, "filename" : "t/00-compile.t", "module_finder" : [ ":InstallModules" ], "needs_display" : 0, "phase" : "test", "script_finder" : [ ":PerlExecFiles" ], "skips" : [], "switch" : [] } }, "name" : "@Filter/Test::Compile", "version" : "2.058" }, { "class" : "Dist::Zilla::Plugin::Test::CPAN::Changes", "config" : { "Dist::Zilla::Plugin::Test::CPAN::Changes" : { "changelog" : "Changes", "filename" : "xt/release/cpan-changes.t" } }, "name" : "@Filter/Test::CPAN::Changes", "version" : "0.013" }, { "class" : "Dist::Zilla::Plugin::Test::EOL", "config" : { "Dist::Zilla::Plugin::Test::EOL" : { "filename" : "xt/author/eol.t", "finder" : [ ":ExecFiles", ":InstallModules", ":TestFiles" ], "trailing_whitespace" : 1 } }, "name" : "@Filter/Test::EOL", "version" : "0.19" }, { "class" : "Dist::Zilla::Plugin::Test::NoTabs", "config" : { "Dist::Zilla::Plugin::Test::NoTabs" : { "filename" : "xt/author/no-tabs.t", "finder" : [ ":InstallModules", ":ExecFiles", ":TestFiles" ] } }, "name" : "@Filter/Test::NoTabs", "version" : "0.15" }, { "class" : "Dist::Zilla::Plugin::Test::TrailingSpace", "name" : "@Filter/Test::TrailingSpace", "version" : null }, { "class" : "Dist::Zilla::Plugin::TestRelease", "name" : "@Filter/TestRelease", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::PodWeaver", "config" : { "Dist::Zilla::Plugin::PodWeaver" : { "finder" : [ ":InstallModules", ":PerlExecFiles" ], "plugins" : [ { "class" : "Pod::Weaver::Plugin::SingleEncoding", "name" : "@SHLOMIF/SingleEncoding", "version" : "4.020" }, { "class" : "Pod::Weaver::Plugin::WikiDoc", "name" : "@SHLOMIF/WikiDoc", "version" : "0.093004" }, { "class" : "Pod::Weaver::Plugin::EnsurePod5", "name" : "@CorePrep/EnsurePod5", "version" : "4.020" }, { "class" : "Pod::Weaver::Plugin::H1Nester", "name" : "@CorePrep/H1Nester", "version" : "4.020" }, { "class" : "Pod::Weaver::Section::Generic", "name" : "@SHLOMIF/Name", "version" : "4.020" }, { "class" : "Pod::Weaver::Section::Version", "name" : "@SHLOMIF/Version", "version" : "4.020" }, { "class" : "Pod::Weaver::Section::Region", "name" : "@SHLOMIF/Prelude", "version" : "4.020" }, { "class" : "Pod::Weaver::Section::Generic", "name" : "@SHLOMIF/Synopsis", "version" : "4.020" }, { "class" : "Pod::Weaver::Section::Generic", "name" : "@SHLOMIF/Description", "version" : "4.020" }, { "class" : "Pod::Weaver::Section::Generic", "name" : "@SHLOMIF/Usage", "version" : "4.020" }, { "class" : "Pod::Weaver::Section::Generic", "name" : "@SHLOMIF/Overview", "version" : "4.020" }, { "class" : "Pod::Weaver::Section::Generic", "name" : "@SHLOMIF/Stability", "version" : "4.020" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "Requirements", "version" : "4.020" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "Attributes", "version" : "4.020" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "Constructors", "version" : "4.020" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "Methods", "version" : "4.020" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "Functions", "version" : "4.020" }, { "class" : "Pod::Weaver::Section::Leftovers", "name" : "@SHLOMIF/Leftovers", "version" : "4.020" }, { "class" : "Pod::Weaver::Section::Region", "name" : "@SHLOMIF/postlude", "version" : "4.020" }, { "class" : "Pod::Weaver::Section::Support", "name" : "@SHLOMIF/Support", "version" : "1.014" }, { "class" : "Pod::Weaver::Section::Authors", "name" : "@SHLOMIF/Authors", "version" : "4.020" }, { "class" : "Pod::Weaver::Section::Bugs", "name" : "@SHLOMIF/Bugs", "version" : "4.020" }, { "class" : "Pod::Weaver::Section::Contributors", "name" : "@SHLOMIF/Contributors", "version" : "0.009" }, { "class" : "Pod::Weaver::Section::Legal", "name" : "@SHLOMIF/Legal", "version" : "4.020" }, { "class" : "Pod::Weaver::Plugin::Transformer", "name" : "@SHLOMIF/List", "version" : "4.020" } ] } }, "name" : "@Filter/PodWeaver", "version" : "4.010" }, { "class" : "Dist::Zilla::Plugin::UploadToCPAN", "name" : "@Filter/UploadToCPAN", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::Keywords", "config" : { "Dist::Zilla::Plugin::Keywords" : { "keywords" : [ "feed", "feeds", "generate", "generating", "parse", "parsing", "rss", "RSS", "web-feed", "web-feeds", "xml" ] } }, "name" : "Keywords", "version" : "0.007" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":InstallModules", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":IncModules", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":TestFiles", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ExtraTestFiles", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ExecFiles", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":PerlExecFiles", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ShareFiles", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":MainModule", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":AllFiles", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":NoFiles", "version" : "6.032" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : "@Filter/MetaProvides::Package/AUTOVIV/:InstallModulesPM", "version" : "6.032" } ], "zilla" : { "class" : "Dist::Zilla::Dist::Builder", "config" : { "is_trial" : 0 }, "version" : "6.032" } }, "x_generated_by_perl" : "v5.40.1", "x_serialization_backend" : "Cpanel::JSON::XS version 4.38", "x_spdx_expression" : "Artistic-1.0-Perl OR GPL-1.0-or-later" } weaver.ini100644001750001750 1314756547744 15073 0ustar00shlomifshlomif000000000000XML-RSS-1.65[@SHLOMIF] version.t100644001750001750 224314756547744 15265 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t# $Id: version.t,v 1.2 2004/04/21 02:44:40 kellan Exp $ use Test::More tests => 7; $|++; use XML::RSS; { my $rss = XML::RSS->new( version => '0.9' ); # TEST isa_ok( $rss, 'XML::RSS' ); make_rss( $rss ); # TEST like( $rss->as_string, qr|]*>|, "rdf tag for version 0.9" ); $rss = XML::RSS->new( version => '0.91' ); # TEST isa_ok( $rss, 'XML::RSS' ); make_rss( $rss ); # TEST like( $rss->as_string, qr//, "rss tag for version 0.91" ); $rss = XML::RSS->new( version => '1.0' ); # TEST isa_ok( $rss, 'XML::RSS' ); make_rss( $rss ); # TEST like( $rss->as_string, qr|]*>|, "rdf tag for version 1.0" ); } sub make_rss { my $rss = shift; $rss->channel( title => 'Test RSS', link => 'http://www.example.com', description => '', ); } { my $rss = XML::RSS->new(version => "2.0"); my $r = $rss->_get_rendering_obj("0.9"); # TEST is( $r->_rss_out_version(), "0.9", "_rss_out_version"); } Makefile.PL100644001750001750 330314756547744 15120 0ustar00shlomifshlomif000000000000XML-RSS-1.65# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.032. use strict; use warnings; use 5.008; use ExtUtils::MakeMaker; my %WriteMakefileArgs = ( "ABSTRACT" => "creates and updates RSS files", "AUTHOR" => "Shlomi Fish ", "BUILD_REQUIRES" => { "Module::Build" => "0.28" }, "CONFIGURE_REQUIRES" => { "ExtUtils::MakeMaker" => 0, "Module::Build" => "0.28" }, "DISTNAME" => "XML-RSS", "LICENSE" => "perl", "MIN_PERL_VERSION" => "5.008", "NAME" => "XML::RSS", "PREREQ_PM" => { "Carp" => 0, "DateTime::Format::Mail" => 0, "DateTime::Format::W3CDTF" => 0, "HTML::Entities" => 0, "XML::Parser" => 0, "strict" => 0, "vars" => 0, "warnings" => 0 }, "TEST_REQUIRES" => { "File::Find" => 0, "File::Spec" => 0, "IO::Handle" => 0, "IPC::Open3" => 0, "POSIX" => 0, "Test::More" => "0.88", "constant" => 0 }, "VERSION" => "1.65", "test" => { "TESTS" => "t/*.t" } ); my %FallbackPrereqs = ( "Carp" => 0, "DateTime::Format::Mail" => 0, "DateTime::Format::W3CDTF" => 0, "File::Find" => 0, "File::Spec" => 0, "HTML::Entities" => 0, "IO::Handle" => 0, "IPC::Open3" => 0, "Module::Build" => "0.28", "POSIX" => 0, "Test::More" => "0.88", "XML::Parser" => 0, "constant" => 0, "strict" => 0, "vars" => 0, "warnings" => 0 ); unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { delete $WriteMakefileArgs{TEST_REQUIRES}; delete $WriteMakefileArgs{BUILD_REQUIRES}; $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; WriteMakefile(%WriteMakefileArgs); xml-base.t100644001750001750 462714756547744 15320 0ustar00shlomifshlomif000000000000XML-RSS-1.65/tuse strict; use warnings; use Test::More tests => 13; use XML::RSS; sub output_contains { local $Test::Builder::Level = $Test::Builder::Level + 1; my ($rss_output, $sub_string, $msg) = @_; my $ok = ok (index ($rss_output, $sub_string) >= 0, $msg ); if (! $ok) { diag( "Could not find the substring [$sub_string]" . " in:{{{{\n$rss_output\n}}}}\n" ); } return $ok; } my $xml; { my $rss; $rss = XML::RSS->new( 'xml:base' => 'http://example.com' ); # TEST ok ($rss, "Created new rss"); # TEST is($rss->{'xml:base'}, 'http://example.com', 'Got base'); $rss->{'xml:base'} = 'http://foo.com/'; # TEST ok($rss->channel( title => 'Test Feed', link => "http://example.com", description => "Foo", ), "Added channel"); # TEST ok($rss->add_item( title => 'foo', 'xml:base' => "http://foo.com/archive/", description => { content => "Bar", 'xml:base' => "http://foo.com/archive/1.html", } ), "Added item"); $xml = $rss->as_rss_2_0(); # TEST ok($xml, "Got xml"); # TEST output_contains( $xml, 'xml:base="http://foo.com/"', "Found rss base" ); # TEST output_contains( $xml, 'xml:base="http://foo.com/archive/"', "Found item base" ); # TEST output_contains( $xml, 'xml:base="http://foo.com/archive/1.html"', "Found description base" ); } { my $rss = XML::RSS->new; # TEST ok( $rss->parse($xml, { hashrefs_instead_of_strings => 1 }), "Reparsed xml" ); # TEST is( $rss->{'xml:base'}, 'http://foo.com/', "Found parsed rss base" ); # TEST is( scalar(@{$rss->{items}}), 1, "Got 1 item" ); my $item = $rss->{items}->[0]; # TEST is( $item->{'xml:base'}, 'http://foo.com/archive/', "Found parsed item base" ); { if (ref $item->{description} eq 'HASH') { # TEST is( $item->{description}->{'xml:base'}, 'http://foo.com/archive/1.html', "Found parsed description base" ); } else { fail("Description is not a hash ref"); } } } charset1.t100644001750001750 322714756547744 15315 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t#!/usr/bin/perl # This is a regression test for: # http://rt.cpan.org/Public/Bug/Display.html?id=5438 # based on the original script supplied with the report. use strict; use warnings; use XML::RSS; use File::Spec; use Test::More; if (eval "require Test::Differences") { Test::Differences->import; plan tests => 2; } else { plan skip_all => 'Test::Differences required'; } { my $rss_file = File::Spec->catfile("t", "generated", "charset1-generated.xml"); my %rss_new = (version => '1.0', encoding => 'iso-8859-1', output => '1.0'); my $rss = XML::RSS->new(%rss_new); # # Add a channel # $rss->channel (title => "Channel Title", link => "http://channel.url/", description => "Channel Description"); # # Add an item with accented characters # $rss->add_item (title => "Item Title", link => "http://item.url/", description => "Item Description (©)"); # # Save RSS content to file. # open (RSS, ">", $rss_file) || die "Unable to open $rss_file."; my $rss1 = $rss->as_string; print RSS $rss1; close (RSS); # # Now read it back in # $rss = XML::RSS->new(%rss_new); $rss->parsefile($rss_file); # # save it again # open (RSS, ">", $rss_file) || die "Unable to open $rss_file."; my $rss2 = $rss->as_string; print RSS $rss2; close (RSS); eq_or_diff($rss1, $rss2, 'got the same RSS both times'); # # And read it back in again. # $rss = XML::RSS->new; $rss->parsefile($rss_file); # Check that no exception was thrown along the way. ok(1); } encoding.t100644001750001750 216714756547744 15373 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t# $Id: encoding.t,v 1.2 2004/04/21 02:44:40 kellan Exp $ use Test::More tests => 18; $|++; use XML::RSS; my @versions = qw( 0.9 0.91 1.0 ); foreach my $version ( @versions ) { # default my $rss = XML::RSS->new( version => $version ); isa_ok( $rss, 'XML::RSS' ); make_rss( $rss ); like( $rss->as_string, qr/^<\?xml version="1.0" encoding="UTF-8"\?>/, "Default encoding for version $version" ); # UTF-8 $rss = XML::RSS->new( version => $version, encoding => 'UTF-8' ); isa_ok( $rss, 'XML::RSS' ); make_rss( $rss ); like( $rss->as_string, qr/^<\?xml version="1.0" encoding="UTF-8"\?>/, "Default encoding for version $version" ); # home brew $rss = XML::RSS->new( version => $version, encoding => 'Fooey' ); isa_ok( $rss, 'XML::RSS' ); make_rss( $rss ); like( $rss->as_string, qr/^<\?xml version="1.0" encoding="Fooey"\?>/, "Default encoding for version $version" ); } sub make_rss { my $rss = shift; $rss->channel( title => 'Test RSS', link => 'http://www.example.com', description => "Hello", ); } MANIFEST.SKIP100644001750001750 314756547744 14756 0ustar00shlomifshlomif000000000000XML-RSS-1.65~$ 1.0-parse.t100644001750001750 500414756547744 15204 0ustar00shlomifshlomif000000000000XML-RSS-1.65/tuse strict; use warnings; use Test::More; use constant RSS_VERSION => "1.0"; use constant RSS_CHANNEL_TITLE => "Example 1.0 Channel"; use constant RSS_DEFAULTNS => "http://purl.org/rss/1.0/"; use constant RSS_DOCUMENT => qq( Example 1.0 Channel http://example.com To lead by example en-us News for September the Second http://example.com/2002/09/02 other things happened today News for September the First http://example.com/2002/09/01 something happened today ); plan tests => 8; use_ok("XML::RSS"); my $xml = XML::RSS->new(); isa_ok($xml,"XML::RSS"); eval { $xml->parse(RSS_DOCUMENT); }; is($@,'',"Parsed RSS feed"); cmp_ok($xml->{'_internal'}->{'version'}, "eq", RSS_VERSION, "Is RSS version ".RSS_VERSION); cmp_ok($xml->{namespaces}->{'#default'}, "eq", RSS_DEFAULTNS, RSS_DEFAULTNS); cmp_ok($xml->{channel}->{'title'}, "eq", RSS_CHANNEL_TITLE, "Feed title is ".RSS_CHANNEL_TITLE); cmp_ok(ref($xml->{items}), "eq", "ARRAY", "\$xml->{items} is an ARRAY ref"); my $ok = 1; foreach my $item (@{$xml->{items}}) { foreach my $el ("title","link","description") { if (! exists $item->{$el}) { $ok = 0; last; } } last if (! $ok); } ok($ok,"All items have title,link and description elements"); __END__ =head1 NAME 1.0-parse.t - tests for parsing RSS 1.0 data with XML::RSS.pm =head1 SYNOPSIS use Test::Harness qw (runtests); runtests (./XML-RSS/t/*.t); =head1 DESCRIPTION Tests for parsing RSS 1.0 data with XML::RSS.pm =head1 VERSION $Revision: 1.2 $ =head1 DATE $Date: 2002/11/19 23:57:20 $ =head1 AUTHOR Aaron Straup Cope =head1 SEE ALSO http://web.resource.org/rss/1.0 =cut 2.0-parse.t100644001750001750 544214756547744 15213 0ustar00shlomifshlomif000000000000XML-RSS-1.65/tuse strict; use warnings; use Test::More; use constant RSS_VERSION => "2.0"; use constant RSS_CHANNEL_TITLE => "Example 2.0 Channel"; use constant RSS_DOCUMENT => qq( Example 2.0 Channel http://example.com/ To lead by example en-us All content Public Domain, except comments which remains copyright the author editor\@example.com webmaster\@example.com http://backend.userland.com/rss Reference/Libraries/Library_and_Information_Science/Technical_Services/Cataloguing/Metadata/RDF/Applications/RSS/ The Superest Dooperest RSS Generator Mon, 02 Sep 2002 03:19:17 GMT 60 News for September the Second http://example.com/2002/09/02 other things happened today http://example.com/2002/09/02/comments.html joeuser\@example.com Mon, 02 Sep 2002 03:19:00 GMT http://example.com/2002/09/02 News for September the First http://example.com/2002/09/01 something happened today http://example.com/2002/09/01/comments.html joeuser\@example.com Sun, 01 Sep 2002 12:01:00 GMT http://example.com/2002/09/02 ); plan tests => 7; use_ok("XML::RSS"); my $xml = XML::RSS->new(); isa_ok($xml,"XML::RSS"); eval { $xml->parse(RSS_DOCUMENT); }; is($@,'',"Parsed RSS feed"); cmp_ok($xml->{'_internal'}->{'version'},"eq",RSS_VERSION,"Is RSS version ".RSS_VERSION); cmp_ok($xml->{channel}->{'title'},"eq",RSS_CHANNEL_TITLE,"Feed title is ".RSS_CHANNEL_TITLE); cmp_ok(ref($xml->{items}),"eq","ARRAY","\$xml->{items} is an ARRAY ref"); my $ok = 1; foreach my $item (@{$xml->{items}}) { my $min = 0; foreach my $el ("title","description") { if (exists $item->{$el}) { $min ||= 1; } } $ok = $min; last if (! $ok); } ok($ok,"All items have either a title or a description element"); __END__ =head1 NAME 2.0-parse.t - tests for parsing RSS 2.0 data with XML::RSS.pm =head1 SYNOPSIS use Test::Harness qw (runtests); runtests (./XML-RSS/t/*.t); =head1 DESCRIPTION Tests for parsing RSS 2.0 data with XML::RSS.pm =head1 VERSION $Revision: 1.2 $ =head1 DATE $Date: 2002/11/19 23:56:53 $ =head1 AUTHOR Aaron Straup Cope =head1 SEE ALSO http://backend.userland.com/rss2 =cut 0.9-parse.t100644001750001750 376614756547744 15231 0ustar00shlomifshlomif000000000000XML-RSS-1.65/tuse strict; use warnings; use strict; use Test::More; plan tests => 7; use constant RSS_VERSION => "0.9"; use constant RSS_CHANNEL_TITLE => "Example 0.9 Channel"; use constant RSS_DOCUMENT => qq( Example 0.9 Channel http://www.example.com To lead by example Mozilla http://www.example.com/images/whoisonfirst.gif http://www.example.com News for September the second http://www.example.com/2002/09/02 News for September the first http://www.example.com/2002/09/01 ); use_ok("XML::RSS"); my $xml = XML::RSS->new(); isa_ok($xml,"XML::RSS"); eval { $xml->parse(RSS_DOCUMENT); }; is($@,'',"Parsed RSS feed"); cmp_ok($xml->{'_internal'}->{'version'}, "eq", RSS_VERSION, "Is RSS version ".RSS_VERSION); cmp_ok($xml->{channel}->{'title'}, "eq", RSS_CHANNEL_TITLE, "Feed title is ".RSS_CHANNEL_TITLE); cmp_ok(ref($xml->{items}), "eq", "ARRAY", "\$xml->{items} is an ARRAY ref"); my $ok = 1; foreach my $item (@{$xml->{items}}) { foreach my $el ("title","link") { if (! exists $item->{$el}) { $ok = 0; last; } } last if (! $ok); } ok($ok,"All items have title and link elements"); __END__ =head1 NAME 0.9-parse.t - tests for parsing RSS 0.90 data with XML::RSS.pm =head1 SYNOPSIS use Test::Harness qw (runtests); runtests (./XML-RSS/t/*.t); =head1 DESCRIPTION Tests for parsing RSS 0.90 data with XML::RSS.pm =head1 VERSION $Revision: 1.2 $ =head1 DATE $Date: 2002/11/20 00:01:44 $ =head1 AUTHOR Aaron Straup Cope =head1 SEE ALSO http://www.purplepages.ie/RSS/netscape/rss0.90.html =cut enclosures.t100644001750001750 333314756547744 15763 0ustar00shlomifshlomif000000000000XML-RSS-1.65/tuse strict; use warnings; use Test::More; use constant RSS_VERSION => "2.0"; use constant RSS_CHANNEL_TITLE => "Example 2.0 Channel"; use constant RSS_DOCUMENT => qq( Example 2.0 Channel http://example.com/ To lead by example en-us All content Public Domain, except comments which remains copyright the author editor\@example.com webmaster\@example.com http://backend.userland.com/rss Reference/Libraries/Library_and_Information_Science/Technical_Services/Cataloguing/Metadata/RDF/Applications/RSS/ The Superest Dooperest RSS Generator Mon, 02 Sep 2002 03:19:17 GMT 60 News for September the Second http://example.com/2002/09/02 other things happened today http://example.com/2002/09/02/comments.html joeuser\@example.com Mon, 02 Sep 2002 03:19:00 GMT http://example.com/2002/09/02 ); plan tests => 4; use_ok("XML::RSS"); my $xml = XML::RSS->new(); isa_ok($xml,"XML::RSS"); eval { $xml->parse(RSS_DOCUMENT); }; is($@,'',"Parsed RSS feed"); is_deeply($xml->{items}->[0]->{enclosure}, { url => "http://example.com/test.mp3", length => "5352283", type => "audio/mpeg" }, "got enclosure"); 1.0-to-2.0.t100644001750001750 436314756547744 15020 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t#!/usr/bin/perl use strict; use warnings; use File::Spec; use Test::More tests => 7; use XML::RSS; { my $rss = XML::RSS->new; $rss->parsefile(File::Spec->catfile(File::Spec->curdir(), "t", "data", "merlyn1.rss")); $rss->{output} = "2.0"; my $string = $rss->as_string; # DateTime::Format::Mail emits +0000 starting from version 0.400 # and -0000 on older versions so we need to accomodate for that. # # TEST like ($string, qr{Sat, 14 Oct 2006 21:15:36 [+-]0000}, "Correct date was found", ); # TEST like ($string, qr{Sat, 14 Oct 2006 21:15:36 [+-]0000}, "Correct pubDate was found", ); } { my $rss = XML::RSS->new; $rss->parsefile(File::Spec->catfile(File::Spec->curdir(), "t", "data", "merlyn1.rss")); $rss->{output} = "0.91"; my $string = $rss->as_string; # TEST like( $string, qr{Sat, 14 Oct 2006 21:15:36 [+-]0000\nSat, 14 Oct 2006 21:15:36 [+-]0000\n}, "Correct date was found in 1.0 -> 0.91 conversion", ); } { my $rss = XML::RSS->new; $rss->parsefile(File::Spec->catfile(File::Spec->curdir(), "t", "data", "2.0","sf-hs-with-pubDate.rss")); $rss->{output} = "1.0"; my $string = $rss->as_string; my $index = index($string, qq{2006-09-24T10:12:49Z\n}); # TEST ok ($index >= 0, "Correct date was found in 1.0 -> 0.91 conversion", ); my $item_index = index($string, "new; $rss->parsefile(File::Spec->catfile(File::Spec->curdir(), "t", "data", "2.0","sf-hs-with-lastBuildDate.rss")); $rss->{output} = "1.0"; my $string = $rss->as_string; my $index = index($string, qq{2006-09-24T10:12:49Z\n}); # TEST ok ($index >= 0, "Correct date was found in 1.0 -> 0.91 conversion", ); my $item_index = index($string, " "0.91"; use constant RSS_CHANNEL_TITLE => "Example 0.91 Channel"; use constant RSS_DOCUMENT => qq( Example 0.91 Channel http://example.com To lead by example News for September the Second http://example.com/2002/09/02 other things happened today News for September the First http://example.com/2002/09/01 something happened today ); plan tests => 7; use_ok("XML::RSS"); my $xml = XML::RSS->new(); isa_ok($xml,"XML::RSS"); eval { $xml->parse(RSS_DOCUMENT); }; is($@,'',"Parsed RSS feed"); cmp_ok($xml->{'_internal'}->{'version'}, "eq", RSS_VERSION, "Is RSS version ".RSS_VERSION); cmp_ok($xml->{channel}->{'title'}, "eq", RSS_CHANNEL_TITLE, "Feed title is ".RSS_CHANNEL_TITLE); cmp_ok(ref($xml->{items}), "eq", "ARRAY", "\$xml->{items} is an ARRAY ref"); my $ok = 1; foreach my $item (@{$xml->{items}}) { foreach my $el ("title","link","description") { if (! exists $item->{$el}) { $ok = 0; last; } } last if (! $ok); } ok($ok,"All items have title,link and description elements"); __END__ =head1 NAME 0.91-parse.t - tests for parsing RSS 0.91 data with XML::RSS.pm =head1 SYNOPSIS use Test::Harness qw (runtests); runtests (./XML-RSS/t/*.t); =head1 DESCRIPTION Tests for parsing RSS 0.91 data with XML::RSS.pm =head1 VERSION $Revision: 1.2 $ =head1 DATE $Date: 2002/11/19 23:58:03 $ =head1 AUTHOR Aaron Straup Cope =head1 SEE ALSO http://my.netscape.com/publish/formats/rss-spec-0.91.html http://backend.userland.com/rss091 =cut xml-header.t100644001750001750 712514756547744 15632 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t#!/usr/bin/perl use strict; use warnings; use Test::More tests => 8; use XML::RSS; sub starts_with { local $Test::Builder::Level = $Test::Builder::Level + 1; my ($rss, $prefix, $msg) = @_; my $rss_output = $rss->as_string(); my $ok = is ( substr($rss_output, 0, length($prefix)-1), substr($prefix, 0, length($prefix)-1), $msg ); } sub create_rss_1 { my $args = shift; my @style = exists($args->{stylesheet}) ? (stylesheet => $args->{stylesheet}) : () ; my $rss = XML::RSS->new( version => $args->{version}, @style ); my $image_link = exists($args->{image_link}) ? $args->{image_link} : "http://freshmeat.net/"; my $extra_image_params = $args->{image_params} || []; $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 => "0", link => $image_link, @{$extra_image_params}, ); $rss->add_item( title => "GTKeyboard 0.85", link => "http://freshmeat.net/news/1999/06/21/930003829.html" ); return $rss; } { # TEST starts_with( create_rss_1({'version' => "0.9"}), <<'EOF', "0.91"}), <<'EOF', EOF "header of RSS 0.9.1 without the stylesheet" ); } { # TEST starts_with( create_rss_1({'version' => "1.0"}), <<'EOF', "2.0"}), <<'EOF', "0.9", stylesheet => "http://myhost.tld/foo.xsl"}), <<'EOF', "0.91", stylesheet => "http://myhost.tld/foo.xsl"}), <<'EOF', EOF "header of RSS 0.9.1 with the stylesheet" ); } { # TEST starts_with( create_rss_1({'version' => "1.0", stylesheet => "http://myhost.tld/foo.xsl"}), <<'EOF', "2.0", stylesheet => "http://myhost.tld/foo.xsl"}), <<'EOF', 12; use XML::RSS; sub item_throws_like { local $Test::Builder::Level = $Test::Builder::Level + 1; my ($rss, $params, $regex, $msg) = @_; eval { $rss->add_item(@$params); }; like ($@, $regex, $msg); } { my $rss = XML::RSS->new(version => "0.9"); $rss->strict(1); $rss->channel( title => "freshmeat.net", link => "http://freshmeat.net", description => "the one-stop-shop for all your Linux software needs", ); # TEST item_throws_like($rss, [link => "http://foobar.tld/from/"], qr{\Atitle and link elements are required}, "strict - checking for exception on non-specified title" ); # TEST item_throws_like($rss, [title => "From Foobar"], qr{\Atitle and link elements are required}, "strict - checking for exception on non-specified link" ); # TEST item_throws_like($rss, [link => "http://foobar.tld/", title => ("Very long title indeed" x 50)], qr{\Atitle cannot exceed}, "strict - checking for long title" ); # TEST item_throws_like($rss, [ link => "http://" . ("foobarminimoni" x 200) . ".tld/", title => "Short Title" ], qr{\Alink cannot exceed}, "strict - checking for long link" ); # TEST item_throws_like($rss, [ link => "http://foobar.tld/from/", title => "Short Title", description => ("This description is way too long!" x 100), ], qr{\Adescription cannot exceed}, "strict - checking for a long description" ); } { my $rss = XML::RSS->new(version => "0.9"); $rss->strict(1); $rss->channel( title => "freshmeat.net", link => "http://freshmeat.net", description => "the one-stop-shop for all your Linux software needs", ); foreach my $i (1 .. 15) { $rss->add_item( link => "http://foobar.tld/item-$i", title => "Item $i", ); } # TEST item_throws_like($rss, [ link => "http://foobar.tld/from/", title => "Short Title", description => "Good description", ], qr{\Atotal items cannot exceed}, "strict - checking for too many items" ); } { my $rss = XML::RSS->new(version => "0.9"); $rss->strict(1); $rss->channel( title => "freshmeat.net", link => "http://freshmeat.net", description => "the one-stop-shop for all your Linux software needs", stupid_key => ("I think therefore I am." x 1000), ); # TEST ok (1, "Can add unknown keys of unlimited size without restriction"); } { my $rss = XML::RSS->new(version => "0.9"); $rss->strict(1); eval { $rss->channel( title => "freshmeat.net", link => "http://freshmeat.net", description => ("I think therefore I am." x 1000), ); }; # TEST like ($@, qr{\Adescription cannot exceed 500 characters in length}, "Testing for exception thrown on a very long key" ); } { my $rss = XML::RSS->new(version => "0.9"); $rss->strict(1); eval { $rss->skipHours( hour => 5, ); }; # TEST like ($@, qr{\AUnregistered entity: Can't access skipHours field in object of class}, "Testing for exception thrown on an unknown field" ); } { my $rss = XML::RSS->new(version => "0.9"); $rss->channel( title => "freshmeat.net", link => "http://freshmeat.net", description => "the one-stop-shop for all your Linux software needs", ); # TEST is ($rss->channel()->{title}, "freshmeat.net", "Testing for an AUTOLOAD accessor with 0 arguments" ); # TEST is ($rss->channel('title'), "freshmeat.net", "Testing for an AUTOLOAD accessor with 1 argument" ); } { my $rss = XML::RSS->new(version => "0.91"); $rss->strict(1); eval { $rss->skipDays( day => "FoolambdaCroakThemOfMonetaryJudgement" ); }; # TEST like ($@, qr{\Aday cannot exceed 10 characters in length}, "Testing for exception thrown on a key for 0.91" ); } XML000755001750001750 014756547744 14215 5ustar00shlomifshlomif000000000000XML-RSS-1.65/libRSS.pm100644001750001750 17261314756547744 15434 0ustar00shlomifshlomif000000000000XML-RSS-1.65/lib/XMLpackage XML::RSS; $XML::RSS::VERSION = '1.65'; use strict; use warnings; use Carp qw/ confess croak /; use XML::Parser (); use XML::RSS::Private::Output::Base (); use XML::RSS::Private::Output::V0_9 (); use XML::RSS::Private::Output::V0_91 (); use XML::RSS::Private::Output::V1_0 (); use XML::RSS::Private::Output::V2_0 (); use vars qw($VERSION $AUTOLOAD @ISA $AUTO_ADD); require 5.008; $AUTO_ADD = 0; sub _get_ok_fields { return { "0.9" => { channel => { title => undef, description => undef, link => undef, }, image => { title => undef, url => undef, link => undef, }, textinput => { title => undef, description => undef, name => undef, link => undef, }, }, "0.91" => { channel => { title => undef, copyright => undef, description => undef, docs => undef, language => undef, lastBuildDate => undef, 'link' => undef, managingEditor => undef, pubDate => undef, rating => undef, webMaster => undef, }, image => { title => undef, url => undef, 'link' => undef, width => undef, height => undef, description => undef, }, skipDays => {day => undef,}, skipHours => {hour => undef,}, textinput => { title => undef, description => undef, name => undef, 'link' => undef, }, }, "2.0" => { channel => { title => undef, 'link' => undef, description => undef, language => undef, copyright => undef, managingEditor => undef, webMaster => undef, pubDate => undef, lastBuildDate => undef, category => undef, generator => undef, docs => undef, cloud => '', ttl => undef, image => '', textinput => '', skipHours => '', skipDays => '', }, image => { title => undef, url => undef, 'link' => undef, width => undef, height => undef, description => undef, }, skipDays => {day => undef,}, skipHours => {hour => undef,}, textinput => { title => undef, description => undef, name => undef, 'link' => undef, }, }, 'default' => { channel => { title => undef, description => undef, link => undef, }, image => { title => undef, url => undef, link => undef, }, textinput => { title => undef, description => undef, name => undef, link => undef, }, }, }; } # 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', }; sub _rdf_resource_fields { return { '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} }; } my %empty_ok_elements = (enclosure => 1); my %hashref_ok_elements = (description => 1); sub _get_default_modules { return { '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', 'http://purl.org/rss/1.0/modules/content/' => 'content', }; } sub _get_default_rss_2_0_modules { return {'http://backend.userland.com/blogChannelModule' => 'blogChannel',}; } sub _get_syn_ok_fields { return [qw(updateBase updateFrequency updatePeriod)]; } sub _get_dc_ok_fields { return [ qw( contributor coverage creator date description format identifier language publisher relation rights source subject title type ) ]; } sub new { my $class = shift; my $self = {}; bless $self, $class; $self->_initialize(@_); return $self; } sub _get_init_default_key_assignments { return [ {key => "version", default => '1.0',}, {key => "encode_output", default => 1,}, {key => "output", default => "",}, {key => "encoding", default => "UTF-8",}, {key => "encode_cb", default => undef(),}, {key => "xml:base", default => undef(),}, ]; } # This method resets the contents of the instance to an empty one (with no # items, empty keys, etc.). Useful before parsing or during initialization. sub _reset { my $self = shift; # internal hash $self->{_internal} = {}; # init num of items to 0 $self->{num_items} = 0; # initialize items $self->{items} = []; delete $self->{_allow_multiple}; # reset empty OK to default %empty_ok_elements = (enclosure => 1); my $ok_fields = $self->_get_ok_fields(); my $ver_ok_fields = exists($ok_fields->{$self->{version}}) ? $ok_fields->{$self->{version}} : $ok_fields->{default}; while (my ($k, $v) = each(%$ver_ok_fields)) { $self->{$k} = +{%{$v}}; } return; } sub _initialize { my $self = shift; my %hash = @_; # adhere to Netscape limits; no by default $self->{'strict'} = 0; # namespaces $self->{namespaces} = {}; $self->{rss_namespace} = ''; foreach my $k (@{$self->_get_init_default_key_assignments()}) { my $key = $k->{key}; $self->{$key} = exists($hash{$key}) ? $hash{$key} : $k->{default}; } # modules $self->{modules} = ( ($self->{version} eq "2.0") ? $self->_get_default_rss_2_0_modules() : $self->_get_default_modules() ); # stylesheet if (exists($hash{stylesheet})) { $self->{stylesheet} = $hash{stylesheet}; } if ($self->{version} eq "2.0") { $self->{namespaces}->{'blogChannel'} = "http://backend.userland.com/blogChannelModule"; } $self->_reset; return; } sub add_module { my $self = shift; my $hash = {@_}; $hash->{prefix} =~ /^[a-z_][a-z0-9.\-_]*$/i or croak "a namespace prefix should look like [A-Za-z_][A-Za-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}; } # $self->_render_complete_rss_output($xml_version) # # This function is the workhorse of the XML output and does all the work of # rendering the RSS, delegating the work to specialised functions. # # It accepts the requested version number as its argument. sub _get_rendering_class { my ($self, $ver) = @_; if ($ver eq "1.0") { return "XML::RSS::Private::Output::V1_0"; } elsif ($ver eq "0.9") { return "XML::RSS::Private::Output::V0_9"; } elsif ($ver eq "0.91") { return "XML::RSS::Private::Output::V0_91"; } else { return "XML::RSS::Private::Output::V2_0"; } } sub _get_encode_cb_params { my $self = shift; return defined($self->{encode_cb}) ? ("encode_cb" => $self->{encode_cb}) : (); } sub _get_rendering_obj { my ($self, $ver) = @_; return $self->_get_rendering_class($ver)->new( { main => $self, version => $ver, $self->_get_encode_cb_params(), } ); } sub _render_complete_rss_output { my ($self, $ver) = @_; return $self->_get_rendering_obj($ver)->_render_complete_rss_output(); } sub as_rss_0_9 { return shift->_render_complete_rss_output("0.9"); } sub as_rss_0_9_1 { return shift->_render_complete_rss_output("0.91"); } sub as_rss_1_0 { return shift->_render_complete_rss_output("1.0"); } sub as_rss_2_0 { return shift->_render_complete_rss_output("2.0"); } sub _get_output_methods_map { return { '0.9' => "as_rss_0_9", '0.91' => "as_rss_0_9_1", '2.0' => "as_rss_2_0", '1.0' => "as_rss_1_0", }; } sub _get_default_output_method { return "as_rss_1_0"; } sub _get_output_method { my ($self, $version) = @_; if (my $output_method = $self->_get_output_methods_map()->{$version}) { return $output_method; } else { return $self->_get_default_output_method(); } } sub _get_output_version { my $self = shift; return ($self->{output} =~ /\d/) ? $self->{output} : $self->{version}; } # This is done to preserve backwards compatibility with older versions # of XML-RSS that had the channel/{link,description,title} as the empty # string by default. sub _output_env { my $self = shift; my $callback = shift; local $self->{channel}->{'link'} = $self->{channel}->{'link'}; local $self->{channel}->{'description'} = $self->{channel}->{'description'}; local $self->{channel}->{'title'} = $self->{channel}->{'title'}; foreach my $field (qw(link description title)) { if (!defined($self->{channel}->{$field})) { $self->{channel}->{$field} = ''; } } return $callback->(); } sub as_string { my $self = shift; my $version = $self->_get_output_version(); my $output_method = $self->_get_output_method($version); return $self->_output_env(sub { return $self->$output_method(); }); } # Checks if inside a possibly namespaced element # TODO : After increasing test coverage convert all such conditionals to this # method. sub _my_in_element { my ($self, $elem) = @_; my $parser = $self->_parser; return $parser->within_element($elem) || $parser->within_element($parser->generate_ns_name($elem, $self->{rss_namespace})); } sub _get_elem_namespace_helper { my ($self, $el) = @_; my $ns = $self->_parser->namespace($el); return (defined($ns) ? $ns : ""); } sub _get_elem_namespace { my $self = shift; my ($el) = @_; my $ns = $self->_get_elem_namespace_helper(@_); my $verdict = (!$ns && !$self->{rss_namespace}) || ($ns eq $self->{rss_namespace}); return ($ns, $verdict); } sub _current_element { my $self = shift; return $self->_parser->current_element; } sub _get_current_namespace { my $self = shift; return $self->_get_elem_namespace($self->_current_element); } sub _is_rdf_resource { my $self = shift; my $el = shift; my $ns = shift; if (!defined($ns)) { $ns = $self->_parser->namespace($el); } return ( exists($self->_rdf_resource_fields->{$ns}) && exists($self->_rdf_resource_fields->{$ns}{$el})); } sub _get_ns_arrayity { my ($self, $ns) = @_; my $is_array = $self->_parse_options()->{'modules_as_arrays'} && (!exists($self->_get_default_modules()->{$ns})) # RDF && ($ns ne "http://www.w3.org/1999/02/22-rdf-syntax-ns#"); my $default_ref = sub { $is_array ? [] : {} }; return ($is_array, $default_ref); } sub _append_text_to_elem_struct { my ($self, $struct, $cdata, $mapping_sub, $is_array_sub) = @_; my $elem = $self->_current_element; my ($ns, $verdict) = $self->_get_current_namespace; # If it's in the default namespace if ($verdict) { $self->_append_struct( $struct, scalar($mapping_sub->($struct, $elem)), scalar($is_array_sub->($struct, $elem)), $cdata ); } else { my $prefix = $self->{modules}->{$ns}; my ($is_array, $default_ref) = $self->_get_ns_arrayity($ns); $self->_append_struct( ($struct->{$ns} ||= $default_ref->()), $elem, (defined($prefix) && $prefix eq "dc"), $cdata ); # If it's in a module namespace, provide a friendlier prefix duplicate if ($prefix) { $self->_append_struct(($struct->{$prefix} ||= $default_ref->()), $elem, ($prefix eq "dc"), $cdata); } } return; } { my @_ITEM_KEYS_ELEM_STACK = ("rss", "channel", "item", "link"); sub _should_skip_item_keys_in_custom_tags { my ($self, $struct, $key) = @_; if (length $struct->{$key}) { if ($self->{_internal}->{version} eq "2.0") { if ($key eq "link") { my @context = $self->_parser->context(); if (@context > @_ITEM_KEYS_ELEM_STACK) { return 1; } } } } return; } } sub _append_struct { my ($self, $struct, $key, $can_be_array, $cdata) = @_; if (ref($struct) eq 'ARRAY') { $struct->[-1]->{'val'} .= $cdata; return; } elsif (defined $struct->{$key}) { if (ref($struct->{$key}) eq 'HASH') { $struct->{$key}->{content} .= $cdata; return; } elsif ($can_be_array && ref($struct->{$key}) eq 'ARRAY') { $struct->{$key}->[-1] .= $cdata; return; } } # Somewhat sympotamtic cure for item/link nested inside # custom tags: # # https://github.com/shlomif/perl-XML-RSS/issues/7 # # Thanks to @jkramer . if ($self->_should_skip_item_keys_in_custom_tags($struct, $key)) { return; } $struct->{$key} .= $cdata; return; } sub _return_elem { my ($struct, $elem) = @_; return $elem; } sub _return_elem_is_array { my ($struct, $elem) = @_; # Always return false because no element should be an array. return; } sub _append_text_to_elem { my ($self, $ext_tag, $cdata) = @_; return $self->_append_text_to_elem_struct($self->$ext_tag(), $cdata, \&_return_elem, \&_return_elem_is_array,); } sub _within_topics { my $self = shift; my $parser = $self->_parser; return $parser->within_element( $parser->generate_ns_name("topics", 'http://purl.org/rss/1.0/modules/taxonomy/')); } sub _return_item_elem { my ($item, $elem) = @_; if ($elem eq "guid") { return $item->{isPermaLink} ? "permaLink" : "guid"; } else { return $elem; } } sub _return_item_elem_is_array { my ($item, $elem) = @_; return ($elem eq "category"); } sub _append_text_to_item { my ($self, $cdata) = @_; if (@{$self->{'items'}} < $self->{num_items}) { push @{$self->{items}}, {}; } $self->_append_text_to_elem_struct($self->_last_item, $cdata, \&_return_item_elem, \&_return_item_elem_is_array); } sub _append_to_array_elem { my ($self, $category, $cdata) = @_; if (!$self->_my_in_element($category)) { return; } my $el = $self->_current_element; if (ref($self->{$category}->{$el}) eq "ARRAY") { $self->{$category}->{$el}->[-1] .= $cdata; } else { $self->{$category}->{$el} .= $cdata; } return 1; } sub _handle_char { my ($self, $cdata) = (@_); # image element if ($self->_my_in_element("image")) { $self->_append_text_to_elem("image", $cdata); } # item element elsif (defined($self->{_inside_item_elem})) { return if $self->_within_topics; $self->_append_text_to_item($cdata); } # textinput element elsif ($self->_my_in_element("textinput") || $self->_my_in_element("textInput")) { $self->_append_text_to_elem("textinput", $cdata); } # skipHours element elsif ($self->_append_to_array_elem("skipHours", $cdata)) { # Do nothing - already done in the predicate. } elsif ($self->_append_to_array_elem("skipDays", $cdata)) { # Do nothing - already done in the predicate. } # channel element elsif ($self->_my_in_element("channel")) { if ($self->_within_topics() || $self->_my_in_element("items")) { return; } if ($self->_current_element eq "category") { $self->_append_to_array_elem("channel", $cdata); } else { $self->_append_text_to_elem("channel", $cdata); } } } sub _handle_dec { my ($self, $version, $encoding, $standalone) = (@_); $self->{encoding} = $encoding; #print "ENCODING: $encoding\n"; } sub _should_be_hashref { my ($self, $el) = @_; return ( $empty_ok_elements{$el} || ($self->_parse_options()->{'hashrefs_instead_of_strings'} && $hashref_ok_elements{$el}) ); } sub _start_array_element_in_struct { my ($self, $input_struct, $el, $prefix) = @_; my ($el_ns, $el_verdict) = $self->_get_elem_namespace($el); my ($is_array, $default_ref) = $self->_get_ns_arrayity($el_ns); my @structs = (!$el_verdict) ? ( ( exists($self->{modules}->{$el_ns}) ? ($input_struct->{$self->{modules}->{$el_ns}} ||= $default_ref->()) : () ), ($input_struct->{$el_ns} ||= $default_ref->()), ) : ($input_struct); foreach my $struct (@structs) { if (ref($struct) eq 'ARRAY') { push @$struct, {el => $el, val => "",}; } # If it's an array - append a new empty element because a new one # was started. elsif (ref($struct->{$el}) eq "ARRAY") { push @{$struct->{$el}}, ""; } # If it's not an array but still full (i.e: it's only the second # element), then turn it into an array elsif (defined($struct->{$el}) && length($struct->{$el})) { $struct->{$el} = [$struct->{$el}, ""]; } # Else - do nothing and let the function append to the new value # } return 1; } sub _start_array_element { my ($self, $cat, $el) = @_; if (!$self->_my_in_element($cat)) { return; } $self->_start_array_element_in_struct($self->{$cat}, $el); return 1; } sub _last_item { my $self = shift; my $items = $self->{'items'}; my $num_items = $self->{num_items}; if( (($num_items != @$items + 1) and ($num_items != @$items ))) # or (not @$items)) { confess "num_items [ $num_items vs @{[scalar@$items]} ] is not big enough"; } my $pos =$num_items - 1; if ($pos < 0) { push @$items, +{}; ++$pos; if ($pos != 0) { confess "num_items [ $num_items vs @{[scalar@$items]} ] is not big enough"; } } elsif ($pos > $#$items) { push @$items, +{}; # ++$pos; if ($pos !=$#$items) { confess "num_items [ $num_items vs @{[scalar@$items]} ] is not big enough"; } } return ($items->[$pos]); } sub _handle_start { my $self = shift; my $el = shift; my %attribs = @_; my $parser = $self->_parser; my ($el_ns, $el_verdict) = $self->_get_elem_namespace($el); if ($el eq "image") { if (exists($attribs{'resource'})) { $self->image("rdf:resource", $attribs{'resource'}); } } # 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"; } # handle xml:base $self->{'xml:base'} = $attribs{'base'} if exists $attribs{'base'}; # beginning of RSS 1.0 or RSS 0.9 } elsif ($el eq 'RDF') { my @prefixes = $parser->new_ns_prefixes; foreach my $prefix (@prefixes) { my $uri = $parser->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"; #} # handle xml:base $self->{'xml:base'} = $attribs{'base'} if exists $attribs{'base'}; # beginning of item element } elsif ($self->_start_array_element("skipHours", $el)) { # Do nothing - already done in the predicate. } elsif ($self->_start_array_element("skipDays", $el)) { # Do nothing - already done in the predicate. } elsif ($el eq 'cloud') { if (keys %attribs) { $self->{channel}{cloud} = \%attribs; } } elsif ($el eq 'item') { # deal with trouble makers who use mod_content :) my ($ns, $verdict) = $self->_get_elem_namespace($el); if ($verdict) { # Sanity check to make sure we don't have nested elements that # can confuse the parser. if (!defined($self->{_inside_item_elem})) { # increment item count $self->{num_items}++; $self->{_inside_item_elem} = $parser->depth(); } } # handle xml:base $self->_last_item->{'xml:base'} = $attribs{'base'} if exists $attribs{'base'}; # guid element is a permanent link unless isPermaLink attribute is set to false } elsif (($el eq 'guid') and ($self->{_inside_item_elem})) { $self->_last_item->{'isPermaLink'} = ((!exists($attribs{'isPermaLink'})) || (lc($attribs{'isPermaLink'}) ne 'false')); # beginning of taxo li element in item element #'http://purl.org/rss/1.0/modules/taxonomy/' => 'taxo' } elsif ( $self->_current_element eq "item" && (($el eq "category") || (exists($self->{modules}->{$el_ns}) && ($self->{modules}->{$el_ns} eq "dc")) ) ) { $self->_start_array_element_in_struct($self->_last_item, $el); } elsif ( $parser->within_element( $parser->generate_ns_name("topics", 'http://purl.org/rss/1.0/modules/taxonomy/') ) && $parser->within_element($parser->generate_ns_name("item", $namespace_map->{'rss10'})) && $self->_current_element eq 'Bag' && $el eq 'li' ) { #print "taxo: ", $attribs{'resource'},"\n"; push(@{$self->_last_item->{'taxo'}}, $attribs{'resource'}); $self->{'modules'}->{'http://purl.org/rss/1.0/modules/taxonomy/'} = 'taxo'; # beginning of taxo li in channel element } elsif ( $parser->within_element( $parser->generate_ns_name("topics", 'http://purl.org/rss/1.0/modules/taxonomy/') ) && $parser->within_element($parser->generate_ns_name("channel", $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 ($parser->namespace($el) && $self->_is_rdf_resource($el) && $self->_current_element eq 'channel') { my $ns = $parser->namespace($el); # Commented out by shlomif - the RSS namespaces are not present # in the 'rdf_resource_fields' so this condition always evaluates # to false. # if ( $ns eq $self->{rss_namespace} ) { # $self->{channel}->{$el} = $attribs{resource}; # } # else { $self->{channel}->{$ns}->{$el} = $attribs{resource}; # add short cut # if (exists($self->{modules}->{$ns})) { $ns = $self->{modules}->{$ns}; $self->{channel}->{$ns}->{$el} = $attribs{resource}; } } } # beginning of an item element that stores its info in rdf:resource elsif ($parser->namespace($el) && $self->_is_rdf_resource($el) && $self->_current_element eq 'item') { my $ns = $parser->namespace($el); # Commented out by shlomif - the RSS namespaces are not present # in the 'rdf_resource_fields' so this condition always evaluates # to false. # if ( $ns eq $self->{rss_namespace} ) { # $self->_last_item->{ $el } = $attribs{resource}; # } # else { $self->_last_item->{$ns}->{$el} = $attribs{resource}; # add short cut # if (exists($self->{modules}->{$ns})) { $ns = $self->{modules}->{$ns}; $self->_last_item->{$ns}->{$el} = $attribs{resource}; } } } elsif ($self->_should_be_hashref($el) and $self->_current_element eq 'item') { if (defined $attribs{base}) { $attribs{'xml:base'} = delete $attribs{base}; } if (keys(%attribs)) { if ($el_verdict) { $self->_last_item->{$el} = $self->_make_array($el, $self->_last_item->{$el}, \%attribs); } else { $self->_last_item->{$el_ns}->{$el} = $self->_make_array($el, $self->_last_item->{$el_ns}->{$el}, \%attribs); my $prefix = $self->{modules}->{$el_ns}; if ($prefix) { $self->_last_item->{$prefix}->{$el} = $self->_make_array($el, $self->_last_item->{$prefix}->{$el}, \%attribs); } } } } elsif ($self->_start_array_element("image", $el)) { # Do nothing - already done in the predicate. } elsif (($el eq "category") && (!$parser->within_element("item")) && $self->_start_array_element("channel", $el)) { # Do nothing - already done in the predicate. } elsif (($self->_current_element eq 'channel') && ($el_verdict)) { # Make sure an opening tag signifies that the element has been # encountered. if (exists($self->{'channel'}->{$el}) && (!defined($self->{'channel'}->{$el}))) { $self->{'channel'}->{$el} = ""; } } } sub _make_array { my $self = shift; my $el = shift; my $old = shift; my $new = shift; if (!$self->_allow_multiple($el)) { return $new; } if (!defined $old) { $old = []; } elsif (ref($old) ne 'ARRAY') { $old = [$old]; } push @$old, $new; return $old; } sub _allow_multiple { my $self = shift; my $el = shift; $self->{_allow_multiple} ||= {map { $_ => 1 } @{$self->_parse_options->{allow_multiple} || []}}; return $self->{_allow_multiple}->{$el}; } sub _handle_end { my ($self, $el) = @_; if (defined($self->{_inside_item_elem}) && $self->{_inside_item_elem} == $self->_parser->depth()) { delete($self->{_inside_item_elem}); } } 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 _parser { my $self = shift; if (@_) { $self->{_parser} = shift; } return $self->{_parser}; } sub _get_parser { my $self = shift; return XML::Parser->new( Namespaces => 1, NoExpand => 1, ParseParamEnt => 0, Handlers => { Char => sub { my ($parser, $cdata) = @_; $self->_parser($parser); $self->_handle_char($cdata); # Detach the parser to avoid reference loops. $self->_parser(undef); }, XMLDecl => sub { my $parser = shift; $self->_parser($parser); $self->_handle_dec(@_); # Detach the parser to avoid reference loops. $self->_parser(undef); }, Start => sub { my $parser = shift; $self->_parser($parser); $self->_handle_start(@_); # Detach the parser to avoid reference loops. $self->_parser(undef); }, End => sub { my $parser = shift; $self->_parser($parser); $self->_handle_end(@_); # Detach the parser to avoid reference loops. $self->_parser(undef); }, ExternEnt => sub { return ''; }, } ); } sub _parse_options { my $self = shift; if (@_) { $self->{_parse_options} = shift; } return $self->{_parse_options}; } sub _empty { } sub _generic_parse { my $self = shift; my $method = shift; my $arg = shift; my $options = shift; $self->_reset; $self->_parse_options($options || {}); # patch to allow a parse-time option for elements to be empty foreach my $el (@{$self->_parse_options()->{'allow_empty'}}) { $empty_ok_elements{$el} = 1; } # Workaround to make sure that if we were defined with version => "2.0" # then we can still parse 1.0 and 0.9.x feeds correctly. if ($self->{version} eq "2.0") { $self->{modules} = +{%{$self->_get_default_modules()}, %{$self->{modules}}}; } { my $parser = $self->_get_parser(); eval { $parser->$method($arg); }; if ($@) { my $err = $@; # Cleanup so perl-5.6.2 will be happy. $parser->setHandlers(map { ($_ => \&_empty) } (qw(Char XMLDecl Start End))); $self->_parser(0); undef($parser); die $err; } } $self->_auto_add_modules if $AUTO_ADD; $self->{version} = $self->{_internal}->{version}; return $self; } sub parse { my $self = shift; my $text_to_parse = shift; my $options = shift; return $self->_generic_parse("parse", $text_to_parse, $options); } sub parsefile { my $self = shift; my $file_to_parse = shift; my $options = shift; return $self->_generic_parse("parsefile", $file_to_parse, $options); } sub _untaint { my $self = shift; my $value = shift; my ($untainted) = ($value =~ m{(.*)}s); return $untainted; } sub _get_save_output_mode { my $self = shift; return (">:encoding(" . $self->_untaint($self->_encoding()) . ")"); } sub save { my ($self, $file) = @_; local (*OUT); open(OUT, $self->_get_save_output_mode(), "$file") or croak "Cannot open file $file for write: $!"; print OUT $self->as_string; close OUT; } sub strict { my ($self, $value) = @_; $self->{'strict'} = $value; } sub _handle_accessor { my $self = shift; my $name = shift; my $type = ref($self); 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]}; # 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}; } # 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]; #} } sub _modules { my $self = shift; return $self->_handle_accessor("modules", @_); } sub channel { my $self = shift; return $self->_handle_accessor("channel", @_); } sub image { my $self = shift; return $self->_handle_accessor("image", @_); } sub textinput { my $self = shift; return $self->_handle_accessor("textinput", @_); } sub skipDays { my $self = shift; return $self->_handle_accessor("skipDays", @_); } sub skipHours { my $self = shift; return $self->_handle_accessor("skipHours", @_); } ### Read only, scalar accessors sub _encode_output { my $self = shift; return $self->{'encode_output'}; } sub _encoding { my $self = shift; return $self->{'encoding'}; } sub _stylesheet { my $self = shift; return $self->{'stylesheet'}; } sub _get_items { my $self = shift; return $self->{items}; } 1; __END__ =pod =encoding UTF-8 =head1 NAME XML::RSS - creates and updates RSS files =head1 VERSION version 1.65 =head1 SYNOPSIS # create an RSS 1.0 file (http://purl.org/rss/1.0/) use XML::RSS; my $rss = XML::RSS->new(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@freshmeat.net', publisher => 'scoop@freshmeat.net', 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 (graphics at freshmeat.net)", }, ); $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 (s2mdalle at titan.vcu.edu)", }, 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 = XML::RSS->new (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@freshmeat.net', webMaster => 'scoop@freshmeat.net' ); $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 = XML::RSS->new( 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 ones if # there are already 15 items or more my $rss = XML::RSS->new; $rss->parsefile("fm.rdf"); while (@{$rss->{'items'}} >= 15) { shift (@{ $rss->{'items'} }); } $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, 1.0, and 2.0 version, and other nifty things. This might be helpful if you want to include news feeds on your Web site from sources like Slashdot and Freshmeat or if you want to syndicate your own content. XML::RSS currently supports versions L<0.9|http://www.rssboard.org/rss-0-9-0>, L<0.91|http://www.rssboard.org/rss-0-9-1>, L<1.0|http://web.resource.org/rss/1.0/>, and L<2.0|http://www.rssboard.org/rss-2-0> of RSS. 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 messages, products catalogs, etc. B In order to parse and generate dates (such as C and C) it is recommended to use L and L , which is what L uses internally and requires. It should also be possible to pass L objects which will be formatted accordingly. E.g: use DateTime (); my $dt = DateTime->from_epoch(epoch => 1_500_000_000); $rss->channel( pubDate => $dt, . . . ); =head1 METHODS =over 4 =item XML::RSS->new(version=>$version, encoding=>$encoding, output=>$output, stylesheet=>$stylesheet_url, 'xml:base'=>$base) 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 is 1.0. The default B is UTF-8. You may also specify the B format regardless 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 XML::RSS will make sure to encode any entities in generated RSS. This is now on by default. You can also pass an optional URL to an XSL stylesheet that can be used to output an C<<< >>> meta-tag in the header that will allow some browsers to render the RSS file as HTML. You can also set C to a reference to a subroutine that will encode the output in a custom way. This subroutine accepts two parameters: a reference to the C-derived object (which should normally not concern you) and the text to encode. It should return the text to encode. If not set, then the module will encode using its custom encoding routine. xml:base will set an C property as per http://www.w3.org/TR/xmlbase/ Note that in order to encode properly, you need to handle "CDATA" sections properly. Look at L's C<_default_encode()> method for how to do it properly. =item add_item (title=>$title, link=>$link, description=>$desc, mode=>$mode) Adds an item to the XML::RSS object. B and B are optional. The default B is append, which adds the item to the end of the list. To insert an item, set the mode to B. The items are stored in the array C<< @{$obj->{'items'}} >> where B<$obj> is a reference to an XML::RSS object. One can specify a category by using the B<'category'> key. B<'category'> can point to an array reference of categories: $rss->add_item( title => "Foo&Bar", link => "http://www.my.tld/", category => ["OneCat", "TooCat", "3Kitties"], ); =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 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 retrieve 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, \%options) Parses an RDF Site Summary which is passed into B<parse()> as the first parameter. Returns the instance of the object so one can say C<< $rss->parse($string)->other_method() >>. See the add_module() method for instructions on automatically adding modules as a string is parsed. %options is a list of options that specify how parsing is to be done. The available options are: =over 4 =item * allow_multiple Takes an array ref of names which indicates which elements should be allowed to have multiple occurrences. So, for example, to parse feeds with multiple enclosures $rss->parse($xml, { allow_multiple => ['enclosure'] }); =item * hashrefs_instead_of_strings If true, then some items (so far "C<description>") will become hash-references instead of strings (with a B<content> key containing their content , B<if> they have XML attributes. Without this key, the attributes will be ignored and there will only be a string. Thus, specifying this option may break compatibility. =item * modules_as_arrays This option when true, will parse the modules key-value-pairs as an arrayref of C<<< { el => $key_name, value => $value, } >>> hash-refs to gracefully handle duplicate items (see below). It will not affect the known modules such as dc ("Dublin Core"). =item * allow_empty Takes an array ref of names which indicates which elements are allowed to be empty. So, for example, to parse feeds with custom fields with the form C<<< <foo bar="1" baz="2" /> >>> which have no content, only attributes, add: $rss->parse($xml, { allow_empty => ['foo'] }); ( Added in XML::RSS v 1.63 .) =back =item parsefile ($file, \%options) 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 skipDays (day => $day) Populates the skipDays element with the day $day. =item skipHours (hour => $hour) Populates the skipHours element, with the hour $hour. =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 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 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, date=>$date }); 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/ The Dublin Core ('dc') hash keys may be point to an array reference, which in turn will specify multiple such keys, and render them one after the other. For example: $rss->add_item ( title => $title, link => $link, dc => { subject=> ["Jungle", "Desert", "Swamp"], creator=>$creator, date=>$date }, ); 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 }); You can also set the value of the module's prefix to an array reference of C<<< { el => , val => } >>> hash-references, in which case duplicate elements are possible: $rss->add_item(title=>$title, link=>$link, my=> [ {el => "rating", value => $rating1, } {el => "rating", value => $rating2, }, ] 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 Non-API Methods =head2 $rss->as_rss_0_9() B<WARNING>: this function is not an API function and should not be called directly. It is kept as is for backwards compatibility with legacy code. Use the following code instead: $rss->{output} = "0.9"; my $text = $rss->as_string(); This function renders the data in the object as an RSS version 0.9 feed, and returns the resultant XML as text. =head2 $rss->as_rss_0_9_1() B<WARNING>: this function is not an API function and should not be called directly. It is kept as is for backwards compatibility with legacy code. Use the following code instead: $rss->{output} = "0.91"; my $text = $rss->as_string(); This function renders the data in the object as an RSS version 0.91 feed, and returns the resultant XML as text. =head2 $rss->as_rss_1_0() B<WARNING>: this function is not an API function and should not be called directly. It is kept as is for backwards compatibility with legacy code. Use the following code instead: $rss->{output} = "1.0"; my $text = $rss->as_string(); This function renders the data in the object as an RSS version 1.0 feed, and returns the resultant XML as text. =head2 $rss->as_rss_2_0() B<WARNING>: this function is not an API function and should not be called directly. It is kept as is for backwards compatibility with legacy code. Use the following code instead: $rss->{output} = "2.0"; my $text = $rss->as_string(); This function renders the data in the object as an RSS version 2.0 feed, and returns the resultant XML as text. =head2 $rss->handle_char() Needed for XML::Parser. Don't use this directly. =head2 $rss->handle_dec() Needed for XML::Parser. Don't use this directly. =head2 $rss->handle_start() Needed for XML::Parser. Don't use this directly. =head1 BUGS Please use rt.cpan.org for tracking bugs. The list of current open bugs is at L<http://rt.cpan.org/Dist/Display.html?Queue=XML-RSS>. To report a new bug, go to L<http://rt.cpan.org/Ticket/Create.html?Queue=XML-RSS> Please include a failing test in your bug report. I'd much rather have a well written test with the bug report than a patch. When you create diffs (for tests or patches), please use the C<-u> parameter to diff. =head1 SOURCE AVAILABILITY The source is available from the GitHub repository: L<https://github.com/shlomif/perl-XML-RSS> =head1 AUTHOR Original code: Jonathan Eisenzopf <eisen@pobox.com> Further changes: Rael Dornfest <rael@oreilly.com>, Ask Bjoern Hansen <ask@develooper.com> Currently: Shlomi Fish <shlomif@cpan.org> =head1 COPYRIGHT Copyright (c) 2001 Jonathan Eisenzopf <eisen@pobox.com> and Rael Dornfest <rael@oreilly.com>, Copyright (C) 2006-2007 Ask Bjoern Hansen <ask@develooper.com>. =head1 LICENSE XML::RSS is free software. You can redistribute it and/or modify it under the same terms as Perl itself. =head1 CREDITS Wojciech Zwiefka <wojtekz@cnt.pl> Chris Nandor <pudge@pobox.com> Jim Hebert <jim@cosource.com> Randal Schwartz <merlyn@stonehenge.com> rjp@browser.org Kellan Elliott-McCrea <kellan@protest.net> Rafe Colburn <rafe@rafe.us> Adam Trickett <atrickett@cpan.org> Aaron Straup Cope <asc@vineyard.net> Ian Davis <iand@internetalchemy.org> rayg@varchars.com Shlomi Fish <shlomif@cpan.org> =head1 SEE ALSO perl(1), XML::Parser(3). =for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan =head1 SUPPORT =head2 Websites The following websites have more information about this module, and may be of help to you. As always, in addition to those websites please use your favorite search engine to discover more resources. =over 4 =item * MetaCPAN A modern, open-source CPAN search engine, useful to view POD in HTML format. L<https://metacpan.org/release/XML-RSS> =item * RT: CPAN's Bug Tracker The RT ( Request Tracker ) website is the default bug/issue tracking system for CPAN. L<https://rt.cpan.org/Public/Dist/Display.html?Name=XML-RSS> =item * CPANTS The CPANTS is a website that analyzes the Kwalitee ( code metrics ) of a distribution. L<http://cpants.cpanauthors.org/dist/XML-RSS> =item * CPAN Testers The CPAN Testers is a network of smoke testers who run automated tests on uploaded CPAN distributions. L<http://www.cpantesters.org/distro/X/XML-RSS> =item * CPAN Testers Matrix The CPAN Testers Matrix is a website that provides a visual overview of the test results for a distribution on various Perls/platforms. L<http://matrix.cpantesters.org/?dist=XML-RSS> =item * CPAN Testers Dependencies The CPAN Testers Dependencies is a website that shows a chart of the test results of all dependencies for a distribution. L<http://deps.cpantesters.org/?module=XML::RSS> =back =head2 Bugs / Feature Requests Please report any bugs or feature requests by email to C<bug-xml-rss at rt.cpan.org>, or through the web interface at L<https://rt.cpan.org/Public/Bug/Report.html?Queue=XML-RSS>. You will be automatically notified of any progress on the request by the system. =head2 Source Code The code is open to the world, and available for you to hack on. Please feel free to browse it and play with it, or whatever. If you want to contribute patches, please send me a diff or prod me to pull from your repository :) L<https://github.com/shlomif/perl-XML-RSS> git clone git://github.com/shlomif/perl-XML-RSS.git =head1 AUTHOR Shlomi Fish <shlomif@cpan.org> =head1 BUGS Please report any bugs or feature requests on the bugtracker website L<https://github.com/shlomif/perl-XML-RSS/issues> When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature. =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2001 by Various. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut ���������������������������������������������������������������������������������������������������������������������00-compile.t����������������������������������������������������������������������������������������100644��001750��001750�� 3274�14756547744� 15452� 0����������������������������������������������������������������������������������������������������ustar�00shlomif�������������������������shlomif�������������������������000000��000000��XML-RSS-1.65/t���������������������������������������������������������������������������������������������������������������������������������������������������������use 5.006; use strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::Compile 2.058 use Test::More; plan tests => 8 + ($ENV{AUTHOR_TESTING} ? 1 : 0); my @module_files = ( 'XML/RSS.pm', 'XML/RSS/Private/Output/Base.pm', 'XML/RSS/Private/Output/Roles/ImageDims.pm', 'XML/RSS/Private/Output/Roles/ModulesElems.pm', 'XML/RSS/Private/Output/V0_9.pm', 'XML/RSS/Private/Output/V0_91.pm', 'XML/RSS/Private/Output/V1_0.pm', 'XML/RSS/Private/Output/V2_0.pm' ); # no fake home requested my @switches = ( -d 'blib' ? '-Mblib' : '-Ilib', ); use File::Spec; use IPC::Open3; use IO::Handle; open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!"; my @warnings; for my $lib (@module_files) { # see L<perlfaq8/How can I capture STDERR from an external command?> my $stderr = IO::Handle->new; diag('Running: ', join(', ', map { my $str = $_; $str =~ s/'/\\'/g; q{'} . $str . q{'} } $^X, @switches, '-e', "require q[$lib]")) if $ENV{PERL_COMPILE_TEST_DEBUG}; my $pid = open3($stdin, '>&STDERR', $stderr, $^X, @switches, '-e', "require q[$lib]"); binmode $stderr, ':crlf' if $^O eq 'MSWin32'; my @_warnings = <$stderr>; waitpid($pid, 0); is($?, 0, "$lib loaded ok"); shift @_warnings if @_warnings and $_warnings[0] =~ /^Using .*\bblib/ and not eval { +require blib; blib->VERSION('1.01') }; if (@_warnings) { warn @_warnings; push @warnings, @_warnings; } } is(scalar(@warnings), 0, 'no warnings found') or diag 'got warnings: ', ( Test::More->can('explain') ? Test::More::explain(\@warnings) : join("\n", '', @warnings) ) if $ENV{AUTHOR_TESTING}; ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������enclosures2.t���������������������������������������������������������������������������������������100644��001750��001750�� 5553�14756547744� 16053� 0����������������������������������������������������������������������������������������������������ustar�00shlomif�������������������������shlomif�������������������������000000��000000��XML-RSS-1.65/t���������������������������������������������������������������������������������������������������������������������������������������������������������use strict; use warnings; use Test::More; use constant RSS_VERSION => "2.0"; use constant RSS_ENCLOSURE_URL => qq(http://www.scripting.com/mp3s/weatherReportSuite.mp3); use constant RSS_ENCLOSURE_LENGTH => qq(12216320); use constant RSS_ENCLOSURE_TYPE => qq(audio/mpeg); use constant RSS_DOCUMENT => qq(<?xml version="1.0"?> <rss version="2.0"> <channel> <title>Example 2.0 Channel with Enclosure sub-element of Item http://example.com/ To lead by example en-us All content Public Domain, except comments which remains copyright the author editor\@example.com webmaster\@example.com http://backend.userland.com/rss Reference/Libraries/Library_and_Information_Science/Technical_Services/Cataloguing/Metadata/RDF/Applications/RSS/ The Superest Dooperest RSS Generator Mon, 02 Sep 2002 03:19:17 GMT 60 News for September the Second http://example.com/2002/09/02 other things happened today http://example.com/2002/09/02/comments.html joeuser\@example.com Mon, 02 Sep 2002 03:19:00 GMT http://example.com/2002/09/02 ); plan tests => 8; use_ok("XML::RSS"); my $xml = XML::RSS->new(); isa_ok($xml,"XML::RSS"); eval { $xml->parse(RSS_DOCUMENT); }; is($@,'',"Parsed RSS feed"); cmp_ok($xml->{'_internal'}->{'version'},"eq",RSS_VERSION,"Is RSS version ".RSS_VERSION); cmp_ok(ref($xml->{items}),"eq","ARRAY","\$xml->{items} is an ARRAY ref"); if($xml->{items} && ref($xml->{items}) eq 'ARRAY'){ my $item = shift @{$xml->{items}}; if($item->{enclosure} && ref($item->{enclosure}) eq 'HASH'){ my $encl = $item->{enclosure}; cmp_ok($encl->{'url'},"eq",RSS_ENCLOSURE_URL, "ENCLOSURE URL is ".RSS_ENCLOSURE_URL); cmp_ok($encl->{'length'},"eq",RSS_ENCLOSURE_LENGTH, "ENCLOSURE URL is ".RSS_ENCLOSURE_LENGTH); cmp_ok($encl->{'type'},"eq",RSS_ENCLOSURE_TYPE, "ENCLOSURE URL is ".RSS_ENCLOSURE_TYPE); }else{ ok(0,"Parsing Enclosure element, sub-element of Item"); } } __END__ =head1 NAME enclosures2.t - tests for parsing RSS 2.0 data with XML::RSS.pm =head1 SYNOPSIS use Test::Harness qw (runtests); runtests (./XML-RSS/t/*.t); =head1 DESCRIPTION Tests for parsing RSS 2.0 data with XML::RSS.pm L =head1 AUTHOR Aaron Straup Cope =head1 SEE ALSO http://backend.userland.com/rss2 =cut 1.0-parse-2.t100644001750001750 353714756547744 15354 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t#!/usr/bin/perl use strict; use warnings; use Test::More tests => 8; use XML::RSS; { my $rss = XML::RSS->new(); $rss->parsefile(File::Spec->catfile(File::Spec->curdir(), "t", "data", "merlyn1.rss")); { my $item = $rss->{items}->[0]; # TEST is ($item->{dc}->{creator}, "merlyn", "item[0]/dc/creator in RSS 1.0" ); # TEST is ($item->{dc}->{date}, "2006-10-05T14:56:02+00:00", "item[0]/dc/date in RSS 1.0" ); # TEST is ($item->{dc}->{subject}, "journal", "item[0]/dc/subject in RSS 1.0" ); } } { my $rss = XML::RSS->new(version => "2.0"); $rss->parsefile(File::Spec->catfile(File::Spec->curdir(), "t", "data", "merlyn1.rss")); { my $item = $rss->{items}->[0]; # TEST is ($item->{dc}->{creator}, "merlyn", "item[0]/dc/creator in RSS 1.0" ); # TEST is ($item->{dc}->{date}, "2006-10-05T14:56:02+00:00", "item[0]/dc/date in RSS 1.0" ); # TEST is ($item->{dc}->{subject}, "journal", "item[0]/dc/subject in RSS 1.0" ); } } { my $rss = XML::RSS->new(); $rss->parsefile( File::Spec->catfile( File::Spec->curdir(), "t", "data", "1.0","with_content.rdf" ) ); { my $item = $rss->{items}->[0]; # TEST is ($item->{content}->{encoded}, "

Hello!

", "Testing the \"content\" namespace"); } } { my $rss = XML::RSS->new(); $rss->parsefile( File::Spec->catfile( File::Spec->curdir(), "examples", "1.0", "rss1.0.rdf", ) ); # TEST is ( $rss->image("rdf:resource"), "http://freshmeat.net/images/fm.mini.jpg", "rdf:resource for image was read correctly.", ); } subcategory.t100644001750001750 516614756547744 16136 0ustar00shlomifshlomif000000000000XML-RSS-1.65/tuse strict; use warnings; use XML::RSS; use Test::More; if (eval "require Test::Differences") { Test::Differences->import; plan tests => 3; } else { plan skip_all => 'Test::Differences required'; } my $simple_xml = < EOF my $sub_xml = < EOF my $complex_xml = < EOF my $simple_rss = XML::RSS->new(version => '2.0'); my $sub_rss = XML::RSS->new(version => '2.0'); my $complex_rss = XML::RSS->new(version => '2.0'); foreach my $rss ($simple_rss, $sub_rss, $complex_rss) { $rss->add_module( prefix => 'itunes', uri => 'http://www.itunes.com/dtds/podcast-1.0.dtd' ); } $simple_rss->channel(itunes => {category => {text => 'Technology'}}); $sub_rss->channel( itunes => { category => { text => 'Technology', category => {text => 'Computers'} } } ); $complex_rss->channel( itunes => { category => [ { text => 'Society & Culture', category => {text => 'History'} }, { text => 'Technology', category => [{text => 'Gadgets'}, {text => 'Computers'}, {text => 'News'}] } ] } ); # TEST eq_or_diff($simple_rss->as_string . "\n", $simple_xml, 'Single category'); # TEST eq_or_diff($sub_rss->as_string . "\n", $sub_xml, 'Subcategory'); # TEST eq_or_diff($complex_rss->as_string . "\n", $complex_xml, 'Multiple categories with subcategoris'); 2.0-parse-2.t100644001750001750 1332514756547744 15371 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t#!/usr/bin/perl use strict; use warnings; use Test::More tests => 14; use XML::RSS; use File::Spec; { my $rss = XML::RSS->new(); $rss->parse(<<"EOF"); Journalism - Topix.net http://www.topix.net/news/journalism News on Journalism from Topix.net en-us Copyright 2006, Topix.net Topix.net http://www.topix.net/ http://www.topix.net/pics/logo4.gif Gannett Reportedly Mulling Tribune Bid http://topix.net/r/0l1Qq8DEtErajq5wDAIHZ0RavmEQ=2BIyZGBfGjcVwyQpW0DFdgUcy=2FtbxGNgMtYEdbU7ucVOR=2Bw2Bu6K4EDvt9=2B7ILEWB6Q5Zxy64f9JxkGU92am=2FLdMjb=2FCxbmfNuBQX6 Comment]]> The Associated Press on Topix.net Mon, 13 Nov 2006 15:50:44 GMT eQE3vmbXGCzvaHn0deSSyA Journalism - Topix.net Use the text input below to search Topix.net q http://www.topix.net/search/ EOF # TEST is ($rss->{textinput}->{link}, "http://www.topix.net/search/", "Testing for textinput link" ); # TEST is ($rss->{channel}->{link}, "http://www.topix.net/news/journalism", "Testing for channel link" ); } { my $rss = XML::RSS->new(); $rss->parsefile( File::Spec->catfile( File::Spec->curdir(), "examples", "2.0", "rss-2.0-sample-from-rssboard-multiple-skip-days-and-hours.xml" ) ); # TEST is_deeply( $rss->{'skipHours'}->{'hour'}, [qw(0 1 2 22 23)], "skipHours/hour is parsed into an array with the individual elements", ); # TEST is_deeply( $rss->{'skipDays'}->{'day'}, [qw(Saturday Sunday)], "skipDays/day is parsed into an array with indiv elements", ); # TEST is_deeply( $rss->{'channel'}->{'category'}, [qw(Media Texas)], "Multiple categories", ); } { my $rss = XML::RSS->new(); $rss->parsefile( File::Spec->catfile( File::Spec->curdir(), "t", "data", "2.0", "sf-hs-with-pubDate.rss" ), ); # TEST is_deeply( $rss->{'items'}->[0]->{'category'}, [qw( mathml mathematics math dos jokes tucan ideas mathventures unixdoc )], "items/category is an array-ref", ); } { my $rss = XML::RSS->new(); $rss->parsefile( File::Spec->catfile( File::Spec->curdir(), "t", "data", "2.0", "no-desc.rss", ), ); # TEST ok (!defined($rss->channel("description")), "description is undefined if not present" ); # TEST ok (!defined($rss->channel("title")), "title is undefined if not present", ); } { my $rss = XML::RSS->new(); $rss->parsefile( File::Spec->catfile( File::Spec->curdir(), "t", "data", "2.0", "empty-desc.rss", ), ); # TEST is ($rss->channel("description"), "", "description is an empty string if an empty tag" ); # TEST is ($rss->channel("title"), "", "title is an empty string if an empty tasg", ); } { my $rss = XML::RSS->new(); $rss->parsefile( File::Spec->catfile( File::Spec->curdir(), qw(examples 2.0 flickr-rss-with-both-desc-and-media-desc.xml) ), { hashrefs_instead_of_strings => 1 }, ); # TEST like ($rss->{'items'}->[0]->{'description'}, qr{\A\Q

{'items'}->[0] ->{'http://search.yahoo.com/mrss/'}->{'description'} ->{'content'}, qr{\A

No active bugs}, "media:desc content is OK.", ); # TEST is ($rss->{'items'}->[0] ->{'http://search.yahoo.com/mrss/'}->{'description'} ->{'type'}, "html", "media:desc type is OK.", ); } { my $rss = XML::RSS->new(); $rss->parse(<<'EOF'); ]> The Blog http://example.com/ A blog about things Mon, 03 Feb 2014 00:00:00 -0000 Without&xxe;Entity http://example.com a post author@example.com Mon, 03 Feb 2014 00:00:00 -0000 EOF # TEST is ($rss->{items}->[0]->{title}, "WithoutEntity", "Fix for RT #100660 - XML External Entities Exploit", ); } 2.0-modules.t100644001750001750 254314756547744 15550 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t#!/usr/bin/perl use strict; use warnings; use Test::More tests => 4; use XML::RSS; { my $rss = XML::RSS->new( version => '2.0' ); $rss->channel( link => "http://www.homesite.tld/", description => "My homesite", title => "With content", ); $rss->add_module( prefix => 'content', uri => 'http://purl.org/rss/1.0/modules/content/' ); $rss->add_item( title => 'title', content => { encoded => 'this is content' }, ); # TEST like $rss->as_string, qr/this is content/; } { my $rss = XML::RSS->new( version => '2.0' ); eval { $rss->add_module( prefix => 'a/b', uri => 'http://foobar.tld/foo/' ); }; # TEST like ($@, qr{\Aa namespace prefix should look like}, "Testing for invalidty of / as a prefix char"); } { my $rss = XML::RSS->new( version => '2.0' ); eval { $rss->add_module( prefix => "myprefix", ); }; # TEST like ($@, qr{\Aa URI must be provided}, "Testing for exception upon an unspecified URI."); } { my $rss = XML::RSS->new( version => '2.0' ); # TEST ok($rss->add_module(prefix=>'creativeCommons', uri=>'http://backend.userland.com/creativeCommonsRssModule'),"Added namespace with uppercase letters in prefix"); } examples000755001750001750 014756547744 14625 5ustar00shlomifshlomif000000000000XML-RSS-1.65README100644001750001750 24414756547744 15625 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examplesgeneral tools are in the examples top directory. RSS examples are located in their respective version directories along with any specific scripts for that version. author000755001750001750 014756547744 14744 5ustar00shlomifshlomif000000000000XML-RSS-1.65/xteol.t100644001750001750 356414756547744 16060 0ustar00shlomifshlomif000000000000XML-RSS-1.65/xt/authoruse strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::EOL 0.19 use Test::More 0.88; use Test::EOL; my @files = ( 'lib/XML/RSS.pm', 'lib/XML/RSS/Private/Output/Base.pm', 'lib/XML/RSS/Private/Output/Roles/ImageDims.pm', 'lib/XML/RSS/Private/Output/Roles/ModulesElems.pm', 'lib/XML/RSS/Private/Output/V0_9.pm', 'lib/XML/RSS/Private/Output/V0_91.pm', 'lib/XML/RSS/Private/Output/V1_0.pm', 'lib/XML/RSS/Private/Output/V2_0.pm', 't/0.9-generate.t', 't/0.9-parse.t', 't/0.9-strict.t', 't/0.91-parse.t', 't/00-compile.t', 't/1.0-gen-errors-on-missing-fields.t', 't/1.0-generate.t', 't/1.0-parse-2.t', 't/1.0-parse-exotic.t', 't/1.0-parse.t', 't/1.0-to-2.0.t', 't/2.0-generate.t', 't/2.0-modules.t', 't/2.0-parse-2.t', 't/2.0-parse-cloud.t', 't/2.0-parse-self.t', 't/2.0-parse.t', 't/2.0-permalink.t', 't/2.0-wo-title.t', 't/add-item-insert-vs-append.t', 't/auto_add_modules.t', 't/charset1.t', 't/data/1.0/rss1.0.exotic.rdf', 't/data/1.0/with_content.rdf', 't/data/2.0/empty-desc.rss', 't/data/2.0/no-desc.rss', 't/data/2.0/sf-hs-with-lastBuildDate.rss', 't/data/2.0/sf-hs-with-pubDate.rss', 't/data/freshmeat.rdf', 't/data/merlyn1.rss', 't/data/rss-permalink.xml', 't/empty-elements.t', 't/enclosures-multi.t', 't/enclosures.t', 't/enclosures2.t', 't/encode-output.t', 't/encoding.t', 't/generated/placeholder.txt', 't/guid-outside-item.t', 't/guid.t', 't/load.t', 't/render-upon-init.t', 't/rss2-gt-encoding.t', 't/rss2-nested-custom-tag.t', 't/save-while-in-taint-mode.t', 't/subcategory.t', 't/test-generated-items.t', 't/version.t', 't/xml-base.t', 't/xml-header.t' ); eol_unix_ok($_, { trailing_whitespace => 1 }) foreach @files; done_testing; 0.9-generate.t100644001750001750 101014756547744 15665 0ustar00shlomifshlomif000000000000XML-RSS-1.65/tuse strict; use warnings; use Test::More; plan tests => 1; ok(1, "More tests soon"); __END__ =head1 NAME 0.9-generate.t - tests for generating RSS 0.90 data with XML::RSS.pm =head1 SYNOPSIS use Test::Harness qw (runtests); runtests (./XML-RSS/t/*.t); =head1 DESCRIPTION Tests for generating RSS 0.90 data with XML::RSS.pm =head1 VERSION $Revision: 1.2 $ =head1 DATE $Date: 2003/02/20 17:12:44 $ =head1 AUTHOR Aaron Straup Cope =head1 SEE ALSO http://www.purplepages.ie/RSS/netscape/rss0.90.html =cut 2.0-generate.t100644001750001750 1255614756547744 15717 0ustar00shlomifshlomif000000000000XML-RSS-1.65/tuse strict; use warnings; use Test::More tests => 29; BEGIN { use_ok("XML::RSS"); use_ok("POSIX"); } use constant DATE_TEMPLATE_LONG => "%Y-%m-%dT%H:%M:%S%z"; use constant DATE_TEMPLATE_SHORT => "%Y/%m/%d"; use constant DATE_TEMPLATE_PUB => "%c GMT"; my $current_date = &POSIX::strftime( DATE_TEMPLATE_LONG, gmtime ); my $short_date = &POSIX::strftime( DATE_TEMPLATE_SHORT, gmtime ); my $pub_date = &POSIX::strftime( DATE_TEMPLATE_PUB, gmtime ); ok( $current_date, "Current date: $current_date" ); use constant RSS_VERSION => "2.0"; use constant RSS_SAVEAS => "t/generated/" . RSS_VERSION . "-generated.xml"; use constant RSS_MOD_PREFIX => "my"; use constant RSS_MOD_URI => 'http://purl.org/my/rss/module/'; use constant RSS_BLOGCHANNEL_PREFIX => "blogChannel"; use constant RSS_BLOGCHANNEL_URI => "http://backend.userland.com/blogChannelModule"; use constant RSS_CREATOR => "joeuser\@example.com"; use constant RSS_ITEM_TITLE => "This is an item"; use constant RSS_ITEM_LINK => "http://example.com/" . &POSIX::strftime( DATE_TEMPLATE_SHORT, gmtime ); # "$short_date"; use constant RSS_ITEM_DESC => "Yadda yadda yadda - R&D;"; use constant RSS_XML_BASE => "http://example.com"; my $rss = XML::RSS->new( version => RSS_VERSION, 'xml:base' => RSS_XML_BASE ); isa_ok( $rss, "XML::RSS" ); is( $rss->{'version'}, RSS_VERSION, 'Version is ' . RSS_VERSION ); is( $rss->{'xml:base'}, RSS_XML_BASE, 'Base is ' . RSS_XML_BASE ); # This includes all fields, only title, link, and description # are required. ok( $rss->channel( 'title' => "Test 2.0 Feed", 'link' => "http://example.com/", 'description' => "", 'language' => 'en-us', copyright => 'Copyright 2002', pubDate => $current_date, lastBuildDate => $current_date, docs => 'http://backend.userland.com/rss', managingEditor => 'editor\@example.com', webMaster => 'webmaster\@example.com', category => 'MyCategory', ttl => '60', 'generator' => 'XML::RSS Test', ), "Set RSS channel" ); ok($rss->image( title => 'Test Image', url => 'http://example.com/example.gif', 'link' => 'http://example.com/', description => 'Test Image', height => '25', weight => '144', ), "Set RSS image" ); ok($rss->textinput( title => 'Search', description => 'Search for an example', name => 'q', 'link' => 'http://example.com/search.pl', ), "Set RSS text input" ); ok($rss->add_item( title => RSS_ITEM_TITLE, 'link' => RSS_ITEM_LINK, description => RSS_ITEM_DESC, author => RSS_CREATOR, category => 'MyCategory', comments => "http://example.com/$short_date/comments.html", permaLink => "http://example.com/$short_date", pubDate => $pub_date, source => 'my brain', sourceUrl => 'http://example.com', enclosure => { type=>"application/x-bittorrent", url => 'http://127.0.0.1/torrents/The_Passion_of_Dave_Winer.torrent' }, ), "Set one RSS item" ); ok( $rss->add_module( prefix => RSS_MOD_PREFIX, uri => RSS_MOD_URI ), "Added module: " . RSS_MOD_PREFIX ); my $uri = RSS_MOD_URI; #use Data::Dumper; #warn Data::Dumper->Dump([\$rss], [qw(rss)] ); is( $rss->{modules}->{$uri}, RSS_MOD_PREFIX, "Namespace URI is " . RSS_MOD_URI); my $as_string = $rss->as_string(); my $len = length($as_string); ok( $len, "RSS feed has '$len' characters" ); ok( $rss->save(RSS_SAVEAS), "Wrote to disk: " . RSS_SAVEAS ); my $file_contents; { local $/; open I, "<", RSS_SAVEAS(); $file_contents = ; close(I); } is($file_contents,$as_string,RSS_SAVEAS." contains the as_string() result"); eval { $rss->parsefile( RSS_SAVEAS ) }; is( $@, '', "Parsed " . RSS_SAVEAS ); is( $rss->{channel}->{lastBuildDate}, $current_date, "Last built: " . $current_date ); is( $rss->{channel}->{category}, 'MyCategory', 'channel->{category}'); is( $rss->{'xml:base'}, RSS_XML_BASE, 'Base has been reparsed'); cmp_ok( keys %{ $rss->{namespaces} }, ">=", 1, "RSS feed has at least one namespace"); my $prefix = RSS_BLOGCHANNEL_PREFIX; ok( exists $rss->{namespaces}->{$prefix}, "$prefix namespace is registered" ); is($rss->{namespaces}->{$prefix}, RSS_BLOGCHANNEL_URI, RSS_BLOGCHANNEL_URI ); isa_ok( $rss->{'items'} ,"ARRAY", "RSS object has an array of objects" ); is( scalar( @{$rss->{'items'}} ), 1, "RSS object has one item" ); is( $rss->{items}->[0]->{title}, RSS_ITEM_TITLE, RSS_ITEM_TITLE ); is( $rss->{items}->[0]->{link}, RSS_ITEM_LINK, RSS_ITEM_LINK ); is( $rss->{items}->[0]->{description}, RSS_ITEM_DESC, RSS_ITEM_DESC ); is( $rss->{items}->[0]->{author}, RSS_CREATOR, RSS_CREATOR ); eval { $rss->save("."); }; ok ($@ =~ m{\ACannot open file \. for write}, "Exception upon saving to an invalid location" ); #END{ unlink RSS_SAVEAS } __END__ =head1 NAME 2.0-generate.t - tests for generating RSS 2.0 data with XML::RSS.pm =head1 SYNOPSIS use Test::Harness qw (runtests); runtests (./XML-RSS/t/*.t); =head1 DESCRIPTION Tests for generating RSS 2.0 data with XML::RSS.pm =head1 VERSION $Revision: 1.8 $ =head1 DATE $Date: 2004/04/21 02:44:40 $ =head1 AUTHOR Aaron Straup Cope =head1 SEE ALSO http://backend.userland.com/rss2 =cu 2.0-wo-title.t100644001750001750 246614756547744 15650 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t#!/usr/bin/perl -w use strict; use warnings; use Test::More tests => 2; # TEST use_ok('XML::RSS'); my $rss = XML::RSS->new(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@freshmeat.net', webMaster => 'scoop@freshmeat.net' ); $rss->add_item( # 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=>"http://www.foo.tld/", type=>"application/x-bittorrent" }, description => 'My Life Changed Absolutely', ); my $string = $rss->as_string(); # TEST ok ( (index($string, 'My Life Changed Absolutely' ) >= 0 ), "Testing for the item being rendered." ); 1; 1.0-generate.t100644001750001750 1044314756547744 15707 0ustar00shlomifshlomif000000000000XML-RSS-1.65/tuse strict; use warnings; use Test::More; plan tests => 25; # 1 use_ok("XML::RSS"); use POSIX; use constant DATE_TEMPLATE_LONG => "%Y-%m-%dT%H:%M:%S%z"; use constant DATE_TEMPLATE_SHORT => "%Y/%m/%d"; use constant DATE_TEMPLATE_PUB => "%c GMT"; my ($current_date, $short_date, $pub_date); BEGIN { $current_date = &POSIX::strftime(DATE_TEMPLATE_LONG, gmtime); $short_date = &POSIX::strftime(DATE_TEMPLATE_SHORT, gmtime); $pub_date = &POSIX::strftime(DATE_TEMPLATE_PUB, gmtime); } use constant RSS_VERSION => "1.0"; use constant RSS_SAVEAS => "./t/generated/".RSS_VERSION."-generated.xml"; use constant RSS_MOD_PREFIX => "my"; use constant RSS_MOD_URI => 'http://purl.org/my/rss/module/'; use constant RSS_CREATOR => "joeuser\@example.com"; use constant RSS_ITEM_TITLE => "This is an item"; use constant RSS_ITEM_LINK => "http://example.com/$short_date"; use constant RSS_ITEM_DESC => "Yadda & yadda & yadda"; use constant RSS_XML_BASE => "http://example.com/"; # 2 ok($current_date,"Current date:$current_date"); # 3 my $rss = XML::RSS->new(version => RSS_VERSION, 'xml:base' => RSS_XML_BASE); isa_ok($rss,"XML::RSS"); # 4-5 cmp_ok($rss->{'version'},"eq",RSS_VERSION,"Version is ".RSS_VERSION); cmp_ok($rss->{'xml:base'},"eq",RSS_XML_BASE,"Base is ".RSS_XML_BASE); # 6-16 ok($rss->channel( 'title' => "Test 1.0 Feed", 'link' => "http://example.com/", 'description' => "To lead by example", 'image' => "http://example.com/example.gif", 'textinput' => 'http://example.com/search.pl', 'dc' => { date => $current_date, }, ),"Set RSS channel"); ok($rss->image( 'title' => 'Test Image', 'url' => 'http://example.com/example.gif', 'link' => 'http://example.com/', 'description' => 'Test Image', 'height' => '25', 'weight' => '144', ),"Set RSS image"); ok($rss->textinput( 'title' => 'Search', 'description' => 'Search for an example', 'name' => 'q', 'link' => 'http://example.com/search.pl', ),"Set RSS text input"); ok($rss->add_item( 'title' => RSS_ITEM_TITLE, 'link' => RSS_ITEM_LINK, 'description' => RSS_ITEM_DESC, 'dc' => { creator => RSS_CREATOR, dc => $short_date, }, ),"Set one RSS item"); ok($rss->add_module(prefix=>RSS_MOD_PREFIX,uri=>RSS_MOD_URI), "Added namespace:".RSS_MOD_PREFIX); ok($rss->add_module(prefix=>'creativeCommons',uri=>'http://backend.userland.com/creativeCommonsRssModule'), "Added namespace with uppercase letters in prefix"); # Dunno - some degree of weirdness # with the constant that I don't # feel like dealing with... my $uri = RSS_MOD_URI; cmp_ok($rss->{modules}->{$uri}, "eq", RSS_MOD_PREFIX, "Namespace URI is ".RSS_MOD_URI); my $as_string = $rss->as_string(); my $len = length($as_string); ok($len,"RSS feed has '$len' characters"); ok($rss->save(RSS_SAVEAS), "Wrote to disk: ".RSS_SAVEAS); my $file_contents; { local $/; open I, "<", RSS_SAVEAS(); $file_contents = ; close(I); } cmp_ok($file_contents,"eq",$as_string,RSS_SAVEAS." contains the as_string() result"); eval { $rss->parsefile(RSS_SAVEAS)}; is($@,'',"Parsed ".RSS_SAVEAS); # 17 cmp_ok($rss->{channel}->{dc}{date}, "eq", $current_date, "dc:date:".$current_date); # 18 cmp_ok(keys(%{$rss->{namespaces}}), ">=", 1, "RSS feed has atleast one namespace"); # 19 cmp_ok($rss->{'xml:base'}, "eq", RSS_XML_BASE, "Base is still ".RSS_XML_BASE); # 20 cmp_ok(ref($rss->{'items'}),"eq","ARRAY","RSS object has an array of objects"); # 21 cmp_ok(scalar(@{$rss->{'items'}}),"==",1,"RSS object has one item"); # 22 cmp_ok($rss->{items}->[0]->{title},"eq",RSS_ITEM_TITLE,RSS_ITEM_TITLE); # 23 cmp_ok($rss->{items}->[0]->{link},"eq",RSS_ITEM_LINK,RSS_ITEM_LINK); # 24 cmp_ok($rss->{items}->[0]->{description},"eq",RSS_ITEM_DESC,RSS_ITEM_DESC); # 25 cmp_ok($rss->{items}->[0]->{dc}->{creator},"eq",RSS_CREATOR,RSS_CREATOR); __END__ =head1 NAME 1.0-generate.t - tests for generating RSS 1.0 data with XML::RSS.pm =head1 SYNOPSIS use Test::Harness qw (runtests); runtests (./XML-RSS/t/*.t); =head1 DESCRIPTION Tests for generating RSS 1.0 data with XML::RSS.pm =head1 VERSION $Revision: 1.5 $ =head1 DATE $Date: 2003/02/20 17:12:45 $ =head1 AUTHOR Aaron Straup Cope =head1 SEE ALSO http://web.resource.org/rss/1.0 =cut 2.0-permalink.t100644001750001750 221014756547744 16051 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t#!/usr/bin/perl use strict; use warnings; use Test::More tests => 4; use File::Spec; use XML::RSS; my $rss = XML::RSS->new; $rss->parsefile(File::Spec->catfile('t', 'data', 'rss-permalink.xml') ); my $item_with_guid_true = $rss->{'items'}->[0]; my $item_with_guid_missing = $rss->{'items'}->[1]; my $item_with_guid_false = $rss->{'items'}->[2]; # TEST is ($item_with_guid_true->{"permaLink"}, "http://community.livejournal.com/lj_dev/714037.html", "guid's isPermaLink is set to true, so the item permalink property should be set to the value of the guid tag" ); # TEST is ($item_with_guid_missing->{"permaLink"}, "http://community.livejournal.com/lj_dev/713810.html", "guid's isPermaLink is missing (implicitly true), so the item permalink property should be set to the value of the guid tag" ); # TEST ok ((!$item_with_guid_false->{"permaLink"}), "guid's isPermaLink is false, so the permalink should be false" ); # TEST is ($item_with_guid_false->{"guid"}, "http://community.livejournal.com/lj_dev/713549.html", "guid's isPermaLink is false so item->{guid} should be equal to" . " the contents of the guid element" ); encode-output.t100644001750001750 104014756547744 16365 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t# $Id: encode-output.t,v 1.2 2003/01/18 01:11:33 comdog Exp $ use Test::More tests => 1; use XML::RSS; use File::Spec; $|++; my $file = File::Spec->catfile(File::Spec->curdir(), "t", "data", "1.0", "rss1.0.exotic.rdf"); my $rss = XML::RSS->new(encode_output => 1); eval { $rss->parsefile( $file ); }; # Test 5. # Encode illegal characters (e.g. &) when outputting RSS # my $rss_str = $rss->as_string(); my $rss2 = XML::RSS->new(); eval { $rss2->parse( $rss_str ); }; unlike ($@, qr/invalid token/, "encode invalid characters" ); empty-elements.t100644001750001750 331114756547744 16545 0ustar00shlomifshlomif000000000000XML-RSS-1.65/tuse strict; use warnings; use Test::More tests => 4; use XML::RSS (); my $RSS_DOCUMENT = qq( Example 2.0 Channel http://example.com/ To lead by example en-us editor\@example.com webmaster\@example.com http://backend.userland.com/rss The Superest Dooperest RSS Generator Mon, 02 Sep 2002 03:19:17 GMT 60 News for September the Second http://example.com/2002/09/02 other things happened today http://example.com/2002/09/02/comments.html joeuser\@example.com Mon, 02 Sep 2002 03:19:00 GMT http://example.com/2002/09/02 ); { my $xml = XML::RSS->new(); # TEST isa_ok($xml, "XML::RSS"); eval { $xml->parse($RSS_DOCUMENT); }; # TEST is($@, '', "Parsed RSS feed"); } { my $xml = XML::RSS->new; eval { $xml->parse($RSS_DOCUMENT, {allow_empty => ['custom']}) }; # TEST is($@, '', "Parsed RSS feed for with option to allow empty 'custom' elements"); # TEST is_deeply( $xml->{items}->[0]->{custom}, {name => "seeds", value => "100"}, "returned custom empty element and its attributes" ); } 2.0-parse-self.t100644001750001750 455014756547744 16141 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t#!/usr/bin/perl use strict; use warnings; use Test::More tests => 4; use XML::RSS; my $text = <<"EOF"; Journalism - Topix.net http://www.topix.net/news/journalism News on Journalism from Topix.net en-us Copyright 2006, Topix.net Topix.net http://www.topix.net/ http://www.topix.net/pics/logo4.gif Gannett Reportedly Mulling Tribune Bid http://topix.net/r/0l1Qq8DEtErajq5wDAIHZ0RavmEQ=2BIyZGBfGjcVwyQpW0DFdgUcy=2FtbxGNgMtYEdbU7ucVOR=2Bw2Bu6K4EDvt9=2B7ILEWB6Q5Zxy64f9JxkGU92am=2FLdMjb=2FCxbmfNuBQX6 Comment]]> The Associated Press on Topix.net Mon, 13 Nov 2006 15:50:44 GMT eQE3vmbXGCzvaHn0deSSyA Journalism - Topix.net Use the text input below to search Topix.net q http://www.topix.net/search/ EOF { my $rss = XML::RSS->new(); # TEST is ($rss->parse($text)->{textinput}->{link}, "http://www.topix.net/search/", "->parse() returns the object again" ); # TEST is ($rss->{textinput}->{link}, "http://www.topix.net/search/", "Testing for textinput link" ); # TEST is ($rss->{channel}->{link}, "http://www.topix.net/news/journalism", "Testing for channel link" ); } { my $rss = XML::RSS->new(); # TEST is ($rss->parsefile( File::Spec->catfile("t", "data", "2.0", "sf-hs-with-pubDate.rss") )->{channel}->{link}, "http://community.livejournal.com/shlomif_hsite/", "->parsefile() returns the object", ); } data000755001750001750 014756547744 14163 5ustar00shlomifshlomif000000000000XML-RSS-1.65/tmerlyn1.rss100644001750001750 10227714756547744 16514 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t/data merlyn's Journal http://use.perl.org/~merlyn/journal/ merlyn's use Perl Journal en-us use Perl; is Copyright 1998-2006, Chris Nandor. Stories, comments, journals, and other submissions posted on use Perl; are Copyright their respective owners. 2006-10-14T21:15:36+00:00 pudge pudge@perl.org Technology hourly 1 1970-01-01T00:00+00:00 merlyn's Journal http://use.perl.org/images/topics/useperl.gif http://use.perl.org/~merlyn/journal/ "Communication is free" http://use.perl.org/~merlyn/journal/31225?from=rss Not sure why it took this long, but <a href="http://www.digitalcitizen.info/2006/10/05/observations-on-the-ramifications-of-electronic-communication-media/">someone has finally posted audio</a> from my "Communication is free" talk at FISL7.0 in Brazil a few months ago. merlyn 2006-10-05T14:56:02+00:00 journal You don't know objects if you don't know Smalltalk http://use.perl.org/~merlyn/journal/31081?from=rss <p>I've often argued that a programmer who says "I know objects" without having touched one of the "pure object" systems like Smalltalk or Eiffel, doesn't really know "objects". When people would ask "what is smalltalk?", I'd point them at <a href="http://www.squeak.org/">Squeak</a>. </p><p>Well <a href="http://www.onlamp.com/pub/au/2584">Keith Fieldhouse</a> has gone and done the next good thing: he's written <a href="http://www.onlamp.com/pub/a/onlamp/2006/09/21/learning_smalltalk.html">an article for OnLAMP about Squeak</a> that gives far more handholding than I've been able to do quickly. Yeay Keith. That one's going into my bookmarks.</p> merlyn 2006-09-22T14:17:47+00:00 journal "Responsible Breech Reporting" - me on another podcast again http://use.perl.org/~merlyn/journal/31034?from=rss <p>I was interviewed for <a href="http://www.securitycatalyst.com/2006/09/17/srt-episode-4-responsible-reporting-of-breaches/">another episode of Security Catalyst</a>: this time, a panel on reponsible breech reporting. Check it out! </p><p> <i>Update:</i> or yeah, breach not breech!</p> merlyn 2006-09-18T02:37:55+00:00 journal Perl Fridge Magnets as OmniGraffle Template http://use.perl.org/~merlyn/journal/31025?from=rss Perhaps posted before, but I just stumbled across <a href="http://www.graffletopia.com/stencils/75">the Perl Fridge Magnets as an OmniGraffle stencil</a>. Enjoy. merlyn 2006-09-17T16:51:58+00:00 journal Plates on sticks! Bears on bicycles! http://use.perl.org/~merlyn/journal/30801?from=rss And a group doing <a href="http://blogfiles.wfmu.org/KF/2006/02/marimba_ponies.mpg">the Sabre Dance</a> on marimba! merlyn 2006-08-30T04:39:32+00:00 journal More Leo, more cruise comments, and now in MP3 goodness http://use.perl.org/~merlyn/journal/30556?from=rss <p> I've just pushed episodes 12 to 14 of <a href="http://podcast.geekcruises.com/">GeekCruises News-es: The Podcast</a> on the time-release site (the first came out today). In these episodes, my buddy Leo Laporte interviews <i>me</i> in a sort of "reverse interview format". </p><p> Also, based on a lot of feedback, I've dropped the "enhanced podcast" format and replaced it with a traditional MP3 flavor. All my grand plans of having lots of embedded pictures and URL links haven't materialized in the first 11 shows, so it's time to fall back to something almost everybody can enjoy.</p> merlyn 2006-08-07T15:55:38+00:00 journal FLOSS weekly interviews *me* http://use.perl.org/~merlyn/journal/30297?from=rss <a href="http://www.twit.tv/floss9">Hear me talk!</a> merlyn 2006-07-15T07:31:01+00:00 journal podcast.geekcruises.com - part 2 of leo laporte http://use.perl.org/~merlyn/journal/30153?from=rss Part 2 of my podcast interview with Leo Laporte is up, where we talk about the origin of the name of the <a href="http://en.wikipedia.org/wiki/Amazon_Mechanical_Turk">Amazon Mechanical Turk</a>. Subscribe or just listen at <a href="http://podcast.geekcruises.com/">podcast.geekcruises.com</a>. merlyn 2006-07-03T13:19:03+00:00 journal Why muni-provided "free" wi-fi is a bad idea http://use.perl.org/~merlyn/journal/30016?from=rss <p>I'm against muni-provided connectivity for three reasons. And none of these apply to things like "police" or "fire", so let me explain why the typical analogy to "public services" doesn't apply. </p><dl> <dt>First, there's the "accountability" issue:</dt> <dd> <p> Without "billing", there's no accountability. If I can get free connections, I can send spam to my heart's content, and you can't turn me off, because I can quickly become "another free user" in a matter of microseconds. </p><p> And I can start p2p-sharing my child pr0n and ripped movie and song collections, and again, you can't turn me off, because I don't actually have a contract with you to terminate. Sure, you can arrest me, but you have to find me in the mesh. It's not like you have a street address for me. Heck, I might even be operating from a van that constantly drives around.</p></dd> <dt> Second, there's the "taxpayer dollar" issue:</dt> <dd> <p> Whether we like it or not, when citizens start paying for shipping bits, they're gonna want some say in the kinds of things that are being shipped across the wire. The moment the soccer mom figures out that part of her tax dollar is paying for that creepy guy over there to download his pr0n, she's gonna be storming city hall. And she's also going to be complaining loudly when she finds out that her son can access all sorts of evil things "over the city's wireless system!" She'll want controls put in place, and rightfully so. After all, she's paying for it. </p><p> As evidence, look at the constant tug-of-war and lawsuits regarding internet access at public libraries. Do you really want to open this up on a city-wide scale? It's the very same issue. </p><p> So, no matter how "open" some of us want this, it's going to start getting filtered. We'll never have a truly censorship-free mesh, except for perhaps the first six months. And if there's a constitutional challenge that comes down to a free-speech thing, it'll more likely get shut off than opened back up.</p></dd> <dt> Third, we kill the incentive for competition:</dt> <dd> <p> OK, you say. Then if there's enough demand for an uncensored equivalent, some private sector can come along and provide a different mesh that provides the full bits. </p><p> Well, that's ignoring the economics of the situtation. To deploy a city-wide private sector net requires a fairly large infrastructure, and that can only be supported by having access to a large customer base. But most of the customers of the "free" citywide net won't be buying, because for them, the "free" net is almost good enough. This is false economics, because they're effectively being subsidized $10 a month by the city's taxbase, and if they had to choose between that and a $15 "get everything" net, they might make a more rational choice.</p></dd> </dl> <p> So, for these reasons, I say that cities <i>must</i> stay out of the wifi business. As much as I'd like "free" wifi, there's no such thing as a free lunch, and as soon as someone realizes they are paying for it, they'll want to control it. </p><p> I'd much rather have a few companies vie for my $15, than for me to get censored, slow, no-choice free service. </p><p> Disclaimer - I pay $60/month for Verizon's EVDO service. I'd still have that in every city, regardless of what they do. I'm speaking more for the friends of mine that can't justify that sort of cost.</p> merlyn 2006-06-23T10:45:02+00:00 journal Misquoting JWZ about databases http://use.perl.org/~merlyn/journal/30002?from=rss <p> When some people are confonted with a database problem, they say to themselves, "I know, I'll use MySQL!" </p><p> Now they have two problems.</p> merlyn 2006-06-22T02:11:26+00:00 journal Look what I could win! http://use.perl.org/~merlyn/journal/29987?from=rss <a href="http://www.freesoftwaremagazine.com/node/1623">I could win a copy of Learning Perl!</a> merlyn 2006-06-21T11:57:24+00:00 journal Grad school instructor, having never been to college? http://use.perl.org/~merlyn/journal/29946?from=rss I'm just thinking that my accomplishment of having taught a grad-school level course for credit (Intro to Perl 501 for cse.ogi.edu) without having <i>ever</i> been to college might be somewhat rare. Are there other instances that you've seen of a grad-school professor who has never themselves been to anything beyond a high-school education? merlyn 2006-06-18T18:58:51+00:00 journal "Duck and Cover" and "A is for Atom" http://use.perl.org/~merlyn/journal/29933?from=rss <p>Thanks to <a href="http://www.renmenven.org/tooncast/tooncast.html">The Vintage Tooncast</a> for making me aware (again) of <a href="http://www.archive.org/details/DuckandC1951">Duck and Cover</a> and <a href="http://www.archive.org/details/isforAto1953">A is for Atom</a>. </p><p> Duck and Cover is a "civil defense" film about how to protect yourself in a nuclear blast. It'd be a perfect MST3K piece now: the idea of protecting yourself from radiation with a newspaper seems amazingly naive and almost malicious. The repetitive "and stay in that position until the danger has passed", without ever explaining (perhaps deliberately) how to know when that has been reached. </p><p> "A is for Atom" is an astonishingly complete and easy-to-watch piece describing precisely how uranium and plutonium bombs work, and goes on to explain how wonderful atomic power will be in the future, providing power, helping farmers, and even producing medical miracles. Of course, to acheive these goals, the dangers of nuclear waste are never mentioned, nor the medical risks from using nuke materials as tracers in the body. </p><p> Although these have both disappeared from the Tooncast feed by the time I watched them (I'm a bit behind), I'd really suggest subscribing to this feed, as they seem to be picking some amazingly cool stuff from archive.org and providing it directly to my video ipod on a regular basis.</p> merlyn 2006-06-17T04:25:31+00:00 journal In praise of good testing http://use.perl.org/~merlyn/journal/29842?from=rss <p> In my work for $client, last week I spent a few hours making sure that Devel::Cover was mostly happy with my code, running through enough branches so that when I had to "go live" with minor revisions, I could push the change with a fair degree of confidence. </p><p> This week, I concluded that a fundamental data structure (an in-memory hash-of-hashes) that controlled the entire operation and was passed from one part to the next of this 2000-line set of modules, should be changed to be permanent. </p><p> So I pulled out Rose::DB, designed a simple main-row-plus-1-to-n-children database schema, and started refactoring. Of course, after I got rid of the initial data structure, every test failed. I would take each test, run it, and watch it fail, and then I would keep hacking the code and fixing it again until the test passed. Then I'd move on to the next one. </p><p> Six hours later, my complex application was now completely running with Rose::DB-based persistence instead of an in-memory data structure. And I was very happy that the client had insisted on complete tests before I started, because I was now confident to push this <i>new</i> version into production. </p><p> Tests. Not just for breakfast, any more.</p> merlyn 2006-06-08T15:52:00+00:00 journal Not quite getting the picture http://use.perl.org/~merlyn/journal/29788?from=rss <p> I had just seen <a href="http://us.imdb.com/title/tt0475276/"> <i>United 93</i> </a>, and after the movie, bumped in to <a href="http://us.imdb.com/name/nm0458662/">a friend of mine</a>, who is known more for her physical assets than her mental achievements. (Although she's not blonde, this week.) </p><p> I had stayed through the credits, and noticed a lot of "HIMSELF" and "HERSELF", which obviously added to the authenticity of this biopic feeling almost like a documentary. So I commented to her "Hey, a lot of the people originally involved played themselves", because it had impressed me. </p><p> She replied, "The people on the airplane?" </p><p> {sigh}</p> merlyn 2006-06-02T15:42:31+00:00 journal Geek Cruises News-es: the podcast http://use.perl.org/~merlyn/journal/29749?from=rss I've started a <a href="http://podcast.geekcruises.com/">weekly podcast for GeekCruises.com</a>. You can <a href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=156151980">subscribe via iTunes</a> (the best for us, since it increases the popularity) or <a href="http://geekcruises.libsyn.com/rss">add the URL directly to your podcatcher</a>. merlyn 2006-05-29T18:39:02+00:00 journal Simple and sweet http://use.perl.org/~merlyn/journal/29721?from=rss Q: "How do I get my pid into a file, simply?" <p> A: print { open my $out, "&gt;", "pidfile"; $out or die } $$, "\n"; </p><p> Yes, I like Perl.</p> merlyn 2006-05-26T13:04:54+00:00 journal Podcast and upload of my "Perl Best Practices" talk http://use.perl.org/~merlyn/journal/29622?from=rss <p> See <a href="http://www.ourmedia.org/node/225170">my slides!</a> </p><p> Hear <a href="http://www.podasp.com/episodes/p/pd/pdxlug/599.mp3">me talk!</a> </p><p> Buy <a href="http://www.stonehenge.com/cgi/amazon?isbn=0596001738">the book!</a></p> merlyn 2006-05-17T00:41:39+00:00 journal PHP poster http://use.perl.org/~merlyn/journal/29568?from=rss See <a href="http://tnx.nl/php">my favorite description of PHP, in visual form</a>. merlyn 2006-05-09T16:07:43+00:00 journal "my bad" origin http://use.perl.org/~merlyn/journal/29519?from=rss <p><p>From <a href="http://www.bookofjoe.com/2006/02/the_origin_of_m.html">The origin of 'my bad'</a>: </p><blockquote> <div><i> The best evidence obtainable at present points to Manute Bol (above), the 7'7" Sudanese NBA player whose native tongue was Dinka, as the inventor, sometime in the 1980s, of this now&#8211;ubiquitous phrase. </i></div> </blockquote> <p>Finally, someone to blame for this incredibly hard-to-hear phrase. Yeay. I keep wanting to say "my bad <i>what?</i>", since my and bad are both adjectives there to my ears.</p> merlyn 2006-05-03T19:25:35+00:00 journal Podcast interview with me about my legal entanglement http://use.perl.org/~merlyn/journal/29401?from=rss <p> The <a href="http://www.securitycatalyst.com/">Security Catalyst</a> podcast recently <a href="http://www.securitycatalyst.com/?p=110">interviewed me</a> regarding my <a href="http://www.lightlink.com/fors/">legal entanglement</a> with the State of Oregon ("victim": Intel Corporation). I haven't had time to listen to this particular show yet, but I remember liking it while I was being interviewed, so it should be a good listen. </p><p> I consider Security Catalyst a very informative and easy-to-listen-to show about desktop and enterprise information security. If you're not already listening, please give it a run. Best of breed, as far as I've seen.</p> merlyn 2006-04-21T15:53:07+00:00 journal Today's lesson on job posting http://use.perl.org/~merlyn/journal/29272?from=rss <p> <b>Good</b>: using <a href="http://jobs.perl.org/">http://jobs.perl.org/</a> to <a href="http://jobs.perl.org/job/3923">post your Perl job to help build a website</a>. </p><p> <b>Bad</b>: Providing the <a href="http://www.fashionsmasher.com/">URL of the yet-to-be-built website</a> as the "URL for more information" in your post! (At the time of this writing, the URL leads simply to the name of the site and "coming soon"). </p><p> Doh!</p> merlyn 2006-04-10T13:13:04+00:00 journal Missing the facts http://use.perl.org/~merlyn/journal/29103?from=rss <p> <a href="http://slashdot.org/~Dr.+Dysphora/journal/132151">He says</a>: </p><blockquote> <div><i> But what is beyond forgiveable is that Perl 6 has made the market of new Perl books nonexistent. This alone assures Perl's eventual nonexistence. Why would an author want to write a Perl book that is obsolete in some fuzzy time period. </i></div> </blockquote> <p> To which I replied: </p><blockquote> <div><p><i> We just released the 4th edition of "Learning Perl" last summer, and "Intermediate Perl" this month. We're very committed to keeping the flagship tutorial books for the Perl community up to date until Perl6 arrives. There are also a number of other Perl books in the pipeline at O'Reilly that I cannot comment on. </i></p><p><i> If other publishers are slowing down on turning out the junk that spells Perl in all-caps and promises a complete Perl education in some small number of hours or days, that's actually better for the community, not worse. </i></p></div> </blockquote> merlyn 2006-03-25T18:29:33+00:00 journal Ain't technology grand? http://use.perl.org/~merlyn/journal/28936?from=rss <p> So, I'm working for $client, and I needed to send a presentation to my $boss so that he can push it up on the webinar system for a brownbag I'm presenting today at lunchtime. He wanted both the powerpoint (ugh) slides (converted from nice nifty Keynote), and a backup PDF in case things broke. </p><p> When I printed the PDF from powerpoint, it came out as a whopping 22 Megabytes. Ouch. However, I didn't notice this, and simply attached the message in Thunderbird (another ugh, but that's another story), and pressed "send". My message was rejected during the send (and also took a while), so I found a way to reprint the PDF from the original Keynote, and it came out to 252K, so I happily sent that along instead. </p><p> But now for the "WTF" moment. I get a message about 20 seconds later from "the mail administrator" (not a human), advising me that "the attached message is too large to deliver". Yes. Follow the logic. The attached message was too large to deliver, so it <i>delivered</i> it to me in its entirety. </p><p> Oh, joy. </p><p> If only I had faked the "from" on the original message, the bounce would have been "delivered" to the desired recipient instead!</p> merlyn 2006-03-09T15:49:35+00:00 journal Ishmael http://use.perl.org/~merlyn/journal/28886?from=rss I recently glanced over to see a friend of mine reading a book titled "Ishmael". <p> I bet him that I knew the first line of the book. My guess, which turned out to be wrong, was "Call me, Moby Dick." </p><p> However, that seems like it would be a great fiction novel... the story of a great white whale who is obsessed with tormenting this one Captain Ahab until he loses everything. Anyone want to set up a collaborative writing project for this? </p><p> Disclaimer: everything I know about Moby Dick, I got from <a href="http://en.wikipedia.org/wiki/Moby_Dick">Wikipedia</a>.</p> merlyn 2006-03-06T03:11:20+00:00 journal Why do newscasters always ... pause? http://use.perl.org/~merlyn/journal/28859?from=rss Why do field radio and TV newscasters invariably... pause before delivering the last few words of their delivery? Was this originally some sort of signal to the studio that they were done, similar to "over" in pilot communications? Who started it? Why do they still do it? Can you tell it annoys me?<nobr> <wbr></nobr>:-) <p> "For my use.perl journal... I'm Randal Schwartz."</p> merlyn 2006-03-03T13:29:57+00:00 journal Still fodder for the conversation http://use.perl.org/~merlyn/journal/28736?from=rss It's nice to see that my legal case <a href="http://cyb3rcrim3.blogspot.com/2006/02/seizure.html">continues to be noticed and discussed by experts</a>. merlyn 2006-02-20T01:50:17+00:00 journal Pot. Kettle. Black. http://use.perl.org/~merlyn/journal/28687?from=rss <blockquote> <div>Sams signed the code of conduct but didn't know that working at Hooters could be grounds for termination, she said. "I love this school," Sams said. "I felt so proud to cheer for our teams. I was always the loudest one out there screaming (for the Bucs)."</div> </blockquote> &mdash; <a href="http://www.easttennessean.com/media/paper203/news/2006/02/06/News/Cheerleader.Booted.For.Working.At.Hooters.Cries.Foul-1599602.shtml?norewrite&amp;sourcedomain=www.easttennessean.com">Cheerleader booted for working at Hooters cries foul</a> merlyn 2006-02-15T18:37:18+00:00 journal Sell music on iTunes with no middleman cost http://use.perl.org/~merlyn/journal/28510?from=rss This is brave: a small music label is setting up a way for <a href="http://www.tunecore.com/">indie artists to put their music on iTunes and keep 100% of what iTunes pays in response!</a>. That's very very cool. <p> Pudge? Time to start publishing!</p> merlyn 2006-01-29T18:44:53+00:00 journal The 90's called... they want their code back... http://use.perl.org/~merlyn/journal/28298?from=rss From <a href="http://groups.google.com/group/comp.infosystems.www.authoring.cgi/browse_thread/thread/752e74dbd910b2a5/6710721867093cc8">a recent comp.infosystems.www.authoring.cgi post</a>: <blockquote> <div><blockquote> <div><tt>sub ParseForm<br>&nbsp; &nbsp; {<br>&nbsp; &nbsp; my ($key, $prefs, $buffer);<br>&nbsp; &nbsp; if ($ENV{'REQUEST_METHOD'} eq 'GET')<br>&nbsp; &nbsp; &nbsp; &nbsp; { @pairs = split(/&amp;/, $ENV{'QUERY_STRING'}) }<br>&nbsp; &nbsp; elsif ($ENV{'REQUEST_METHOD'} eq 'POST')<br>&nbsp; &nbsp; &nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});<br>&nbsp; &nbsp; &nbsp; &nbsp; @pairs = split(/&amp;/, $buffer)<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; else {Error('Bad or Unknown Request Method',<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "The form's request method must be either 'POST' or<br>'GET'. Please check your HTML.")}<br> <br>&nbsp; &nbsp; foreach $pair (@pairs)<br>&nbsp; &nbsp; &nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; local($name, $value) = split(/=/, $pair);<br>&nbsp; &nbsp; &nbsp; &nbsp; $name =~ tr/+/<nobr> <wbr></nobr>/;<br>&nbsp; &nbsp; &nbsp; &nbsp; $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;<br>&nbsp; &nbsp; &nbsp; &nbsp; $value =~ tr/+/<nobr> <wbr></nobr>/;<br>&nbsp; &nbsp; &nbsp; &nbsp; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;<br>&nbsp; &nbsp; &nbsp; &nbsp; $value =~ s/&lt;!--(.)*?--&gt;//mg;<br>&nbsp; &nbsp; &nbsp; &nbsp; $FORM{$name} = $value;<br>...</tt></div> </blockquote></div> </blockquote> And the horror doesn't stop there, but I wanted to minimize your exposure. This <b>is</b> 2006, right? merlyn 2006-01-10T08:20:17+00:00 journal 2.0-parse-cloud.t100644001750001750 642614756547744 16322 0ustar00shlomifshlomif000000000000XML-RSS-1.65/tuse strict; use warnings; # Should be 11. use Test::More tests => 11; use XML::RSS; use constant RSS_VERSION => "2.0"; use constant RSS_CHANNEL_TITLE => "Example 2.0 Channel"; use constant RSS_DOCUMENT => qq( Example 2.0 Channel http://example.com/ To lead by example en-us All content Public Domain, except comments which remains copyright the author editor\@example.com webmaster\@example.com http://backend.userland.com/rss Reference/Libraries/Library_and_Information_Science/Technical_Services/Cataloguing/Metadata/RDF/Applications/RSS/ The Superest Dooperest RSS Generator Mon, 02 Sep 2002 03:19:17 GMT 60 News for September the Second http://example.com/2002/09/02 other things happened today http://example.com/2002/09/02/comments.html joeuser\@example.com Mon, 02 Sep 2002 03:19:00 GMT http://example.com/2002/09/02 News for September the First http://example.com/2002/09/01 something happened today http://example.com/2002/09/01/comments.html joeuser\@example.com Sun, 01 Sep 2002 12:01:00 GMT http://example.com/2002/09/02 ); my $xml = XML::RSS->new(); # TEST isa_ok($xml,"XML::RSS"); eval { $xml->parse(RSS_DOCUMENT); }; # TEST is($@,'',"Parsed RSS feed"); # TEST is($xml->{channel}{cloud}{domain}, 'rpc.rsscloud.org'); # TEST is($xml->{channel}{cloud}{port}, '5337'); # TEST is($xml->{channel}{cloud}{path}, '/rsscloud/pleaseNotify'); # TEST is($xml->{channel}{cloud}{registerProcedure}, ''); # TEST is($xml->{channel}{cloud}{protocol}, 'http-post'); # TEST cmp_ok($xml->{'_internal'}->{'version'},"eq",RSS_VERSION,"Is RSS version ".RSS_VERSION); # TEST cmp_ok($xml->{channel}->{'title'},"eq",RSS_CHANNEL_TITLE,"Feed title is ".RSS_CHANNEL_TITLE); # TEST cmp_ok(ref($xml->{items}),"eq","ARRAY","\$xml->{items} is an ARRAY ref"); my $ok = 1; foreach my $item (@{$xml->{items}}) { my $min = 0; foreach my $el ("title","description") { if (exists $item->{$el}) { $min ||= 1; } } $ok = $min; last if (! $ok); } # TEST ok($ok,"All items have either a title or a description element"); __END__ =head1 NAME 2.0-parse-cloud.t - parse rssCloud: https://rt.cpan.org/Ticket/Display.html?id=67241 =head1 SYNOPSIS use Test::Harness qw (runtests); runtests (./XML-RSS/t/*.t); =head1 DESCRIPTION Tests for parsing RSS 2.0 with rssCloud with XML-RSS. =head1 VERSION $Revision: 1.2 $ =head1 DATE $Date: 2002/11/19 23:56:53 $ =head1 AUTHOR Aaron Straup Cope =head1 SEE ALSO http://backend.userland.com/rss2 =cut convert.pl100644001750001750 107114756547744 17001 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examples#!/usr/bin/perl use strict; use warnings; use XML::RSS (); # print an error unless there are 2 command-line args syntax() unless @ARGV == 2; # get rss file and version to convert to from # the command line my ($file,$version) = @ARGV; # create new instance my $rss = XML::RSS->new; # set output version $rss->{output} = $version unless $version eq 'default'; # parse the rss file $rss->parsefile(shift); # output the new RSS to STDOUT print $rss->as_string; sub syntax { die "Syntax: convert.pl \n ex: convert.pl fm.rdf 1.0\n\n"; } no-tabs.t100644001750001750 353214756547744 16637 0ustar00shlomifshlomif000000000000XML-RSS-1.65/xt/authoruse strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::NoTabs 0.15 use Test::More 0.88; use Test::NoTabs; my @files = ( 'lib/XML/RSS.pm', 'lib/XML/RSS/Private/Output/Base.pm', 'lib/XML/RSS/Private/Output/Roles/ImageDims.pm', 'lib/XML/RSS/Private/Output/Roles/ModulesElems.pm', 'lib/XML/RSS/Private/Output/V0_9.pm', 'lib/XML/RSS/Private/Output/V0_91.pm', 'lib/XML/RSS/Private/Output/V1_0.pm', 'lib/XML/RSS/Private/Output/V2_0.pm', 't/0.9-generate.t', 't/0.9-parse.t', 't/0.9-strict.t', 't/0.91-parse.t', 't/00-compile.t', 't/1.0-gen-errors-on-missing-fields.t', 't/1.0-generate.t', 't/1.0-parse-2.t', 't/1.0-parse-exotic.t', 't/1.0-parse.t', 't/1.0-to-2.0.t', 't/2.0-generate.t', 't/2.0-modules.t', 't/2.0-parse-2.t', 't/2.0-parse-cloud.t', 't/2.0-parse-self.t', 't/2.0-parse.t', 't/2.0-permalink.t', 't/2.0-wo-title.t', 't/add-item-insert-vs-append.t', 't/auto_add_modules.t', 't/charset1.t', 't/data/1.0/rss1.0.exotic.rdf', 't/data/1.0/with_content.rdf', 't/data/2.0/empty-desc.rss', 't/data/2.0/no-desc.rss', 't/data/2.0/sf-hs-with-lastBuildDate.rss', 't/data/2.0/sf-hs-with-pubDate.rss', 't/data/freshmeat.rdf', 't/data/merlyn1.rss', 't/data/rss-permalink.xml', 't/empty-elements.t', 't/enclosures-multi.t', 't/enclosures.t', 't/enclosures2.t', 't/encode-output.t', 't/encoding.t', 't/generated/placeholder.txt', 't/guid-outside-item.t', 't/guid.t', 't/load.t', 't/render-upon-init.t', 't/rss2-gt-encoding.t', 't/rss2-nested-custom-tag.t', 't/save-while-in-taint-mode.t', 't/subcategory.t', 't/test-generated-items.t', 't/version.t', 't/xml-base.t', 't/xml-header.t' ); notabs_ok($_) foreach @files; done_testing; render-upon-init.t100644001750001750 115414756547744 16777 0ustar00shlomifshlomif000000000000XML-RSS-1.65/tuse strict; use warnings; use Test::More tests => 3; use XML::RSS; { my $rss = XML::RSS->new( version => '0.9' ); # TEST like( $rss->as_string, qr|]*>|, "rdf tag for version 0.9" ); $rss = XML::RSS->new( version => '0.91' ); # TEST like( $rss->as_string, qr//, "rss tag for version 0.91" ); $rss = XML::RSS->new( version => '1.0' ); # TEST like( $rss->as_string, qr|]*>|, "rdf tag for version 1.0" ); } enclosures-multi.t100644001750001750 440314756547744 17112 0ustar00shlomifshlomif000000000000XML-RSS-1.65/tuse strict; use warnings; use Test::More tests => 6; use XML::RSS; use constant RSS_VERSION => "2.0"; use constant RSS_CHANNEL_TITLE => "Example 2.0 Channel"; use constant RSS_DOCUMENT => qq( Example 2.0 Channel http://example.com/ To lead by example en-us editor\@example.com webmaster\@example.com http://backend.userland.com/rss The Superest Dooperest RSS Generator Mon, 02 Sep 2002 03:19:17 GMT 60 News for September the Second http://example.com/2002/09/02 other things happened today http://example.com/2002/09/02/comments.html joeuser\@example.com Mon, 02 Sep 2002 03:19:00 GMT http://example.com/2002/09/02 ); { my $xml = XML::RSS->new(); # TEST isa_ok($xml,"XML::RSS"); eval { $xml->parse(RSS_DOCUMENT); }; # TEST is($@,'',"Parsed RSS feed"); # TEST is_deeply($xml->{items}->[0]->{enclosure}, { url => "http://example.com/test2.mp3", length => "5352283", type => "audio/mpeg" }, "got enclosure"); } { my $xml = XML::RSS->new; eval { $xml->parse(RSS_DOCUMENT, { allow_multiple => [ 'enclosure' ] } ) }; # TEST is($@,'',"Parsed RSS feed again"); # TEST is_deeply($xml->{items}->[0]->{enclosure}->[0], { url => "http://example.com/test.mp3", length => "5352283", type => "audio/mpeg" }, "got first enclosure" ); # TEST is_deeply($xml->{items}->[0]->{enclosure}->[1], { url => "http://example.com/test2.mp3", length => "5352283", type => "audio/mpeg" }, "got second enclosure" ); } rss2-gt-encoding.t100644001750001750 325714756547744 16673 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t#!/usr/bin/perl -w use strict; use warnings; use Test::More; if (eval "require Test::Differences") { Test::Differences->import; plan tests => 2; } else { plan skip_all => 'Test::Differences required'; } use_ok('XML::RSS'); my $rss = XML::RSS->new(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@freshmeat.net', webMaster => 'scoop@freshmeat.net' ); $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=>"http://www.foo.tld/", type=>"application/x-bittorrent" }, description => 'Whoa' ); my ($string) = grep { m/shlomifish/ } split /\n/, $rss->as_string(); my $expected_encoded_html = '<a href="http://www.shlomifish.org/"><span style="color:#658912">Whoa</span></a>'; eq_or_diff($string, $expected_encoded_html, "Testing for a correctly encoded HTML"); 1; auto_add_modules.t100644001750001750 214614756547744 17112 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t# $Id: auto_add_modules.t,v 1.3 2004/04/21 02:44:40 kellan Exp $ use Test::More tests => 5; use XML::RSS; use File::Spec; $XML::RSS::AUTO_ADD = 1; my $URL = 'http://freshmeat.net/backend/fm-releases-0.1.dtd'; my $TAG = 'fm'; { my $rss = XML::RSS->new(); # TEST isa_ok( $rss, 'XML::RSS' ); $rss->parsefile( File::Spec->catfile( File::Spec->curdir(), 't', 'data', 'freshmeat.rdf' ) ); #use Data::Dumper; #print Data::Dumper::Dumper( $rss ); # TEST ok( exists $rss->{modules}{$URL}, 'Freshmeat module exists' ); # TEST is( $rss->{modules}{$URL}, $TAG, 'Freshmeat module has right URI' ); } { my $rss = XML::RSS->new(); my $text; { local $/; local *I; open I, "<", File::Spec->catfile( File::Spec->curdir(), 't', 'data', 'freshmeat.rdf' ); $text = ; close(I); } $rss->parse( $text, ); # TEST ok( exists $rss->{modules}{$URL}, 'Freshmeat module exists' ); # TEST is( $rss->{modules}{$URL}, $TAG, 'Freshmeat module has right URI' ); } 1.0-parse-exotic.t100644001750001750 251714756547744 16503 0ustar00shlomifshlomif000000000000XML-RSS-1.65/tuse Test::More tests => 4; use XML::RSS; use File::Spec; $|++; my $file = File::Spec->catfile(File::Spec->curdir(), "t", "data", "1.0", "rss1.0.exotic.rdf"); my $rss = XML::RSS->new(encode_output => 1); eval { $rss->parsefile( $file ); }; # Test 1. # Support for feeds that use a default namespace other then RSS # unlike ($@, qr/invalid version/, "non-default namespace" ); # Test 2. # Make sure modules are parsed and loaded # my $namespaces = { 'rss' => 'http://purl.org/rss/1.0/', 'dc' => 'http://purl.org/dc/elements/1.1/', 'annotate' => 'http://purl.org/rss/1.0/modules/annotate/', 'cp' => 'http://my.theinfo.org/changed/1.0/rss/', 'admin' => 'http://webns.net/mvcb/', 'rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', '#default' => 'http://www.w3.org/1999/xhtml' }; ok ( eq_hash( $rss->{namespaces}, $namespaces ), "modules and namespaces" ); # Test 3. # Make sure modules that use rdf:resource are being properly parsed # in channel element # ok ($rss->{'channel'}->{'http://webns.net/mvcb/'}->{'errorReportsTo'} eq 'mailto:admin@example.org', 'parse rdf:resource on channel' ); # Test 4. # rdf:resrouce properly parsed in item # ok ($rss->{'items'}->[0]->{'http://my.theinfo.org/changed/1.0/rss/'}->{'server'} eq "http://example.org/changedPage", 'parse rdf:resource on item' ); freshmeat.rdf100644001750001750 1434414756547744 17024 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t/data freshmeat.net - Themes http://themes.freshmeat.net/ freshmeat.net maintains the Web's largest index of Unix and cross-platform open source software. Thousands of applications are meticulously cataloged in the freshmeat.net database, and links to new code are added daily. en-us Technology freshmeat.net freshmeat.net contributors Copyright (c) 1997-2002 OSDN 2003-01-18T01:20+00:00 freshmeat.net http://images.freshmeat.net/button.gif http://themes.freshmeat.net/ AlterEgo 1.0 (Stable) http://themes.freshmeat.net/releases/109704/ A classy theme with blue, silver, grey, and green. 2003-01-16T14:12-06:00 http://images.freshmeat.net/screenshots/34238_thumb.jpg WhiteBox 0.1 http://themes.freshmeat.net/releases/109670/ A light and clean theme. 2003-01-16T14:12-06:00 http://images.freshmeat.net/screenshots/34235_thumb.png MacOS9 .3 http://themes.freshmeat.net/releases/109706/ A MacOS 9 theme. 2003-01-16T10:21-06:00 http://images.freshmeat.net/screenshots/33230_thumb.png MacOS9 .2 http://themes.freshmeat.net/releases/109705/ A MacOS 9 theme. 2003-01-16T10:21-06:00 http://images.freshmeat.net/screenshots/33230_thumb.png Fossils of the Machines 1.1 http://themes.freshmeat.net/releases/109489/ An old rusty machine look. Some elements inspired by the steamgoth Winamp theme. 2003-01-13T22:50-06:00 http://images.freshmeat.net/screenshots/31633_thumb.jpg Think Tux 1.0 http://themes.freshmeat.net/releases/109383/ An Aqua/MacOS-style background featuring Tux. 2003-01-13T09:21-06:00 http://images.freshmeat.net/screenshots/34165_thumb.jpg Radio Birdman Clothified 1.0 http://themes.freshmeat.net/releases/109250/ The Radio Birdman emblem clothied 2003-01-12T17:25-06:00 http://images.freshmeat.net/screenshots/34142_thumb.png Slackflux_Blue 1.0 http://themes.freshmeat.net/releases/109215/ A simple Fluxbox theme featuring the Slack logo and Mr. Penguin. 2003-01-12T17:25-06:00 http://images.freshmeat.net/screenshots/34129_thumb.png MyBox 0.1 http://themes.freshmeat.net/releases/109204/ A bright/bluish clean theme for Fluxbox/Blackbox. 2003-01-12T17:24-06:00 http://images.freshmeat.net/screenshots/34124_thumb.jpg Linux Power Wallpaper 1.0 http://themes.freshmeat.net/releases/108775/ Wallpaper depicting the &quot;power&quot; of Linux. 2003-01-12T17:24-06:00 http://images.freshmeat.net/screenshots/34019_thumb.jpg Search freshmeat.net Search freshmeat.net projects q http://themes.freshmeat.net/search/ rss2html.pl100644001750001750 514414756547744 17104 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examples#!/usr/bin/perl # rss2html - converts an RSS file to HTML # It take one argument, either a file on the local system, # or an HTTP URL like http://slashdot.org/slashdot.rdf # by Jonathan Eisenzopf. v1.0 19990901 # See http://www.webreference.com/perl for more information # INCLUDES use strict; use warnings; use XML::RSS; use LWP::Simple; # Declare variables my $content; my $file; binmode STDOUT, ":encoding(utf8)"; # MAIN # check for command-line argument die "Usage: rss2html.pl ( | )\n" unless @ARGV == 1; # get the command-line argument my $arg = shift; # create new instance of XML::RSS my $rss = XML::RSS->new; # argument is a URL if ($arg=~ /http:/i) { $content = get($arg); die "Could not retrieve $arg" unless $content; # parse the RSS content $rss->parse($content); # argument is a file } else { $file = $arg; die "File \"$file\" does't exist.\n" unless -e $file; # parse the RSS file $rss->parsefile($file); } # print the HTML channel print_html($rss); # SUBROUTINES sub print_html { my $rss = shift; print <<"HTML";
$rss->{'channel'}->{'title'}
HTML # print channel image if ($rss->{'image'}->{'link'}) { print <<"HTML";

$rss->{'image'}->{'title'}{'image'}->{'width'}\"" if $rss->{'image'}->{'width'}; print " height=\"$rss->{'image'}->{'height'}\"" if $rss->{'image'}->{'height'}; print ">

\n"; } # print the channel items foreach my $item (@{$rss->{'items'}}) { next unless defined($item->{'title'}) && defined($item->{'link'}); print "

  • {'link'}\">$item->{'title'}
    \n"; } # if there's a textinput element if ($rss->{'textinput'}->{'title'}) { print <<"HTML";
    $rss->{'textinput'}->{'description'}

    HTML } # if there's a copyright element if ($rss->{'channel'}->{'copyright'}) { print <<"HTML";

    $rss->{'channel'}->{'copyright'}

    HTML } print <<"HTML";
  • HTML } rss_info.pl100644001750001750 122214756547744 17141 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examples#!/usr/bin/perl # channel_info.pl # print channel info use lib '.'; use strict; use warnings; use XML::RSS (); my $rss = XML::RSS->new; $rss->parsefile(shift); print "XML encoding: ".$rss->encoding."\n"; print "RSS Version: ".$rss->version."\n"; print "Title: ".$rss->channel('title')."\n"; print "Language: ".$rss->channel('language')."\n"; print "Rating: ".$rss->channel('rating')."\n"; print "Copyright: ".$rss->channel('copyright')."\n"; print "Publish Date: ".$rss->channel('pubDate')."\n"; print "Last Build Date: ".$rss->channel('lastBuildDate')."\n"; print "CDF URL: ".$rss->channel('docs')."\n"; print "Items: ".scalar(@{$rss->items})."\n"; 0.91000755001750001750 014756547744 15214 5ustar00shlomifshlomif000000000000XML-RSS-1.65/examplesfm.rdf100644001750001750 500714756547744 16455 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examples/0.91 freshmeat.net http://freshmeat.net the one-stop-shop for all your Linux software needs en-us freshmeat.net http://freshmeat.net/images/fm.mini.jpg http://freshmeat.net 90 36 Xskat 3.1 http://freshmeat.net/news/1999/09/01/936224942.html Skatordnung card game, playable against humans or the computer Java Test Driver 1.1 http://freshmeat.net/news/1999/09/01/936224907.html Test driver for Java class libraries WaveLAN/IEEE driver 1.0.1 http://freshmeat.net/news/1999/09/01/936224545.html Kernel network device driver for WaveLAN/IEEE wireless network card macfork 1.0 http://freshmeat.net/news/1999/09/01/936224336.html Macintosh resource fork reader and extracter QScheme 0.2.2 http://freshmeat.net/news/1999/09/01/936223755.html Really fast, small and easy to interface Scheme interpreter CompuPic 4.6 build 1018 http://freshmeat.net/news/1999/09/01/936223729.html CompuPic Graphical Digital Content and File Manager for Linux eXtace 1.1.16 http://freshmeat.net/news/1999/09/01/936223709.html ESD FFT visual plugin, eye-candy GTC 0.3 http://freshmeat.net/news/1999/09/01/936223686.html Game Programming Library RocketJSP 0.9c http://freshmeat.net/news/1999/09/01/936223646.html JSP 1.0 Engine Majik 3D 0.0/M3 http://freshmeat.net/news/1999/09/01/936223622.html An online role-playing world quick finder Use the text input below to search the freshmeat application database query http://core.freshmeat.net/search.php3 guid-outside-item.t100644001750001750 105114756547744 17132 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t# This is to test the following bug: # https://github.com/shlomif/perl-XML-RSS/issues/24 use strict; use warnings; use Test::More tests => 1; use XML::RSS (); { my $rss_text = <<"EOF"; 11111111-1111-1111-1111-111111111111 EOF my $xml = XML::RSS->new(version => "2.0"); $xml->parse($rss_text); # TEST pass("guid not inside an item element") } 2.0000755001750001750 014756547744 14462 5ustar00shlomifshlomif000000000000XML-RSS-1.65/t/datano-desc.rss100644001750001750 1312214756547744 16722 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t/data/2.0 http://community.livejournal.com/shlomif_hsite/ shlomif@iglu.org.il LiveJournal / LiveJournal.com Sun, 24 Sep 2006 10:12:49 GMT http://community.livejournal.com/shlomif_hsite/3573.html Sun, 24 Sep 2006 10:12:49 GMT New Additions to the Site shlomif@iglu.org.il http://community.livejournal.com/shlomif_hsite/3573.html <p> Exactly two weeks passed since the last update and many things have been added or improved. Read below for what's new. </p> <p> Two of the pages in <a href="http://www.shlomifish.org/MathVentures/">the MathVentures section</a> were converted to use embedded <a href="http://www.w3.org/Math/">MathML</a>. This should make viewing them with MathML-compliant browsers easier. The old ASCII-art based pages are still available. </p> <p> The ideas <a href="http://www.shlomifish.org/philosophy/ideas/#tucan">Tucan</a> and <a href="http://www.shlomifish.org/philosophy/ideas/#unixdoc">Unixdoc</a> were added to the Random Ideas page. </p> <p> I've placed <a href="http://www.shlomifish.org/open-source/nostalgia/">some of my old DOS-era programs online</a> for your amusement. </p> <p> I added a <a href="http://www.shlomifish.org/meta/FAQ/#site_history">question about the site history</a> to the <a href="http://www.shlomifish.org/meta/FAQ/">FAQ</a>. </p> <p> More CDs were added to the <a href="http://www.shlomifish.org/art/recommendations/music/">Music Recommendations</a>. </p> <p> There's <a href="http://www.shlomifish.org/humour.html#if_god_exists">a new Joke</a> in the Humour archive. </p> http://community.livejournal.com/shlomif_hsite/3573.html mathml mathematics math dos jokes tucan ideas mathventures unixdoc Metallica - Nothing Else Matters full public http://community.livejournal.com/shlomif_hsite/3165.html Sun, 10 Sep 2006 13:41:17 GMT Changes at Shlomi Fish Homesite shlomif@iglu.org.il http://community.livejournal.com/shlomif_hsite/3165.html <p> It's been about two weeks since my last update, and here's what's new: </p> <ol> <li> <p> <a href="http://www.shlomifish.org/art/recommendations/music/">A currently partial list</a> of my favourite compact discs is now live. Creating this list involved a large amount of <a href="http://en.wikipedia.org/wiki/Document_Type_Definition">DTD</a>, <a href="http://www.w3.org/TR/xslt">XSLT</a>, <a href="http://perl-begin.berlios.de/">Perl</a>, and CSS hacking on the <a href="http://search.cpan.org/dist/XML-Grammar-ProductsSyndication/">XML-Grammar-ProductsSyndication</a> framework, that was written from scratch to facilitate making construction of such lists possible by and others. </p> <p> I will add the missing CDs as time goes by, and will also later on add lists for fiction books and for movies, as well as convert the existing <a href="http://www.shlomifish.org/philosophy/books-recommends/">non-fiction books recommendations</a> into the new framework. </p> </li> <li> <p> More pages on the site were made to validate according to the <a href="http://www.w3.org/">World-wide-web consortium</a> standards, and some ancient leftovers that were no longer important were removed. </p> </li> <li> <p> <a href="http://www.shlomifish.org/open-source/favourite/">My list of favourite open source software</a> was updated, with many corrections, added programs and a new navigation menu. </p> </li> <li> <p> <a href="http://www.shlomifish.org/prog-evolution/pre-elpas.html">My memoirs as a programmer from High School</a> were heavily fixed and updated. </p> </li> </ol> http://community.livejournal.com/shlomif_hsite/3165.html xml grammar homesite shlomi fish syndication memoirs products valid html Monkey Island Am I Evil OC Remix annoyed public update_rss.pl100644001750001750 62714756547744 17460 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examples#!/usr/bin/perl # update_rss.pl # Adds a new item to the RSS file use strict; use warnings; use XML::RSS (); die "Syntax: update_rss.pl source.rdf destination.rdf\n\n" unless @ARGV == 2; my $rss = XML::RSS->new; $rss->parsefile(shift); $rss->add_item(title => "MpegTV Player (mtv) 1.0.9.7", link => "http://freshmeat.net/news/1999/06/21/930003958.html", mode => 'insert' ); $rss->save(shift); 1.0000755001750001750 014756547744 15123 5ustar00shlomifshlomif000000000000XML-RSS-1.65/examplesslash.rdf100644001750001750 477114756547744 17103 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examples/1.0 Slash Site http://yaz.pudge.net/ Slash Site nobody@yaz.pudge.net en rdfsubject rdfpublisher rdfcopyright somedate rdfupdate rdffrequency somedate Slash Site http://yaz.pudge.net/images/topics/topicslash.gif http://yaz.pudge.net/ You've Installed Slash! http://yaz.pudge.net/article.pl?sid=00/01/25/1430236 sometext ... define elsewhere pudge slash congratulations-dude articles 1 1,1,1,0,0,0,0 Now What? http://yaz.pudge.net/article.pl?sid=00/01/25/1236215 sometext ... define elsewhere pudge slash where-do-you-go-from-here? articles 0 0,0,0,0,0,0,0 Search Slash Site Search Slash Site stories query http://yaz.pudge.net/search.pl pod-syntax.t100644001750001750 25214756547744 17356 0ustar00shlomifshlomif000000000000XML-RSS-1.65/xt/author#!perl # This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests. use strict; use warnings; use Test::More; use Test::Pod 1.41; all_pod_files_ok(); rss1.0.rdf100644001750001750 364514756547744 17016 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examples/1.0 freshmeat.net http://freshmeat.net the one-stop-shop for all your Linux software needs scoop@freshmeat.net en-us Linux Software scoop@freshmeat.net Copyright 1999, Freshmeat.net 2000-08-23T07:00+00:00 hourly 1 1901-01-01T00:00+00:00 freshmeat.net http://freshmeat.net/images/fm.mini.jpg http://freshmeat.net G. Raphics (graphics at freshmeat.net) GTKeyboard 0.85 http://freshmeat.net/news/1999/06/21/930003829.html GTKeyboard is a graphical keyboard that ... David Allen (s2mdalle at titan.vcu.edu) X11/Utilities quick finder Use the text input below to search freshmeat query http://core.freshmeat.net/search.php3 test-generated-items.t100644001750001750 34134414756547744 17702 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t#!/usr/bin/perl use strict; use warnings; use Test::More tests => 198; use XML::RSS; use HTML::Entities qw(encode_entities); sub output_contains { local $Test::Builder::Level = $Test::Builder::Level + 1; my ($rss_output, $sub_string, $msg) = @_; my $ok = ok (index ($rss_output, $sub_string) >= 0, $msg ); if (! $ok) { diag("Could not find the substring [$sub_string] in:{{{{\n$rss_output\n}}}}\n"); } return $ok; } sub contains { local $Test::Builder::Level = $Test::Builder::Level + 1; my ($rss, $sub_string, $msg) = @_; return output_contains($rss->as_string(), $sub_string, $msg); } sub not_contains { local $Test::Builder::Level = $Test::Builder::Level + 1; my ($rss, $sub_string, $msg) = @_; ok ((index ($rss->as_string(), $sub_string) < 0), $msg ); } sub create_rss_1 { my $args = shift; my $extra_rss_args = $args->{rss_args} || []; my $rss = XML::RSS->new (version => $args->{version}, @$extra_rss_args); my $image_link = exists($args->{image_link}) ? $args->{image_link} : "http://freshmeat.net/"; my $extra_image_params = $args->{image_params} || []; $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 => "0", link => $image_link, @{$extra_image_params}, ); $rss->add_item( title => "GTKeyboard 0.85", link => "http://freshmeat.net/news/1999/06/21/930003829.html" ); return $rss; } sub create_no_image_rss { my $args = shift; my $rss = XML::RSS->new (version => $args->{version}); $rss->channel( title => "freshmeat.net", link => "http://freshmeat.net", description => "the one-stop-shop for all your Linux software needs", ); $rss->add_item( title => "GTKeyboard 0.85", link => "http://freshmeat.net/news/1999/06/21/930003829.html" ); return $rss; } sub create_item_with_0_rss { my $args = shift; my $rss = XML::RSS->new (version => $args->{version}); my $image_link = exists($args->{image_link}) ? $args->{image_link} : "http://freshmeat.net/"; my $extra_image_params = $args->{image_params} || []; my $extra_item_params = $args->{item_params} || []; $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 => "0", link => $image_link, @{$extra_image_params}, ); $rss->add_item( title => "0", link => "http://rss.mytld/", @{$extra_item_params}, ); return $rss; } sub create_textinput_with_0_rss { my $args = shift; my $rss = XML::RSS->new (version => $args->{version}); my $image_link = exists($args->{image_link}) ? $args->{image_link} : "http://freshmeat.net/"; my $extra_image_params = $args->{image_params} || []; my $extra_item_params = $args->{item_params} || []; my $extra_textinput_params = $args->{textinput_params} || []; $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 => "0", link => $image_link, @{$extra_image_params}, ); $rss->add_item( title => "0", link => "http://rss.mytld/", @{$extra_item_params}, ); $rss->textinput( (map { $_ => 0 } (qw(link title description name))), @{$extra_textinput_params}, ); return $rss; } sub create_channel_rss { my $args = shift; my $rss = XML::RSS->new (version => $args->{version}); my $extra_channel_params = $args->{channel_params} || []; my @build_date = ($args->{version} eq "2.0" && !$args->{omit_date}) ? (lastBuildDate => "Sat, 07 Sep 2002 09:42:31 GMT",) : (); $rss->channel( title => "freshmeat.net", link => "http://freshmeat.net", description => "Linux software", @build_date, @{$extra_channel_params}, ); $rss->add_item( title => "GTKeyboard 0.85", link => "http://freshmeat.net/news/1999/06/21/930003829.html" ); return $rss; } sub create_skipHours_rss { my $args = shift; my $rss = XML::RSS->new (version => $args->{version}); my $extra_channel_params = $args->{channel_params} || []; my $extra_skipHours_params = $args->{skipHours_params} || []; my @build_date = ($args->{version} eq "2.0" && !$args->{omit_date}) ? (lastBuildDate => "Sat, 07 Sep 2002 09:42:31 GMT",) : (); $rss->channel( title => "freshmeat.net", link => "http://freshmeat.net", description => "Linux software", @build_date, @{$extra_channel_params}, ); $rss->add_item( title => "GTKeyboard 0.85", link => "http://freshmeat.net/news/1999/06/21/930003829.html" ); $rss->skipHours(@{$extra_skipHours_params}); return $rss; } sub create_skipDays_rss { my $args = shift; my $rss = XML::RSS->new (version => $args->{version}); my $extra_channel_params = $args->{channel_params} || []; my $extra_skipDays_params = $args->{skipDays_params} || []; my @build_date = ($args->{version} eq "2.0" && !$args->{omit_date}) ? (lastBuildDate => "Sat, 07 Sep 2002 09:42:31 GMT",) : (); $rss->channel( title => "freshmeat.net", link => "http://freshmeat.net", description => "Linux software", @build_date, @{$extra_channel_params}, ); $rss->add_item( title => "GTKeyboard 0.85", link => "http://freshmeat.net/news/1999/06/21/930003829.html" ); $rss->skipDays(@{$extra_skipDays_params}); return $rss; } sub create_rss_with_image_w_undef_link { my $args = shift; my $rss = XML::RSS->new (version => $args->{version}); my $extra_image_params = $args->{image_params} || []; $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 => "0", @{$extra_image_params}, ); $rss->add_item( title => "GTKeyboard 0.85", link => "http://freshmeat.net/news/1999/06/21/930003829.html" ); return $rss; } sub create_item_rss { my $args = shift; my $rss = XML::RSS->new (version => $args->{version}); my $extra_item_params = $args->{item_params} || []; $rss->channel( title => "freshmeat.net", link => "http://freshmeat.net", description => "the one-stop-shop for all your Linux software needs", ); $rss->add_item( title => "Freecell Solver", link => "http://fc-solve.berlios.de/", @$extra_item_params, ); return $rss; } sub create_rss_without_item { my $args = shift; my $rss = XML::RSS->new (version => $args->{version}); $rss->channel( title => "freshmeat.net", link => "http://freshmeat.net", description => "the one-stop-shop for all your Linux software needs", ); return $rss; } { my $rss = create_no_image_rss({version => "0.9"}); # TEST not_contains($rss, "", "0.9 - if an image was not specified it isn't there." ); } { my $rss = create_no_image_rss({version => "0.91"}); # TEST not_contains($rss, "", "0.91 - if an image was not specified it isn't there." ); } { my $rss = create_no_image_rss({version => "1.0"}); # TEST not_contains($rss, " "2.0"}); # TEST not_contains($rss, "", "1.0 - if an image was not specified it isn't there." ); } { my $rss = create_rss_1({version => "0.9"}); # TEST ok ($rss->as_string =~ m{.*?freshmeat.net.*?0.*?http://freshmeat.net/.*?}s, "Checking for image in RSS 0.9"); } { my $rss = create_rss_1({version => "0.91"}); # TEST ok ($rss->as_string =~ m{.*?freshmeat.net.*?0.*?http://freshmeat.net/.*?}s, "Checking for image in RSS 0.9.1"); } { my $rss = create_rss_1({version => "1.0"}); # TEST ok ($rss->as_string =~ m{.*?freshmeat.net.*?0.*?http://freshmeat.net/.*?}s, "Checking for image in RSS 1.0"); # TEST contains ($rss, "\n\n", "1.0 - contains image rdf:resource." ); } { my $rss = create_rss_1({version => "2.0"}); # TEST ok ($rss->as_string =~ m{.*?freshmeat.net.*?0.*?http://freshmeat.net/.*?}s, "Checking for image in RSS 2.0"); } { my $rss = create_rss_1({version => "0.9", image_link => "0",}); # TEST ok (index($rss->as_string(), "\nfreshmeat.net\n0\n0\n\n") >= 0, "Testing for link == 0 appearance in RSS 0.9" ); } { my $version = "0.91"; my $rss = create_rss_1({version => $version, image_link => "0",}); # TEST ok (index($rss->as_string(), "\nfreshmeat.net\n0\n0\n\n") >= 0, "Testing for link == 0 appearance in RSS $version" ); } { my $version = "1.0"; my $rss = create_rss_1({version => $version, image_link => "0",}); # TEST ok (index($rss->as_string(), qq{\nfreshmeat.net\n0\n0\n\n}) >= 0, "Testing for link == 0 appearance in RSS $version" ); } { my $version = "2.0"; my $rss = create_rss_1({version => $version, image_link => "0",}); # TEST ok (index($rss->as_string(), qq{\nfreshmeat.net\n0\n0\n\n}) >= 0, "Testing for link == 0 appearance in RSS $version" ); } { my $version = "0.91"; my $rss = create_rss_1({ version => $version, image_params => [width => 0, height => 0, description => 0], } ); # TEST contains($rss, "\nfreshmeat.net\n0\n" . "http://freshmeat.net/\n" . "0\n0\n" . "0\n\n", "Testing for width, height, description == 0 appearance in RSS $version" ); } { my $rss = create_rss_1({ version => "2.0", image_params => [width => 0, height => 0, description => 0], } ); # TEST contains($rss, "\nfreshmeat.net\n0\n" . "http://freshmeat.net/\n" . "0\n0\n" . "0\n\n", "2.0 - all(width, height, description) == 0 appearance" ); } { my $rss = create_item_with_0_rss({version => "0.9"}); # TEST contains( $rss, "\n0\nhttp://rss.mytld/\n", "0.9 - item/title == 0", ); } { my $rss = create_item_with_0_rss({version => "0.91", item_params => [description => "Hello There"], }); # TEST contains( $rss, "\n0\nhttp://rss.mytld/\nHello There\n", "0.9.1 - item/title == 0", ); } { my $rss = create_item_with_0_rss({version => "0.91", item_params => [description => "0"], }); # TEST contains( $rss, "\n0\nhttp://rss.mytld/\n0\n", "0.9.1 - item/title == 0 && item/description == 0", ); } { my $rss = create_item_with_0_rss({version => "1.0", item_params => [description => "Hello There", about => "Yowza"], }); # TEST contains( $rss, "\n0\nhttp://rss.mytld/\nHello There\n", "1.0 - item/title == 0", ); } { my $rss = create_item_with_0_rss({version => "1.0", item_params => [description => "0", about => "Yowza"], }); # TEST contains( $rss, "\n0\nhttp://rss.mytld/\n0\n", "1.0 - item/title == 0 && item/description == 0", ); } # TODO : Test the dc: items. { my @subs = (qw(title link description author category comments pubDate)); my $rss = create_item_with_0_rss({version => "2.0", item_params => [ map { $_ => 0 } @subs ], } ); # TEST contains( $rss, ("\n" . join("", map { "<$_>0\n" } @subs) . ""), "2.0 - item/* == 0 - 1", ); } { my $rss = create_item_with_0_rss({version => "2.0", item_params => [ title => "Foo&Bar", link => "http://www.mytld/", permaLink => "0", ], } ); # TEST contains( $rss, ("\n" . "Foo&Bar\n" . "http://www.mytld/\n" . "0\n" . "" ), "2.0 - item/permaLink == 0", ); } { my $rss = create_item_with_0_rss({version => "2.0", item_params => [ title => "Foo&Bar", link => "http://www.mytld/", guid => "0", ], } ); # TEST contains( $rss, ("\n" . "Foo&Bar\n" . "http://www.mytld/\n" . "0\n" . "" ), "2.0 - item/guid == 0", ); } { # TEST:$num_iters=4; foreach my $s ( ["Hercules", "http://www.hercules.tld/",], ["0", "http://www.hercules.tld/",], ["Hercules", "0",], ["0", "0",], ) { my $rss = create_item_with_0_rss({version => "2.0", item_params => [ title => "Foo&Bar", link => "http://www.mytld/", source => $s->[0], sourceUrl => $s->[1], ], } ); # TEST*$num_iters contains( $rss, ("\n" . "Foo&Bar\n" . "http://www.mytld/\n" . "[1]\">$s->[0]\n" . "" ), "2.0 - item - source = $s->[0] sourceUrl = $s->[1]", ); } } { my $rss = create_no_image_rss({version => "0.9"}); # TEST not_contains($rss, "", "0.9 - if a textinput was not specified it isn't there." ); } { my $rss = create_textinput_with_0_rss({version => "0.9"}); # TEST contains( $rss, ("\n" . join("", map {"<$_>0\n"} (qw(title description name link))) . "\n"), "0.9 - textinput/link == 0", ); } { my $rss = create_no_image_rss({version => "0.91"}); # TEST not_contains($rss, "", "0.9.1 - if a textinput was not specified it isn't there." ); } { my $rss = create_textinput_with_0_rss({version => "0.91"}); # TEST contains( $rss, ("\n" . join("", map {"<$_>0\n"} (qw(title description name link))) . "\n"), "0.9.1 - textinput/link == 0", ); } { my $rss = create_no_image_rss({version => "1.0"}); # TEST not_contains($rss, " "1.0"}); # TEST contains( $rss, ("\n" . join("", map {"<$_>0\n"} (qw(title description name link))) . "\n"), "1.0 - textinput/link == 0", ); # TEST contains( $rss, "\n\n", "1.0 - textinput/link == 0 and textinput rdf:resource", ); } { my $rss = create_no_image_rss({version => "2.0"}); # TEST not_contains($rss, "", "2.0 - if a textinput was not specified it isn't there." ); } { my $rss = create_textinput_with_0_rss({version => "2.0"}); # TEST contains( $rss, ("\n" . join("", map {"<$_>0\n"} (qw(title description name link))) . "\n"), "2.0 - textinput/link == 0", ); } { my $rss = create_channel_rss({version => "0.91"}); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "\n" . "\n", "0.9.1 - if a channel/dc/language was not specified it isn't there." ); } { my $rss = create_channel_rss({ version => "0.91", channel_params => [dc => { language => "0",},], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "0\n" . "\n" . "\n", "0.9.1 - channel/dc/language == 0" ); } { my $rss = create_channel_rss({ version => "0.91", channel_params => [language => "0",], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "0\n" . "\n" . "\n", "0.9.1 - channel/language == 0" ); } { my $rss = create_channel_rss({version => "1.0"}); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "\n", "1.0 - if a channel/dc/language was not specified it isn't there." ); } { my $rss = create_channel_rss({ version => "1.0", channel_params => [dc => { language => "0",},], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "0\n" . "\n", "1.0 - channel/dc/language == 0" ); } { my $rss = create_channel_rss({ version => "1.0", channel_params => [language => "0",], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "0\n" . "\n", "1.0 - channel/language == 0" ); } { my $rss = create_channel_rss({version => "2.0"}); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Sat, 07 Sep 2002 09:42:31 GMT\n" . "\n" . "\n", "2.0 - if a channel/dc/language was not specified it isn't there." ); } { my $rss = create_channel_rss({ version => "2.0", channel_params => [dc => { language => "0",},], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "0\n" . "Sat, 07 Sep 2002 09:42:31 GMT\n" . "\n" . "\n", "2.0 - channel/dc/language == 0" ); } { my $rss = create_channel_rss({ version => "2.0", channel_params => [language => "0",], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "0\n" . "Sat, 07 Sep 2002 09:42:31 GMT\n" . "\n" . "\n", "2.0 - channel/language == 0" ); } { my $rss = create_channel_rss({ version => "0.91", channel_params => [rating => "0",], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "0\n" . "\n" . "\n", "0.9.1 - channel/rating == 0" ); } { my $rss = create_channel_rss({ version => "0.91", channel_params => [rating => "Hello", dc => {rights => "0"},], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Hello\n" . "0\n" . "\n" . "\n", "0.9.1 - channel/dc/copyright == 0" ); } { my $rss = create_channel_rss({ version => "0.91", channel_params => [rating => "Hello", copyright => "0",], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Hello\n" . "0\n" . "\n" . "\n", "0.9.1 - channel/copyright == 0" ); } { my $rss = create_channel_rss({ version => "2.0", channel_params => [dc => {rights => "0"},], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "0\n" . "Sat, 07 Sep 2002 09:42:31 GMT\n" . "\n" . "\n", "2.0 - channel/dc/rights == 0" ); } { my $rss = create_channel_rss({ version => "2.0", channel_params => [copyright=> "0",], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "0\n" . "Sat, 07 Sep 2002 09:42:31 GMT\n" . "\n" . "\n", "2.0 - channel/copyright == 0" ); } { my $rss = create_channel_rss({ version => "0.91", channel_params => [rating => "Hello", copyright => "Martha",docs => "0",], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Hello\n" . "Martha\n" . "0\n" . "\n" . "\n", "0.9.1 - channel/docs == 0" ); } { my $rss = create_channel_rss({ version => "2.0", channel_params => [copyright => "Martha", docs => "0",], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Martha\n" . "Sat, 07 Sep 2002 09:42:31 GMT\n" . "0\n" . "\n" . "\n", "2.0 - channel/docs == 0" ); } { my $rss = create_channel_rss({ version => "0.91", channel_params => [rating => "Hello", copyright => "Martha", docs => "MyDr. docs",dc => {publisher => 0}], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Hello\n" . "Martha\n" . "MyDr. docs\n" . "0\n" . "\n" . "\n", "0.9.1 - channel/dc/publisher == 0" ); } { my $rss = create_channel_rss({ version => "0.91", channel_params => [rating => "Hello", copyright => "Martha", docs => "MyDr. docs",managingEditor => 0], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Hello\n" . "Martha\n" . "MyDr. docs\n" . "0\n" . "\n" . "\n", "0.9.1 - channel/managingEditor == 0" ); } { my $rss = create_channel_rss({ version => "2.0", channel_params => [copyright => "Martha", docs => "MyDr. docs",managingEditor => 0], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Martha\n" . "Sat, 07 Sep 2002 09:42:31 GMT\n" . "MyDr. docs\n" . "0\n" . "\n" . "\n", "2.0 - channel/managingEditor == 0" ); } { my $rss = create_channel_rss({ version => "2.0", channel_params => [copyright => "Martha", docs => "MyDr. docs", dc => {publisher => 0}], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Martha\n" . "Sat, 07 Sep 2002 09:42:31 GMT\n" . "MyDr. docs\n" . "0\n" . "\n" . "\n", "2.0 - channel/dc/publisher == 0" ); } { my $rss = create_channel_rss({ version => "1.0", channel_params => [copyright => "Martha", dc => {publisher => 0}], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Martha\n" . "0\n" . "\n", "1.0 - channel/dc/publisher == 0" ); } { # Here we create an RSS 2.0 object and render it as 1.0 to get the # "managingEditor" field acknowledged. my $rss = create_channel_rss({ version => "2.0", channel_params => [copyright => "Martha", managingEditor => 0,], omit_date => 1, }); $rss->{output} = "1.0"; # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Martha\n" . "0\n" . "\n", "1.0 - channel/managingEditor == 0" ); } { my $rss = create_channel_rss({ version => "0.91", channel_params => [rating => "Hello", copyright => "Martha", docs => "MyDr. docs",dc => {creator => 0}], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Hello\n" . "Martha\n" . "MyDr. docs\n" . "0\n" . "\n" . "\n", "0.9.1 - channel/dc/publisher == 0" ); } { my $rss = create_channel_rss({ version => "0.91", channel_params => [rating => "Hello", copyright => "Martha", docs => "MyDr. docs",webMaster => 0], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Hello\n" . "Martha\n" . "MyDr. docs\n" . "0\n" . "\n" . "\n", "0.9.1 - channel/webMaster == 0" ); } { my $rss = create_channel_rss({ version => "1.0", channel_params => [copyright => "Martha", dc => {creator => 0}], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Martha\n" . "0\n" . "\n", "1.0 - channel/dc/creator == 0" ); } { # Here we create an RSS 2.0 object and render it as 1.0 to get the # "managingEditor" field acknowledged. my $rss = create_channel_rss({ version => "2.0", channel_params => [copyright => "Martha", webMaster => 0,], omit_date => 1, }); $rss->{output} = "1.0"; # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Martha\n" . "0\n" . "\n", "1.0 - channel/managingEditor == 0" ); } { my $rss = create_channel_rss({ version => "2.0", channel_params => [copyright => "Martha", docs => "MyDr. docs",webMaster => 0], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Martha\n" . "Sat, 07 Sep 2002 09:42:31 GMT\n" . "MyDr. docs\n" . "0\n" . "\n" . "\n", "2.0 - channel/webMaster == 0" ); } { my $rss = create_channel_rss({ version => "2.0", channel_params => [copyright => "Martha", docs => "MyDr. docs", dc => {creator => 0}], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Martha\n" . "Sat, 07 Sep 2002 09:42:31 GMT\n" . "MyDr. docs\n" . "0\n" . "\n" . "\n", "2.0 - channel/dc/creator == 0" ); } { my $rss = create_no_image_rss({version => "0.91"}); # TEST not_contains($rss, "", "0.91 - if skipHours was not specified it isn't there." ); } { my $rss = create_skipHours_rss({ version => "0.91", skipHours_params => [ hour => "0" ], }); # TEST contains($rss, "\n0\n\n", "0.91 - skipHours/hours == 0" ); } { my $rss = create_no_image_rss({version => "2.0"}); # TEST not_contains($rss, "", "2.0 - if skipHours was not specified it isn't there." ); } { my $rss = create_skipHours_rss({ version => "2.0", skipHours_params => [ hour => "0" ], }); # TEST contains($rss, "\n0\n\n", "2.0 - skipHours/hour == 0" ); } { my $rss = create_no_image_rss({version => "0.91"}); # TEST not_contains($rss, "", "0.91 - if skipDays was not specified it isn't there." ); } { my $rss = create_skipDays_rss({ version => "0.91", skipDays_params => [ day => "0" ], }); # TEST contains($rss, "\n0\n\n", "0.91 - skipDays/days == 0" ); } { my $rss = create_no_image_rss({version => "2.0"}); # TEST not_contains($rss, "", "2.0 - if skipDays was not specified it isn't there." ); } { my $rss = create_skipDays_rss({ version => "2.0", skipDays_params => [ day => "0" ], }); # TEST contains($rss, "\n0\n\n", "2.0 - skipDays/day == 0" ); } { my $rss = create_channel_rss({ version => "1.0", }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "\n", "1.0 - channel/dc/creator == 0" ); } { my $rss = create_channel_rss({ version => "1.0", channel_params => [copyright => 0,], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "0\n" . "\n", "1.0 - channel/copyright == 0" ); } { my $rss = create_channel_rss({ version => "1.0", channel_params => [dc => { rights => 0},], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "0\n" . "\n", "1.0 - channel/dc/rights == 0" ); } { my $rss = create_channel_rss({ version => "1.0", channel_params => [dc => { title => 0},], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "0\n" . "\n", "1.0 - channel/dc/title == 0" ); } { my $rss = create_channel_rss({ version => "1.0", channel_params => [syn => { updateBase=> 0},], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "0\n" . "\n", "1.0 - channel/syn/updateBase == 0" ); } { my $rss = create_rss_1({version => "1.0", image_params => [ dc => { subject => 0, }] }); # TEST contains ($rss, (qq{\nfreshmeat.net\n} . qq{0\nhttp://freshmeat.net/\n} . qq{0\n}), "1.0 - Checking for image/dc/subject == 0"); } { my $rss = create_item_with_0_rss({version => "1.0", item_params => [ description => "Hello There", about => "Yowza", dc => { subject => 0,}, ], }); # TEST contains( $rss, "\n0\nhttp://rss.mytld/\nHello There\n0\n", "1.0 - item/dc/subject == 0", ); } { my $rss = create_textinput_with_0_rss({version => "1.0", textinput_params => [dc => { subject => 0,},], }); # TEST contains( $rss, ("\n" . join("", map {"<$_>0\n"} (qw(title description name link dc:subject))) . "\n"), "1.0 - textinput/dc/subject == 0", ); } { # TEST:$num_fields=3; foreach my $field (qw(category generator ttl)) { # TEST:$num_dc=2; foreach my $dc (1,0) { my $rss = create_channel_rss({ version => "2.0", channel_params => [$dc ? (dc => {$field => 0 }) : ($field => 0) ], }); # TEST*$num_fields*$num_dc contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Sat, 07 Sep 2002 09:42:31 GMT\n" . "<$field>0\n" . "\n" . "\n", "2.0 - Testing for fields with an optional dc being 0. (dc=$dc,field=$field)" ); } } } { my $rss = create_channel_rss({ version => "0.91", channel_params => [pubDate => "There&Everywhere"], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "</pubDate><hello>There&amp;Everywhere</hello>\n" . "\n" . "\n", "0.9.1 - channel/pubDate Markup Injection" ); } { my $rss = create_channel_rss({ version => "0.91", channel_params => [lastBuildDate => "There&Everywhere"], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "</pubDate><hello>There&amp;Everywhere</hello>\n" . "\n" . "\n", "0.9.1 - channel/lastBuildDate Markup Injection" ); } { my $rss = create_channel_rss({ version => "1.0", channel_params => [ dc => { date => "There&Everywhere" }, ], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "</pubDate><hello>There&amp;Everywhere</hello>\n" . "\n", "1.0 - dc/date Markup Injection" ); } { my $rss = create_channel_rss({version => "2.0", channel_params => [pubDate => "There&Everywhere"], omit_date => 1, }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "</pubDate><hello>There&amp;Everywhere</hello>\n" . "\n" . "\n", "2.0 - channel/pubDate Markup Injection" ); } { my $rss = create_channel_rss({version => "2.0", channel_params => [lastBuildDate => "There&Everywhere"], omit_date => 1, }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "</pubDate><hello>There&amp;Everywhere</hello>\n" . "\n" . "\n", "2.0 - channel/lastBuildDate Markup Injection" ); } { my $rss = create_rss_with_image_w_undef_link({version => "0.9"}); # TEST contains ($rss, qq{\nfreshmeat.net\n0\n\n}, "Image with undefined link does not render the Image - RSS version 0.9" ); } { my $rss = create_rss_with_image_w_undef_link({version => "1.0"}); # TEST contains ($rss, qq{\nfreshmeat.net\n} . qq{0\n\n}, "Image with undefined link does not render the Image - RSS version 1.0" ); } { my $rss = create_channel_rss({ version => "1.0", channel_params => [about => "http://xml-rss-hackers.tld/"], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "\n", "1.0 - channel/about overrides the rdf:about attribute." ); } { my $rss = create_channel_rss({ version => "1.0", channel_params => [ taxo => ["Foo", "Bar", "QuGof", "Lambda&Delta"], ], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . qq{\n \n} . qq{ \n} . qq{ \n} . qq{ \n} . qq{ \n} . qq{ \n\n} . "\n", "1.0 - taxo topics" ); } { my $rss = create_channel_rss({ version => "1.0", channel_params => [ admin => { 'foobar' => "Quod", }, ], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Quod\n" . "\n", '1.0 - channel/[module] with unknown key' ); } { my $rss = create_channel_rss({ version => "1.0", channel_params => [ eloq => { 'grow' => "There", }, ], }); $rss->add_module(prefix => "eloq", uri => "http://eloq.tld2/Gorj/"); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "There\n" . "\n", '1.0 - channel/[module] with new module' ); } { my $rss = create_rss_1({ version => "1.0", image_params => [ admin => { 'foobar' => "Quod", }, ], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "0\n" . "http://freshmeat.net/\n" . "Quod\n" . "", '1.0 - image/[module] with unknown key' ); } { my $rss = create_rss_1({ version => "1.0", image_params => [ eloq => { 'grow' => "There", }, ], }); $rss->add_module(prefix => "eloq", uri => "http://eloq.tld2/Gorj/"); # TEST contains($rss, "\n" . "freshmeat.net\n" . "0\n" . "http://freshmeat.net/\n" . "There\n" . "", '1.0 - image/[module] with new module' ); } { my $rss = create_rss_1({ version => "1.0", image_params => [ admin => { 'generatorAgent' => "Spozilla 5.5", }, ], }); # TEST contains($rss, "\n" . "freshmeat.net\n" . "0\n" . "http://freshmeat.net/\n" . "\n" . "", '1.0 - image/[module] with known module' ); } { my $rss = create_channel_rss({ version => "1.0", }); $rss->add_item( title => "In the Jungle", link => "http://jungle.tld/Enter/", taxo => ["Foo","Loom", "", "Yok&Dol"], ); # TEST contains($rss, "\n" . "In the Jungle\n" . "http://jungle.tld/Enter/\n" . qq{\n} . qq{ \n} . qq{ \n} . qq{ \n} . qq{ \n} . qq{ \n} . qq{ \n} . qq{\n} . "\n", "1.0 - item/taxo:topics (with escaping)" ); } ## Test the RSS 1.0 items' ad-hoc modules support. { my $rss = create_item_rss({ version => "1.0", item_params => [ admin => { 'foobar' => "Quod", }, ], }); # TEST contains($rss, "\n" . "Freecell Solver\n" . "http://fc-solve.berlios.de/\n" . "Quod\n" . "", '1.0 - item/[module] with unknown key' ); } { my $rss = create_item_rss({ version => "1.0", item_params => [ eloq => { 'grow' => "There", }, ], }); $rss->add_module(prefix => "eloq", uri => "http://eloq.tld2/Gorj/"); # TEST contains($rss, "\n" . "Freecell Solver\n" . "http://fc-solve.berlios.de/\n" . "There\n" . "", '1.0 - item/[module] with new module' ); } { my $rss = create_item_rss({ version => "1.0", item_params => [ admin => { 'generatorAgent' => "Spozilla 5.5", }, ], }); # TEST contains($rss, "\n" . "Freecell Solver\n" . "http://fc-solve.berlios.de/\n" . "\n" . "", '1.0 - item/[module] with known module' ); } { my $rss = create_textinput_with_0_rss({version => "1.0", textinput_params => [admin => { 'foobar' => "Quod", },], }); # TEST contains( $rss, ("\n" . join("", map {"<$_>0\n"} (qw(title description name link))) . "Quod\n" . "\n" ), "1.0 - textinput/[module]", ); } { my $rss = create_channel_rss({ version => "2.0", channel_params => [ admin => { 'generatorAgent' => "Spozilla 5.5", }, ], }); $rss->add_module(prefix => "admin", uri => "http://webns.net/mvcb/"); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Sat, 07 Sep 2002 09:42:31 GMT\n" . "\n" . "\n" . "\n", '2.0 - channel/[module] with known module and key' ); } { my $rss = create_channel_rss({ version => "2.0", channel_params => [ admin => { 'foobar' => "Quod", }, ], }); $rss->add_module(prefix => "admin", uri => "http://webns.net/mvcb/"); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Sat, 07 Sep 2002 09:42:31 GMT\n" . "Quod\n" . "\n" . "\n", '2.0 - channel/[module] with unknown key' ); } { my $rss = create_channel_rss({ version => "2.0", channel_params => [ eloq => { 'grow' => "There", }, ], }); $rss->add_module(prefix => "eloq", uri => "http://eloq.tld2/Gorj/"); # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Sat, 07 Sep 2002 09:42:31 GMT\n" . "There\n" . "\n" . "\n", '2.0 - channel/[module] with new module' ); } ## Testing the RSS 2.0 Image Modules Support { my $rss = create_rss_1({ version => "2.0", image_params => [ admin => { 'foobar' => "Quod", }, ], }); $rss->add_module(prefix => "admin", uri => "http://webns.net/mvcb/"); # TEST contains($rss, "\n" . "freshmeat.net\n" . "0\n" . "http://freshmeat.net/\n" . "Quod\n" . "\n", '2.0 - image/[module] with unknown key' ); } { my $rss = create_rss_1({ version => "2.0", image_params => [ eloq => { 'grow' => "There", }, ], }); $rss->add_module(prefix => "eloq", uri => "http://eloq.tld2/Gorj/"); # TEST contains($rss, "\n" . "freshmeat.net\n" . "0\n" . "http://freshmeat.net/\n" . "There\n" . "", '2.0 - image/[module] with new module' ); } { my $rss = create_rss_1({ version => "2.0", image_params => [ admin => { 'generatorAgent' => "Spozilla 5.5", }, ], }); $rss->add_module(prefix => "admin", uri => "http://webns.net/mvcb/"); # TEST contains($rss, "\n" . "freshmeat.net\n" . "0\n" . "http://freshmeat.net/\n" . "\n" . "", '2.0 - image/[module] with known module' ); } ## Test the RSS 2.0 items' ad-hoc modules support. { my $rss = create_item_rss({ version => "2.0", item_params => [ admin => { 'foobar' => "Quod", }, ], }); $rss->add_module(prefix => "admin", uri => "http://webns.net/mvcb/"); # TEST contains($rss, "\n" . "Freecell Solver\n" . "http://fc-solve.berlios.de/\n" . "Quod\n" . "", '2.0 - item/[module] with unknown key' ); } { my $rss = create_item_rss({ version => "2.0", item_params => [ eloq => { 'grow' => "There", }, ], }); $rss->add_module(prefix => "eloq", uri => "http://eloq.tld2/Gorj/"); # TEST contains($rss, "\n" . "Freecell Solver\n" . "http://fc-solve.berlios.de/\n" . "There\n" . "", '2.0 - item/[module] with new module' ); } { my $rss = create_item_rss({ version => "2.0", item_params => [ admin => { 'generatorAgent' => "Spozilla 5.5", }, ], }); $rss->add_module(prefix => "admin", uri => "http://webns.net/mvcb/"); # TEST contains($rss, "\n" . "Freecell Solver\n" . "http://fc-solve.berlios.de/\n" . "\n" . "", '2.0 - item/[module] with known module' ); } ## Test the RSS 2.0 skipping-items condition. { my $rss = create_rss_without_item({ version => "2.0", }); $rss->add_item( link => "http://freshmeat.net/news/1999/06/21/930003829.html" ); # TEST not_contains($rss, "\n", '2.0 - Item without description or title is skipped' ); } ## Test the RSS 2.0 "2.0", item_params => [ title => "Foo&Bar", link => "http://www.mylongtldyeahbaby/", source => $s->[0], sourceUrl => $s->[1], ], } ); # TEST*$num_iters contains( $rss, ("\n" . "Foo&Bar\n" . "http://www.mylongtldyeahbaby/\n" . "" ), "2.0 - item - Source and/or Source URL are not defined", ); } } { # Here we create an RSS 2.0 object and render it as the output # version "3.5" in order to test that version 1.0 is the default # version for output. my $rss = create_channel_rss({ version => "2.0", channel_params => [copyright => "Martha", managingEditor => 0,], omit_date => 1, }); $rss->{output} = "3.5"; # TEST contains($rss, "\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "Martha\n" . "0\n" . "\n", "Unknown version renders as 1.0" ); } { my $version = "0.91"; my $rss = create_rss_1({ version => $version, image_link => "Hello ", rss_args => ["encode_output" => 0], }); # TEST contains($rss, "\nfreshmeat.net\n0\nHello \n\n", "Testing encode_output is false", ); } sub named_encode { my ($self, $text) = @_; if (!defined($text)) { require Carp; Carp::confess "\$text is undefined in XML::RSS::_encode(). We don't know how " . "to handle it!"; } my $encoded_text = ''; while ($text =~ s/(.*?)(\<\!\[CDATA\[.*?\]\]\>)//s) { # we use &named; entities here because it's HTML $encoded_text .= encode_entities($1) . $2; } # we use numeric entities here because it's XML $encoded_text .= encode_entities($text); return $encoded_text; } { my $version = "0.91"; my $rss = create_rss_1({ version => $version, image_link => "Hello ", rss_args => ["encode_cb" => \&named_encode], }); # TEST contains($rss, "\nfreshmeat.net\n0\nHello <there&Yes>\n\n", "Testing encode_cb with named encodings", ); } { my $rss = create_channel_rss({ version => "0.91", image_link => undef, channel_params => [ title => "Hello and ]]>"], }); # TEST contains($rss, "Hello and <![CDATA[Aloha<&>]]>", ); } ################ ### RSS Parsing Tests: ### We generate RSS and test that we get the same results. ################ sub parse_generated_rss { my $args = shift; my $gen_func = $args->{'func'}; my $rss_generator = $gen_func->($args); $rss_generator->{output} = $args->{version}; my $output = $rss_generator->as_string(); if ($args->{postproc}) { $args->{postproc}->(\$output); } my $parser = XML::RSS->new(version => $args->{version}); $parser->parse($output); return $parser; } { my $rss = parse_generated_rss({ func => \&create_textinput_with_0_rss, version => "0.9", textinput_params => [ description => "Welcome to the Jungle.", 'link' => "http://fooque.tld/", 'title' => "The Jungle of the City", 'name' => "There's more than one way to do it.", ], postproc => sub { for (${shift()}) { s{(]*(>)}{}; s{}{}; } }, }); # TEST is ($rss->{textinput}->{description}, "Welcome to the Jungle.", "0.9 parse - textinput/description", ); # TEST is ($rss->{textinput}->{link}, "http://fooque.tld/", "0.9 parse - textinput/link", ); # TEST is ($rss->{textinput}->{title}, "The Jungle of the City", "0.9 parse - textinput/title", ); # TEST is ($rss->{textinput}->{name}, "There's more than one way to do it.", "0.9 parse - textinput/name", ); } { my $rss_parser = parse_generated_rss( { func => \&create_textinput_with_0_rss, version => "0.9", textinput_params => [ description => "Welcome to the Jungle.", 'link' => "http://fooque.tld/", 'title' => "The Jungle of the City", 'name' => "There's more than one way to do it.", ], postproc => sub { for (${shift()}) { s{(]*(>)}{}; s{}{}; s{<(/?)textinput>}{<$1textInput>}g; } }, } ); # TEST is ($rss_parser->{textinput}->{description}, "Welcome to the Jungle.", "0.9 parse - textinput/description", ); # TEST is ($rss_parser->{textinput}->{link}, "http://fooque.tld/", "Parse textInput (with capital I) - textinput/link", ); # TEST is ($rss_parser->{textinput}->{title}, "The Jungle of the City", "Parse textInput (with capital I) - textinput/title", ); # TEST is ($rss_parser->{textinput}->{name}, "There's more than one way to do it.", "Parse textInput (with capital I) - textinput/name", ); } { my $rss_parser = parse_generated_rss( { func => \&create_textinput_with_0_rss, version => "0.9", textinput_params => [ description => "Welcome to the Jungle.", 'link' => "http://fooque.tld/", 'title' => "The Jungle of the City", 'name' => "There's more than one way to do it.", ], postproc => sub { for (${shift()}) { s{<(/?)textinput>}{<$1textInput>}g } }, } ); # TEST is ($rss_parser->{textinput}->{description}, "Welcome to the Jungle.", "0.9 parse - textinput/description", ); # TEST is ($rss_parser->{textinput}->{link}, "http://fooque.tld/", "Parse textInput (with capital I) - textinput/link", ); # TEST is ($rss_parser->{textinput}->{title}, "The Jungle of the City", "Parse textInput (with capital I) - textinput/title", ); # TEST is ($rss_parser->{textinput}->{name}, "There's more than one way to do it.", "Parse textInput (with capital I) - textinput/name", ) } { my $rss_parser = parse_generated_rss( { func => \&create_skipHours_rss, version => "0.91", skipHours_params => [ hour => "5" ], } ); # TEST is ($rss_parser->{skipHours}->{hour}, "5", "Parse 0.91 - skipHours/hour", ); } { my $rss_parser = parse_generated_rss( { func => \&create_skipHours_rss, version => "2.0", skipHours_params => [ hour => "5" ], } ); # TEST is ($rss_parser->{skipHours}->{hour}, "5", "Parse 2.0 - skipHours/hour", ); } ## Test the skipDays parsing. { my $rss_parser = parse_generated_rss( { func => \&create_skipDays_rss, version => "0.91", skipDays_params => [ day => "5" ], } ); # TEST is ($rss_parser->{skipDays}->{day}, "5", "Parse 0.91 - skipDays/day", ); } { my $rss_parser = parse_generated_rss( { func => \&create_skipDays_rss, version => "2.0", skipDays_params => [ day => "5" ], } ); # TEST is ($rss_parser->{skipDays}->{day}, "5", "Parse 2.0 - skipDays/day", ); } { my $rss_parser = XML::RSS->new(version => "2.0"); $rss_parser->parse(<<'EOF'); Test 2.0 Feed http://example.com/ en-us Copyright 2002 2007-01-19T14:21:43+0200 2007-01-19T14:21:43+0200 http://backend.userland.com/rss editor@example.com webmaster@example.com MyCategory XML::RSS Test 60 Test Image http://example.com/example.gif http://example.com/ 25 Test Image Hi there! This is an item http://example.com/2007/01/19 Yadda yadda yadda - R&D; joeuser@example.com MyCategory http://example.com/2007/01/19/comments.html http://example.com/2007/01/19 Fri 19 Jan 2007 02:21:43 PM IST GMT my brain EOF # TEST is ($rss_parser->{image}->{"http://foo.tld/foobar/"}->{hello}, "Hi there!", "Parsing 2.0 - element in a different namespace contained in image", ); } { my $rss_parser = XML::RSS->new(version => "1.0"); $rss_parser->parse(<<'EOF'); Test 1.0 Feed http://example.com/ To lead by example 2007-01-19T14:21:18+0200 Test Image http://example.com/example.gif http://example.com/ Aye Karamba This is an item http://example.com/2007/01/19 Yadda & yadda & yadda joeuser@example.com Search Search for an example q http://example.com/search.pl EOF # TEST is ($rss_parser->{image}->{""}->{foo}, "Aye Karamba", "Parsing 1.0 - element in a null namespace contained in image", ); } { my $rss_parser = XML::RSS->new(version => "2.0"); $rss_parser->parse(<<'EOF'); Test 2.0 Feed http://example.com/ en-us Copyright 2002 2007-01-19T14:21:43+0200 2007-01-19T14:21:43+0200 http://backend.userland.com/rss editor@example.com webmaster@example.com MyCategory XML::RSS Test 60 Test Image http://example.com/example.gif http://example.com/ 25 Test Image This is an item http://example.com/2007/01/19 Yadda yadda yadda - R&D; joeuser@example.com MyCategory http://example.com/2007/01/19/comments.html http://example.com/2007/01/19 Fri 19 Jan 2007 02:21:43 PM IST GMT my brain Hi there! EOF # TEST is ($rss_parser->{items}->[0]->{"http://foo.tld/foobar/"}->{hello}, "Hi there!", "Parsing 2.0 - element in a different namespace contained in an item", ); } { my $rss_parser = XML::RSS->new(version => "1.0"); $rss_parser->parse(<<'EOF'); Test 1.0 Feed http://example.com/ To lead by example 2007-01-19T14:21:18+0200 Test Image http://example.com/example.gif http://example.com/ This is an item http://example.com/2007/01/19 Yadda & yadda & yadda joeuser@example.com Aye Karamba Search Search for an example q http://example.com/search.pl EOF # TEST is ($rss_parser->{items}->[0]->{""}->{foo}, "Aye Karamba", "Parsing 1.0 - element in a null namespace contained in image", ); } { my $rss_parser = XML::RSS->new(version => "2.0"); $rss_parser->parse(<<'EOF'); Test 2.0 Feed http://example.com/ en-us Copyright 2002 2007-01-19T14:21:43+0200 2007-01-19T14:21:43+0200 http://backend.userland.com/rss editor@example.com webmaster@example.com MyCategory XML::RSS Test 60 Test Image http://example.com/example.gif http://example.com/ 25 Test Image This is an item http://example.com/2007/01/19 Yadda yadda yadda - R&D; joeuser@example.com MyCategory http://example.com/2007/01/19/comments.html http://example.com/2007/01/19 Fri 19 Jan 2007 02:21:43 PM IST GMT my brain Search Search for an example q http://example.com/search.pl Show Baloon EOF # TEST is ($rss_parser->{textinput}->{"http://foo.tld/foobar/"}->{hello}, "Show Baloon", "Parsing 2.0 - element in a different namespace contained in a textinput", ); } { my $rss_parser = XML::RSS->new(version => "1.0"); $rss_parser->parse(<<'EOF'); Test 1.0 Feed http://example.com/ To lead by example 2007-01-19T14:21:18+0200 Test Image http://example.com/example.gif http://example.com/ This is an item http://example.com/2007/01/19 Yadda & yadda & yadda joeuser@example.com Search Search for an example q http://example.com/search.pl Priceless EOF # TEST is ($rss_parser->{textinput}->{""}->{foo}, "Priceless", "Parsing 1.0 - element in a null namespace contained in a textinput", ); } { my $rss_parser = XML::RSS->new(version => "2.0"); $rss_parser->parse(<<'EOF'); Test 2.0 Feed http://example.com/ en-us Copyright 2002 2007-01-19T14:21:43+0200 2007-01-19T14:21:43+0200 http://backend.userland.com/rss editor@example.com webmaster@example.com MyCategory XML::RSS Test 60 The RSS Must Flow Test Image http://example.com/example.gif http://example.com/ 25 Test Image This is an item http://example.com/2007/01/19 Yadda yadda yadda - R&D; joeuser@example.com MyCategory http://example.com/2007/01/19/comments.html http://example.com/2007/01/19 Fri 19 Jan 2007 02:21:43 PM IST GMT my brain Search Search for an example q http://example.com/search.pl EOF # TEST is ($rss_parser->{channel}->{"http://foo.tld/foobar/"}->{hello}, "The RSS Must Flow", "Parsing 2.0 - element in a different namespace contained in a channel", ); } { my $rss_parser = XML::RSS->new(version => "1.0"); $rss_parser->parse(<<'EOF'); Test 1.0 Feed http://example.com/ To lead by example 2007-01-19T14:21:18+0200 Placebo is here Test Image http://example.com/example.gif http://example.com/ This is an item http://example.com/2007/01/19 Yadda & yadda & yadda joeuser@example.com Search Search for an example q http://example.com/search.pl EOF # TEST is ($rss_parser->{channel}->{""}->{foo}, "Placebo is here", "Parsing 1.0 - element in a null namespace contained in a channel", ); } { my $rss_parser = XML::RSS->new(version => "1.0"); $rss_parser->parse(<<'EOF'); freshmeat.net http://freshmeat.net Linux software GTKeyboard 0.85 http://freshmeat.net/news/1999/06/21/930003829.html In the Jungle http://jungle.tld/Enter/ EOF # TEST is_deeply ($rss_parser->{items}->[1]->{taxo}, ["Foo", "Loom", "Hello", "myowA"], "Parsing 1.0 - taxo items", ); } { my $rss_parser = XML::RSS->new(version => "1.0"); $rss_parser->parse(<<'EOF'); freshmeat.net http://freshmeat.net Linux software GTKeyboard 0.85 http://freshmeat.net/news/1999/06/21/930003829.html In the Jungle http://jungle.tld/Enter/ EOF # TEST is_deeply ($rss_parser->{items}->[1]->{taxo}, ["Everybody", "needs", "a", "[[[HUG]]]"], "Parsing 1.0 - taxo bag in with junk elements", ); } { my $rss_parser = XML::RSS->new(version => "1.0"); $rss_parser->parse(<<'EOF'); freshmeat.net http://freshmeat.net Linux software GTKeyboard 0.85 http://freshmeat.net/news/1999/06/21/930003829.html In the Jungle http://jungle.tld/Enter/ EOF # TEST is_deeply ($rss_parser->{channel}->{taxo}, ["Elastic", "Plastic", "stochastic", "dynamic^^K"], "Parsing 1.0 - taxo items in channel", ); } { my $rss_parser = XML::RSS->new(version => "1.0"); $rss_parser->parse(<<'EOF'); freshmeat.net http://freshmeat.net Linux software GTKeyboard 0.85 http://freshmeat.net/news/1999/06/21/930003829.html In the Jungle http://jungle.tld/Enter/ EOF # TEST is_deeply ($rss_parser->{channel}->{taxo}, ["Elastic", "Plastic", "stochastic", "dynamic^^K"], "Parsing 1.0 - taxo items in channel with junk items", ); } { my $rss_parser = XML::RSS->new(version => "1.0"); $rss_parser->parse(<<'EOF'); freshmeat.net http://freshmeat.net Linux software GTKeyboard 0.85 http://freshmeat.net/news/1999/06/21/930003829.html In the Jungle http://jungle.tld/Enter/ Gow EOF # TEST is ($rss_parser->{items}->[1]->{"http://webns.net/mvcb/"}->{hello}, "Gow", "Parsing 1.0 - Elements inside that don't exist in \%rdf_resource_fields", ); } { my $rss_parser = XML::RSS->new(version => "1.0"); $rss_parser->parse(<<'EOF'); freshmeat.net http://freshmeat.net Linux software Gow GTKeyboard 0.85 http://freshmeat.net/news/1999/06/21/930003829.html In the Jungle http://jungle.tld/Enter/ EOF # TEST ok ((!grep { exists($_->{"http://webns.net/mvcb/"}->{generatorAgent}) } @{$rss_parser->{items}}), "Parsing 1.0 - Elements that exist in \%rdf_resource_fields but not inside item", ); } { my $rss_parser = XML::RSS->new(version => "1.0"); $rss_parser->parse(<<'EOF'); freshmeat.net http://freshmeat.net Linux software GTKeyboard 0.85 http://freshmeat.net/news/1999/06/21/930003829.html In the Jungle http://jungle.tld/Enter/ EOF # TEST ok ((!grep { exists($_->{enclosure}) } @{$rss_parser->{items}}), "Parsing 1.0 - Testing \%empty_ok_elements", ); } { my $rss_parser = XML::RSS->new(version => "1.0"); $rss_parser->parse(<<'EOF'); freshmeat.net http://freshmeat.net Linux software GTKeyboard 0.85 http://freshmeat.net/news/1999/06/21/930003829.html In the Jungle http://jungle.tld/Enter/ EOF # TEST is (scalar(@{$rss_parser->{items}}), 1, "Parse 1.0 with item in a different NS - There is 1 item"); # TEST is ($rss_parser->{items}->[0]->{title}, "GTKeyboard 0.85", "Parse 1.0 with item in a different NS - it is not the item in the other NS"); } { my $rss_parser = XML::RSS->new(version => "1.0"); $rss_parser->parse(<<'EOF'); freshmeat.net http://freshmeat.net Linux software In the Jungle http://jungle.tld/Enter/ EOF # TEST is (scalar(@{$rss_parser->{items}}), 0, "Parse 1.0 with item in null namespace"); } { my $rss_parser = XML::RSS->new(version => "1.0"); $rss_parser->parse(<<'EOF'); Test 1.0 Feed http://example.com/ To lead by example 2007-01-19T14:21:18+0200 Test Image http://example.com/example.gif http://example.com/ 5 Sep 2006 This is an item http://example.com/2007/01/19 Yadda & yadda & yadda joeuser@example.com Search Search for an example q http://example.com/search.pl EOF # TEST is ($rss_parser->{image}->{dc}->{date}, "5 Sep 2006", "Parsing 1.0 - Known module in image", ); } { my $rss_parser = XML::RSS->new(version => "1.0"); $rss_parser->parse(<<'EOF'); Test 1.0 Feed http://example.com/ To lead by example 2007-01-19T14:21:18+0200 Test Image http://example.com/example.gif http://example.com/ This is an item http://example.com/2007/01/19 Yadda & yadda & yadda joeuser@example.com Search Search for an example q http://example.com/search.pl 5 May 1977 EOF # TEST is ($rss_parser->{textinput}->{dc}->{date}, "5 May 1977", "Parsing 1.0 - Known module in a textinput", ); } { my $rss_parser = XML::RSS->new(version => "2.0"); my $xml_text = <<'EOF'; Test 2.0 Feed http://example.com/ en-us Copyright 2002 2007-01-19T14:21:43+0200 2007-01-19T14:21:43+0200 http://backend.userland.com/rss editor@example.com webmaster@example.com MyCategory XML::RSS Test 60 Test Image http://example.com/example.gif http://example.com/ 25 Test Image Hi there! This is an item http://example.com/2007/01/19 Yadda yadda yadda - R&D; joeuser@example.com MyCategory http://example.com/2007/01/19/comments.html http://example.com/2007/01/19 Fri 19 Jan 2007 02:21:43 PM IST GMT my brain EOF eval { $rss_parser->parse($xml_text); }; # TEST ok ($@ =~ m{\AMalformed RSS}, "Checking for thrown exception on missing version attribute" ); } { my $rss_parser = XML::RSS->new(version => "1.0"); my $xml_text = <<'EOF'; Test 1.0 Feed http://example.com/ To lead by example 2007-01-19T14:21:18+0200 Test Image http://example.com/example.gif http://example.com/ This is an item http://example.com/2007/01/19 Yadda & yadda & yadda joeuser@example.com Search Search for an example q http://example.com/search.pl 5 May 1977 EOF eval { $rss_parser->parse($xml_text); }; # TEST ok ($@ =~ m{\AMalformed RSS: invalid version}, "Checking for thrown exception on missing version attribute" ); } { my $rss_parser = XML::RSS->new(version => "1.0"); $rss_parser->parse(<<'EOF'); freshmeat.net http://freshmeat.net Linux software GTKeyboard 0.85 http://freshmeat.net/news/1999/06/21/930003829.html EOF # TEST is (scalar(@{$rss_parser->{items}}), 1, "Parse 1.0 with nested "); } { my $rss_parser = XML::RSS->new(version => "2.0"); my $xml_text = <<'EOF'; Test 2.0 Feed http://example.com/ Lambda EOF $rss_parser->parse($xml_text); my $channel = $rss_parser->{channel}; # Sanitize the channel out of uninitialised keys. foreach my $field (qw( category channel cloud copyright docs generator image language lastBuildDate managingEditor pubDate skipDays skipHours textinput ttl webMaster )) { delete $channel->{$field}; } # TEST is_deeply($channel, { title => "Test 2.0 Feed", link => "http://example.com/", description => "Lambda", "http://purl.org/rss/1.0/modules/annotate/" => { reference => "Aloha", }, }, "Testing for non-moduled-namespaced element inside the channel." ); } { my $rss_parser = XML::RSS->new(version => "2.0"); my $xml_text = <<'EOF'; Test 2.0 Feed http://example.com/ Lambda This is an item http://example.com/2007/01/19 Yadda yadda yadda joeuser@example.com EOF $rss_parser->parse($xml_text); my $item = $rss_parser->{items}->[0]; # Sanitize the channel out of uninitialised keys. foreach my $field (qw( item )) { delete $item->{$field}; } # TEST is_deeply($item, { title => "This is an item", link => "http://example.com/2007/01/19", description => "Yadda yadda yadda", author => "joeuser\@example.com", "http://purl.org/rss/1.0/modules/annotate/" => { reference => "Aloha", }, }, "Testing for non-moduled-namespaced element inside an item." ); } { my $rss_parser = XML::RSS->new(version => "1.0"); $rss_parser->parse(<<'EOF'); Test 1.0 Feed http://example.com/ To lead by example 2007-01-19T14:21:18+0200 Test Image http://example.com/example.gif http://example.com/ 5 Sep 2006 This is an item http://example.com/2007/01/19 Yadda & yadda & yadda joeuser@example.com Search Search for an example q http://example.com/search.pl EOF # TEST is ($rss_parser->{items}->[0]->{admin}->{generatorAgent}, "XmlRssGenKon", "Parsing 1.0 - known module rdf_resource_field", ); } { my $rss = create_item_rss( { version => "2.0", item_params => [ media => { title => "media title", text => "media text", content => { url => "http://somrurl.org/img/foo.jpg", type => "image/jpeg", height => "100", width => "100", }, }, ], } ); $rss->add_module(prefix=>'media', uri=>'http://search.yahoo.com/mrss/'); # TEST contains($rss, qq{\n}, "namespaces with attributes are rendered correctly. (bug #25336)" ); } { my $xml; { my $rss = XML::RSS->new( 'xml:base' => 'http://example.com/' ); # TEST ok($rss, "Created new rss"); # TEST is($rss->{'xml:base'}, 'http://example.com/', 'Got base'); $rss->{'xml:base'} = 'http://foo.com/'; $rss->channel( description => "Foo", title => "Hi", link => "http://www.tld/", ); # TEST ok($rss->add_item( title => 'foo', 'xml:base' => "http://foo.com/archive/", description => { content => "Bar", 'xml:base' => "http://foo.com/archive/1.html", } ), "Added item"); $xml = $rss->as_rss_2_0(); # TEST ok($xml, "Got xml"); # TEST output_contains( $xml, qq{new; # TEST ok($rss->parse($xml), "Reparsed xml"); # TEST is( $rss->{'xml:base'}, 'http://foo.com/', "Found parsed rss base" ); # TEST is (scalar(@{$rss->{items}}), 1, "Got 1 item"); my $item = $rss->{items}->[0]; # TEST is($item->{'xml:base'}, 'http://foo.com/archive/', "Found parsed item base" ); # TEST is($item->{description}, "Bar", "description is a string - not a hash ref with correct content" ); } { my $rss = XML::RSS->new; # TEST ok($rss->parse($xml, {hashrefs_instead_of_strings => 1}), "Reparsed xml" ); # TEST is( $rss->{'xml:base'}, 'http://foo.com/', "Found parsed rss base" ); # TEST is (scalar(@{$rss->{items}}), 1, "Got 1 item"); my $item = $rss->{items}->[0]; # TEST is($item->{'xml:base'}, 'http://foo.com/archive/', "Found parsed item base"); # TEST is($item->{description}->{'xml:base'}, 'http://foo.com/archive/1.html', "Found parsed description base"); } } { my $xml; { my $rss = XML::RSS->new( 'xml:base' => 'http://example.com/' ); # TEST ok($rss, "Created new rss"); # TEST is($rss->{'xml:base'}, 'http://example.com/', 'Got base'); $rss->{'xml:base'} = 'http://foo.com/'; $rss->channel( title => "freshmeat.net", link => "http://freshmeat.net", description => "the one-stop-shop for all your Linux software needs", ); # TEST ok($rss->add_item( title => 'foo', 'xml:base' => "http://foo.com/archive/", description => { content => "Bar", 'xml:base' => "", } ), "Added item"); $xml = $rss->as_rss_2_0(); # TEST ok($xml, "Got xml"); # TEST output_contains ( $xml, qq{ "1.0", image_params => [ eloq => [ { 'el' => 'grow', 'val' => "There" }, { 'el' => 'grow', 'val' => "Position", }, { 'el' => 'show', 'val' => "and tell", }, { 'el' => 'show', 'val' => "must go on", }, ], ], }); $rss->add_module(prefix => "eloq", uri => "http://eloq.tld2/Gorj/"); # TEST contains($rss, "\n" . "freshmeat.net\n" . "0\n" . "http://freshmeat.net/\n" . "There\n" . "Position\n" . "and tell\n" . "must go on\n" . "", 'Multiple values for the same key in a module, usign an array ref' ); my $parsed_rss = XML::RSS->new(version => '1.0'); $parsed_rss->add_module(prefix => "eloq", uri => "http://eloq.tld2/Gorj/"); $parsed_rss->parse($rss->as_string(), { modules_as_arrays => 1, }); # TEST is_deeply( $parsed_rss->{'image'}->{'eloq'}, [ { 'el' => 'grow', 'val' => "There" }, { 'el' => 'grow', 'val' => "Position", }, { 'el' => 'show', 'val' => "and tell", }, { 'el' => 'show', 'val' => "must go on", }, ], "modules_as_arrays parsed the namespace into an array." ); } { my $rss = create_channel_rss({ version => "1.0", }); $rss->add_item( title => "In the Dublin Core Jungle", link => "http://jungle.tld/Enter/", dc => { subject => ['tiger', 'elephant', 'snake',], language => "en-GB", }, ); # TEST contains($rss, "\n" . "In the Dublin Core Jungle\n" . "http://jungle.tld/Enter/\n" . "en-GB\n" . "tiger\n" . "elephant\n" . "snake\n" . "\n", "1.0 - item/multiple dc:subject's" ); my $parsed_rss = XML::RSS->new(version => '1.0'); $parsed_rss->parse($rss->as_string()); # TEST is_deeply ( $parsed_rss->{'items'}->[1]->{'dc'}->{'subject'}, [qw(tiger elephant snake)], "Properly parsed dc:subject into an array.", ); # TEST is( $parsed_rss->{'items'}->[1]->{'dc'}->{'language'}, "en-GB", "Properly parsed dc:language.", ); } { my $rss = create_skipDays_rss({ version => "2.0", skipDays_params => [ day => [qw(Sunday Thursday Saturday)] ], }); # TEST contains($rss, ("\n" . "Sunday\n" . "Thursday\n" . "Saturday\n" . "\n"), "Generate skipDays with multiple values (array)." ); } { my $rss = create_skipHours_rss({ version => "2.0", skipHours_params => [ hour => [qw(5 10 16)] ], }); # TEST contains($rss, ("\n" . "5\n" . "10\n" . "16\n" . "\n"), "2.0 - skipHours/hour == 0" ); } { my $rss = create_item_with_0_rss({version => "2.0", item_params => [ title => "Foo&Bar", link => "http://www.mytld/", category => ["OneCat", "TooCat", "3Kitties"], ], } ); # TEST contains( $rss, ("\n" . "Foo&Bar\n" . "http://www.mytld/\n" . "OneCat\n" . "TooCat\n" . "3Kitties\n" . "" ), "2.0 - item/multiple-category's", ); } { # Here we create an RSS 2.0 object and render it as the output # version "3.5" in order to test that version 1.0 is the default # version for output. my $rss = create_channel_rss({ version => "2.0", channel_params => [category => [qw(OneCat TooManyCats KittensGalore)]], omit_date => 1, }); # TEST contains($rss, ("\n" . "freshmeat.net\n" . "http://freshmeat.net\n" . "Linux software\n" . "OneCat\n" . "TooManyCats\n" . "KittensGalore\n" . "\n" . "\n"), "Multiple channel/category elements" ); } rss-permalink.xml100644001750001750 14276614756547744 17714 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t/data LiveJournal Development http://community.livejournal.com/lj_dev/ LiveJournal Development - LiveJournal.com Tue, 18 Apr 2006 18:29:22 GMT LiveJournal / LiveJournal.com http://www.livejournal.com/userpic/42132/26901 LiveJournal Development http://community.livejournal.com/lj_dev/ 100 75 http://community.livejournal.com/lj_dev/714037.html Tue, 18 Apr 2006 18:29:22 GMT MogileFS - LJ - Replication http://community.livejournal.com/lj_dev/714037.html Got MogileFS up and running on a single test server running both mogstored and mogilefsd.<br />For test purposes instead of mounting different drives or partitions at /var/mogdata I just created three local directories dev1, dev2, dev3.<br /><br />When I create userpics, single copies of the pics are stored to /var/mogdata/dev1/0/000/000 - /var/mogdata/dev3/0/000/000. But it is only storing 1 copy of each userpic (mindevcount is set to 3 for userpics).<br /><br />Question - Is this working as designed because it is smart enough to realize that dev1-dev3 are really the same file system so why waist space?, or do I have something configured wrong that is preventing replication? (I did notice in the host table for hostid 1 the http_port set to 7500 but there is nothing in the http_get_port).<br /><br />Thanks..... http://community.livejournal.com/lj_dev/714037.html http://community.livejournal.com/lj_dev/713810.html Tue, 11 Apr 2006 17:25:28 GMT different ljconfig.pl for apache-ssl http://community.livejournal.com/lj_dev/713810.html Hi.<br /><br />I apologize if this is the wrong place for this post, but this is what I need to do.<br /><br />External access to our company's intranet is through https and through redirection. basically, from the internet, the user types in<br /><br /><a href="https://mycompany/blog">https://mycompany/blog</a> <br /><br />which the IIS server changes to<br /><br /><a href="https://blog/blog">https://blog/blog</a> (don't ask me why they have this setup) .. grabs the content and displays it to the outside user.<br /><br />so now, I am in a quandary.<br /><br />I want normal users (in the intranet) to be able to access <a href="http://blog">http://blog</a> and the users accessing from the extranet to be able to access <a href="https://blog/blog">https://blog/blog</a><br /><br />so what's the best way to do this?<br /><br />Here is what I have done so far.<br /><br />a) created a subdirectory (/home/lj/blog) and symlinked (/home/lj to /home/lj/blog) except ljconfig.pl<br />b) pointed /etc/apache-ssl/httpd.conf<br /> i) the document root to be /home/lj/blog <br /> ii) PERLSETEV LJHOME /home/lj/blog<br />c) changed /home/lj/blog/ljconfig.pl so that the $SITE variable is <a href="https://blog/blog">https://blog/blog</a><br /><br />basically what i want is that /home/lj be served by apache-perl and /home/lj/blog be served by apache-ssl <br /><br />when i try all this, unfortunately, I get the following error in /var/log/apache-ssl/error.log<br /><br />cannot find /home/lj/blog/htdocs/blog<br /><br />i must be making a stupid mistake.. but am i wrong in thinking the above will work?<br /><br />is there a better/easier way to do this? basically have 2 ljconfig.pl and make apache-perl read one and apache-ssl read the other? http://community.livejournal.com/lj_dev/713810.html http://community.livejournal.com/lj_dev/713549.html Sun, 09 Apr 2006 16:58:17 GMT Interests API http://community.livejournal.com/lj_dev/713549.html Hi, I'm Israeli development consulter and working on some product that using LiveJournal.com API<br /><br />I'm not sure, that's right place to ask, but I'm seeking for "interests" API for LJ. The only information found was regarding set_interests(setinterests) and get_interests(getinterests) in changelogs. Maybe members of this community can point me to the right way to figure information regarding this interface<br /><br />Thank you http://community.livejournal.com/lj_dev/713549.html http://community.livejournal.com/lj_dev/713324.html Sun, 09 Apr 2006 16:57:58 GMT One happy Dev machine? http://community.livejournal.com/lj_dev/713324.html The new userpic factory requires MogileFS in order to work and does not error out real gracefully if Mogilefs is not there. No biggey, I wanted to turn MogileFS on anyway. After reading up I think I see how to create the DB, create the storage devices, user mogadmin to populate the DB, set up the config files for mogstored and mogilefsd, start the daemons.<br /><br />The questions: Is there any hidden gotcha that will prevent this from all working on the same machine (obviously a dev env not a production env) if I set it up with only one storage device?<br /><br /><br />Thanks, http://community.livejournal.com/lj_dev/713324.html http://community.livejournal.com/lj_dev/713006.html Fri, 07 Apr 2006 23:47:37 GMT subversion http://community.livejournal.com/lj_dev/713006.html We're now using Subversion instead of CVS. Everything's been imported into:<br /><br /><a href="http://code.sixapart.com/svn/livejournal/trunk/">http://code.sixapart.com/svn/livejourna<wbr />l/trunk/</a><br /><a href="http://code.sixapart.com/svn/ljcom/trunk/">http://code.sixapart.com/svn/ljcom/trun<wbr />k/</a><br /><br />And dozens of other repositories. (wcmtools was broken out into a repo per directory, pretty much, as each directory there was basically an old project....)<br /><br />But multicvs.pl (which the historical cvsreport.pl wraps) will take care of checking them all out. But for details, see:<br /><br /><a href="http://code.sixapart.com/svn/livejournal/trunk/cvs/multicvs.conf">http://code.sixapart.com/svn/livejourna<wbr />l/trunk/cvs/multicvs.conf</a><br /><br />Which has this list:<br /><br />SVN(livejournal) = <a href="http://code.sixapart.com/svn/livejournal/trunk/">http://code.sixapart.com/svn/livejourna<wbr />l/trunk/</a><br />SVN(gearman) = <a href="http://code.sixapart.com/svn/gearman/trunk/">http://code.sixapart.com/svn/gearman/tr<wbr />unk/</a><br />SVN(perlbal) = <a href="http://code.sixapart.com/svn/perlbal/trunk/">http://code.sixapart.com/svn/perlbal/tr<wbr />unk/</a><br />SVN(memcached) = <a href="http://code.sixapart.com/svn/memcached/trunk/">http://code.sixapart.com/svn/memcac<wbr />hed/trunk/</a><br />SVN(CSS-Cleaner) = <a href="http://code.sixapart.com/svn/CSS-Cleaner/trunk/">http://code.sixapart.com/svn/CSS-Cleane<wbr />r/trunk/</a><br />SVN(Sys-Syscall) = <a href="http://code.sixapart.com/svn/Sys-Syscall/trunk/">http://code.sixapart.com/svn/Sys-Syscal<wbr />l/trunk/</a><br />SVN(LWPx-ParanoidAgent) = <a href="http://code.sixapart.com/svn/LWPx-ParanoidAgent/trunk/">http://code.sixapart.com/svn/LWPx-Paran<wbr />oidAgent/trunk/</a><br />SVN(adengine) = <a href="http://code.sixapart.com/svn/adengine/trunk/">http://code.sixapart.com/svn/adengine/t<wbr />runk/</a><br />SVN(Danga-Socket) = <a href="http://code.sixapart.com/svn/Danga-Socket/trunk/">http://code.sixapart.com/svn/Danga-Sock<wbr />et/trunk/</a><br />SVN(djabberd) = <a href="http://code.sixapart.com/svn/djabberd/trunk/">http://code.sixapart.com/svn/djabberd/t<wbr />runk/</a><br />SVN(s2) = <a href="http://code.sixapart.com/svn/s2/trunk/">http://code.sixapart.com/svn/s2/trunk/</a><wbr /><br /><br />The machine has Trac and viewcvs installed as well. See <a href="http://code.sixapart.com/">http://code.sixapart.com/</a> which will soon be updated with more links/info. http://community.livejournal.com/lj_dev/713006.html multicvs cvs svn http://community.livejournal.com/lj_dev/712833.html Wed, 05 Apr 2006 22:43:00 GMT Public Asterisk server http://community.livejournal.com/lj_dev/712833.html The public SIP/IAX2-to-LiveJournal <a href="http://community.livejournal.com/lj_dev/706430.html">project</a> has been finally resurrected.<br /><br />Try to do SIP/IAX2 to: <b>204.9.177.24</b><br /><br />And do a LJ voicepost. (if you have a paid account)<br /><br />The system is now outside of our network, but is using your LJ pin auth, and we're importing its recordings into LJ's network for posting to your journal.<br /><br />Please report success/failure with method/OS/client/etc.<br /><br />Thanks!<br /><br />P.S. It's known to work with <a href="http://iaxclient.sourceforge.net/iaxcomm/">iaxComm</a> on Win/Linux/Mac, but note that the iaxComm program is pretty flakey and the initial "Account settings" page is buggy, so you'll likely have to quit that screen and go back into preferences and re-add it. Username whatever ("guest" or blank), no password. Dial any number (say, "1"), then press "Dial" to connect. http://community.livejournal.com/lj_dev/712833.html asterisk voicepost http://community.livejournal.com/lj_dev/712581.html Mon, 03 Apr 2006 22:08:41 GMT LJ and PGP http://community.livejournal.com/lj_dev/712581.html I wonder if you have thought about it before.<br />Recently there was a case in the Russian livejournal community when someone set up a hoax account of a prominent person and used it to produce loads of silly comments in highly visible journals.<br />That made me wonder how to make sure that a hoax author can be easily identified. I didn't come to a complete solution of the problem, but it occurred to me that livejournal is a good implementation of a trusted peer network, and seems to be a good place to sign, exchange and use public keys. What do you think about this idea (as if you had nothing else to think about)? http://community.livejournal.com/lj_dev/712581.html http://community.livejournal.com/lj_dev/712356.html Mon, 20 Mar 2006 06:33:17 GMT utf-8 bug http://community.livejournal.com/lj_dev/712356.html I'm sure there are more pressing bugs, but here's a note all the same.:<br /><br />Livejournal stores and transmits <strike>malformed</strike> illegal utf-8 characters such as the following: � (U+DBA0, a UTF-16 surrogate). This breaks clients and services that expect utf-8 replies, especially on xml which is usually more strict than html. http://community.livejournal.com/lj_dev/712356.html http://community.livejournal.com/lj_dev/712139.html Wed, 15 Mar 2006 17:39:43 GMT BUG REPORT: Slight glitch with malformed tags. http://community.livejournal.com/lj_dev/712139.html I created a post with a tag that's just a "."<br /><br />LJ's tag system doesn't handle that condition as it should.<br /><br />Clicking on the . tag sends you to:<br /><br /><a href="http://m-leprae.livejournal.com/tag/">http://m-leprae.livejournal.com/tag/<wbr /></a><br /><br />It really ought to send you to:<br /><br /><a href="http://m-leprae.livejournal.com/tag/">http://m-leprae.livejournal.com/tag/<wbr /></a>.<br /><br />I guess that's not a legal URL however.<br /><br />A little more experimenting yields a few more glitches:<br /><br />Clicking on a tag that's .. will cause you to climb up to <a href="http://m-leprae.livejournal.com">http://m-leprae.livejournal.com</a><br /><br />Clicking on tag that's ../friends sends you to my friends page.<br /><br />Example entry at: <a href="http://m-leprae.livejournal.com/294364.html">http://m-leprae.livejournal.com/294<wbr />364.html</a><br /><br />There may be worse things one can do, but I'd rather not go there. http://community.livejournal.com/lj_dev/712139.html http://community.livejournal.com/lj_dev/711730.html Fri, 10 Mar 2006 18:40:56 GMT Don't know where else to post this: Sprint picturemail fix http://community.livejournal.com/lj_dev/711730.html Cut in case it's off topic.<br /><a name="cutid1"></a><br /><br />Okay, so I use sprint, and their stupid method of emailing picture messages annoys me to no end. I otherwise like their service, and even if I didn't, we're married for the next two years anyhow :)<br /><br />Anyway, so I noticed with my samsung A900, I was posting pictures to livejournal and noticing they looked small and grainy. For a 1280x960 image, that didn't look right. It turns out that the actual image livejournal is posting is based on the xml crud in the email, which actually generates a small version of the image suitable for mobile phones. Ugh.<br /><br /><pre> &lt;!-- lsPictureMail-Share-iETr4JPjm77BG8Bo7UHh-comment &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF&#45;8&quot;?&gt; &lt;shareMessage&gt; &lt;messageContents type=&quot;PICTURE&quot;&gt; &lt;messageText&gt;Hi&lt;/messageText&gt; &lt;mediaItems&gt; &lt;mediaItem id=&quot;1&quot;&gt; &lt;title&gt;&lt;/title&gt; &amp;lt;url&amp;gt;http://pictures.sprintpcs.com/getMMBOXMessageMedia?id=Xw1004H8sLv6S3x76lVPYmsnJP2O20g3zlhB%2Fx7njqW9MscUXIEXBQmk5gW%2FZUWGmojEaNnHPws%2F%0A5lpklQ8%2Bufjui%2BAXcLyJG3ClZw2m2Gi1qkXdBdb5KgoH8KyzBNpwHmgReddy4aqnGyBYMpsPyA%3D%3D%0A&amp;lt;/url&amp;gt; &lt;urlExpiration&gt;2006&#45;03&#45;10T19:31:51Z&lt;/urlExpiration&gt; &lt;/mediaItem&gt; &lt;/mediaItems&gt; &lt;/messageContents&gt; &lt;/shareMessage&gt; --&gt; &lt;!-- lsPictureMail-UserInfo-iETr4JPjm77BG8Bo7UHh-comment &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF&#45;8&quot;?&gt; &lt;UserInfo timestamp=&quot;2006&#45;03&#45;03T19:31:51.785+00:00&quot; originating_from_address=&quot;USERNAMEREDACTED@pm.sprint.com&quot;&gt;&lt;credential name=&quot;MDN&quot;&gt;248XXXXXXX&lt;/credential&gt;&lt;/UserInfo&gt; --&gt; </pre><br /><br />Ugly, huh?<br /><br />Anyway, there's some useful information, and the parser for this is at line 200 of livejournal/cgi-bin/ljemailgateway.pl.<br /><br />Now, I'm a perl ninja and all, but I really don't want to hack this deep into the code having never laid my hands on it before, and offer up a patch that will one day break, or not work right, so I'm hoping that if I supply a method of grabbing the full media file, someone else can make the fix and push it in? :)<br /><br /><br />Anyway, the key is in the actual body of the email, in the middle of the HTML. Yes, I know, parsing HTML to get this is fugly. Just wait, because it gets worse.<br /><br /><pre> &lt;img src="http://pictures.sprintpcs.com//mmps/RECIPIENT/001_01116de4bcdbcd9c_1/2.2?inviteToken=iETr4JPjm77BG8Bo7UHh&amp;limitsize=258,258&amp;outquality=90&amp;squareoutput=255,255,255&amp;ext=.jpg&amp;iconifyVideo=true&amp;wm=1"/&gt; </pre><br /><br />Okay, so there's the line from the email that has the actual image string we want in it. Here's what you have to do:<br /><br />Search the email for an image tag with the string "/mmps/RECIPIENT/" in the src.<br /><br />Pull out the url:<br /><a href="http://pictures.sprintpcs.com//mmps/RECIPIENT/001_01116de4bcdbcd9c_1/2.2?inviteToken=iETr4JPjm77BG8Bo7UHh&amp;limitsize=258,258&amp;outquality=90&amp;squareoutput=255,255,255&amp;ext=.jpg&amp;iconifyVideo=true&amp;wm=1">http://pictures.sprintpcs.com//mmps/REC<wbr />IPIENT/001_01116de4bcdbcd9c_1/2.2?invite<wbr />Token=iETr4JPjm77BG8Bo7UHh&amp;limitsize=258,2<wbr />58&amp;outquality=90&amp;squareoutput=255,255,25<wbr />5&amp;ext=.jpg&amp;iconifyVideo=true&amp;wm=1</a><br /><br />In the real email, they're actually HTML entities too, so you have to use HTML::Entities::decode_entities() to make it work right. It's already loaded (and used in the current code) so no biggie.<br /><br />What you have to end up doing is removing all arguments to that URL, except for inviteToken=blalbalbalblab and ext=.jpg<br /><br />So it now looks like:<br /><a href="http://pictures.sprintpcs.com//mmps/RECIPIENT/001_01116de4bcdbcd9c_1/2.2?inviteToken=iETr4JPjm77BG8Bo7UHh&amp;ext=.jpg">http://pictures.sprintpcs.com//mmps/REC<wbr />IPIENT/001_01116de4bcdbcd9c_1/2.2?invite<wbr />Token=iETr4JPjm77BG8Bo7UHh&amp;ext=.jpg</a><br /><br />This has the upside of removing the stupid "frame" from around the picture too. ugh.<br /><br />You now hold the raw media file, which in this example, is from my girlfriend's 640x480 phone, a picture of hello kitty.<br /><br />The upside to this URL, is also, strangely enough, that unlike the tag in the XML, this image does not expire. You can fetch it at any time, even if the mailserver is lagging bad, and doesn't process the message for the default expiry of 7 days.<br /><br /><br /><br />I'd be willing to pitch in what I can in terms of code to get this going, but from my description, it should be pretty self explanitory, and allow for much higher quality images to come from sprint phones.<br /><br />Thanks! http://community.livejournal.com/lj_dev/711730.html geeky http://community.livejournal.com/lj_dev/711461.html Thu, 09 Mar 2006 10:58:17 GMT OpenId: wrongly escaped url? http://community.livejournal.com/lj_dev/711461.html Hey,<br /><br />Our users (<a href="http://www.foodcandy.com">http://www.foodcandy.com</a>) have issues with Lj's OpenId implementation on Firefox running on Linux. Details after the cut.<br /><a name="cutid1"></a><br />We redirect to something like this: <a href="http://www.livejournal.com:80/openid/server.bml?openid.identity=http%3a%2f%2fharryh.livejournal.com%2f&openid.return_to=http%3a%2f%www.foodcandy.com%2fAccountLogin.aspx&openid.trust_root=http%3a%2f%2fwww.foodcandy.com&openid.mode=checkid_setup&openid.assoc_handle=1141175386%3azLGZESEzvNsNz52O41kC%3a94aec3bf89">http://www.livejournal.com:80/openid/se<wbr />rver.bml?openid.identity=http%3a%2f%2fha<wbr />rryh.livejournal.com%2f&openid.return_to=http%3a%2f%www.foodcand<wbr />y.com%2fAccountLogin.aspx&openid.trust_root=http%3a%2f%2fwww.foodc<wbr />andy.com&openid.mode=checkid_setup&openid.assoc_handle=1141175386%3azLGZESE<wbr />zvNsNz52O41kC%3a94aec3bf89</a> - that seems to land at <a href="http://www.livejournal.com/openid/approve.bml?return_to=http://www.foodcandy.com/AccountLogin.aspx&identity=http://harryh.livejournal.com/&assoc_handle=1141175929:av40yQ946R3z4WrUd70P:42b4506fe8&trust_root=http://www.foodcandy.com">http://www.livejournal.com/openid/appro<wbr />ve.bml?return_to=http://www.foodcandy.co<wbr />m/AccountLogin.aspx&identity=http://harryh.livejournal.com/&assoc_handle=1141175929:av40yQ946R3z4WrU<wbr />d70P:42b4506fe8&trust_root=http://www.foodcandy.com</a>. <br /><br />Notice the unescaped parameters (looks wrong to me).<br /><br />My users are saying this is a blank page on firefox+linux.<br /><br />Ideas? Comments? Bug?<br /><br />Much appreciated,<br />dB.<br /> http://community.livejournal.com/lj_dev/711461.html http://community.livejournal.com/lj_dev/711286.html Tue, 07 Mar 2006 00:25:25 GMT XSS exploits & perm accounts http://community.livejournal.com/lj_dev/711286.html Another security bughunt round will begin soon (the code on both the live site and dev site needs to be updated), but before that begins I want to make sure everybody has their perm accounts.<br /><br />We notice that there are 9 people that haven't got theirs yet. If you're one, email accounts@livejournal.com (using the email you would've sent the XSS-LJ email with) with the username you want to have a perm account and we'll look up your ticket and award you.<br /><br />The SHA1s of the lowercased emails that still need perm accounts are:<br /><br />165ca37eabfd30d39c0b02063643fe2a73aa25d6<br />335410032e8c0c44a1c30f8f848ad0ac8a7e03c5<br />3f2c8af8ff061ccbe08494a62d714457d1a71c30<br />59e9914025681bb2145661c781d048b458880595<br />7457cb4526638c4304143688ed242a45847658d0<br />b619c73a32aa92ae6909cf9ec5b6c0bcbd481ba7<br />b87d5a97a2fce540e97edbc969d769f083b02f8d<br />cb5ae7ce9c253fd803a682a2816adc1fc692883e<br />d8c33159d760a5e5602728d9e52f7dbb9fa971e9 http://community.livejournal.com/lj_dev/711286.html http://community.livejournal.com/lj_dev/711020.html Mon, 27 Feb 2006 23:31:49 GMT Duplicate feeds for communities http://community.livejournal.com/lj_dev/711020.html Hello.<br />I'm product manager for Yandex Blog Search, russian blog search engine.<br /><br />We have some difficulties with LJ.<br /><br />Main difficulty now is that any community, for example, <a href="http://lj-dev.livejournal.com/">http://lj-dev.livejournal.com/</a> (and <a href="http://lj-dev.livejournal.com/data/rss">http://lj-dev.livejournal.com/data/rss</a><wbr />) is not a redirect to right location (<a href="http://community.livejournal.com/lj_dev/">http://community.livejournal.com/lj_de<wbr />v/</a>), but a duplicate. It leads to some side effects in our blog search.<br /><br />Do you think it is bug? We reported it first day after URLs changed, but it was not fixed.<br /><br />Sorry if this is wrong place for such questions. http://community.livejournal.com/lj_dev/711020.html http://community.livejournal.com/lj_dev/710896.html Thu, 16 Feb 2006 17:00:34 GMT LJ Apache/mod_perl2 Port http://community.livejournal.com/lj_dev/710896.html Hello to everyone on ljdev!<br /><br />This is my first time post in ljdev although I've been monitoring ljdev on and off for many months now. I'm primarily interested in having a version of LJ running on Apache/mod_perl2 - finally getting around making it happen. Unfortunately I had to incorporate it as part of a school project to carve out the time.<br /><br />In a couple of weeks I hope to have semi-functioning LJ code that supports both Apache 1.x & 2.x and associated mod_perl (since that's when the project is due) - especially interested in having it run with minimal work with vanilla Fedora Core 4.<br /><br />There are a couple of ljdev posts regarding LJ and Apache 2.0 so there seems to be some interest. Will anyone be interested in my port? I'd like to contribute my work if anyone's willing to try it out.<br /><br />Advice and comments would be greatly appreciated!<br /><br />And finally I have some questions - some for the purposes of the port and others are for the project report (I have to get the school fluff out of the way!). A big thanks to those who reply!<br /><br /><ol><li>Why are you interested in a 2.x port? My initial motivation was to run a small private, LJ site for small group of friends but I couldn't get it to work with Fedora-out-of-the-box. My goal is to have LJ running with as little modification as possible to a Fedora system.</li><br /><li>For those who plan to install LJ on their own servers, how many users are you looking to support?</li><br /><li>What kind of systems are you planning to use as LJ server? OS? Desktop PC? Server machine?</li><br /><li>What are the primary reason(s) for using LJ? What kind of journals (work? personal?)</li><br /><li>Are you interested in a straight port to 2.x or one that supports both 1.x and 2.x?</li><br /><li>Why do you want backwards compatibility?</li><br /><li>What are you most worried about with installing/upgrading LJ?</li><br /><li>What part of the (LJ) installation process causes the most pain?</li><br /><li>What kind of configurations of LJ/Apache/mod_perl do you have?</li><br /><li>Additional comments/insights/suggestions? Any questions you think I should have asked?</li><br /></ol> http://community.livejournal.com/lj_dev/710896.html http://community.livejournal.com/lj_dev/710503.html Tue, 14 Feb 2006 18:09:27 GMT CVS repository down? http://community.livejournal.com/lj_dev/710503.html Hi,<br /><br />I'm new to livejournal, and would like to download the opensource for reference in my school project. However, I can't seem to be able to download anything through the cvs. Is the server currently down? If so, when will it be up again? Please advice, Thank you. :)<br /><br />Cheers. http://community.livejournal.com/lj_dev/710503.html http://community.livejournal.com/lj_dev/710161.html Mon, 13 Feb 2006 19:53:25 GMT XSS update http://community.livejournal.com/lj_dev/710161.html Fixed a bunch, still got a handful to go.<br /><br />We're keeping all the emails in our ticket tracking system, and keeping track of who needs a permanent account. Ryan is going through the list this week (and some of last week) and emailing out perm account coupons/information.<br /><br />Will post more about round 3 when we're done fixing all current known issues. http://community.livejournal.com/lj_dev/710161.html http://community.livejournal.com/lj_dev/709783.html Wed, 08 Feb 2006 05:02:41 GMT Enhancing the RTE http://community.livejournal.com/lj_dev/709783.html So I've been spending part of the day working on integrating <a href="http://www.fckeditor.net/">FCKeditor</a> into LJ, since we all know the current rich text editor isn't great. Issue I'm running into is it always converts &lt;, &gt;, and & to their html entities on submit. So this presents a problem for people wanting to type something like &lt;lj user='test' /&gt;.<br /><br />So two solutions I see:<br />A) Stop the entity conversion<br />B) Write a plugin that adds toolbar buttons for LJ specific tags<br /><br />Issue with A is that I can't figure out where the this conversion is happening. I have disabled the FCKConfig.ProcessHTMLEntities option, but a comment in fckhtmlentities.js says, "This entity is automatically handled by the XHTML parser". Every place it seems like it would be doing this conversion, it isn't. So frustrated with this option.<br /><br />Issue with B is I that can write a plugin to add a toolbar button with no problem, but don't think I can make it convert an lj tag when someone goes from normal to rich mode. Also not sure how to visually represent things like an lj-cut in the editing interface.<br /><br />Another option is to always convert the entity back on form submission, client or server side, this however would mean that I couldn't type the entities in the RTE like I did above as an example tag.<br /><br />So two solutions, neither of which seem perfect. Seems like the good solution is a combination of A and B, so a button to add these tags, and have them show up as a tag in the rich view while not being converted to entities on submit. Been reading through the project's site on SourceForge and seems like others have this same issue with entities; though I guess the project hasn't decided to address it yet. Costs $175 in a donation to get "email support". Anyone familiar with FCKeditor?<br /><br />Edit: Seems like I've just been going crazy with this all day and it is a fairly easy solution. On submit we do a bit of a onversion which should end up with the right stuff in the end. Sorry for the friends page spam. :P http://community.livejournal.com/lj_dev/709783.html http://community.livejournal.com/lj_dev/709562.html Tue, 07 Feb 2006 21:29:41 GMT LJ crawler for reasearch purposes http://community.livejournal.com/lj_dev/709562.html Hello! I'm sure this has been asked many times, but I haven't found such a post looking back for a while. Anyway: I'm currently writing a crawler for LJ for a research project that I'm working on, and I want to make sure I'm following all the rules, and also if anyone has advice they could give me. <br /><br />First of all: the research is to determine group sentiment towards particular topics. We will make a single crawl over LJ and then use the data to develop agregate results. Details of individual users will not be mentioned in the report. <br /><br />For this project we plan to first seed our crawler with usernames and community names found in google searches on a particular topic. We will then crawl over community members and friends of users whose robots.txt files don't exclude crawlers. From each user we are considering only pulling the RSS file, or possibly pulling articles from up to a year in the past. <br /><br />I have a few questions, though:<br /><br /><ul><br /><li>What about pulling user comments? Would that be ok?</li><br /><li>How do I know if a community allows robots or not, since they don't have a subdomain with a robots.txt file?</li><br /><li>At what rate of requests/sec should I set my crawler to in order for it to be "nice"?</li><br /><li>Are there any previous simmilar works that anyone is aware of?</li><br /><li>For users that exclude robots: would it be appropriate if I send them a message via their livejournal email address asking if they would like to be included in the research?</li><br /></ul><br /><br />Again, this is strictly not for profit, aggregate data collection for research purposes only. I would appreciate any comments anyone has. http://community.livejournal.com/lj_dev/709562.html http://community.livejournal.com/lj_dev/709314.html Tue, 07 Feb 2006 19:06:39 GMT An easier way to find CSS exploits http://community.livejournal.com/lj_dev/709314.html Another way to get permanent accounts, if nobody has beaten you to the exploit:<br /><br /><a href="http://www.test.dev.livejournal.org/misc/csstest.bml">http://www.test.dev.livejournal.org/mis<wbr />c/csstest.bml</a><br /><br />Find some CSS which does an alert box (or any JavaScript, but alerts are very in-your-face), then email me with at least subject "XSS-LJ <i>whatever</i>", the browser, and the CSS you put in the box.<br /><br />Happy Hacking. http://community.livejournal.com/lj_dev/709314.html http://community.livejournal.com/lj_dev/708866.html Tue, 07 Feb 2006 00:06:07 GMT XSS contest, round 2 http://community.livejournal.com/lj_dev/708866.html Same rules <a href="http://community.livejournal.com/lj_dev/708313.html">as before</a>. Try and inject JavaScript into the test server, now running newer code:<br /><br /><a href="http://www.test.dev.livejournal.org/">http://www.test.dev.livejournal.org/<wbr /></a><br /><br />Mail me if you find an exploit, and tell me which browser. Read the old post I linked for more details.<br /><br />Happy hacking!<br /><br /><b>BTW</b>, we're still tracking everybody's submissions. If you haven't gotten your permanent account, don't worry ... we haven't forgotten about you. Just backlogged. http://community.livejournal.com/lj_dev/708866.html http://community.livejournal.com/lj_dev/708810.html Fri, 03 Feb 2006 06:55:07 GMT legacy cookie support actually fixed now http://community.livejournal.com/lj_dev/708810.html The code in LJ::Session which supported legacy cookie support was broken due to a subtle bug in BML's cookie handling. That's now fixed:<br /><br /><a href="http://community.livejournal.com/changelog/2656195.html">http://community.livejournal.com/change<wbr />log/2656195.html</a><br /><br />So all these issues will go away after the next code push:<br /><br /><a href="http://community.livejournal.com/lj_dev/706840.html">http://community.livejournal.com/lj<wbr />_dev/706840.html</a><br /><br />Sorry for not testing it last time... the code in LJ::Session was so simple it was "obviously" correct (and it was, afterall), but the BML bug messed it up. (that we got back [undef], not [], when ljmastersession wasn't present....) http://community.livejournal.com/lj_dev/708810.html http://community.livejournal.com/lj_dev/708425.html Wed, 01 Feb 2006 05:01:23 GMT XSS challenge: update http://community.livejournal.com/lj_dev/708425.html Whoa, thanks everybody.<br /><br />Please, though, hold off on the XSS bug reports. We got way more than we thought. Embarassing. I was hoping for 5 or 6, not ~30.<br /><br />We've fixed most of them but still have a few hard ones remaining and most the incoming emails now are dups.<br /><br />Please wait for round two. (tomorrow or tomorrow night I'm guessing, after we update the test server's code...)<br /><br />Don't worry, we're making tickets for all of them, and we're keeping track of each ones who/what/when of them all. We'll be doing perm accounts in a batch after we put up round two. http://community.livejournal.com/lj_dev/708425.html http://community.livejournal.com/lj_dev/708313.html Tue, 31 Jan 2006 06:29:46 GMT the XSS security challenge http://community.livejournal.com/lj_dev/708313.html Anybody bored and want a permanent account? Read on:<br /><br />We're going to be running an XSS (Cross site scripting / Javascript injection) bug hunt challenge soon here. The biz people like the idea but need to squabble over rules and legal stuff. <b>Unofficially</b>, it'll involve giving out permanent accounts and money (or gift certificates).<br /><br />So while I can't promise you jack right now in terms of money, I can give out permanent accounts like candy, so I'll announce the first round of the game:<br /><br /><b>STEP 1:</b> Go to <a href="http://www.test.dev.livejournal.org/">http://www.test.dev.livejournal.org/<wbr /></a> . Make an account. Probably need to <a href="http://www.test.dev.livejournal.org/admin/accounts/acctedit.bml">change it to paid</a> so you can make styles/etc.<br /><br /><b>STEP 2:</b> Inject some JavaScript. Use S1, S2, CSS, overrides, you name it. It'd probably help if you read the HTML and CSS cleaner code in cvs to look for bugs, but it's not required. If you want, the code is at:<br /><br />cvs/livejournal/cgi-bin/cleanhtml.pl<br />cvs/wcmtools/lib/HTMLCleaner.pm<br />cvs/wcmtools/lib/CSS-Cleaner/lib/CSS/Cle<wbr />aner.pm<br /><br />CVS viewers are at <a href="http://cvs.danga.com/">http://cvs.danga.com/</a> and <a href="http://cvs.livejournal.org/">http://cvs.livejournal.org/</a> .<br /><br /><b>STEP 3:</b> Email me (brad@danga.com) with subject containing at least "<b>XSS-LJ</b>", and a URL to a <b><i>minimal test case</i></b> illustrating your hole. I need to know how you did it, source code, maybe your test account's password, whatever it takes. The more clear it is, the more likely you win and I don't accept somebody else's later but more clear bug report first. After you find a hole, go create a new account for your next hole.<br /><br />Brad's unofficial rules: I am judge, jury, and sole candy giver, at least until there are official rules. If I give you a permanent account, that doesn't mean you're not eligible for money/gift certificates later. We'll retroactively give that out for the best/hardest-to-fix/most-clever holes after the fact.<br /><br /><b>NOTE:</b> The code running on the above URLs isn't live on the site yet. We don't care about holes at www.livejournal.com, because they're likely already fixed in the test code. The test code will go live on the site soon-ish. So reproduce (or produce) your bug reports on the test machine.<br /><br /><b>NOTE 2:</b> The test machine above is a small virtual machine. I might not have given it enough memory. If it sucks, I'll increase it. Bear with me. http://community.livejournal.com/lj_dev/708313.html http://community.livejournal.com/lj_dev/708069.html Fri, 27 Jan 2006 00:38:18 GMT Discussing The Security Changes http://community.livejournal.com/lj_dev/708069.html As we announced last week in <span class='ljuser' style='white-space: nowrap;'><a href='http://news.livejournal.com/profile'><img src='http://stat.livejournal.com/img/newsinfo.gif' alt='[info]' width='16' height='16' style='vertical-align: bottom; border: 0;' /></a><a href='http://news.livejournal.com/'><b>news</b></a></span>, we have changed the canonical URL of most journal, community, and syndicated content. We have also now changed our cookie handling <a href="http://community.livejournal.com/lj_dev/706058.html">as Brad previously described</a>. In the end this means that it is much more difficult to steal a useful cookie. Our goal with our new cookie scheme is to limit the damage that can occur when your cookies do get stolen, which we're just going to assume is inevitable, as vulnerabilities have been found in all major browsers and we're quite sure new vulnerabilities will continue to be found.<br /><br />Shortly before our news post last week, we became aware that it was possible to use the “-moz-binding” CSS attribute within Mozilla and Mozilla Firefox to execute arbitrary offsite JavaScript. As this attribute is designed to allow attaching an XBL transform and JavaScript to any node within the DOM, it is quite easy to use in a malicious fashion. A <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=324253">bug</a> has also been filed in Mozilla's BugZilla tracker to try and address this issue. Over a year ago, <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=178993">we sponsored and developed</a> a patch for Mozilla to support HTTPOnly cookies which emerged in Internet Explorer 6 and would have prevented this attack, though this patch was never included in Mozilla.<br /><br />We immediately altered our cleaner to strip this attribute from entries and comments, though also realized that wasn't even half the battle. As we allow custom CSS in many of our styles, as well as the ability to link to an external stylesheet in a variety of fashions, it was quite possible to take advantage of this exploit and hijack the session cookie of any user who views your journal. As we, along with many other sites, used one cookie to authenticate a user, this cookie was quite powerful if stolen. If the user had not chosen to bind their cookie to their IP address, a malicious user could steal it, login as that user, deface the account and spam with it, as well as modify that user's style to include the exploit thus causing this problem to spread much like a virus.<br /><br />Borrowing the idea from another development team within Six Apart, we decided we needed to break our cookies into three categories. One cookie would be our master cookie, this cookie would only be accessible on www.livejournal.com where we will not display untrusted content. A second cookie will be accessible on all subdomains of livejournal.com, though it only will say if you are logged in or not; it is solely for optimization. We then will issue one cookie for each journal you visit. This cookie will be only accessible on username.livejournal.com or community.livejournal.com/username as it is limited to a single journal. This cookie will only grant you the permission to read protected entries and post in the particular journal. This means that if the journal owner steals your cookie, they will be able to do nothing more than view their journal as if they are you. In the end you will have n+2 cookies, with n being the number of journals you visit.<br /><br />Due to the fact that we cannot clean every external CSS stylesheet linked to every time we generate a journal page, this change is required. While it does not fully protect us from some new cross site scripting vulnerability that can be exploited via entries or comments, they are much easier to block, patch, and recover from quickly. With Mozilla deciding to allow the execution of arbitrary JavaScript via CSS, there is no other viable solution than the one we have undertaken.<br /><br />We've already taken a variety of steps to further protect your account such as we've <a href="http://www.livejournal.com/manage/logins.bml">implemented a page where you can see all of your login session</a>, now require your password to change your email address, and now send secure password reset emails. We also are planning future improvements, especially related to external CSS stylesheets, and hope everyone realizes the amount of attention we place on the security of every account. We're more than happy to answer any questions you have in regards to the changes we've made over the past week, though also hope it is understood that we are limited in what information we can share when actively dealing with a situation such as this. http://community.livejournal.com/lj_dev/708069.html http://community.livejournal.com/lj_dev/707830.html Thu, 26 Jan 2006 17:43:10 GMT Apache2 + LJ fun http://community.livejournal.com/lj_dev/707830.html So, I decided to ignore the warnings about the LiveJournal code not working on Apache2 and try it anyway (using Apache2::compat for now). Oddly enough, some of the problems I've run into so far are mod_perl ones (I'm using 2.0.2) rather than LiveJournal ones...<br /><br /><ul><li>PerlSetEnv doesn't seem to have any effect in a VirtualHost, even though the docs say it should work (this is where <a href="http://community.livejournal.com/lj_dev/690668.html">someone else's attempts failed</a>). Moving it to global scope made it work. This would probably also apply if porting to mod_perl 2.0 properly.</li><li>Apache::LiveJournal::Interface::S2 - 'Bareword "OK" not allowed while "strict subs" in use', solved by changing the include to 'use Apache::Constants qw(NOT_FOUND OK);'. Not sure what causes this (but the change might still be necessary if porting properly)...</li><li>Apache2::compat <a href="http://perl.apache.org/docs/2.0/user/porting/compat.html#C_Apache__Constants_">"doesn't provide a complete back compatibility layer"</a> for Apache::Constants. BAD_REQUEST is missing (it's Apache2::Const::HTTP_BAD_REQUEST in mod_perl 2). This breaks FotoBilder.pm</li><li>Apache::Log and Apache::URI aren't provided by Apache2::compat, though their functionality is</li><li>Apache::compat doesn't work outside of Apache. update-db.pl indirectly depends on Apache::Constants. If anyone actually ports LJ, this should work properly.</li><br /><br />It still doesn't work (BML docs not handled, DocumentRoot not set, etc - IOW, the httpd.conf injection doesn't seem to work), though at least Apache starts now. I wonder how much work porting it to mod_perl 2 (rather than using Apache2::compat) would be?</ul> http://community.livejournal.com/lj_dev/707830.html 0.9000755001750001750 014756547744 15133 5ustar00shlomifshlomif000000000000XML-RSS-1.65/examplesrss-0.9.dtd100644001750001750 1740014756547744 17125 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examples/0.9 fm0.91.rdf100644001750001750 170514756547744 16766 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examples/0.91 freshmeat.net http://freshmeat.net the one-stop-shop for all your Linux software needs en freshmeat.net http://freshmeat.net/images/fm.mini.jpg http://freshmeat.net 88 31 GTKeyboard 0.85 http://freshmeat.net/news/1999/06/21/930003829.html Spruce 0.4.7b http://freshmeat.net/news/1999/06/21/930003816.html quick finder Use the text input below to search freshmeat query http://core.freshmeat.net/search.php3 pod-coverage.t100644001750001750 36514756547744 17630 0ustar00shlomifshlomif000000000000XML-RSS-1.65/xt/author#!perl # This file was automatically generated by Dist::Zilla::Plugin::PodCoverageTests. use strict; use warnings; use Test::Pod::Coverage 1.08; use Pod::Coverage::TrustPod; all_pod_coverage_ok({ coverage_class => 'Pod::Coverage::TrustPod' }); empty-desc.rss100644001750001750 1320214756547744 17443 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t/data/2.0 http://community.livejournal.com/shlomif_hsite/ shlomif@iglu.org.il LiveJournal / LiveJournal.com Sun, 24 Sep 2006 10:12:49 GMT http://community.livejournal.com/shlomif_hsite/3573.html Sun, 24 Sep 2006 10:12:49 GMT New Additions to the Site shlomif@iglu.org.il http://community.livejournal.com/shlomif_hsite/3573.html <p> Exactly two weeks passed since the last update and many things have been added or improved. Read below for what's new. </p> <p> Two of the pages in <a href="http://www.shlomifish.org/MathVentures/">the MathVentures section</a> were converted to use embedded <a href="http://www.w3.org/Math/">MathML</a>. This should make viewing them with MathML-compliant browsers easier. The old ASCII-art based pages are still available. </p> <p> The ideas <a href="http://www.shlomifish.org/philosophy/ideas/#tucan">Tucan</a> and <a href="http://www.shlomifish.org/philosophy/ideas/#unixdoc">Unixdoc</a> were added to the Random Ideas page. </p> <p> I've placed <a href="http://www.shlomifish.org/open-source/nostalgia/">some of my old DOS-era programs online</a> for your amusement. </p> <p> I added a <a href="http://www.shlomifish.org/meta/FAQ/#site_history">question about the site history</a> to the <a href="http://www.shlomifish.org/meta/FAQ/">FAQ</a>. </p> <p> More CDs were added to the <a href="http://www.shlomifish.org/art/recommendations/music/">Music Recommendations</a>. </p> <p> There's <a href="http://www.shlomifish.org/humour.html#if_god_exists">a new Joke</a> in the Humour archive. </p> http://community.livejournal.com/shlomif_hsite/3573.html mathml mathematics math dos jokes tucan ideas mathventures unixdoc Metallica - Nothing Else Matters full public http://community.livejournal.com/shlomif_hsite/3165.html Sun, 10 Sep 2006 13:41:17 GMT Changes at Shlomi Fish Homesite shlomif@iglu.org.il http://community.livejournal.com/shlomif_hsite/3165.html <p> It's been about two weeks since my last update, and here's what's new: </p> <ol> <li> <p> <a href="http://www.shlomifish.org/art/recommendations/music/">A currently partial list</a> of my favourite compact discs is now live. Creating this list involved a large amount of <a href="http://en.wikipedia.org/wiki/Document_Type_Definition">DTD</a>, <a href="http://www.w3.org/TR/xslt">XSLT</a>, <a href="http://perl-begin.berlios.de/">Perl</a>, and CSS hacking on the <a href="http://search.cpan.org/dist/XML-Grammar-ProductsSyndication/">XML-Grammar-ProductsSyndication</a> framework, that was written from scratch to facilitate making construction of such lists possible by and others. </p> <p> I will add the missing CDs as time goes by, and will also later on add lists for fiction books and for movies, as well as convert the existing <a href="http://www.shlomifish.org/philosophy/books-recommends/">non-fiction books recommendations</a> into the new framework. </p> </li> <li> <p> More pages on the site were made to validate according to the <a href="http://www.w3.org/">World-wide-web consortium</a> standards, and some ancient leftovers that were no longer important were removed. </p> </li> <li> <p> <a href="http://www.shlomifish.org/open-source/favourite/">My list of favourite open source software</a> was updated, with many corrections, added programs and a new navigation menu. </p> </li> <li> <p> <a href="http://www.shlomifish.org/prog-evolution/pre-elpas.html">My memoirs as a programmer from High School</a> were heavily fixed and updated. </p> </li> </ol> http://community.livejournal.com/shlomif_hsite/3165.html xml grammar homesite shlomi fish syndication memoirs products valid html Monkey Island Am I Evil OC Remix annoyed public slashdot.rdf100644001750001750 356014756547744 17615 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examples/0.9 Slashdot:News for Nerds. Stuff that Matters. http://slashdot.org/ News for Nerds. Stuff that Matters Slashdot http://slashdot.org/images/slashdotlg.gif http://slashdot.org Red Hat Tightening Trademarks? http://slashdot.org/articles/99/09/01/0943219.shtml Scientists map schematic of brain's fibers http://slashdot.org/articles/99/09/01/1429226.shtml More Mission-Critical Linux http://slashdot.org/articles/99/09/01/1827215.shtml Amiga's president unexpectedly resigns http://slashdot.org/articles/99/09/01/1856251.shtml XFree86 3.3.5 released http://slashdot.org/articles/99/09/01/0716233.shtml GT Interactive Sued for piracy http://slashdot.org/articles/99/09/01/1347204.shtml ProjectUDI spec goes 1.0 http://slashdot.org/articles/99/09/01/1430242.shtml Chad Davis May Be the Next Kevin Mitnick http://slashdot.org/articles/99/09/01/1547226.shtml Clearing up FreeBSD confusion http://slashdot.org/articles/99/09/01/141247.shtml Linuxcare and Sun partner on StarOffice for Linux http://slashdot.org/articles/99/09/01/1333220.shtml xmlnews.rdf100644001750001750 2071214756547744 17570 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examples/0.91 XML News and Features from XML.com XML.com features a rich mix of information and services for the XML community. en-us http://xml.com/pub Copyright 1999, O'Reilly and Associates and Seybold Publications dale@xml.com (Dale Dougherty) peter@xml.com (Peter Wiggin) XML News and Features from XML.com http://xml.com/universal/images/xml_tiny.gif http://xml.com/pub 88 31 Issue: XML Data Servers http://xml.com/pub?wwwrrr_rss Although not everyone agrees that XML should become a full-fledged data-management discipline, object-database vendors are busy repositioning their object-database products as XML data servers. Jon Udell looks at one of these, Object Design's eXcelon and finds it a solid product. O'Reilly Labs Review: Object Design's eXcelon 1.1 http://xml.com/pub/1999/08/excelon/index.html?wwwrrr_rss Jon Udell takes a look at eXcelon, Object Design's XML data servers, and explains its user interface and general approach to XML. Report from Montreal http://xml.com/pub/1999/08/excelon/montreal.html?wwwrrr_rss Lisa Rein reports from MetaStructures 99 and XML Developers' Day. Reviews: Bluestone Software's XML Suite: Promising App, Rough Around the Edges http://xml.com/pub/1999/08/bluestone/index.html?wwwrrr_rss Our reviewer tested Bluestone's XML Suite (XML Server and Visual XML) on the Windows NT platform, simulating a two-way exchange of business information between a book publisher and book stores. The results were encouraging (with a few caveats). Interviews: CBL: Ecommerce Componentry http://xml.com/pub/1999/08/glushko/glushko.html?wwwrrr_rss In this audio interview, Bob Glushko of Commerce One talks about the Common Business Library (CBL) as a set of building blocks for XML document types and schemas used in ecommerce. Backends Sharing Data http://xml.com/pub/1999/08/rpc/index.html?wwwrrr_rss What if you could script remote procedure calls between web sites as easily as you can between programs? Edd Dumbill shows how it can be done in PHP. Back Issue: XML Suite http://xml.com/pub/1999/08/18/index.html?wwwrrr_rss Barry Nance runs Bluestone's XML Suite through the paces. The tools show promise for passing data between databases and XML. But there are still a few kinks to be worked out. Back Issue: XML-RPC http://xml.com/pub/1999/08/11/index.html?wwwrrr_rss A major promise of XML is its ability to pass data simply from one place to another, regardless of platform. In this issue, Edd Dumbill shows how to use XML-RPC in PHP to pass data from a web site to a PDA. News: InDelv XML/XSL Client Version 0.4. http://xml.com/pub/coverpage/newspage.html#ni1999-08-27-a?wwwrrr_rss A posting from Rob Brown reports on the public availability of the new InDelv XML Client version 0.4. This version represent an upgrade to InDelv's previously released XML Browser, but "it has been renamed as a 'Client' to reflect the fact that it now contains both an XML/XSL browser and an XML/XSL editor. The browser is available free for all uses. The editor comes packaged with the browser as a demo, which can later be upgraded to a full commercial version. This is a 100% Java appl... News: OpenJade Development Team Releases OpenJade 1.3pre1 (Beta). http://xml.com/pub/coverpage/newspage.html#ni1999-08-27-g?wwwrrr_rss A recent posting from Avi Kivity and the OpenJade Development Team announced the release of OpenJade 1.3pre1 (Beta). "OpenJade is the DSSSL user community's open source implementation of DSSSL, Document Style Semantics and Specification Language, an ISO standard for rendering SGML and XML documents. OpenJade is based on James Clark's widely used Jade. OpenJade 1.3pre1 is a more complete implementation of the DSSSL standard, and introduces many new features, including (1) Implementat... News: IBM XML Parser Update: XML4C2 Version 2.3.1 Released. http://xml.com/pub/coverpage/newspage.html#ni1999-08-27-b?wwwrrr_rss Dean Roddey posted an announcement for the update of XML4C. IBM's XML for C++ parser (XML4C) "is a validating XML parser written in a portable subset of C++. XML4C makes it easy to give an application the ability to read and write XML data. Its two shared libraries provide classes for parsing, generating, manipulating, and validating XML documents. XML4C is faithful to the XML 1.0 Recommendation and associated standards (DOM 1.0, SAX 1.0). Source code, samples and API documentation ... News: Platform for Privacy Preferences (P3P) Specification Working Draft. http://xml.com/pub/coverpage/newspage.html#ni1999-08-27-h?wwwrrr_rss As part of the W3C P3P Activity, a fifth public working draft of the Platform for Privacy Preferences (P3P) Specification has been published for review by W3C members. The working draft "describes the Platform for Privacy Preferences (P3P). P3P enables Web sites to express their privacy practices and enables users to exercise preferences over those practices. P3P compliant products will allow users to be informed of site practices (in both machine and human readable formats), to deleg... News: Extended XLink with XSLT. http://xml.com/pub/coverpage/newspage.html#ni1999-08-27-c?wwwrrr_rss Nikita Ogievetsky (President, Cogitech, Inc.) posted an announcement for the availability of slides from the Metastructures '99 presentation "HTML Form Templates with XML. All in One and One for All. XSLT template library for WEB applications." The paper describes building XSLT template library for web applications. The goal was to "demonstrate data processing on the web made easy with XSL transformations: Generate a data maintenance web with data-structure controlled by XML, scree... News: HyBrick Web Site Reopens. http://xml.com/pub/coverpage/newspage.html#ni1999-08-27-d?wwwrrr_rss A posting from Toshimitsu Suzuki (Fujitsu Laboratories Ltd.) to the XLXP-DEV mailing list recently announced the reopening of the HyBrick Web site. 'HyBrick' is "an advanced SGML/XML browser developed by Fujitsu Laboratories, the research arm of Fujitsu. HyBrick is based on an architecture that supports advanced linking and formatting capabilities. HyBrick includes a DSSSL renderer and XLink/XPointer engine running on top of James Clark's SP and Jade. HyBrick supports: (1) Both v... News: Extended DocBook Synopses Version 1.0. http://xml.com/pub/coverpage/newspage.html#ni1999-08-27-e?wwwrrr_rss Norman Walsh has posted an announcement for a preliminary release of 'Extended DocBook Synopses'. Extended DocBook Synopses is a customization layer that extends DocBook, "adding a function synopsis element, ClassSynopsis for modern, mostly object-oriented, programming languages such as Java, C++, Perl, and IDL." DocBook is an SGML [and XML] DTD maintained by the DocBook Technical Committee of OASIS that particularly well suited to books and papers about computer hardware and softwar... release000755001750001750 014756547744 15062 5ustar00shlomifshlomif000000000000XML-RSS-1.65/xtcpan-changes.t100644001750001750 34414756547744 17717 0ustar00shlomifshlomif000000000000XML-RSS-1.65/xt/releaseuse strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::CPAN::Changes 0.013 use Test::More 0.96 tests => 1; use Test::CPAN::Changes; subtest 'changes_ok' => sub { changes_file_ok('Changes'); }; rss2-nested-custom-tag.t100644001750001750 130714756547744 20032 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t#!/usr/bin/env perl use strict; use warnings; use Test::More tests => 1; use XML::RSS (); { my $rss = XML::RSS->new(); $rss->parse(<<'EOT'); random title http://correct.url/ some text random text that's in a tag named link for whatever reason EOT # TEST is($rss->{items}->[0]->{link}, 'http://correct.url/', 'item link parsed correctly'); } __END__ =head1 ABOUT See L. Thanks to L . rejects000755001750001750 014756547744 16177 5ustar00shlomifshlomif000000000000XML-RSS-1.65/keep-outappend.pl100644001750001750 170514756547744 20146 0ustar00shlomifshlomif000000000000XML-RSS-1.65/keep-out/rejects# This function was present in the lib/XML/RSS.pm sources for a long time # and has been completely unused. Our guess was that it introduced to later # serve in refactoring the module and was never used. It was not moved to # this file, to possibly be used for future reference. 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 $self->{modules}->{$ns} and $inside->{$self->{modules}->{$ns}}->{$self->current_element} .= $cdata; return $inside; } create_rss.pl100644001750001750 155214756547744 17765 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examples/0.9#!/usr/bin/perl # create_rss.pl # creates and prints RSS 0.9 file use strict; use warnings; use XML::RSS (); my $rss = XML::RSS->new(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->add_item(title => "Spruce 0.4.7b", link => "http://freshmeat.net/news/1999/06/21/930003816.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 $rss->as_string; rss-0.91.dtd100644001750001750 2023314756547744 17265 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examples/0.91 1.0000755001750001750 014756547744 14461 5ustar00shlomifshlomif000000000000XML-RSS-1.65/t/datawith_content.rdf100644001750001750 343014756547744 20023 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t/data/1.0 First Weblog http://localhost/weblog/ This is a test weblog. en-us Melody 2004-05-29T23:39:57-08:00 Entry Two http://localhost/weblog/2004/05/entry_two.html Hello!... Hello!

    ]]> Travel Melody 2004-05-29T23:39:25-08:00
    Test http://localhost/weblog/2004/05/test.html This is a test. Why don't you come down to our place for a coffee and a chat?... This is a test.

    Why don't you come down to our place for a coffee and a chat?

    ]]>
    Sports Melody 2004-05-08T23:03:28-08:00
    generated000755001750001750 014756547744 15210 5ustar00shlomifshlomif000000000000XML-RSS-1.65/tplaceholder.txt100644001750001750 14014756547744 20346 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t/generatedThis file is a placeholder to make sure the distribution contains the ./t/generated/ directory. linuxtoday.rdf100644001750001750 307014756547744 20170 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examples/0.9 Linux Today http://linuxtoday.com Linux Today News Service Linux Today http://linuxtoday.com/pics/ltnet.gif http://linuxtoday.com PRNewswire: Texas Software Startup, Serenity Systems, Advises Business Users to Get Off Windows http://linuxtoday.com/story.php3?sn=9443 LinuxPR: MyDesktop Launches Linux Software Section http://linuxtoday.com/story.php3?sn=9442 LinuxPR: Franklin Institute Science Museum Chooses Linux http://linuxtoday.com/story.php3?sn=9441 Yellow Dog Linux releases updated am-utils http://linuxtoday.com/story.php3?sn=9440 LinuxPR: LinuxCare Adds Laser5 Linux To Roster of Supported Linux Distributions http://linuxtoday.com/story.php3?sn=9439 Search Search Linux Today: query http://linuxtoday.com/search/search-action.pl trailing-space.t100644001750001750 107714756547744 20316 0ustar00shlomifshlomif000000000000XML-RSS-1.65/xt/release#!perl use strict; use warnings; use Test::More; eval "use Test::TrailingSpace"; if ($@) { plan skip_all => "Test::TrailingSpace required for trailing space test."; } else { plan tests => 1; } # TODO: add .pod, .PL, the README/Changes/TODO/etc. documents and possibly # some other stuff. my $finder = Test::TrailingSpace->new( { root => '.', filename_regex => qr#(?:\.(?:t|pm|pl|xs|c|h|txt|pod|PL)|README|Changes|TODO|LICENSE)\z#, abs_path_prune_re => undef, }, ); # TEST $finder->no_trailing_space( "No trailing space was found." ); save-while-in-taint-mode.t100644001750001750 102514756547744 20304 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t#!perl -T use strict; use warnings; use Test::More tests => 1; use XML::RSS; { my $rss = XML::RSS->new(); $rss->parsefile( File::Spec->catfile( File::Spec->curdir(), "t", "data", "2.0", "sf-hs-with-pubDate.rss" ) ); my $target_fn = File::Spec->catfile( File::Spec->curdir(), "t", "data", "2.0", "sf-hs-temp.rss" ) ; $rss->save($target_fn); # TEST ok(scalar(-e $target_fn), "Test that save was successful"); unlink($target_fn); } rss1.0.exotic.rdf100644001750001750 345214756547744 17642 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t/data/1.0 Example Site http://example.org/ An example site admin@example.org en-us 2002-11-01T07:16:51-08:00 A Title & An Ampersand A silly description http://example/archives/000001.html Personal kellan 2002-11-01T07:16:51-08:00 add-item-insert-vs-append.t100644001750001750 503514756547744 20463 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t#!/usr/bin/perl # Test the add_item(mode => "insert") use strict; use warnings; use Test::More tests => 3; use XML::RSS; sub contains { local $Test::Builder::Level = $Test::Builder::Level + 1; my ($rss, $sub_string, $msg) = @_; my $rss_output = $rss->as_string(); my $ok = ok (index ($rss_output, $sub_string) >= 0, $msg ); if (! $ok) { diag("Could not find the substring [$sub_string] in:{{{{\n$rss_output\n}}}}\n"); } } sub create_rss { my $rss = XML::RSS->new(version => "2.0"); $rss->channel( title => "freshmeat.net", link => "http://freshmeat.net", description => "the one-stop-shop for all your Linux software needs", ); $rss->add_item( title => "GTKeyboard 0.85", link => "http://freshmeat.net/news/1999/06/21/930003829.html" ); return $rss; } { my $rss = create_rss(); $rss->add_item( title => "gcc 10.0.10", link => "http://gcc-compiler.tld/", ); # TEST contains($rss, qq{\nGTKeyboard 0.85\n} . qq{http://freshmeat.net/news/1999/06/21/930003829.html\n} . qq{\n} . qq{\ngcc 10.0.10\n} . qq{http://gcc-compiler.tld/\n} . qq{\n}, "Checking for second item after first item when add_item without mode." ); } { my $rss = create_rss(); $rss->add_item( mode => "append", title => "gcc 10.0.10", link => "http://gcc-compiler.tld/", ); # TEST contains($rss, qq{\nGTKeyboard 0.85\n} . qq{http://freshmeat.net/news/1999/06/21/930003829.html\n} . qq{\n} . qq{\ngcc 10.0.10\n} . qq{http://gcc-compiler.tld/\n} . qq{\n}, "Checking for second item after first item when add_item with mode == append." ); } { my $rss = create_rss(); $rss->add_item( mode => "insert", title => "gcc 10.0.10", link => "http://gcc-compiler.tld/", ); # TEST contains($rss, qq{\ngcc 10.0.10\n} . qq{http://gcc-compiler.tld/\n} . qq{\n} . qq{\nGTKeyboard 0.85\n} . qq{http://freshmeat.net/news/1999/06/21/930003829.html\n} . qq{\n}, "Checking for second item before first item when add_item with mode == insert." ); } languages.pm100644001750001750 620714756547744 20650 0ustar00shlomifshlomif000000000000XML-RSS-1.65/keep-out/rejects# Note: # This hash of languages was present in lib/XML/RSS.pm but was completely # unused. It was moved here as an eliminated code. 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' ); fm0.91_full.rdf100644001750001750 277014756547744 20013 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examples/0.91 freshmeat.net http://freshmeat.net the one-stop-shop for all your Linux software needs en (PICS-1.1 "http://www.classify.org/safesurf/" 1 r (SS~~000 1)) Copyright 1999, Freshmeat.net Thu, 23 Aug 1999 07:00:00 GMT Thu, 23 Aug 1999 16:20:26 GMT http://www.blahblah.org/fm.cdf freshmeat.net http://freshmeat.net/images/fm.mini.jpg http://freshmeat.net 88 31 This is the Freshmeat image stupid kdbg 1.0beta2 http://www.freshmeat.net/news/1999/08/23/935449823.html This is the Freshmeat image stupid HTML-Tree 1.7 http://www.freshmeat.net/news/1999/08/23/935449856.html This is the Freshmeat image stupid quick finder Use the text input below to search freshmeat query http://core.freshmeat.net/search.php3 2 1 update_rss_1.0.pl100644001750001750 162214756547744 20350 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examples/1.0#!/usr/bin/perl -w # this script adds a new item to an existing rss file and # updates the channel date and publisher use XML::RSS; # create a new instance of the XML::RSS my $rss = XML::RSS->new; # parse the local file $rss->parsefile("rss1.0.rdf"); # add a new item to the file $rss->add_item( title => "QScheme 0.2.2", link => "http://freshmeat.net/news/1999/06/21/930003829.html", description => "Really fast, small and easy to interface Scheme interpreter", dc => { subject => "X11/Utilities", creator => "David Allen (s2mdalle at titan.vcu.edu)", }, ); # update the dublin core information for the channel $rss->channel(dc => { date => "2000-01-01T12:00+00:00", publisher => "Jonathan Eisenzopf (eisen\@xif.com)" } ); # print the new rss file as a string. We could also save it to a file with the save() routine. print $rss->as_string; create_rss_1.0.pl100644001750001750 312014756547744 20324 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examples/1.0#!/usr/bin/perl -w # creates and prints RSS 1.0 file # This is an example of using the XML::RSS # module to create an RSS file with all # the trimmings so you can see what elements # are available. use strict; use warnings; use XML::RSS; my $rss = XML::RSS->new (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@freshmeat.net', publisher => 'scoop@freshmeat.net', rights => 'Copyright 1999, Freshmeat.net', language => 'en-us', }, syn => { updatePeriod => "hourly", updateFrequency => "1", updateBase => "1901-01-01T00:00+00:00", }, ); $rss->image( title => "freshmeat.net", url => "http://freshmeat.net/images/fm.mini.jpg", link => "http://freshmeat.net", dc => { creator => "G. Raphics (graphics at freshmeat.net)", }, ); $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 (s2mdalle at titan.vcu.edu)", }, ); $rss->textinput( title => "quick finder", description => "Use the text input below to search freshmeat", name => "query", link => "http://core.freshmeat.net/search.php3", ); print $rss->as_string; create_rss_multiple.pl100644001750001750 356714756547744 21402 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examples#!/usr/bin/perl # create_rss.pl # creates multiple instances of XML::RSS use strict; use warnings; use XML::RSS; my $rss = XML::RSS->new(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->add_item(title => "Spruce 0.4.7b", link => "http://freshmeat.net/news/1999/06/21/930003816.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 $rss->as_string; my $rss = XML::RSS->new(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->add_item(title => "Spruce 0.4.7b", link => "http://freshmeat.net/news/1999/06/21/930003816.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 $rss->as_string; my $rss2 = XML::RSS->new(version => '0.9'); $rss2->channel(title => "perlxml.com", link => "http://perlxml.com" ); $rss2->add_item(title => "dada", link => "foo" ); print "\n\nTitle2: ",$rss2->channel('title'),"\n"; print $rss2->items->[0]->{'title'},"\n"; create_rss_0.91.pl100644001750001750 173514756547744 20520 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examples/0.91#!/usr/bin/perl -w # creates and prints RSS 0.91 file use strict; use warnings; use XML::RSS; my $rss = XML::RSS->new (version => "0.91") ; $rss->channel(title => "freshmeat.net", link => "http://freshmeat.net", language => "en", 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->add_item(title => "Spruce 0.4.7b", link => "http://freshmeat.net/news/1999/06/21/930003816.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 $rss->as_string; #$rss->save("fm.rdf"); sf-hs-with-pubDate.rss100644001750001750 1331214756547744 20746 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t/data/2.0 Shlomi Fish' Home Site http://community.livejournal.com/shlomif_hsite/ Shlomi Fish' Home Site - LiveJournal.com shlomif@iglu.org.il LiveJournal / LiveJournal.com Sun, 24 Sep 2006 10:12:49 GMT http://community.livejournal.com/shlomif_hsite/3573.html Sun, 24 Sep 2006 10:12:49 GMT New Additions to the Site shlomif@iglu.org.il http://community.livejournal.com/shlomif_hsite/3573.html <p> Exactly two weeks passed since the last update and many things have been added or improved. Read below for what's new. </p> <p> Two of the pages in <a href="http://www.shlomifish.org/MathVentures/">the MathVentures section</a> were converted to use embedded <a href="http://www.w3.org/Math/">MathML</a>. This should make viewing them with MathML-compliant browsers easier. The old ASCII-art based pages are still available. </p> <p> The ideas <a href="http://www.shlomifish.org/philosophy/ideas/#tucan">Tucan</a> and <a href="http://www.shlomifish.org/philosophy/ideas/#unixdoc">Unixdoc</a> were added to the Random Ideas page. </p> <p> I've placed <a href="http://www.shlomifish.org/open-source/nostalgia/">some of my old DOS-era programs online</a> for your amusement. </p> <p> I added a <a href="http://www.shlomifish.org/meta/FAQ/#site_history">question about the site history</a> to the <a href="http://www.shlomifish.org/meta/FAQ/">FAQ</a>. </p> <p> More CDs were added to the <a href="http://www.shlomifish.org/art/recommendations/music/">Music Recommendations</a>. </p> <p> There's <a href="http://www.shlomifish.org/humour.html#if_god_exists">a new Joke</a> in the Humour archive. </p> http://community.livejournal.com/shlomif_hsite/3573.html mathml mathematics math dos jokes tucan ideas mathventures unixdoc Metallica - Nothing Else Matters full public http://community.livejournal.com/shlomif_hsite/3165.html Sun, 10 Sep 2006 13:41:17 GMT Changes at Shlomi Fish Homesite shlomif@iglu.org.il http://community.livejournal.com/shlomif_hsite/3165.html <p> It's been about two weeks since my last update, and here's what's new: </p> <ol> <li> <p> <a href="http://www.shlomifish.org/art/recommendations/music/">A currently partial list</a> of my favourite compact discs is now live. Creating this list involved a large amount of <a href="http://en.wikipedia.org/wiki/Document_Type_Definition">DTD</a>, <a href="http://www.w3.org/TR/xslt">XSLT</a>, <a href="http://perl-begin.berlios.de/">Perl</a>, and CSS hacking on the <a href="http://search.cpan.org/dist/XML-Grammar-ProductsSyndication/">XML-Grammar-ProductsSyndication</a> framework, that was written from scratch to facilitate making construction of such lists possible by and others. </p> <p> I will add the missing CDs as time goes by, and will also later on add lists for fiction books and for movies, as well as convert the existing <a href="http://www.shlomifish.org/philosophy/books-recommends/">non-fiction books recommendations</a> into the new framework. </p> </li> <li> <p> More pages on the site were made to validate according to the <a href="http://www.w3.org/">World-wide-web consortium</a> standards, and some ancient leftovers that were no longer important were removed. </p> </li> <li> <p> <a href="http://www.shlomifish.org/open-source/favourite/">My list of favourite open source software</a> was updated, with many corrections, added programs and a new navigation menu. </p> </li> <li> <p> <a href="http://www.shlomifish.org/prog-evolution/pre-elpas.html">My memoirs as a programmer from High School</a> were heavily fixed and updated. </p> </li> </ol> http://community.livejournal.com/shlomif_hsite/3165.html xml grammar homesite shlomi fish syndication memoirs products valid html Monkey Island Am I Evil OC Remix annoyed public Output000755001750001750 014756547744 17576 5ustar00shlomifshlomif000000000000XML-RSS-1.65/lib/XML/RSS/PrivateV2_0.pm100644001750001750 1051514756547744 21024 0ustar00shlomifshlomif000000000000XML-RSS-1.65/lib/XML/RSS/Private/Outputpackage XML::RSS::Private::Output::V2_0; $XML::RSS::Private::Output::V2_0::VERSION = '1.65'; use strict; use warnings; use vars (qw(@ISA)); use XML::RSS::Private::Output::Base (); use XML::RSS::Private::Output::Roles::ModulesElems (); use XML::RSS::Private::Output::Roles::ImageDims (); @ISA = ( qw( XML::RSS::Private::Output::Roles::ImageDims XML::RSS::Private::Output::Roles::ModulesElems XML::RSS::Private::Output::Base ) ); sub _get_filtered_items { my $self = shift; return [grep { exists($_->{title}) || exists($_->{description}) } @{$self->_get_items()},]; } sub _out_item_2_0_tags { my ($self, $item) = @_; $self->_output_def_item_tag($item, "author"); $self->_output_array_item_tag($item, "category"); $self->_output_def_item_tag($item, "comments"); $self->_out_guid($item); $self->_output_def_item_tag($item, "pubDate"); $self->_out_item_source($item); $self->_out_item_enclosure($item); } sub _get_textinput_tag { return "textInput"; } sub _get_item_defined { return 1; } sub _output_rss_middle { my $self = shift; # PICS rating # Not supported by RSS 2.0 # $output .= ''.$self->{channel}->{rating}.''."\n" # if $self->{channel}->{rating}; # copyright $self->_out_copyright(); $self->_out_dates(); # external CDF URL $self->_out_def_chan_tag("docs"); $self->_out_editors; $self->_out_channel_array_self_dc_field("category"); $self->_out_channel_self_dc_field("generator"); # Insert cloud support here # ttl $self->_out_channel_self_dc_field("ttl"); $self->_out_modules_elements($self->channel()); $self->_out_last_elements; } 1; __END__ =pod =encoding UTF-8 =head1 VERSION version 1.65 =for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan =head1 SUPPORT =head2 Websites The following websites have more information about this module, and may be of help to you. As always, in addition to those websites please use your favorite search engine to discover more resources. =over 4 =item * MetaCPAN A modern, open-source CPAN search engine, useful to view POD in HTML format. L =item * RT: CPAN's Bug Tracker The RT ( Request Tracker ) website is the default bug/issue tracking system for CPAN. L =item * CPANTS The CPANTS is a website that analyzes the Kwalitee ( code metrics ) of a distribution. L =item * CPAN Testers The CPAN Testers is a network of smoke testers who run automated tests on uploaded CPAN distributions. L =item * CPAN Testers Matrix The CPAN Testers Matrix is a website that provides a visual overview of the test results for a distribution on various Perls/platforms. L =item * CPAN Testers Dependencies The CPAN Testers Dependencies is a website that shows a chart of the test results of all dependencies for a distribution. L =back =head2 Bugs / Feature Requests Please report any bugs or feature requests by email to C, or through the web interface at L. You will be automatically notified of any progress on the request by the system. =head2 Source Code The code is open to the world, and available for you to hack on. Please feel free to browse it and play with it, or whatever. If you want to contribute patches, please send me a diff or prod me to pull from your repository :) L git clone git://github.com/shlomif/perl-XML-RSS.git =head1 AUTHOR Shlomi Fish =head1 BUGS Please report any bugs or feature requests on the bugtracker website L When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature. =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2001 by Various. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut V1_0.pm100644001750001750 1211114756547744 21015 0ustar00shlomifshlomif000000000000XML-RSS-1.65/lib/XML/RSS/Private/Outputpackage XML::RSS::Private::Output::V1_0; $XML::RSS::Private::Output::V1_0::VERSION = '1.65'; use strict; use warnings; use vars (qw(@ISA)); use XML::RSS::Private::Output::Base (); use XML::RSS::Private::Output::Roles::ModulesElems (); @ISA = (qw(XML::RSS::Private::Output::Roles::ModulesElems XML::RSS::Private::Output::Base)); sub _get_top_elem_about { my ($self, $tag, $about_sub) = @_; return ' rdf:about="' . $self->_encode($about_sub->()) . '"'; } sub _out_textinput_rss_1_0_elems { my $self = shift; $self->_out_dc_elements($self->textinput()); # Ad-hoc modules # TODO : Should this follow the %rdf_resources conventions of the items' # and channel's modules' support ? while (my ($url, $prefix) = each %{$self->_modules()}) { next if $prefix =~ /^(dc|syn|taxo)$/; while (my ($el, $value) = each %{$self->textinput($prefix) || {}}) { $self->_out_ns_tag($prefix, $el, $value); } } } sub _get_rdf_decl_open_tag { return "_out_dc_elements($self->image()); } sub _out_item_1_0_tags { my ($self, $item) = @_; $self->_out_dc_elements($item); # Taxonomy module $self->_output_taxo_topics($item); } sub _output_rss_middle { my $self = shift; # PICS rating - Dublin Core has not decided how to incorporate PICS ratings yet #$$output .= ''.$self->{channel}->{rating}.''."\n" #$if $self->{channel}->{rating}; $self->_out_copyright(); # publication date $self->_out_defined_tag("dc:date", $self->_calc_dc_date()); # external CDF URL #$output .= ''.$self->{channel}->{docs}.''."\n" #if $self->{channel}->{docs}; $self->_out_editors; $self->_out_all_modules_elems; $self->_out_seq_items(); if ($self->_is_image_defined()) { $self->_out('\n"); } if (defined(my $textinput_link = $self->textinput('link'))) { $self->_out('\n"); } $self->_end_channel; $self->_output_main_elements; } sub _get_end_tag { return "rdf:RDF"; } 1; __END__ =pod =encoding UTF-8 =head1 VERSION version 1.65 =for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan =head1 SUPPORT =head2 Websites The following websites have more information about this module, and may be of help to you. As always, in addition to those websites please use your favorite search engine to discover more resources. =over 4 =item * MetaCPAN A modern, open-source CPAN search engine, useful to view POD in HTML format. L =item * RT: CPAN's Bug Tracker The RT ( Request Tracker ) website is the default bug/issue tracking system for CPAN. L =item * CPANTS The CPANTS is a website that analyzes the Kwalitee ( code metrics ) of a distribution. L =item * CPAN Testers The CPAN Testers is a network of smoke testers who run automated tests on uploaded CPAN distributions. L =item * CPAN Testers Matrix The CPAN Testers Matrix is a website that provides a visual overview of the test results for a distribution on various Perls/platforms. L =item * CPAN Testers Dependencies The CPAN Testers Dependencies is a website that shows a chart of the test results of all dependencies for a distribution. L =back =head2 Bugs / Feature Requests Please report any bugs or feature requests by email to C, or through the web interface at L. You will be automatically notified of any progress on the request by the system. =head2 Source Code The code is open to the world, and available for you to hack on. Please feel free to browse it and play with it, or whatever. If you want to contribute patches, please send me a diff or prod me to pull from your repository :) L git clone git://github.com/shlomif/perl-XML-RSS.git =head1 AUTHOR Shlomi Fish =head1 BUGS Please report any bugs or feature requests on the bugtracker website L When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature. =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2001 by Various. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut V0_9.pm100644001750001750 654414756547744 21022 0ustar00shlomifshlomif000000000000XML-RSS-1.65/lib/XML/RSS/Private/Outputpackage XML::RSS::Private::Output::V0_9; $XML::RSS::Private::Output::V0_9::VERSION = '1.65'; use strict; use warnings; use vars (qw(@ISA)); use XML::RSS::Private::Output::Base (); @ISA = (qw(XML::RSS::Private::Output::Base)); sub _get_rdf_decl { return qq{\n\n}; } # 'description' for item does not exist in RSS 0.9 sub _out_item_desc { return; } # RSS 0.9 does not support the language tag so we nullify this tag. sub _out_language { return; } sub _output_rss_middle { my $self = shift; $self->_end_channel(); $self->_output_main_elements; } sub _get_end_tag { return "rdf:RDF"; } 1; __END__ =pod =encoding UTF-8 =head1 VERSION version 1.65 =for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan =head1 SUPPORT =head2 Websites The following websites have more information about this module, and may be of help to you. As always, in addition to those websites please use your favorite search engine to discover more resources. =over 4 =item * MetaCPAN A modern, open-source CPAN search engine, useful to view POD in HTML format. L =item * RT: CPAN's Bug Tracker The RT ( Request Tracker ) website is the default bug/issue tracking system for CPAN. L =item * CPANTS The CPANTS is a website that analyzes the Kwalitee ( code metrics ) of a distribution. L =item * CPAN Testers The CPAN Testers is a network of smoke testers who run automated tests on uploaded CPAN distributions. L =item * CPAN Testers Matrix The CPAN Testers Matrix is a website that provides a visual overview of the test results for a distribution on various Perls/platforms. L =item * CPAN Testers Dependencies The CPAN Testers Dependencies is a website that shows a chart of the test results of all dependencies for a distribution. L =back =head2 Bugs / Feature Requests Please report any bugs or feature requests by email to C, or through the web interface at L. You will be automatically notified of any progress on the request by the system. =head2 Source Code The code is open to the world, and available for you to hack on. Please feel free to browse it and play with it, or whatever. If you want to contribute patches, please send me a diff or prod me to pull from your repository :) L git clone git://github.com/shlomif/perl-XML-RSS.git =head1 AUTHOR Shlomi Fish =head1 BUGS Please report any bugs or feature requests on the bugtracker website L When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature. =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2001 by Various. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Base.pm100644001750001750 6375214756547744 21203 0ustar00shlomifshlomif000000000000XML-RSS-1.65/lib/XML/RSS/Private/Outputpackage XML::RSS::Private::Output::Base; $XML::RSS::Private::Output::Base::VERSION = '1.65'; use strict; use warnings; use Carp qw/ confess /; use HTML::Entities qw(encode_entities_numeric encode_entities); use DateTime::Format::Mail (); use DateTime::Format::W3CDTF (); use XML::RSS (); sub new { my $class = shift; my $self = {}; bless $self, $class; $self->_initialize(@_); return $self; } # _main() is a reference to the main XML::RSS module sub _main { my $self = shift; if (@_) { $self->{_main} = shift; } return $self->{_main}; } sub _encode_cb { my $self = shift; if (@_) { $self->{_encode_cb} = shift; } return $self->{_encode_cb}; } sub _item_idx { my $self = shift; if (@_) { $self->{_item_idx} = shift; } return $self->{_item_idx}; } sub _initialize { my $self = shift; my $args = shift; $self->{_output} = ""; $self->_main($args->{main}); # TODO : Remove once we have inheritance proper. $self->_rss_out_version($args->{version}); if (defined($args->{encode_cb})) { $self->_encode_cb($args->{encode_cb}); } else { $self->_encode_cb(\&_default_encode); } $self->_item_idx(-1); return 0; } sub _rss_out_version { my $self = shift; if (@_) { $self->{_rss_out_version} = shift; } return $self->{_rss_out_version}; } sub _encode { my ($self, $text) = @_; return $self->_encode_cb()->($self, $text); } sub _default_encode { my ($self, $text) = @_; #return "" unless defined $text; if (!defined($text)) { confess "\$text is undefined in XML::RSS::_encode(). We don't know how " . "to handle it!"; } return $text if (!$self->_main->_encode_output); my $encoded_text = ''; while ($text =~ s/(.*?)(\<\!\[CDATA\[.*?\]\]\>)//s) { # we use &named; entities here because it's HTML $encoded_text .= encode_entities($1) . $2; } # we use numeric entities here because it's XML $encoded_text .= encode_entities_numeric($text); return $encoded_text; } sub _out { my ($self, $string) = @_; $self->{_output} .= $string; return; } sub _out_tag { my ($self, $tag, $inner) = @_; my $content = $inner; my $attr = ""; if (ref($inner) eq 'HASH') { my %inner_copy = %$inner; $content = delete $inner_copy{content}; foreach my $key (keys %inner_copy) { my $value = $inner->{$key}; if (defined($value)) { $attr .= " " . $self->_encode($key) . qq{="} . $self->_encode($value) . '"'; } } } return $self->_out("<$tag$attr>" . $self->_encode($content) . "\n"); } # Remove non-alphanumeric elements and return the modified string. # Useful for user-specified tags' attributes. sub _sanitize { my ($self, $string) = @_; $string =~ s{[^a-zA-Z_\-0-9]}{}g; return $string; } sub _out_ns_tag { my ($self, $prefix, $tag, $inner) = @_; my @subtags; if (ref($inner) eq "HASH") { $self->_out("<${prefix}:${tag}"); foreach my $attr (sort { $a cmp $b } keys(%{$inner})) { if (ref($inner->{$attr}) eq '') { $self->_out(q{ } . $self->_sanitize($attr) . q{="} . $self->_encode($inner->{$attr}) . q{"}); } else { push(@subtags, $attr); } } if (!@subtags) { $self->_out("/>\n"); } else { $self->_out(">\n"); foreach my $attr (sort { $a cmp $b } @subtags) { if (ref($inner->{$attr})) { _out_ns_tag($self, $prefix, $tag, $inner->{$attr}); } } $self->_out("\n"); } } elsif (ref($inner) eq 'ARRAY') { map { $self->_out_ns_tag($prefix, $tag, $_) } @{$inner}; } else { return $self->_out_tag("${prefix}:${tag}", $inner); } } sub _out_defined_tag { my ($self, $tag, $inner) = @_; if (defined($inner)) { $self->_out_tag($tag, $inner); } return; } sub _out_array_tag { my ($self, $tag, $inner) = @_; if (ref($inner) eq "ARRAY") { foreach my $elem (@$inner) { $self->_out_defined_tag($tag, $elem); } } else { $self->_out_defined_tag($tag, $inner); } return; } sub _out_inner_tag { my ($self, $params, $tag) = @_; if (ref($params) eq "") { $params = {'ext' => $params, 'defined' => 0,}; } my $ext_tag = $params->{ext}; if (ref($ext_tag) eq "") { $ext_tag = $self->$ext_tag(); } my $value = $ext_tag->{$tag}; if ($params->{defined} ? defined($value) : 1) { $self->_out_tag($tag, $value); } return; } sub _output_item_tag { my ($self, $item, $tag) = @_; return $self->_out_tag($tag, $item->{$tag}); } sub _output_def_image_tag { my ($self, $tag) = @_; return $self->_out_inner_tag({ext => "image", 'defined' => 1}, $tag); } sub _output_multiple_tags { my ($self, $ext_tag, $tags_ref) = @_; foreach my $tag (@$tags_ref) { $self->_out_inner_tag($ext_tag, $tag); } return; } sub _output_common_textinput_sub_elements { my $self = shift; $self->_output_multiple_tags("textinput", [qw(title description name link)],); } sub _get_top_elem_about { return ""; } sub _start_top_elem { my ($self, $tag, $about_sub) = @_; my $about = $self->_get_top_elem_about($tag, $about_sub); return $self->_out("<$tag$about>\n"); } sub _out_textinput_rss_1_0_elems { } sub _get_textinput_tag { return "textinput"; } sub _output_complete_textinput { my $self = shift; my $master_tag = $self->_get_textinput_tag(); if (defined(my $link = $self->textinput('link'))) { $self->_start_top_elem($master_tag, sub {$link}); $self->_output_common_textinput_sub_elements(); $self->_out_textinput_rss_1_0_elems(); $self->_end_top_level_elem($master_tag); } return; } sub _flush_output { my $self = shift; my $ret = $self->{_output}; $self->{_output} = ""; # Detach _main to avoid referencing loops. $self->_main(undef); return $ret; } sub _date_from_dc_date { my ($self, $string) = @_; my $f = DateTime::Format::W3CDTF->new(); return $f->parse_datetime($string); } sub _date_from_rss2 { my ($self, $string) = @_; my $f = DateTime::Format::Mail->new(); return $f->parse_datetime($string); } sub _date_to_rss2 { my ($self, $date) = @_; my $pf = DateTime::Format::Mail->new(); return $pf->format_datetime($date); } sub _date_to_dc_date { my ($self, $date) = @_; my $pf = DateTime::Format::W3CDTF->new(); return $pf->format_datetime($date); } sub _channel_dc { my ($self, $key) = @_; if ($self->channel('dc')) { return $self->channel('dc')->{$key}; } else { return undef; } } sub _channel_syn { my ($self, $key) = @_; if ($self->channel('syn')) { return $self->channel('syn')->{$key}; } else { return undef; } } sub _calc_lastBuildDate { my $self = shift; if (defined(my $d = $self->_channel_dc('date'))) { return $self->_date_to_rss2($self->_date_from_dc_date($d)); } else { # If lastBuildDate is undef we can still return it because we # need to return undef. return $self->channel("lastBuildDate"); } } sub _calc_pubDate { my $self = shift; if (defined(my $d = $self->channel('pubDate'))) { return $d; } elsif (defined(my $d2 = $self->_channel_dc('date'))) { return $self->_date_to_rss2($self->_date_from_dc_date($d2)); } else { return undef; } } sub _get_other_dc_date { my $self = shift; if (defined(my $d1 = $self->channel('pubDate'))) { return $d1; } elsif (defined(my $d2 = $self->channel('lastBuildDate'))) { return $d2; } else { return undef; } } sub _calc_dc_date { my $self = shift; if (defined(my $d1 = $self->_channel_dc('date'))) { return $d1; } else { my $date = $self->_get_other_dc_date(); if (!defined($date)) { return undef; } else { return $self->_date_to_dc_date($self->_date_from_rss2($date)); } } } sub _output_xml_declaration { my $self = shift; my $encoding = (defined $self->_main->_encoding()) ? ' encoding="' . $self->_main->_encoding() . '"' : ""; $self->_out('' . "\n"); if (defined(my $stylesheet = $self->_main->_stylesheet)) { my $style_url = $self->_encode($stylesheet); $self->_out(qq{\n}); } $self->_out("\n"); return undef; } sub _out_image_title_and_url { my $self = shift; return $self->_output_multiple_tags({ext => "image"}, [qw(title url)]); } sub _start_image { my $self = shift; $self->_start_top_elem("image", sub { $self->image('url') }); $self->_out_image_title_and_url(); $self->_output_def_image_tag("link"); return; } sub _start_item { my ($self, $item) = @_; my $tag = "item"; my $base = $item->{'xml:base'}; $tag .= qq{ xml:base="$base"} if defined $base; $self->_start_top_elem($tag, sub { $self->_get_item_about($item) }); $self->_output_common_item_tags($item); return; } sub _end_top_level_elem { my ($self, $elem) = @_; $self->_out("\n"); } sub _end_item { shift->_end_top_level_elem("item"); } sub _end_image { shift->_end_top_level_elem("image"); } sub _end_channel { shift->_end_top_level_elem("channel"); } sub _output_array_item_tag { my ($self, $item, $tag) = @_; if (defined($item->{$tag})) { $self->_out_array_tag($tag, $item->{$tag}); } return; } sub _output_def_item_tag { my ($self, $item, $tag) = @_; if (defined($item->{$tag})) { $self->_output_item_tag($item, $tag); } return; } sub _get_item_defined { return 0; } sub _out_item_desc { my ($self, $item) = @_; return $self->_output_def_item_tag($item, "description"); } # Outputs the common item tags for RSS 0.9.1 and above. sub _output_common_item_tags { my ($self, $item) = @_; my @fields = (qw( title link )); my $defined = $self->_get_item_defined; if (!$defined) { foreach my $f (@fields) { if (!defined($item->{$f})) { die qq/Item No. / . $self->_item_idx() . qq/ is missing the "$f" field./; } } } $self->_output_multiple_tags( {ext => $item, type => 'item', idx => $self->_item_idx(), 'defined' => $defined,}, [@fields],); $self->_out_item_desc($item); return; } sub _output_common_channel_elements { my $self = shift; $self->_output_multiple_tags("channel", [qw(title link description)],); } sub _out_language { my $self = shift; return $self->_out_channel_self_dc_field("language"); } sub _start_channel { my $self = shift; $self->_start_top_elem("channel", sub { $self->_get_channel_rdf_about }); $self->_output_common_channel_elements(); $self->_out_language(); return; } # Calculates a channel field that has a dc: and non-dc alternative, # prefering the dc: one. sub _calc_channel_dc_field { my ($self, $dc_key, $non_dc_key) = @_; my $dc_value = $self->_channel_dc($dc_key); return defined($dc_value) ? $dc_value : $self->channel($non_dc_key); } sub _prefer_dc { my $self = shift; if (@_) { $self->{_prefer_dc} = shift; } return $self->{_prefer_dc}; } sub _calc_channel_dc_field_params { my ($self, $dc_key, $non_dc_key) = @_; return ( $self->_prefer_dc() ? "dc:$dc_key" : $non_dc_key, $self->_calc_channel_dc_field($dc_key, $non_dc_key) ); } sub _out_channel_dc_field { my ($self, $dc_key, $non_dc_key) = @_; return $self->_out_defined_tag($self->_calc_channel_dc_field_params($dc_key, $non_dc_key),); } sub _out_channel_array_self_dc_field { my ($self, $key) = @_; $self->_out_array_tag($self->_calc_channel_dc_field_params($key, $key),); } sub _out_channel_self_dc_field { my ($self, $key) = @_; return $self->_out_channel_dc_field($key, $key); } sub _out_managing_editor { my $self = shift; return $self->_out_channel_dc_field("publisher", "managingEditor"); } sub _out_webmaster { my $self = shift; return $self->_out_channel_dc_field("creator", "webMaster"); } sub _out_copyright { my $self = shift; return $self->_out_channel_dc_field("rights", "copyright"); } sub _out_editors { my $self = shift; $self->_out_managing_editor; $self->_out_webmaster; } sub _get_channel_rdf_about { my $self = shift; if (defined(my $about = $self->channel('about'))) { return $about; } else { return $self->channel('link'); } } sub _output_taxo_topics { my ($self, $elem) = @_; if (my $list = $elem->{'taxo'}) { $self->_out("\n \n"); foreach my $taxo (@{$list}) { $self->_out(" _encode($taxo) . "\" />\n"); } $self->_out(" \n\n"); } return; } # Output the Dublin core properties of a certain elements (channel, image, # textinput, item). sub _get_dc_ok_fields { my $self = shift; return $self->_main->_get_dc_ok_fields(); } sub _out_dc_elements { my $self = shift; my $elem = shift; my $skip_hash = shift || {}; foreach my $dc (@{$self->_get_dc_ok_fields()}) { next if $skip_hash->{$dc}; $self->_out_array_tag("dc:$dc", $elem->{dc}->{$dc}); } return; } sub _out_module_prefix_elements_hash { my ($self, $args) = @_; my $prefix = $args->{prefix}; my $data = $args->{data}; my $url = $args->{url}; while (my ($el, $value) = each(%$data)) { $self->_out_module_prefix_pair( { %$args, el => $el, val => $value, } ); } return; } sub _out_module_prefix_pair { my ($self, $args) = @_; my $prefix = $args->{prefix}; my $url = $args->{url}; my $el = $args->{el}; my $value = $args->{val}; if ($self->_main->_is_rdf_resource($el, $url)) { $self->_out(qq{<${prefix}:${el} rdf:resource="} . $self->_encode($value) . qq{" />\n}); } else { $self->_out_ns_tag($prefix, $el, $value); } return; } sub _out_module_prefix_elements_array { my ($self, $args) = @_; my $prefix = $args->{prefix}; my $data = $args->{data}; my $url = $args->{url}; foreach my $element (@$data) { $self->_out_module_prefix_pair( { %$args, el => $element->{'el'}, val => $element->{'val'}, } ); } return; } sub _out_module_prefix_elements { my ($self, $args) = @_; my $data = $args->{'data'}; if (!$data) { # Do nothing - empty data return; } elsif (ref($data) eq "HASH") { return $self->_out_module_prefix_elements_hash($args); } elsif (ref($data) eq "ARRAY") { return $self->_out_module_prefix_elements_array($args); } else { die "Don't know how to handle module data of type " . ref($data) . "!"; } } # Output the Ad-hoc modules sub _out_modules_elements { my ($self, $super_elem) = @_; # Ad-hoc modules while (my ($url, $prefix) = each %{$self->_modules}) { next if $prefix =~ /^(dc|syn|taxo)$/; $self->_out_module_prefix_elements( { prefix => $prefix, url => $url, data => $super_elem->{$prefix}, } ); } return; } sub _out_complete_outer_tag { my ($self, $outer, $inner) = @_; my $value = $self->_main->{$outer}->{$inner}; if (defined($value)) { $self->_out("<$outer>\n"); $self->_out_array_tag($inner, $value); $self->_end_top_level_elem($outer); } } sub _out_skip_tag { my ($self, $what) = @_; return $self->_out_complete_outer_tag("skip\u${what}s", $what); } sub _out_skip_hours { return shift->_out_skip_tag("hour"); } sub _out_skip_days { return shift->_out_skip_tag("day"); } sub _get_item_about { my ($self, $item) = @_; return defined($item->{'about'}) ? $item->{'about'} : $item->{'link'}; } sub _out_image_dc_elements { } sub _out_modules_elements_if_supported { } sub _out_image_dims { } sub _output_defined_image { my $self = shift; $self->_start_image(); $self->_out_image_dims; # image width #$output .= ''.$self->{image}->{width}.''."\n" # if $self->{image}->{width}; # image height #$output .= ''.$self->{image}->{height}.''."\n" # if $self->{image}->{height}; # description #$output .= ''.$self->{image}->{description}.''."\n" # if $self->{image}->{description}; $self->_out_image_dc_elements; $self->_out_modules_elements_if_supported($self->image()); $self->_end_image(); } sub _is_image_defined { my $self = shift; return defined($self->image('url')); } sub _output_complete_image { my $self = shift; if ($self->_is_image_defined()) { $self->_output_defined_image(); } } sub _out_seq_items { my $self = shift; # Seq items $self->_out("\n \n"); my $idx = 0; foreach my $item (@{$self->_main->_get_items()}) { my $about_text = $self->_get_item_about($item); if (!defined($about_text)) { die qq/Item No. $idx is missing "about" or "link" fields./; } $self->_out(' ' . "\n"); } continue { $idx++; } $self->_out(" \n\n"); } sub _get_first_rdf_decl_mappings { return (); } sub _get_rdf_decl_mappings { my $self = shift; my $modules = $self->_modules(); return [ $self->_get_first_rdf_decl_mappings(), sort { $a->[0] cmp $b->[0] } map { [$modules->{$_}, $_] } keys(%$modules) ]; } sub _render_xmlns { my ($self, $prefix, $url) = @_; my $pp = defined($prefix) ? ":$prefix" : ""; return qq{ xmlns$pp="$url"\n}; } sub _get_rdf_xmlnses { my $self = shift; return join("", map { $self->_render_xmlns(@$_) } @{$self->_get_rdf_decl_mappings}); } sub _get_rdf_decl_open_tag { return qq{_main()->{'xml:base'}; my $base_decl = (defined $base) ? qq{ xml:base="$base"\n} : ""; return $self->_get_rdf_decl_open_tag() . $base_decl . $self->_get_rdf_xmlnses() . ">\n\n"; } sub _out_rdf_decl { my $self = shift; return $self->_out($self->_get_rdf_decl); } sub _out_guid { my ($self, $item) = @_; # 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.) for my $guid (qw(permaLink guid)) { if (defined $item->{$guid}) { $self->_out('' . $self->_encode($item->{$guid}) . '' . "\n"); last; } } } sub _out_item_source { my ($self, $item) = @_; if (defined $item->{source} && defined $item->{sourceUrl}) { $self->_out('' . $self->_encode($item->{source}) . "\n"); } } sub _out_single_item_enclosure { my ($self, $item, $enc) = @_; return $self->_out("_encode($enc->{$_}) . '"' } keys(%$enc)) . " />\n"); } sub _out_item_enclosure { my ($self, $item) = @_; if (my $enc = $item->{enclosure}) { foreach my $sub ((ref($enc) eq "ARRAY") ? @$enc : ($enc)) { $self->_out_single_item_enclosure($item, $sub); } } } sub _get_items { return shift->_main->{items}; } sub _get_filtered_items { return shift->_get_items; } sub _out_item_2_0_tags { } sub _out_item_1_0_tags { } sub _output_single_item { my ($self, $item) = @_; $self->_start_item($item); $self->_out_item_2_0_tags($item); $self->_out_item_1_0_tags($item); $self->_out_modules_elements_if_supported($item); $self->_end_item($item); } sub _output_items { my $self = shift; $self->_item_idx(0); foreach my $item (@{$self->_get_filtered_items}) { $self->_output_single_item($item); } continue { $self->_item_idx($self->_item_idx() + 1); } } sub _output_main_elements { my $self = shift; $self->_output_complete_image(); $self->_output_items; $self->_output_complete_textinput(); } # Outputs the last elements - for RSS versions 0.9.1 and 2.0 . sub _out_last_elements { my $self = shift; $self->_out("\n"); $self->_output_main_elements; $self->_out_skip_hours(); $self->_out_skip_days(); $self->_end_channel; } sub _calc_prefer_dc { return 0; } sub _output_xml_start { my ($self) = @_; $self->_prefer_dc($self->_calc_prefer_dc()); $self->_output_xml_declaration(); $self->_out_rdf_decl; $self->_start_channel(); } sub _get_end_tag { return "rss"; } sub _out_end_tag { my $self = shift; return $self->_out("_get_end_tag() . ">"); } sub _out_all_modules_elems { my $self = shift; # Dublin Core module $self->_out_dc_elements($self->channel(), {map { $_ => 1 } qw(language creator publisher rights date)}, ); # Syndication module foreach my $syn (@{$self->_main->_get_syn_ok_fields}) { if (defined(my $value = $self->_channel_syn($syn))) { $self->_out_ns_tag("syn", $syn, $value); } } # Taxonomy module $self->_output_taxo_topics($self->channel()); $self->_out_modules_elements($self->channel()); } sub _out_dates { my $self = shift; $self->_out_defined_tag("pubDate", $self->_calc_pubDate()); $self->_out_defined_tag("lastBuildDate", $self->_calc_lastBuildDate()); } sub _out_def_chan_tag { my ($self, $tag) = @_; return $self->_output_multiple_tags({ext => "channel", 'defined' => 1}, [$tag],); } # $self->_render_complete_rss_output($xml_version) # # This function is the workhorse of the XML output and does all the work of # rendering the RSS, delegating the work to specialised functions. # # It accepts the requested version number as its argument. sub _render_complete_rss_output { my ($self) = @_; $self->_output_xml_start(); $self->_output_rss_middle; $self->_out_end_tag; return $self->_flush_output(); } ### ### Delegate the XML::RSS accessors to _main ### sub channel { return shift->_main->channel(@_); } sub image { return shift->_main->image(@_); } sub textinput { return shift->_main->textinput(@_); } sub _modules { return shift->_main->_modules(); } 1; __END__ =pod =encoding UTF-8 =head1 VERSION version 1.65 =head1 METHODS =head2 channel Internal use. =head2 image Internal use. =head2 new Internal use. =head2 textinput Internal use. =for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan =head1 SUPPORT =head2 Websites The following websites have more information about this module, and may be of help to you. As always, in addition to those websites please use your favorite search engine to discover more resources. =over 4 =item * MetaCPAN A modern, open-source CPAN search engine, useful to view POD in HTML format. L =item * RT: CPAN's Bug Tracker The RT ( Request Tracker ) website is the default bug/issue tracking system for CPAN. L =item * CPANTS The CPANTS is a website that analyzes the Kwalitee ( code metrics ) of a distribution. L =item * CPAN Testers The CPAN Testers is a network of smoke testers who run automated tests on uploaded CPAN distributions. L =item * CPAN Testers Matrix The CPAN Testers Matrix is a website that provides a visual overview of the test results for a distribution on various Perls/platforms. L =item * CPAN Testers Dependencies The CPAN Testers Dependencies is a website that shows a chart of the test results of all dependencies for a distribution. L =back =head2 Bugs / Feature Requests Please report any bugs or feature requests by email to C, or through the web interface at L. You will be automatically notified of any progress on the request by the system. =head2 Source Code The code is open to the world, and available for you to hack on. Please feel free to browse it and play with it, or whatever. If you want to contribute patches, please send me a diff or prod me to pull from your repository :) L git clone git://github.com/shlomif/perl-XML-RSS.git =head1 AUTHOR Shlomi Fish =head1 BUGS Please report any bugs or feature requests on the bugtracker website L When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature. =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2001 by Various. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut V0_91.pm100644001750001750 742714756547744 21104 0ustar00shlomifshlomif000000000000XML-RSS-1.65/lib/XML/RSS/Private/Outputpackage XML::RSS::Private::Output::V0_91; $XML::RSS::Private::Output::V0_91::VERSION = '1.65'; use strict; use warnings; use vars (qw(@ISA)); use XML::RSS::Private::Output::Base (); use XML::RSS::Private::Output::Roles::ImageDims (); @ISA = ( qw( XML::RSS::Private::Output::Roles::ImageDims XML::RSS::Private::Output::Base ) ); sub _get_rdf_decl { return qq{\n\n} . qq{\n\n}; } sub _calc_lastBuildDate { my $self = shift; if (defined(my $d = $self->channel('lastBuildDate'))) { return $d; } elsif (defined(my $d2 = $self->_channel_dc('date'))) { return $self->_date_to_rss2($self->_date_from_dc_date($d2)); } else { return undef; } } sub _output_rss_middle { my $self = shift; # PICS rating $self->_out_def_chan_tag("rating"); $self->_out_copyright(); $self->_out_dates(); # external CDF URL $self->_out_def_chan_tag("docs"); $self->_out_editors; $self->_out_last_elements; } 1; __END__ =pod =encoding UTF-8 =head1 VERSION version 1.65 =for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan =head1 SUPPORT =head2 Websites The following websites have more information about this module, and may be of help to you. As always, in addition to those websites please use your favorite search engine to discover more resources. =over 4 =item * MetaCPAN A modern, open-source CPAN search engine, useful to view POD in HTML format. L =item * RT: CPAN's Bug Tracker The RT ( Request Tracker ) website is the default bug/issue tracking system for CPAN. L =item * CPANTS The CPANTS is a website that analyzes the Kwalitee ( code metrics ) of a distribution. L =item * CPAN Testers The CPAN Testers is a network of smoke testers who run automated tests on uploaded CPAN distributions. L =item * CPAN Testers Matrix The CPAN Testers Matrix is a website that provides a visual overview of the test results for a distribution on various Perls/platforms. L =item * CPAN Testers Dependencies The CPAN Testers Dependencies is a website that shows a chart of the test results of all dependencies for a distribution. L =back =head2 Bugs / Feature Requests Please report any bugs or feature requests by email to C, or through the web interface at L. You will be automatically notified of any progress on the request by the system. =head2 Source Code The code is open to the world, and available for you to hack on. Please feel free to browse it and play with it, or whatever. If you want to contribute patches, please send me a diff or prod me to pull from your repository :) L git clone git://github.com/shlomif/perl-XML-RSS.git =head1 AUTHOR Shlomi Fish =head1 BUGS Please report any bugs or feature requests on the bugtracker website L When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature. =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2001 by Various. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut 1.0-gen-errors-on-missing-fields.t100644001750001750 160414756547744 21504 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t#!/usr/bin/perl use strict; use warnings; use Test::More tests => 2; use XML::RSS; { eval { my $rss = XML::RSS->new( version => '1.0' ); $rss->add_item( # title => "Some text", link => 'http://a.com', description => 'abc', ); $rss->as_string; }; my $Err = $@; my $s = 'Item No. 0 is missing the "title" field.'; # TEST like ($Err, qr/\A\Q$s\E/, "Exception on missing title field"); } { eval { my $rss = XML::RSS->new( version => '1.0' ); $rss->add_item( title => "Some text", # link => 'http://a.com', description => 'abc', ); $rss->as_string; }; my $Err = $@; my $s = 'Item No. 0 is missing "about" or "link" fields.'; # TEST like ($Err, qr/\A\Q$s\E/, "Exception on missing link field"); } create_rss_0.91_full.pl100644001750001750 420214756547744 21532 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examples/0.91#!/usr/bin/perl -w # creates and prints RSS 0.91 file # This is an example of using the XML::RSS # module to create an RSS file with all # the trimmings so you can see what elements # are available. use strict; use warnings; use XML::RSS; my $rss = XML::RSS->new (version => '0.91', encoding => 'ISO-8859-1'); $rss->strict("1"); $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@freshmeat.net', webMaster => 'scoop@freshmeat.net' ); $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 => 'kdbg 1.0beta2', link => 'http://www.freshmeat.net/news/1999/08/23/935449823.html', description => 'KDbg is a graphical user interface to gdb, the GNU debugger. It provides an intuitive interface for setting breakpoints, inspecting variables, and stepping through code.' ); $rss->add_item(title => 'HTML-Tree 1.7', link => 'http://www.freshmeat.net/news/1999/08/23/935449856.html', description => 'HTML-Tree is a Perl program that recursively decends directories, and creates a web-page based graphical map of HTML pages on a webserver.' ); $rss->skipHours(hour => 2); $rss->skipDays(day => 1); $rss->textinput(title => "quick finder", description => "Use the text input below to search freshmeat", name => "query", link => "http://core.freshmeat.net/search.php3" ); print $rss->as_string; #$rss->save("fm.rdf"); sf-hs-with-lastBuildDate.rss100644001750001750 1324314756547744 22106 0ustar00shlomifshlomif000000000000XML-RSS-1.65/t/data/2.0 Shlomi Fish' Home Site http://community.livejournal.com/shlomif_hsite/ Shlomi Fish' Home Site - LiveJournal.com shlomif@iglu.org.il Sun, 24 Sep 2006 10:12:49 GMT LiveJournal / LiveJournal.com http://community.livejournal.com/shlomif_hsite/3573.html New Additions to the Site shlomif@iglu.org.il http://community.livejournal.com/shlomif_hsite/3573.html <p> Exactly two weeks passed since the last update and many things have been added or improved. Read below for what's new. </p> <p> Two of the pages in <a href="http://www.shlomifish.org/MathVentures/">the MathVentures section</a> were converted to use embedded <a href="http://www.w3.org/Math/">MathML</a>. This should make viewing them with MathML-compliant browsers easier. The old ASCII-art based pages are still available. </p> <p> The ideas <a href="http://www.shlomifish.org/philosophy/ideas/#tucan">Tucan</a> and <a href="http://www.shlomifish.org/philosophy/ideas/#unixdoc">Unixdoc</a> were added to the Random Ideas page. </p> <p> I've placed <a href="http://www.shlomifish.org/open-source/nostalgia/">some of my old DOS-era programs online</a> for your amusement. </p> <p> I added a <a href="http://www.shlomifish.org/meta/FAQ/#site_history">question about the site history</a> to the <a href="http://www.shlomifish.org/meta/FAQ/">FAQ</a>. </p> <p> More CDs were added to the <a href="http://www.shlomifish.org/art/recommendations/music/">Music Recommendations</a>. </p> <p> There's <a href="http://www.shlomifish.org/humour.html#if_god_exists">a new Joke</a> in the Humour archive. </p> http://community.livejournal.com/shlomif_hsite/3573.html mathml mathematics math dos jokes tucan ideas mathventures unixdoc Metallica - Nothing Else Matters full public http://community.livejournal.com/shlomif_hsite/3165.html Sun, 10 Sep 2006 13:41:17 GMT Changes at Shlomi Fish Homesite shlomif@iglu.org.il http://community.livejournal.com/shlomif_hsite/3165.html <p> It's been about two weeks since my last update, and here's what's new: </p> <ol> <li> <p> <a href="http://www.shlomifish.org/art/recommendations/music/">A currently partial list</a> of my favourite compact discs is now live. Creating this list involved a large amount of <a href="http://en.wikipedia.org/wiki/Document_Type_Definition">DTD</a>, <a href="http://www.w3.org/TR/xslt">XSLT</a>, <a href="http://perl-begin.berlios.de/">Perl</a>, and CSS hacking on the <a href="http://search.cpan.org/dist/XML-Grammar-ProductsSyndication/">XML-Grammar-ProductsSyndication</a> framework, that was written from scratch to facilitate making construction of such lists possible by and others. </p> <p> I will add the missing CDs as time goes by, and will also later on add lists for fiction books and for movies, as well as convert the existing <a href="http://www.shlomifish.org/philosophy/books-recommends/">non-fiction books recommendations</a> into the new framework. </p> </li> <li> <p> More pages on the site were made to validate according to the <a href="http://www.w3.org/">World-wide-web consortium</a> standards, and some ancient leftovers that were no longer important were removed. </p> </li> <li> <p> <a href="http://www.shlomifish.org/open-source/favourite/">My list of favourite open source software</a> was updated, with many corrections, added programs and a new navigation menu. </p> </li> <li> <p> <a href="http://www.shlomifish.org/prog-evolution/pre-elpas.html">My memoirs as a programmer from High School</a> were heavily fixed and updated. </p> </li> </ol> http://community.livejournal.com/shlomif_hsite/3165.html xml grammar homesite shlomi fish syndication memoirs products valid html Monkey Island Am I Evil OC Remix annoyed public Roles000755001750001750 014756547744 20662 5ustar00shlomifshlomif000000000000XML-RSS-1.65/lib/XML/RSS/Private/OutputImageDims.pm100644001750001750 576114756547744 23230 0ustar00shlomifshlomif000000000000XML-RSS-1.65/lib/XML/RSS/Private/Output/Rolespackage XML::RSS::Private::Output::Roles::ImageDims; $XML::RSS::Private::Output::Roles::ImageDims::VERSION = '1.65'; use strict; use warnings; sub _out_image_dims { my $self = shift; # link, image width, image height and description return $self->_output_multiple_tags( {ext => "image", 'defined' => 1}, [qw(width height description)], ); } 1; __END__ =pod =encoding UTF-8 =head1 VERSION version 1.65 =for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan =head1 SUPPORT =head2 Websites The following websites have more information about this module, and may be of help to you. As always, in addition to those websites please use your favorite search engine to discover more resources. =over 4 =item * MetaCPAN A modern, open-source CPAN search engine, useful to view POD in HTML format. L =item * RT: CPAN's Bug Tracker The RT ( Request Tracker ) website is the default bug/issue tracking system for CPAN. L =item * CPANTS The CPANTS is a website that analyzes the Kwalitee ( code metrics ) of a distribution. L =item * CPAN Testers The CPAN Testers is a network of smoke testers who run automated tests on uploaded CPAN distributions. L =item * CPAN Testers Matrix The CPAN Testers Matrix is a website that provides a visual overview of the test results for a distribution on various Perls/platforms. L =item * CPAN Testers Dependencies The CPAN Testers Dependencies is a website that shows a chart of the test results of all dependencies for a distribution. L =back =head2 Bugs / Feature Requests Please report any bugs or feature requests by email to C, or through the web interface at L. You will be automatically notified of any progress on the request by the system. =head2 Source Code The code is open to the world, and available for you to hack on. Please feel free to browse it and play with it, or whatever. If you want to contribute patches, please send me a diff or prod me to pull from your repository :) L git clone git://github.com/shlomif/perl-XML-RSS.git =head1 AUTHOR Shlomi Fish =head1 BUGS Please report any bugs or feature requests on the bugtracker website L When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature. =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2001 by Various. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut old_rss_versions_ok_fields.pm100644001750001750 601214756547744 24310 0ustar00shlomifshlomif000000000000XML-RSS-1.65/keep-out/rejectsuse strict; use warnings; my %v0_9_ok_fields = ( channel => { title => '', description => '', link => '', }, image => { title => undef, url => undef, link => undef, }, textinput => { title => undef, description => undef, name => undef, link => undef, }, items => [], num_items => 0, version => '', encoding => '' ); my %v0_9_1_ok_fields = ( channel => { title => '', copyright => undef, description => '', docs => undef, language => undef, lastBuildDate => undef, 'link' => '', managingEditor => undef, pubDate => undef, rating => undef, webMaster => undef, }, image => { title => undef, url => undef, 'link' => undef, width => undef, height => undef, description => undef, }, skipDays => { day => undef, }, skipHours => { hour => undef, }, textinput => { title => undef, description => undef, name => undef, 'link' => undef, }, items => [], num_items => 0, version => '', encoding => '', category => '' ); my %v1_0_ok_fields = ( channel => { title => '', description => '', link => '', }, image => { title => undef, url => undef, link => undef, }, textinput => { title => undef, description => undef, name => undef, link => undef, }, skipDays => { day => '' }, skipHours => { hour => undef, }, items => [], num_items => 0, version => '', encoding => '', output => '', ); my %v2_0_ok_fields = ( channel => { title => '', 'link' => '', description => '', language => undef, copyright => undef, managingEditor => undef, webMaster => undef, pubDate => undef, lastBuildDate => undef, category => undef, generator => undef, docs => undef, cloud => '', ttl => undef, image => '', textinput => '', skipHours => '', skipDays => '', }, image => { title => undef, url => undef, 'link' => undef, width => undef, height => undef, description => undef, }, skipDays => { day => undef, }, skipHours => { hour => undef, }, textinput => { title => undef, description => undef, name => undef, 'link' => undef, }, items => [], num_items => 0, version => '', encoding => '', category => '', cloud => '', ttl => '' ); code-gen000755001750001750 014756547744 17710 5ustar00shlomifshlomif000000000000XML-RSS-1.65/keep-out/scriptsgen-pod-for-as_rss.pl100644001750001750 145114756547744 24013 0ustar00shlomifshlomif000000000000XML-RSS-1.65/keep-out/scripts/code-gen#!/usr/bin/perl use strict; use warnings; my @versions = ( { 'f' => "0_9", 'rss' => "0.9", }, { 'f' => "0_9_1", 'rss' => "0.91", }, { 'f' => "1_0", 'rss' => "1.0", }, { 'f' => "2_0", 'rss' => "2.0", }, ); my $pod; foreach my $v_struct (@versions) { my $f = $v_struct->{f} or die "f not specified"; my $rss = $v_struct->{rss} or die "rss not specified"; $pod .= <<"EOF"; =head2 \$rss->as_rss_$f() B: this function is not an API function and should not be called directly. It is kept as is for backwards compatibility with legacy code. Use the following code instead: \$rss->{output} = "$rss"; my \$text = \$rss->as_string(); This function renders the data in the object as an RSS version $rss feed, and returns the resultant XML as text. EOF } print $pod; ModulesElems.pm100644001750001750 562014756547744 23761 0ustar00shlomifshlomif000000000000XML-RSS-1.65/lib/XML/RSS/Private/Output/Rolespackage XML::RSS::Private::Output::Roles::ModulesElems; $XML::RSS::Private::Output::Roles::ModulesElems::VERSION = '1.65'; use strict; use warnings; sub _out_modules_elements_if_supported { my ($self, $top_elem) = @_; return $self->_out_modules_elements($top_elem); } 1; __END__ =pod =encoding UTF-8 =head1 VERSION version 1.65 =for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan =head1 SUPPORT =head2 Websites The following websites have more information about this module, and may be of help to you. As always, in addition to those websites please use your favorite search engine to discover more resources. =over 4 =item * MetaCPAN A modern, open-source CPAN search engine, useful to view POD in HTML format. L =item * RT: CPAN's Bug Tracker The RT ( Request Tracker ) website is the default bug/issue tracking system for CPAN. L =item * CPANTS The CPANTS is a website that analyzes the Kwalitee ( code metrics ) of a distribution. L =item * CPAN Testers The CPAN Testers is a network of smoke testers who run automated tests on uploaded CPAN distributions. L =item * CPAN Testers Matrix The CPAN Testers Matrix is a website that provides a visual overview of the test results for a distribution on various Perls/platforms. L =item * CPAN Testers Dependencies The CPAN Testers Dependencies is a website that shows a chart of the test results of all dependencies for a distribution. L =back =head2 Bugs / Feature Requests Please report any bugs or feature requests by email to C, or through the web interface at L. You will be automatically notified of any progress on the request by the system. =head2 Source Code The code is open to the world, and available for you to hack on. Please feel free to browse it and play with it, or whatever. If you want to contribute patches, please send me a diff or prod me to pull from your repository :) L git clone git://github.com/shlomif/perl-XML-RSS.git =head1 AUTHOR Shlomi Fish =head1 BUGS Please report any bugs or feature requests on the bugtracker website L When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature. =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2001 by Various. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut 2.0000755001750001750 014756547744 15124 5ustar00shlomifshlomif000000000000XML-RSS-1.65/examplesflickr-rss-with-both-desc-and-media-desc.xml100644001750001750 1034114756547744 25454 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examples/2.0 Uploads from shlomif2 http://www.flickr.com/photos/shlomif/ Thu, 4 Dec 2008 03:02:12 -0800 Thu, 4 Dec 2008 03:02:12 -0800 http://www.flickr.com/ http://farm1.static.flickr.com/79/buddyicons/81969889@N00.jpg?1158015125#81969889@N00 Uploads from shlomif2 http://www.flickr.com/photos/shlomif/ Zarro Bugs http://www.flickr.com/photos/shlomif/3081446735/ <p><a href="http://www.flickr.com/people/shlomif/">shlomif2</a> posted a photo:</p> <p><a href="http://www.flickr.com/photos/shlomif/3081446735/" title="Zarro Bugs"><img src="http://farm4.static.flickr.com/3043/3081446735_b4d7492611_m.jpg" width="240" height="193" alt="Zarro Bugs" /></a></p> <p>No active bugs in perl-XML-RSS-1.41! Let's see how long it will last…</p> Thu, 4 Dec 2008 03:02:12 -0800 2008-12-04T13:02:12-08:00 nobody@flickr.com (shlomif2) tag:flickr.com,2004:/photo/3081446735 Zarro Bugs <p>No active bugs in perl-XML-RSS-1.41! Let's see how long it will last…</p> shlomif2 screenshot firefox rss landmark bugs xml zero milestone perl zarro Cupcakes http://www.flickr.com/photos/shlomif/3059592974/ <p><a href="http://www.flickr.com/people/shlomif/">shlomif2</a> posted a photo:</p> <p><a href="http://www.flickr.com/photos/shlomif/3059592974/" title="Cupcakes"><img src="http://farm4.static.flickr.com/3272/3059592974_4d79fde160_m.jpg" width="240" height="180" alt="Cupcakes" /></a></p> <p>Photographs of cupcakes that my sister prepared.<br /> <br /> The licence is Creative Commons Public Domain, but an attribution or donation would be appreciated.</p> Tue, 25 Nov 2008 11:11:58 -0800 2008-11-23T15:04:42-08:00 nobody@flickr.com (shlomif2) tag:flickr.com,2004:/photo/3059592974 Cupcakes <p>Photographs of cupcakes that my sister prepared.<br /> <br /> The licence is Creative Commons Public Domain, but an attribution or donation would be appreciated.</p> shlomif2 food hearts muffins cupcakes baking sweet sister sugar cupcake bakery muffin rss-2.0-sample-from-rssboard-multiple-skip-days-and-hours.xml100644001750001750 743214756547744 30606 0ustar00shlomifshlomif000000000000XML-RSS-1.65/examples/2.0 Current headlines from the Dallas Times-Herald newspaper http://dallas.example.com Dallas Times-Herald Media Texas Copyright 2006 Dallas Times-Herald http://www.rssboard.org/rss-specification Radio UserLand v8.2.1 http://dallas.example.com Dallas Times-Herald http://dallas.example.com/masthead.gif Read the Dallas Times-Herald 32 96 epo Sun, 29 Jan 2006 17:17:44 GMT jlehrer@dallas.example.com (Jim Lehrer) Sun, 29 Jan 2006 05:00:00 GMT (PICS-1.1 "http://www.rsac.org/ratingsv01.html" l by "webmaster@example.com" on "2006.01.29T10:09-0800" r (n 0 s 0 v 0 l 0)) Saturday Sunday 0 1 2 22 23 Your aggregator supports the textInput element. What software are you using? http://www.cadenhead.org/textinput.php query TextInput Inquiry 60 helpdesk@dallas.example.com Seventh Heaven! Ryan Hurls Another No Hitter http://dallas.example.com/1991/05/02/nolan.htm Texas Rangers pitcher Nolan Ryan hurled the seventh no-hitter of his legendary career on Arlington Appreciation Night, defeating the Toronto Blue Jays 3-0. The 44-year-old struck out 16 batters before a crowd of 33,439. http://dallas.example.com/1991/05/02/nolan.htm jbb@dallas.example.com (Joe Bob Briggs) rec.arts.movies.reviews http://dallas.example.com/feedback/1983/06/joebob.htm I'm headed for France. I wasn't gonna go this year, but then last week "Valley Girl" came out and I said to myself, Joe Bob, you gotta get out of the country for a while. http://dallas.example.com/1983/05/06/joebob.htm http://dallas.example.com/1983/05/06/joebob.htm Fri, 06 May 1983 09:00:00 CST Los Angeles Herald-Examiner Joe Bob Goes to the Drive-In I'm headed for France. I wasn't gonna go this year, but then last week <a href="http://www.imdb.com/title/tt0086525/">Valley Girl</a> came out and I said to myself, Joe Bob, you gotta get out of the country for a while. tag:dallas.example.com,4131:news Valley Girl came out and I said to myself, Joe Bob, you gotta get out of the country for a while.]]> 1983-05-06+lifestyle+joebob+2