XML-Atom-0.42/000755 000765 000024 00000000000 13105244427 013741 5ustar00miyagawastaff000000 000000 XML-Atom-0.42/Build.PL000644 000765 000024 00000000256 13105244427 015240 0ustar00miyagawastaff000000 000000 # This Build.PL for XML-Atom was generated by Dist::Zilla::Plugin::ModuleBuildTiny 0.015. use strict; use warnings; use 5.008001; use Module::Build::Tiny 0.034; Build_PL(); XML-Atom-0.42/Changes000644 000765 000024 00000032454 13105244427 015244 0ustar00miyagawastaff000000 000000 $Id$ Revision history for XML::Atom 0.42 2017-05-12 14:33:09 JST * Doc fixes * Remove encoding pragma to support latest version of perl https://rt.cpan.org/Ticket/Display.html?id=115101 0.41 2011.09.26 * Added a dependency to DateTime::TimeZone (leto) 0.40 2011.09.18 * Fixed tests for Windows (wchristian) * use all upper case UTF-8 (tsgit) 0.39 2011.06.20 * Disabled external entities and network to avoid possible security flaw (yannk) 0.38 2011.05.22 * Fixed a bug where content with newlines wasn't encoded in perl >= 5.12 (emasaka) https://rt.cpan.org/Public/Bug/Display.html?id=61637 0.37 2009.12.29 * Fixed accessors for source elements (Vince Veselosky) 0.36 2009.12.21 * Fixed various dependency issues RT #23538, #34481, #52519, #41058 (Tomas Doran) 0.35 2009.05.01 * reworked Module::Install stuff to remove junks 0.34 2009.04.29 * Fixed $entry->source support (Martin Atkins) 0.33 2009.01.06 * Client: Send WSSE auth header only when username is set (Thanks to David Bourget at http://rt.cpan.org/Public/Bug/Display.html?id=42201) 0.32 2008.11.23 * Added base and lang to Entry and Feed object. Fixed xml:base attributes. (Simon Wistow) 0.31 2008.11.13 * Update Content-Type in XML::Atom::Client when the entity's version >= 1.0 (Thanks to David Steinbrunner RT 39801) 0.30 2008.11.12 * hopefully fix a bug where xml:base returns an empty string e.g. http://www.nntp.perl.org/group/perl.cpan.testers/2008/11/msg2595696.html (Thanks to tokuhirom http://d.hatena.ne.jp/tokuhirom/20081110/1226280757) 0.29 2008.10.25 * Skips Unicode tests since it doesn't pass with some libxml versions (and it's not actually a bug) 0.28 2007.11.06 * Fixed Namespace handling in extensions so that both URL and NS object work (Thanks to Brian Cassidy) 0.27_01 2007.10.04 * Removes most of hacks to deal with LibXML insane unicode stuff which are fixed with 1.64 0.27 2007.09.15 * Fixed $feed->as_xml_utf8 to work with latest XML::LibXML 0.26 2007.09.15 * This be 0.26 0.25_02 2007.06.20 * Fixed tests that fail with newer libxml (Thanks to knagano) 0.25_01 2007.04.27 * Fixed XML::Atom::Base element accessor to work with attributes (Patch from LTjake and Jshirley for OpenSearch extension) * Make XML::Atom::Link easily subclassable (Patch from Simon Wistow for Google Calendar support) 0.25 2006.11.30 * Fixed memory leaks in XML::Atom::Client (Reported by Brian Cassidy) 0.24 2006.11.25 * Updated document to mention that ID creation is user's responsibility * Added $feed->as_xml_utf8 which always returns UTF-8 bytes string, rather than UTF-8 flagged one. This addresses annoying issues with UTF-8 vs. latin-1 (Thanks to Rui Vilela #21191) * Better fix for the hateful default: prefix issue in libxml2; now we remove the default\d* prefix on any nodes and set the proper namespace URI. * Fix to the test case since 0x242 is now printable character in bleadperl (Thanks to Andreas Koenig and Steve Peters) * Skip tests if 'euc-jp' is unknown encoding on your XML library (via CPAN testers) 0.23 2006.08.27 * Fixed the method to get xml:lang and xml:base due to the XML::LibXML 1.60 change which invalidated it. 0.22 2006.07.24 * Refactored internal element accessors by eating the new dog food mk_elem_accessors and mk_object_list_accessor. * Added support of Atom 1.0 parse and generation * Added $thing->links and $thing->categories as a moniker method that returns an array reference in a scalar context * Fixed a bug in $content->body() where it accidentally thinks the content is not a valid Unicode string even if it is, if you call eval {} in elsewhere in the code and $@ is left set. (Thanks to Chris Dent for the patch) 0.21 2006.07.13 * propagate $entry's version when we create content element off of entry using $entry->content("foo") syntax. (Thanks to Simon Wistow for spotting this bug) 0.20 2006.07.12 * Lots of refactoring, which simplifies much of the code in the various construct modules (Person, Link, etc), and which should also make it much more straightforward to add extension classes in the future. * Added global $XML::Atom::ForceUnicode flag to return everything as Unicode flagged (Suggested by many people) * Added global $XML::Atom::DefaultVersion flag to set default version number for generated Atom feed. Defaults to 0.3 (for backward compatibility) * Added support for atom:content @type in Atom 1.0 feeds (Suggested by many people, especially Chris Dent and Andy Lester from Socialtext) 0.19 2006.03.19 * Fix 0.18 bug where renaming stuff was totally broken. 0.18 2006.03.16 * Support Atom 0.3 -> 1.0 renaming bits (issued -> published, modified -> updated, tagline -> subtitle) * $atom->content->body doesn't return Unicode flagged variable anymore, even if it's text/ data. Now it just returns UTF-8 bytes. (Thanks to Garth Webb) 0.17 2006.02.22 * Fixed problem with XML::XPath 0.16 2005.11.22 * Fixed a terrible bug when you set binary data to $entry->content 0.15 2005.11.01 - Fixed bug found in mode => 'insert' (Thanks to Dominic Mitchell) 0.14 2005.10.21 - Fixed bug that it decodes binary data as UTF-8 octet (Thanks to Mahlon E. Smith) - Don't eat up STDIN in cgi-mode (Thanks to Bayle Shanks) 0.13_02 - Now supports insert mode, by passing hash reference in add_entry $feed->add_entry($entry, { mode => 'insert' }); (Thanks to Dominic Mitchell) 0.13_01 2005.09.13 - Now supports creating version 1.0 feed by passing new(Version => 1.0) - Be more strict in utf-8 handling and base64ing (Thanks to Dave Rolsky) 0.13 2005.08.18 - Bumped up the version 0.12_02 - $feed->version now returns 1.0 when xmlns patches with that for 1.0 - Fixed segmentation fault problem with longer than 2.5k (Thanks to Chris Dent and Ryan King) - No unicode decode hack on content withou mode="xml" 0.12_01 2005.07.19 - Added Atom 1.0 feed support for parsing - Hacked Unicode entity in $content->body - Added $entry->contributor - $entry->contributor and $entry->person returns list in list context - Added $content->lang and $content->base (xml:lang and xml:base) - Make sure $feed->as_xml doesn't set utf-8 flag 0.12 2005.06.07 - Documentation fixes for XML::Atom::Server. Thanks to Tatsuhiko Miyagawa for the patch. - Removed XML::LibXSLT usage. Too much pain for too little gain. To be clear: all it was doing was namespace normalization, so removing it should make no difference. - Fixed _utf8_off bug in XML::Atom::Client that causes fatal error in POSTing multibyte content (Tatsuhiko Miyagawa, Masayoshi Sekimura) - Added XML::Atom::Thing::add method to allow $entry->add() (Tatsuhiko Miyagawa) 0.11 2005.02.23 - Remove the default: namespace when converting to XML using as_xml (the earlier fix only fixed it when getting the contents of an entry using $entry->content). - UTF-8 data is no longer base64-encoded in XML::Atom::Content. Thanks to Tatsuhiko Miyagawa for the patch. - Added XML::Atom::Entry::getlist($ns, $element) to retrieve the values of an element that may appear multiple times in the entry (like dc:subject). Thanks to Tatsuhiko Miyagawa for the patch. - Added ability to set namespaced attributes in an XML::Atom::Link object. Thanks to Tatsuhiko Miyagawa for the patch. - XML::Atom::Entry::add_link($link) no longer clones $link if it's a XML::Atom::Link object. Thanks to Tatsuhiko Miyagawa for the patch. 0.10 2004.12.31 - Eliminated unitialized value warning on attributes that aren't set. - Added XML::Atom::Feed->version to get and set the version of the feed. - XML::Atom::Feed->language can now be used to set the language of the feed. - Added support for using XML::XPath in XML::Atom::Server. Thanks to Autrijus Tang for the patch. 0.09 2004.07.29 - Fixed "500 Malformed characters in syswrite" bug with utf-8. Thanks to Tatsuhiko Miyagawa for the patch. - Fixed bug in server where empty XML response would cause an error. Thanks to Tatsuhiko Miyagawa for the patch. 0.08 2004.06.01 - Added XML::Atom::Feed::language method, which returns the language of the feed (from 'xml:lang'). - Added XML::Atom::Feed::author, which returns a XML::Atom::Person object representing the element. - Remove the default: namespace prefix that XML::LibXML adds inside elements. - Use LWP::Authen::Wsse module for WSSE authentication when in REST mode, which handles redirects properly. 0.07 2004.05.15 - Added (experimental) support for using XML::XPath as an alternative to XML::LibXML. This is detected automatically upon loading XML::Atom; XML::LibXML is still the default. - WSSE authentication tokens now persist properly across server redirects. Thanks to Autrijus Tang for the patch. - Fixed bug where empty password (empty string or "0") would cause an invalid login in Atom server core. Also, improved error message on invalid password for security. Thanks to Tatsuhiki Miyagawa for the patch. 0.06 2004.04.14 - BACKWARDS INCOMPATIBILITY: Fixed Nonce behavior in API. Nonce should be sent in base64-encoded form in SOAP and REST requests, but decoded (raw) nonce should be used when generating PasswordDigest. - Feed->add_link and Entry->add_link now support the same hash reference parameter style as used in 0.041 and below, in addition to the XML::Atom::Link parameter. - Fixed bug with Feed->link so that it no longer returns links that are contained within elements within the . 0.05 2004.01.05 - BACKWARDS INCOMPABILITY: Removed XML::Atom::Entry::get_links and XML::Atom::Feed::get_links, in favor of new link() method in both classes, which returns a list of XML::Atom::Link objects. Also, add_link() now expects an XML::Atom::Link object instead of a hash reference. - BACKWARDS INCOMPABILITY: Renamed XML::Atom::API to XML::Atom::Client. - Added XML::Atom::Link, an encapsulation of the tag in a feed or an entry. - Added XML::Atom::Server, an implementation of an Atom core server (to be subclassed for implementation-specific methods). - Fixed feed auto-discovery to work with all client tests at http://diveintomark.org/tests/client/autodiscovery/ - Added (and documented) XML::Atom::Feed->find_feeds, to return all of the Atom feed URIs on a page given a URI. - Fixed issue with PasswordDigest in API (use sha(), not hex(sha()) for generating password digest). - Stream parameter to XML::Atom::Entry::new and XML::Atom::Feed::new is now optional; if passed only one parameter, it's assumed to be the Stream parameter. - Fixed bug in XML::Atom::Content::as_xml (it didn't work). 0.041 2003.12.15 - Fixed issue with calling $entry->content on list of entries generated from $feed->entries. (Thanks to esummers for the report.) 0.04 2003.12.14 - BACKWARDS INCOMPABILITY: elements are now represented as XML::Atom::Content objects instead of just get/set accessors. You can still set XML::Atom::Entry::content with a scalar (it will be automatically upgraded to an XML::Atom::Content object), but to get the value of , you need to call XML::Atom::Content::Body. For example: $entry->content->body - XML::Atom::Entry::content now removes the
wrapper from XHTML when called with no arguments. - Changed XML::Atom::Author to XML::Atom::Person and re-implemented it. - Changed "WSSE" to "UsernameToken" in X-WSSE header. 0.03 2003.12.05 - Added XML::Atom::Author to represent author or contributor, with accessors for name, email, URL, etc. - Updated XML::Atom::API per the 08 API spec: * Removed searchEntries and replaced it with getFeed * Removed introspection and replaced it with URI parameters to createEntry and getFeed (introspection will be added back in once it is more locked down) - Added support for easily adding tags to feed or entry (eg XML::Atom::Feed::add_link) and getting tags from feed or entry (eg XML::Atom::Feed::get_links). - Fixed XML::Atom::Thing::get to return undef when an element is not found in the object at all (it used to return the empty string). 0.02 2003.09.28 - Completely revamped authentication mechanism to use X-WSSE header (or corresponding SOAP headers). - Removed 03-client.t test, because there aren't any publicly available servers to test against. (Are there?) - Added support for SOAP wrapper in API client. - Added namespace support in XML::Atom::Namespace using get and set methods in XML::Atom::Entry and XML::Atom::Feed. - Added namespace normalization for produced XML (if XML::LibXSLT is installed). This is really just a cosmetic thing. 0.01 2003.09.07 - Initial distribution. XML-Atom-0.42/cpanfile000644 000765 000024 00000000514 13105244427 015445 0ustar00miyagawastaff000000 000000 requires 'Class::Data::Inheritable'; requires 'DateTime'; requires 'DateTime::TimeZone'; requires 'Digest::SHA1'; requires 'LWP::UserAgent'; requires 'MIME::Base64'; requires 'URI'; requires 'XML::LibXML', '1.69'; requires 'XML::XPath'; requires 'perl', '5.008001'; on build => sub { requires 'ExtUtils::MakeMaker', '6.59'; }; XML-Atom-0.42/dist.ini000644 000765 000024 00000000011 13105244427 015375 0ustar00miyagawastaff000000 000000 [@Milla] XML-Atom-0.42/lib/000755 000765 000024 00000000000 13105244427 014507 5ustar00miyagawastaff000000 000000 XML-Atom-0.42/LICENSE000644 000765 000024 00000043757 13105244427 014766 0ustar00miyagawastaff000000 000000 This software is copyright (c) 2017 by Benjamin Trott, Tatsuhiko Miyagawa. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. Terms of the Perl programming language system 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" --- The GNU General Public License, Version 1, February 1989 --- This software is Copyright (c) 2017 by Benjamin Trott, Tatsuhiko Miyagawa. This is free software, licensed under: The GNU General Public License, Version 1, February 1989 GNU GENERAL PUBLIC LICENSE Version 1, February 1989 Copyright (C) 1989 Free Software Foundation, Inc. 51 Franklin St, 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 license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our 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. The General Public License applies to the Free Software Foundation's software and to any other program whose authors commit to using it. You can use it for your programs, too. When we speak of free software, we are referring to freedom, not price. Specifically, the General Public License is designed to make sure that you have the freedom to give away or sell copies of free software, 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 a 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 tell them 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. 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 Agreement 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 work containing the Program or a portion of it, either verbatim or with modifications. Each licensee is addressed as "you". 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 General Public License and to the absence of any warranty; and give any other recipients of the Program a copy of this General Public License along with the Program. You may charge a fee for the physical act of transferring a copy. 2. You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains the Program or any part thereof, either with or without modifications, to be licensed at no charge to all third parties under the terms of this General Public License (except that you may choose to grant warranty protection to some or all third parties, at your option). c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the simplest and most usual 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 General Public License. d) 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. Mere aggregation of another independent work with the Program (or its derivative) on a volume of a storage or distribution medium does not bring the other work under the scope of these terms. 3. You may copy and distribute the Program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 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 Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal charge for the cost of distribution) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) Source code for a work means the preferred form of the work for making modifications to it. For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs, or for standard header files or definitions files that accompany that operating system. 4. You may not copy, modify, sublicense, distribute or transfer the Program except as expressly provided under this General Public License. Any attempt otherwise to copy, modify, sublicense, distribute or transfer the Program is void, and will automatically terminate your rights to use the Program under this License. However, parties who have received copies, or rights to use copies, from you under this General Public License will not have their licenses terminated so long as such parties remain in full compliance. 5. By copying, distributing or modifying 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. 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. 7. 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 the 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 the license, you may choose any version ever published by the Free Software Foundation. 8. 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 9. 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. 10. 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 Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to humanity, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19xx name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (a program to direct compilers to make passes at assemblers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice That's all there is to it! --- The Artistic License 1.0 --- This software is Copyright (c) 2017 by Benjamin Trott, Tatsuhiko Miyagawa. This is free software, licensed under: The Artistic License 1.0 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 XML-Atom-0.42/MANIFEST000644 000765 000024 00000002220 13105244427 015066 0ustar00miyagawastaff000000 000000 # This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.009. Build.PL Changes LICENSE MANIFEST META.json META.yml README cpanfile dist.ini lib/XML/Atom.pm lib/XML/Atom/Base.pm lib/XML/Atom/Category.pm lib/XML/Atom/Client.pm lib/XML/Atom/Content.pm lib/XML/Atom/Entry.pm lib/XML/Atom/ErrorHandler.pm lib/XML/Atom/Feed.pm lib/XML/Atom/Link.pm lib/XML/Atom/Person.pm lib/XML/Atom/Server.pm lib/XML/Atom/Thing.pm lib/XML/Atom/Util.pm t/00-compile.t t/01-util.t t/02-content.t t/03-link.t t/04-person.t t/11-entry.t t/12-feed.t t/13-atom1.t t/14-atom1-create.t t/15-content-image.t t/16-content-binary.t t/17-renames.t t/18-unicode.t t/19-ext.t t/20-content-xhtml.t t/21-client.t t/22-autodiscovery.t t/23-category.t t/24-bad-content.t t/25-utf8-create.t t/27-client-leaks.t t/28-ext.t t/29-source.t t/30-datetime-stringification.t t/31-external-entities-libxml.t t/31-external-entities-xpath.t t/TestLib.pm t/author-pod-syntax.t t/samples/atom-1.0.xml t/samples/entry-euc.xml t/samples/entry-full.xml t/samples/entry-ns.xml t/samples/entry-utf8.xml t/samples/feed.xml t/samples/lifeblog-atom.xml t/samples/me.jpg t/samples/source.xml t/samples/vox.xml XML-Atom-0.42/META.json000644 000765 000024 00000005106 13105244427 015364 0ustar00miyagawastaff000000 000000 { "abstract" : "Atom feed and API implementation", "author" : [ "Benjamin Trott, Tatsuhiko Miyagawa" ], "dynamic_config" : 0, "generated_by" : "Dist::Milla version v1.0.17, Dist::Zilla version 6.009, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "XML-Atom", "no_index" : { "directory" : [ "eg", "examples", "inc", "share", "t", "xt" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "6.59" } }, "configure" : { "requires" : { "Module::Build::Tiny" : "0.034" } }, "develop" : { "requires" : { "Dist::Milla" : "v1.0.17", "Test::Pod" : "1.41" } }, "runtime" : { "requires" : { "Class::Data::Inheritable" : "0", "DateTime" : "0", "DateTime::TimeZone" : "0", "Digest::SHA1" : "0", "LWP::UserAgent" : "0", "MIME::Base64" : "0", "URI" : "0", "XML::LibXML" : "1.69", "XML::XPath" : "0", "perl" : "5.008001" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/miyagawa/xml-atom/issues" }, "homepage" : "https://github.com/miyagawa/xml-atom", "repository" : { "type" : "git", "url" : "https://github.com/miyagawa/xml-atom.git", "web" : "https://github.com/miyagawa/xml-atom" } }, "version" : "0.42", "x_contributors" : [ "Andreas Marienborg ", "Benjamin Trott ", "Christian Walde ", "Dave Cross ", "David Steinbrunner ", "emasaka ", "Jonathan \"Duke\" Leto ", "Martin Atkins ", "root ", "Simon Wistow ", "Tatsuhiko Miyagawa ", "Tatsuhiko Miyagawa ", "tokuhirom ", "Tomas Doran ", "Vince Veselosky ", "Yann Kerherve " ], "x_serialization_backend" : "Cpanel::JSON::XS version 3.0233" } XML-Atom-0.42/META.yml000644 000765 000024 00000003256 13105244427 015220 0ustar00miyagawastaff000000 000000 --- abstract: 'Atom feed and API implementation' author: - 'Benjamin Trott, Tatsuhiko Miyagawa' build_requires: ExtUtils::MakeMaker: '6.59' configure_requires: Module::Build::Tiny: '0.034' dynamic_config: 0 generated_by: 'Dist::Milla version v1.0.17, Dist::Zilla version 6.009, CPAN::Meta::Converter version 2.150010' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: XML-Atom no_index: directory: - eg - examples - inc - share - t - xt requires: Class::Data::Inheritable: '0' DateTime: '0' DateTime::TimeZone: '0' Digest::SHA1: '0' LWP::UserAgent: '0' MIME::Base64: '0' URI: '0' XML::LibXML: '1.69' XML::XPath: '0' perl: '5.008001' resources: bugtracker: https://github.com/miyagawa/xml-atom/issues homepage: https://github.com/miyagawa/xml-atom repository: https://github.com/miyagawa/xml-atom.git version: '0.42' x_contributors: - 'Andreas Marienborg ' - 'Benjamin Trott ' - 'Christian Walde ' - 'Dave Cross ' - 'David Steinbrunner ' - 'emasaka ' - 'Jonathan "Duke" Leto ' - 'Martin Atkins ' - 'root ' - 'Simon Wistow ' - 'Tatsuhiko Miyagawa ' - 'Tatsuhiko Miyagawa ' - 'tokuhirom ' - 'Tomas Doran ' - 'Vince Veselosky ' - 'Yann Kerherve ' x_serialization_backend: 'YAML::Tiny version 1.70' XML-Atom-0.42/README000644 000765 000024 00000000730 13105244427 014621 0ustar00miyagawastaff000000 000000 NAME XML::Atom - Atom feed and API implementation SYNOPSIS use XML::Atom; DESCRIPTION Atom is a syndication, API, and archiving format for weblogs and other data. XML::Atom implements the feed format as well as a client for the API. LICENSE XML::Atom is free software; you may redistribute it and/or modify it under the same terms as Perl itself. AUTHOR Benjamin Trott, Tatsuhiko Miyagawa COPYRIGHT All rights reserved. XML-Atom-0.42/t/000755 000765 000024 00000000000 13105244427 014204 5ustar00miyagawastaff000000 000000 XML-Atom-0.42/t/00-compile.t000644 000765 000024 00000000402 13105244427 016232 0ustar00miyagawastaff000000 000000 # $Id$ use Test::More tests => 6; use_ok('XML::Atom'); use_ok('XML::Atom::Entry'); use_ok('XML::Atom::Feed'); #use_ok('XML::Atom::Client'); #use_ok('XML::Atom::Server'); use_ok('XML::Atom::Person'); use_ok('XML::Atom::Content'); use_ok('XML::Atom::Link'); XML-Atom-0.42/t/01-util.t000644 000765 000024 00000001757 13105244427 015576 0ustar00miyagawastaff000000 000000 # $Id$ use strict; use Test::More; use XML::Atom::Util qw( iso2dt ); BEGIN { unless (eval { require DateTime; }) { plan skip_all => 'DateTime is required for tests'; } else { plan tests => 12; } } my %tests = ( '20030928' => '2003-09-28T00:00:00', '2003-09-28' => '2003-09-28T00:00:00', '2003-09-28T12:49:50' => '2003-09-28T12:49:50', '2003-09-28T12:49:50Z' => '2003-09-28T12:49:50', '2003-09-28T12:49:50-00:00' => '2003-09-28T12:49:50', '2003-09-28T12:49:50+00:00' => '2003-09-28T12:49:50', '2003-09-28T12:49:50-01:00' => '2003-09-28T13:49:50', '2003-09-28T12:49:50+01:00' => '2003-09-28T11:49:50', '2003-09-28T12:49:50-01:30' => '2003-09-28T14:19:50', '2003-09-28T12:49:50+01:30' => '2003-09-28T11:19:50', '2003-09-28T12:49:50+17:00' => '2003-09-27T19:49:50', '2003-09-28T12:49:50-17:00' => '2003-09-29T05:49:50', ); for my $test (keys %tests) { is iso2ts($test), $tests{$test}; } sub iso2ts { iso2dt($_[0])->iso8601 } XML-Atom-0.42/t/02-content.t000644 000765 000024 00000005331 13105244427 016264 0ustar00miyagawastaff000000 000000 # $Id$ use strict; use Test::More tests => 32; use XML::Atom::Content; my $content; $content = XML::Atom::Content->new; isa_ok $content, 'XML::Atom::Content'; ok $content->elem; $content->type('image/jpeg'); is $content->type, 'image/jpeg'; $content->type('application/gzip'); is $content->type, 'application/gzip'; $content = XML::Atom::Content->new('This is a test.'); is $content->body, 'This is a test.'; is $content->mode, 'xml'; $content = XML::Atom::Content->new(Body => 'This is a test.'); is $content->body, 'This is a test.'; is $content->mode, 'xml'; $content = XML::Atom::Content->new(Body => 'This is a test.', Type => 'foo/bar'); is $content->body, 'This is a test.'; is $content->mode, 'xml'; is $content->type, 'foo/bar'; $content = XML::Atom::Content->new; $content->body('This is a test.'); is $content->body, 'This is a test.'; is $content->mode, 'xml'; $content->type('foo/bar'); is $content->type, 'foo/bar'; $content = XML::Atom::Content->new; $content->body('

This is a test with XHTML.

'); is $content->body, '

This is a test with XHTML.

'; is $content->mode, 'xml'; $content = XML::Atom::Content->new; $content->body('

This is a test with invalid XHTML.'); is $content->body, '

This is a test with invalid XHTML.'; is $content->mode, 'escaped'; $content = XML::Atom::Content->new; $content->body("This is a test that should use base64\x7f."); $content->type('text/plain'); is $content->mode, 'base64'; is $content->body, "This is a test that should use base64\x7f."; SKIP: { skip "skip Unicode test since it depends on LibXML", 2; $content = XML::Atom::Content->new; $content->body("My name is \xe5\xae\xae\xe5\xb7\x9d."); is $content->mode, 'xml'; is $content->body, "My name is \xe5\xae\xae\xe5\xb7\x9d."; } $content = XML::Atom::Content->new; $content->type('text/plain'); eval { $content->body("Non-printable: " . chr(0x1034F)) }; is $content->mode, 'base64'; is $content->body, un_utf8("Non-printable: " . chr(0x1034F)); # 1.0 with xhtml $content = XML::Atom::Content->new(Version => 1.0); $content->body("

foo bar
"); is $content->type, 'xhtml'; is $content->body, "
foo bar
"; # 1.0 with html $content = XML::Atom::Content->new(Version => 1.0); $content->body("

foo bar"); is $content->type, 'html'; is $content->body, "

foo bar"; # 1.0 as text $content = XML::Atom::Content->new(Version => 1.0); $content->body("foo bar"); $content->type('text'); is $content->type, 'text'; is $content->body, "foo bar"; # 1.0 as binary $content = XML::Atom::Content->new(Version => 1.0); $content->type('image/jpeg'); $content->body("\xff\xde\xde\xde"); is $content->type, 'image/jpeg'; is $content->body, "\xff\xde\xde\xde"; sub un_utf8 { my $foo = shift; Encode::_utf8_off($foo); $foo; } XML-Atom-0.42/t/03-link.t000644 000765 000024 00000001751 13105244427 015552 0ustar00miyagawastaff000000 000000 # $Id$ use strict; use Test::More tests => 14; use XML::Atom::Link; my $link; $link = XML::Atom::Link->new; isa_ok $link, 'XML::Atom::Link'; ok $link->elem; $link->title('This is a test.'); is $link->title, 'This is a test.'; $link->title('Different title.'); is $link->title, 'Different title.'; $link->title('This is a test.'); $link->rel('alternate'); is $link->rel, 'alternate'; $link->href('http://www.example.com/'); is $link->href, 'http://www.example.com/'; $link->type('text/html'); is $link->type, 'text/html'; my $xml = $link->as_xml; like $xml, qr/^<\?xml version="1.0" encoding="UTF-8"\?>/; like $xml, qr/new(dc => "http://purl.org/dc/elements/1.1/"); $link->set($ns, "subject" => "blah"); $xml = $link->as_xml; like $xml, qr/dc:subject="blah"/; XML-Atom-0.42/t/04-person.t000644 000765 000024 00000001235 13105244427 016121 0ustar00miyagawastaff000000 000000 # $Id$ use strict; use Test::More tests => 9; use XML::Atom::Person; my $person; $person = XML::Atom::Person->new; isa_ok $person, 'XML::Atom::Person'; ok $person->elem; $person->name('Foo Bar'); is $person->name, 'Foo Bar'; $person->name('Baz Quux'); is $person->name, 'Baz Quux'; $person->email('foo@bar.com'); is $person->email, 'foo@bar.com'; my $xml = $person->as_xml; like $xml, qr/^<\?xml version="1.0" encoding="UTF-8"\?>/; like $xml, qr//; like $xml, qr/Baz Quux<\/name>/; like $xml, qr/foo\@bar.com<\/email>/; XML-Atom-0.42/t/11-entry.t000644 000765 000024 00000012313 13105244427 015751 0ustar00miyagawastaff000000 000000 # $Id$ use strict; use t::TestLib; use Test::More; use XML::Atom; use XML::Atom::Entry; use XML::Atom::Person; unless ( xmllib_support_encoding('euc-jp') ){ plan skip_all => 'euc-jp is not supported on your XML library'; } plan tests => 71; my $entry; $entry = XML::Atom::Entry->new; $entry->title('Foo Bar'); is $entry->title, 'Foo Bar'; $entry = XML::Atom::Entry->new('t/samples/entry-ns.xml'); isa_ok $entry, 'XML::Atom::Entry'; is $entry->title, 'Unit Test 1'; $entry = XML::Atom::Entry->new(Stream => 't/samples/entry-ns.xml'); is $entry->title, 'Unit Test 1'; my $body = $entry->content->body; ok $body; like $body, qr/^new(Stream => 't/samples/entry-full.xml'); is $entry->title, 'Guest Author'; is $entry->id, 'tag:typepad.com:post:75207'; is $entry->issued, '2003-07-21T02:47:34-07:00'; is $entry->modified, '2003-08-22T18:36:57-07:00'; is $entry->created, '2003-07-21T02:47:34-07:00'; is $entry->summary, 'No, Ben isn\'t updating. It\'s me testing out guest author functionality....'; isa_ok $entry->author, 'XML::Atom::Person'; is $entry->author->name, 'Mena'; $entry->author->name('Ben'); is $entry->author->url, 'http://mena.typepad.com/'; my $dc = XML::Atom::Namespace->new(dc => 'http://purl.org/dc/elements/1.1/'); is $entry->get($dc->subject), 'Food'; my @subj = $entry->getlist($dc->subject); is scalar(@subj), 2; is $subj[0], 'Food'; is $subj[1], 'Cats'; isa_ok $entry->content, 'XML::Atom::Content'; is $entry->content->body, '

No, Ben isn\'t updating. It\'s me testing out guest author functionality.

'; my @link = $entry->link; is scalar(@link), 2; is $link[0]->rel, 'alternate'; is $link[0]->type, 'text/html'; is $link[0]->href, 'http://ben.stupidfool.org/typepad/2003/07/guest_author.html'; is $link[1]->rel, 'service.edit'; is $link[1]->type, 'application/x.atom+xml'; is $link[1]->href, 'http://www.example.com/atom/entry_id=75207'; is $link[1]->title, 'Edit'; my @links = $entry->links; is scalar(@links), 2; is $links[0]->rel, 'alternate'; my $link = $entry->link; isa_ok $link, 'XML::Atom::Link'; is $link->rel, 'alternate'; is $link->type, 'text/html'; is $link->href, 'http://ben.stupidfool.org/typepad/2003/07/guest_author.html'; $link = XML::Atom::Link->new; $link->title('Number Three'); $link->rel('service.post'); $link->href('http://www.example.com/atom'); $link->type('application/x.atom+xml'); $entry->add_link($link); @link = $entry->link; is scalar(@link), 3; is $link[2]->rel, 'service.post'; is $link[2]->type, 'application/x.atom+xml'; is $link[2]->href, 'http://www.example.com/atom'; is $link[2]->title, 'Number Three'; ## xxx test setting/getting different content encodings ## xxx encodings ## xxx Doc param $entry->title('Foo Bar'); is $entry->title, 'Foo Bar'; $entry->set($dc->subject, 'Food & Drink'); is $entry->get($dc->subject), 'Food & Drink'; ok(my $xml = $entry->as_xml); my $entry2 = XML::Atom::Entry->new(Stream => \$xml); isa_ok $entry2, 'XML::Atom::Entry'; is $entry2->title, 'Foo Bar'; is $entry2->author->name, 'Ben'; is $entry2->get($dc->subject), 'Food & Drink'; isa_ok $entry2->content, 'XML::Atom::Content'; is $entry2->content->body, '

No, Ben isn\'t updating. It\'s me testing out guest author functionality.

'; my $entry3 = XML::Atom::Entry->new; my $author = XML::Atom::Person->new; $author->name('Melody'); is $author->name, 'Melody'; $author->email('melody@nelson.com'); $author->url('http://www.melodynelson.com/'); $entry3->title('Histoire'); ok !$entry3->author; $entry3->author($author); isa_ok $entry3->author, 'XML::Atom::Person'; is $entry3->author->name, 'Melody'; $entry = XML::Atom::Entry->new; $entry->content('

Not well-formed.'); is $entry->content->mode, 'escaped'; is $entry->content->body, '

Not well-formed.'; $entry = XML::Atom::Entry->new( Stream => \$entry->as_xml ); is $entry->content->mode, 'escaped'; is $entry->content->body, '

Not well-formed.'; $entry = XML::Atom::Entry->new; $entry->content("This is a test that should use base64\0."); $entry->content->type('image/gif'); is $entry->content->mode, 'base64'; is $entry->content->body, "This is a test that should use base64\0."; is $entry->content->type, 'image/gif'; $entry = XML::Atom::Entry->new( Stream => \$entry->as_xml ); is $entry->content->mode, 'base64'; is $entry->content->body, "This is a test that should use base64\0."; is $entry->content->type, 'image/gif'; my $ns = XML::Atom::Namespace->new(list => "http://www.sixapart.com/atom/list#"); $link->set($ns, type => "Books"); $entry->add_link($link); $xml = $entry->as_xml; like $xml, qr/list:type="Books"/; $entry->set($dc, "subject" => "Weblog"); like $entry->as_xml, qr/Weblog<\/dc:subject>/; $entry->add($dc, "subject" => "Tech"); like $entry->as_xml, qr/Weblog<\/dc:subject>/; like $entry->as_xml, qr/Tech<\/dc:subject>/; # re-set $entry->set($dc, "subject" => "Weblog"); like $entry->as_xml, qr/Weblog<\/dc:subject>/; # euc-jp feed SKIP: { skip "Skipping UTF-8 tests since it depends on libxml", 2; $entry = XML::Atom::Entry->new('t/samples/entry-euc.xml'); is $entry->title, 'ゲストオーサー'; is $entry->content->body, '

日本語のフィード

'; } XML-Atom-0.42/t/12-feed.t000644 000765 000024 00000004170 13105244427 015516 0ustar00miyagawastaff000000 000000 # $Id$ use strict; use Test::More tests => 33; use XML::Atom::Feed; use URI; my $feed; $feed = XML::Atom::Feed->new('t/samples/feed.xml'); isa_ok $feed, 'XML::Atom::Feed'; is $feed->title, 'dive into atom'; is ref($feed->link), 'XML::Atom::Link'; is $feed->link->href, 'http://diveintomark.org/atom/'; is $feed->version, '0.2'; is $feed->language, 'en'; is $feed->modified, '2003-08-25T11:39:42Z'; is $feed->tagline, ''; is $feed->id, 'tag:diveintomark.org,2003:14'; is $feed->generator, 'http://www.movabletype.org/?v=2.64'; is $feed->copyright, 'Copyright (c) 2003, Atom User'; isa_ok $feed->author, 'XML::Atom::Person'; is $feed->author->name, 'Atom User'; is $feed->author->email, 'atom@example.com'; is $feed->author->homepage, 'http://diveintomark.org/atom/'; $feed->version('0.3'); is $feed->version, '0.3'; $feed->language('fr'); is $feed->language, 'fr'; my @entries = $feed->entries; is scalar(@entries), 15; my $entry = $entries[0]; is ref($entry), 'XML::Atom::Entry'; is $entry->title, 'Test'; is $entry->content->body, '

Python is cool stuff for ReSTy webapps.

'; $entry = XML::Atom::Entry->new; $entry->title('Foo'); $entry->content('

This is a test.

'); $feed->add_entry($entry); @entries = $feed->entries; is scalar @entries, 16; my $last = $entries[-1]; is $last->title, 'Foo'; #ok($last->content->body, '

This is a test.

'); $feed->add_link({ title => 'Number Three', rel => 'service.post', href => 'http://www.example.com/atom', type => 'application/x.atom+xml' }); my @links = $feed->link; is scalar @links, 2; is ref($links[-1]), 'XML::Atom::Link'; is $links[-1]->title, 'Number Three'; is $links[-1]->rel, 'service.post'; is $links[-1]->href, 'http://www.example.com/atom'; is $links[-1]->type, 'application/x.atom+xml'; # Test we can insert an entry in the front. $entry = XML::Atom::Entry->new; $entry->title('Bar'); $entry->content('

This is another test.

'); $feed->add_entry($entry, { mode => 'insert' }); @entries = $feed->entries; is scalar @entries, 17; is $entries[0]->title, 'Bar'; is $feed->title, 'dive into atom'; is $feed->content_type, "application/x.atom+xml"; XML-Atom-0.42/t/13-atom1.t000644 000765 000024 00000004035 13105244427 015635 0ustar00miyagawastaff000000 000000 use strict; use Test::More tests => 23; use XML::Atom::Feed; sub is_deeply_method; my $file = "t/samples/atom-1.0.xml"; open my $fh, $file or die "$file: $!"; my $feed = XML::Atom::Feed->new(Stream => $fh); isa_ok $feed, 'XML::Atom::Feed'; is $feed->title, 'dive into mark', 'atom:title'; is $feed->version, '1.0', 'atom:version based on namespace'; is $feed->updated, "2005-07-11T12:29:29Z", 'atom:updated'; my @link = $feed->link; is @link, 2, "2 links"; is_deeply_method $link[0], { rel => 'alternate', type => 'text/html', hreflang => 'en', href => 'http://example.org/' }; is_deeply_method $link[1], { rel => 'self', type => 'application/atom+xml', href => 'http://example.org/feed.atom' }; my @entry = $feed->entries; is @entry, 1, "1 entry"; my $entry = $entry[0]; is $entry->title, 'Atom draft-07 snapshot'; my @entry_link = $entry->link; is_deeply_method $entry_link[0], { rel => 'alternate', type => 'text/html', href => 'http://example.org/2005/04/02/atom' }; is_deeply_method $entry_link[1], { rel => 'enclosure', type => 'audio/mpeg', length => 1337, href => 'http://example.org/audio/ph34r_my_podcast.mp3' }; is $entry->author->name, 'Mark Pilgrim'; is $entry->author->uri, 'http://example.org/'; is $entry->author->email, 'f8dy@example.com'; my @contrib = $entry->contributor; is @contrib, 2, "2 contribs"; is_deeply_method $contrib[0], { name => 'Sam Ruby' }; is_deeply_method $contrib[1], { name => 'Joe Gregorio' }; @contrib = $entry->contributors; is @contrib, 2, "2 contribs (moniker)"; is_deeply_method $contrib[0], { name => 'Sam Ruby' }; is_deeply_method $contrib[1], { name => 'Joe Gregorio' }; my $contrib = $entry->contributor; is $contrib->name, 'Sam Ruby', 'testing scalar context'; is_deeply_method $entry->content, { type => 'xhtml', lang => 'en', base => 'http://diveintomark.org/' }; like $entry->content->body, qr!

.*\[Update: The Atom draft is finished.\].*

!s; sub is_deeply_method { my($thing, $hashref, $msg) = @_; my %copy = map { $_ => $thing->$_ } keys %$hashref; is_deeply \%copy, $hashref, $msg; } XML-Atom-0.42/t/14-atom1-create.t000644 000765 000024 00000002366 13105244427 017104 0ustar00miyagawastaff000000 000000 # $Id$ use strict; use XML::Atom; use XML::Atom::Feed; use XML::Atom::Link; use Test::More tests => 10; my $feed = XML::Atom::Feed->new(Version => 1.0); $feed->title("foo bar"); my $link = XML::Atom::Link->new(Version => 1.0); $link->href("http://www.example.com/"); my $entry = XML::Atom::Entry->new(Version => 1.0); $entry->title("Foo Bar"); $entry->content("foo bar"); $feed->add_link($link); $feed->add_entry($entry); like $feed->as_xml, qr!as_xml, qr!mode="xml"!; like $feed->as_xml, qr!type="xhtml"!; # usage of DefaultVersion $XML::Atom::DefaultVersion = 1.0; $feed = XML::Atom::Feed->new; $feed->title("foo bar"); $feed->add_link({ href => "http://www.example.com/" }); $entry = XML::Atom::Entry->new( Version => "1.0" ); $entry->title("Foo Bar"); $entry->content("foo bar"); $feed->add_entry($entry); like $feed->as_xml, qr!as_xml, qr!mode="xml"!; like $feed->as_xml, qr!type="xhtml"!; # parse again my $xml = $feed->as_xml; $feed = XML::Atom::Feed->new(Stream => \$xml); is $feed->version, "1.0"; is $feed->title, "foo bar"; is $feed->link->href, 'http://www.example.com/'; is $feed->content_type, "application/atom+xml"; XML-Atom-0.42/t/15-content-image.t000644 000765 000024 00000000544 13105244427 017351 0ustar00miyagawastaff000000 000000 # $Id$ use strict; use Test::More tests => 2; use Encode; use XML::Atom::Entry; my $file = "t/samples/lifeblog-atom.xml"; my $xml = slurp($file); my $entry = XML::Atom::Entry->new(Stream => \$xml); ok $entry; ok !Encode::is_utf8($entry->content->body); sub slurp { my $file = shift; open my$fh, $file or die $!; local $/; <$fh>; } XML-Atom-0.42/t/16-content-binary.t000644 000765 000024 00000000517 13105244427 017554 0ustar00miyagawastaff000000 000000 # $Id$ use strict; use Test::More tests => 1; use Encode; use XML::Atom::Entry; my $file = "t/samples/me.jpg"; my $data = slurp($file); my $entry = XML::Atom::Entry->new; $entry->content($data); ok( $data eq $entry->content->body ); sub slurp { my $file = shift; open my$fh, $file or die $!; local $/; <$fh>; } XML-Atom-0.42/t/17-renames.t000644 000765 000024 00000000643 13105244427 016253 0ustar00miyagawastaff000000 000000 use strict; use FindBin; use Test::More tests => 5; use XML::Atom::Feed; my $f = XML::Atom::Feed->new("$FindBin::Bin/samples/atom-1.0.xml"); is $f->tagline, $f->subtitle; my $e = ($f->entries)[0]; is $e->modified, $e->updated, $e->modified; is $e->issued, $e->published, $e->issued; # create $f = XML::Atom::Feed->new; $f->title("foo bar"); $f->tagline("Hello"); is $f->tagline, "Hello"; is $f->subtitle, "Hello"; XML-Atom-0.42/t/18-unicode.t000644 000765 000024 00000001565 13105244427 016254 0ustar00miyagawastaff000000 000000 # $Id$ use strict; use utf8; use Test::More skip_all => "Skipping Unicode test since it depends on LibXML"; use XML::Atom; use XML::Atom::Entry; use XML::Atom::Person; $XML::Atom::ForceUnicode = 1; my $entry; $entry = XML::Atom::Entry->new('t/samples/entry-utf8.xml'); ok $entry; ok utf8::is_utf8($entry->title); ok utf8::is_utf8($entry->summary); ok utf8::is_utf8($entry->author->name); is $entry->title, "フーバー"; is $entry->summary, "これはサマリ"; is $entry->author->name, "ミナ"; my $dc = XML::Atom::Namespace->new(dc => 'http://purl.org/dc/elements/1.1/'); my @cat = $entry->getlist($dc, 'subject'); ok utf8::is_utf8($cat[0]); ok utf8::is_utf8($cat[1]); is $cat[0], "たべもの"; is $cat[1], "猫"; is $entry->content->type, 'text/html'; ok utf8::is_utf8($entry->content->body); is $entry->content->body, "

これは日本語のポストです。

"; XML-Atom-0.42/t/19-ext.t000644 000765 000024 00000004015 13105244427 015420 0ustar00miyagawastaff000000 000000 # $Id$ use strict; use FindBin; use Test::More tests => 16; use XML::Atom::Feed; my $foo = XML::Atom::Ext::Foo->new; isa_ok $foo, 'XML::Atom::Ext::Foo'; $foo->bar(1); is $foo->bar, 1; like $foo->as_xml, qr//; like $foo->as_xml, qr/1<\/bar>/; my $feed = XML::Atom::Feed->new; $feed->foo($foo); my $foo2 = $feed->foo; isa_ok $foo2, 'XML::Atom::Ext::Foo'; is $foo2->bar, 1; ## Make sure the alternate name works. $feed->foo2($foo); $foo2 = $feed->foo2; isa_ok $foo2, 'XML::Atom::Ext::Foo'; is $foo2->bar, 1; like $feed->as_xml, qr//; { my $elem = XML::Atom::Ext::WithNS->new; isa_ok $elem, 'XML::Atom::Ext::WithNS'; $elem->baz(1); is $elem->baz, 1; like $elem->as_xml, qr{add_with_ns( $elem ); like $feed->as_xml, qr{new( \' ' ); my( @elems ) = $feed->with_ns; is scalar @elems, 1; isa_ok $elems[ 0 ], 'XML::Atom::Ext::WithNS'; is $elems[ 0 ]->baz, 1 ; } package XML::Atom::Ext::Foo; use strict; use base qw( XML::Atom::Base ); BEGIN { __PACKAGE__->mk_elem_accessors('bar'); XML::Atom::Feed->mk_object_accessor( foo => __PACKAGE__ ); XML::Atom::Feed->mk_object_accessor( foo2 => __PACKAGE__ ); } sub element_name { 'foo' } sub element_ns { 'http://www.example.com/ns/' } package XML::Atom::Ext::WithNS; use strict; use warnings; use base qw( XML::Atom::Base ); BEGIN { __PACKAGE__->mk_attr_accessors( 'baz' ); XML::Atom::Feed->mk_object_list_accessor( with_ns => __PACKAGE__ ); } sub element_name { return 'with_ns' } sub element_ns { return XML::Atom::Namespace->new( "withns" => q{http://example.com/withns/} ); } XML-Atom-0.42/t/20-content-xhtml.t000644 000765 000024 00000000747 13105244427 017424 0ustar00miyagawastaff000000 000000 # $Id$ use strict; use XML::Atom; use XML::Atom::Entry; use XML::Atom::Feed; use Test::More tests => 2; my $entry = XML::Atom::Entry->new; $entry->content('Bold'); unlike $entry->as_xml, qr/new; $entry = XML::Atom::Entry->new; $entry->content('Bold'); $feed->add_entry($entry); unlike $feed->as_xml, qr/ "Don't do live Atom test"; } plan tests => 22; my $URL = 'http://localhost/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=1'; for my $is_soap (1, 0) { my $entry = XML::Atom::Entry->new; $entry->title('Unit Test 1'); $entry->summary('This is what you get'); $entry->content('When you do unit testing.'); my $api = XML::Atom::Client->new; $api->use_soap($is_soap); $api->username('Melody'); $api->password('0osHZ.scFVmok'); my $url = $api->createEntry($URL, $entry) or die $api->errstr; ok($url); my $entry2 = $api->getEntry($url); ok($entry2); is($entry2->title, 'Unit Test 1'); my $feed = $api->getFeed($URL); ok($feed); ok($feed->entries); my @entries = $feed->entries; ok($entries[0]); is($entries[0]->title, $entry2->title); $entry->title('Unit Test 2'); ok($api->updateEntry($url, $entry)); $entry2 = $api->getEntry($url); ok($entry2); is($entry2->title, 'Unit Test 2'); my $ok = $api->deleteEntry($url); ok($ok); } XML-Atom-0.42/t/22-autodiscovery.t000644 000765 000024 00000002502 13105244427 017511 0ustar00miyagawastaff000000 000000 # $Id$ use strict; use XML::Atom::Feed; use URI; use HTML::TokeParser; use LWP::UserAgent; use Test::More; my $index = 'http://diveintomark.org/tests/client/autodiscovery/'; my $ua = LWP::UserAgent->new; my $req = HTTP::Request->new(GET => $index); my $res = $ua->request($req); plan skip_all => "$index: ". $res->status_line unless $res->is_success && $ENV{TEST_ALL}; my $p = HTML::TokeParser->new(\$res->content); my $in_list = 0; my @tests; while (my $token = $p->get_token) { $in_list++, next if $token->[0] eq 'S' && $token->[1] eq 'ol'; $in_list--, next if $token->[0] eq 'E' && $token->[1] eq 'ol'; next unless $in_list && $token->[0] eq 'S' && $token->[1] eq 'a'; push @tests, URI->new_abs($token->[2]{href}, $index)->as_string; } unless (@tests) { plan skip_all => "Something's wrong with the test suite"; } plan tests => @tests * 4; for my $uri (@tests) { my @feeds = XML::Atom::Feed->find_feeds($uri); ok(scalar @feeds, "$uri has feeds"); is(scalar @feeds, 1, "$uri has only 1 feed"); my $feed = XML::Atom::Feed->new(URI->new($feeds[0])); ok($feed, "$uri has a valid feed"); my $backlink; if ($feed) { for my $link ($feed->link) { $backlink = $link->href if $link->rel eq 'alternate'; } } is($backlink, $uri, "$uri retrieved correct feed"); } XML-Atom-0.42/t/23-category.t000644 000765 000024 00000002671 13105244427 016436 0ustar00miyagawastaff000000 000000 use strict; use Test::More 'no_plan'; use XML::Atom::Feed; my $feed = XML::Atom::Feed->new("t/samples/vox.xml"); my $entry = ($feed->entries)[0]; ok $entry; is $entry->title, "Pirates of Caribbean - Dead Man's Chest"; my @category = $entry->category; is @category, 4, 'returns list in a list context'; is $category[0]->term, 'disney'; is $category[0]->scheme, 'http://bulknews.vox.com/tags/disney/'; is $category[0]->label, 'disney'; my $cat = $entry->category; isa_ok $cat, 'XML::Atom::Category', 'scalar context'; is $cat->term, 'disney'; my @categories = $entry->categories; is @categories, 4, "moniker"; { my $entry = XML::Atom::Entry->new( Version => 1.0 ); $entry->title("foo bar"); $entry->add_category({ term => "foo", scheme => "http://example.org/foo#", label => "foo bar", }); my @cat = $entry->categories; is @cat, 1; is $cat[0]->term, "foo"; is $cat[0]->scheme, "http://example.org/foo#"; is $cat[0]->label, "foo bar"; $entry->add_category({ term => "bar", scheme => "http://example.org/bar#", }); @cat = $entry->categories; is @cat, 2; is $cat[1]->term, "bar"; my $xml = $entry->as_xml; like $xml, qr!!; like $xml, qr!!; } XML-Atom-0.42/t/24-bad-content.t000644 000765 000024 00000000600 13105244427 017006 0ustar00miyagawastaff000000 000000 use strict; use Test::More tests => 2; use XML::Atom::Content; my $stuff = "\x{1234}"; { my $content = XML::Atom::Content->new(Version => 0.3); $content->body($stuff); isnt $content->mode, 'base64'; } { my $content = XML::Atom::Content->new(Version => 0.3); eval { doo(); }; # this set $@ $content->body($stuff); isnt $content->mode, 'base64'; } XML-Atom-0.42/t/25-utf8-create.t000644 000765 000024 00000000664 13105244427 016752 0ustar00miyagawastaff000000 000000 use strict; use Test::More 'no_plan'; use FindBin; use XML::Atom::Feed; my $feed = XML::Atom::Feed->new(Version => 1.0); $feed->version; # 1.0 $feed->title("Dicion\xc3\xa1rios"); is $feed->title, "Dicion\xc3\xa1rios"; my $out = "$FindBin::Bin/utf8-create.xml"; open my $fh, ">", $out; print $fh $feed->as_xml_utf8; close $fh; $feed = XML::Atom::Feed->new($out); is $feed->title, "Dicion\xc3\xa1rios"; END { unlink $out if -e $out } XML-Atom-0.42/t/27-client-leaks.t000644 000765 000024 00000000640 13105244427 017172 0ustar00miyagawastaff000000 000000 use strict; use warnings; use Test::More; BEGIN { unless (eval { require DateTime }) { plan skip_all => 'DateTime is required for tests'; } } plan tests => 1; use XML::Atom::Client; my $foo; no warnings 'redefine'; my $orig = LWP::UserAgent::AtomClient->can('DESTROY'); *LWP::UserAgent::AtomClient::DESTROY = sub { $orig->(@_); $foo = 1 }; { my $client = XML::Atom::Client->new; }; ok $foo; XML-Atom-0.42/t/28-ext.t000644 000765 000024 00000004614 13105244427 015425 0ustar00miyagawastaff000000 000000 package XML::Atom::Ext::Test; use base qw( XML::Atom::Base ); XML::Atom::Feed->mk_elem_accessors(qw(totalResults startIndex itemsPerPage), [ element_ns() ] ); XML::Atom::Feed->mk_object_list_accessor( ext_link => 'XML::Atom::Ext::Test::Link' ); #XML::Atom::Feed->mk_object_accessor( Query => 'XML::Atom::Ext::::Query' ); sub element_ns { return XML::Atom::Namespace->new("testext" => q{http://test.com/-/spec/test/0.1/} ); } 1; package XML::Atom::Ext::Test::Link; use base qw( XML::Atom::Base ); __PACKAGE__->mk_attr_accessors( qw( href hreflang rel type ) ); sub element_name { return 'link' } sub element_ns { return XML::Atom::Ext::Test->element_ns; } 1; package main; use strict; use warnings; use XML::Atom::Feed; use Test::More tests => 8; my $feed = XML::Atom::Feed->new; my $link = XML::Atom::Link->new; $link->href(q{http://www.legacy_link.com}); $feed->add_link($link); my $ext_link = XML::Atom::Ext::Test::Link->new; $ext_link->href(q{http://www.extended_link.org}); $feed->add_ext_link($ext_link); ok($ext_link, "creating extension link"); # Test simple accessors my @accessors = qw( totalResults startIndex itemsPerPage ); for ( @accessors ) { $feed->$_( 2 ); } for ( @accessors ) { is($feed->$_, 2, "extension accessors"); } my $xml = $feed->as_xml; like( $xml, qr{xmlns:testext="http://test.com/-/spec/test/0.1/"}, "ext namespace"); like( $xml, qr{}, "ext link match"); like( $xml, qr{2}, "ext method match"); like( $xml, qr{}, "standard link match"); __END__ =head2 Expected Output 2 2 2 XML-Atom-0.42/t/29-source.t000644 000765 000024 00000001215 13105244427 016120 0ustar00miyagawastaff000000 000000 use strict; use Test::More tests => 9; use XML::Atom::Feed; my $feed = XML::Atom::Feed->new("t/samples/source.xml"); my $entry = ($feed->entries)[0]; ok $entry; is $entry->title, "Example Entry"; ok $entry->source; is $entry->source->title, "Frank's JiveBlog"; $entry->title("Altered Entry"); is $entry->title, "Altered Entry"; my $link = $entry->source->link; is $link->rel, 'alternate'; is $link->type, 'text/html'; is $link->href, 'http://jiveblog.example.com/frank'; my $new_source = XML::Atom::Feed->new(Version => 1.0); $new_source->title("Jank's FriveBlog"); $entry->source($new_source); is $entry->source->title, "Jank's FriveBlog"; XML-Atom-0.42/t/30-datetime-stringification.t000644 000765 000024 00000001044 13105244427 021576 0ustar00miyagawastaff000000 000000 use strict; use warnings; use Test::More; BEGIN { unless (eval { require DateTime } and eval { require DateTime::Format::Atom }) { plan skip_all => 'DateTime and DateTime::Format::Atom are required for tests'; } } plan tests => 2; use XML::Atom::Feed; my $f = XML::Atom::Feed->new(); my $dt = DateTime->now(); $f->updated($dt); my $xml = $f->as_xml; my $dt_string = DateTime::Format::Atom->format_datetime($dt); like($xml, qr/$dt_string/, "correct format made"); unlike($xml, qr||, "no empty modified elements"); XML-Atom-0.42/t/31-external-entities-libxml.t000644 000765 000024 00000003763 13105244427 021554 0ustar00miyagawastaff000000 000000 use strict; use Test::More; use XML::Atom::Entry; use FindBin; my $filepath = "$FindBin::Bin/samples/entry-ns.xml"; $filepath = "/$filepath" if $filepath !~ m@^/@; BEGIN { unless (eval { require XML::LibXML }) { plan skip_all => 'LibXML required for this test'; } } plan tests => 4; my $xml = <<"EOX"; ]> Guest Author tag:typepad.com:post:75207 2003-07-21T02:47:34-07:00 2003-08-22T18:36:57-07:00 2003-07-21T02:47:34-07:00 No, Ben isn't updating. It's me testing out guest author functionality.... Mena http://mena.typepad.com/ Food Cats &ref;

No, Ben isn't updating. It's me testing out guest author functionality.

EOX ## default sane parser { my $entry = XML::Atom::Entry->new(Stream => \$xml); is $entry->title, "Guest Author", "got title"; my $content = $entry->content->body; unlike $content, qr/This is what you get when you do unit testing/, "ignored entity"; } ## custom parser { my $libxml = XML::LibXML->new; my $entry = XML::Atom::Entry->new(Stream => \$xml, Parser => $libxml); is $entry->title, "Guest Author", "got title"; my $content = $entry->content->body; like $content, qr/This is what you get when you do unit testing/, "resolved entity"; } XML-Atom-0.42/t/31-external-entities-xpath.t000644 000765 000024 00000004346 13105244427 021407 0ustar00miyagawastaff000000 000000 use strict; use Test::More; BEGIN { unless (eval { require XML::XPath }) { plan skip_all => 'XML::XPath required for this test'; } } plan tests => 4; BEGIN { ## hardcore, because XML::Atom doesn't make it easy to change it at ## runtime require XML::Atom; if (XML::Atom->LIBXML) { no strict 'refs'; diag "XPath Override in place"; *{XML::Atom::LIBXML} = sub() {0}; } } use XML::Parser; use XML::Atom::Entry; use FindBin; my $filepath = "$FindBin::Bin/samples/entry-ns.xml"; my $xml = <<"EOX"; ]> Guest Author tag:typepad.com:post:75207 2003-07-21T02:47:34-07:00 2003-08-22T18:36:57-07:00 2003-07-21T02:47:34-07:00 No, Ben isn't updating. It's me testing out guest author functionality.... Mena http://mena.typepad.com/ Food Cats &ref;

No, Ben isn't updating. It's me testing out guest author functionality.

EOX ## Sane default { my $entry = XML::Atom::Entry->new(Stream => \$xml); is $entry->title, "Guest Author", "got title"; my $content = $entry->content->body; unlike $content, qr/This is what you get when you do unit testing/, "ignored entity"; } ## custom parser { my $parser = XML::Parser->new(); # no option my $entry = XML::Atom::Entry->new(Stream => \$xml, Parser => $parser); is $entry->title, "Guest Author", "got title"; my $content = $entry->content->body; like $content, qr/This is what you get when you do unit testing/, "resolved entity"; } XML-Atom-0.42/t/author-pod-syntax.t000644 000765 000024 00000000454 13105244427 020002 0ustar00miyagawastaff000000 000000 #!perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { print qq{1..0 # SKIP these tests are for testing by the author\n}; exit } } # 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(); XML-Atom-0.42/t/samples/000755 000765 000024 00000000000 13105244427 015650 5ustar00miyagawastaff000000 000000 XML-Atom-0.42/t/TestLib.pm000644 000765 000024 00000000664 13105244427 016116 0ustar00miyagawastaff000000 000000 package t::TestLib; use strict; use base qw( Exporter ); our @EXPORT = qw( xmllib_support_encoding ); use XML::Atom; sub xmllib_support_encoding { my $enc = shift; my $xml = qq(\n); if (LIBXML) { eval { XML::LibXML->new->parse_string($xml) }; return $@ ? 0 : 1; } else { eval { XML::XPath->new(xml => $xml) }; return $@ ? 0 : 1; } } 1; XML-Atom-0.42/t/samples/atom-1.0.xml000644 000765 000024 00000003215 13105244427 017627 0ustar00miyagawastaff000000 000000 dive into mark A <em>lot</em> of effort went into making this effortless 2005-07-11T12:29:29Z tag:example.org,2003:3 Copyright (c) 2003, Mark Pilgrim Example Toolkit Atom draft-07 snapshot tag:example.org,2003:3.2397 2005-07-11T12:29:29Z 2003-12-13T08:29:29-04:00 Mark Pilgrim http://example.org/ f8dy@example.com Sam Ruby Joe Gregorio

[Update: The Atom draft is finished.]

XML-Atom-0.42/t/samples/entry-euc.xml000644 000765 000024 00000001745 13105244427 020314 0ustar00miyagawastaff000000 000000 ȥ tag:typepad.com:post:75207 2003-07-21T02:47:34-07:00 2003-08-22T18:36:57-07:00 2003-07-21T02:47:34-07:00 No, Ben isn't updating. It's me testing out guest author functionality.... Mena http://mena.typepad.com/ Food Cats

ܸΥե

XML-Atom-0.42/t/samples/entry-full.xml000644 000765 000024 00000002031 13105244427 020467 0ustar00miyagawastaff000000 000000 Guest Author tag:typepad.com:post:75207 2003-07-21T02:47:34-07:00 2003-08-22T18:36:57-07:00 2003-07-21T02:47:34-07:00 No, Ben isn't updating. It's me testing out guest author functionality.... Mena http://mena.typepad.com/ Food Cats

No, Ben isn't updating. It's me testing out guest author functionality.

XML-Atom-0.42/t/samples/entry-ns.xml000644 000765 000024 00000000541 13105244427 020151 0ustar00miyagawastaff000000 000000 Unit Test 1
This is what you get when you do unit testing.
XML-Atom-0.42/t/samples/entry-utf8.xml000644 000765 000024 00000001700 13105244427 020415 0ustar00miyagawastaff000000 000000 フーバー tag:typepad.com:post:75207 2003-07-21T02:47:34-07:00 2003-08-22T18:36:57-07:00 2003-07-21T02:47:34-07:00 これはサマリ ミナ http://mena.typepad.com/ たべもの

これは日本語のポストです。

XML-Atom-0.42/t/samples/feed.xml000644 000765 000024 00000024200 13105244427 017273 0ustar00miyagawastaff000000 000000 dive into atom 2003-08-25T11:39:42Z Atom User http://diveintomark.org/atom/ atom@example.com tag:diveintomark.org,2003:14 http://www.movabletype.org/?v=2.64 Copyright (c) 2003, Atom User Test tag:diveintomark.org,2003:14.2447 2003-08-25T07:39:42-05:00 2003-08-25T12:10:42Z Well, it's about testing, really. 2003-08-25T11:39:42Z

Python is cool stuff for ReSTy webapps.

Created using the Fix Auth tag:diveintomark.org,2003:14.2444 2003-08-25T04:04:26-05:00 2003-08-25T08:04:26Z Stuff.... 2003-08-25T08:04:26Z Stuff. just a test - updated tag:diveintomark.org,2003:14.2441 2003-08-24T00:08:37-05:00 2003-08-25T16:48:49Z rubys 2003-08-24T04:08:37Z nothing to see here, move along Second attempt. tag:diveintomark.org,2003:14.2440 2003-08-22T21:28:17-05:00 2003-08-23T01:40:03Z Updating now works too. How about a new paragraph?... 2003-08-23T01:28:17Z Updating now works too.

How about a new paragraph?

]]>
First post. tag:diveintomark.org,2003:14.2439 2003-08-22T21:17:21-05:00 2003-08-25T11:40:02Z Testing a javascript client. Test. Again. and again.... 2003-08-23T01:17:21Z javascript client. Test. Again. and again.]]> Can anyone post? tag:diveintomark.org,2003:14.2437 2003-08-20T12:11:55-05:00 2003-08-25T08:03:41Z (not) Mark tries to make a post 2003-08-20T16:11:55Z It works! Yes! for now]]> Unit Test 1 tag:diveintomark.org,2003:14.2431 2003-08-18T15:21:06-05:00 2003-08-18T19:21:06Z This is what you get 2003-08-18T19:21:06Z When you do unit testing. Unit Test 1 tag:diveintomark.org,2003:14.2430 2003-08-18T15:18:54-05:00 2003-08-18T19:18:54Z This is what you get 2003-08-18T19:18:54Z When you do unit testing. Unit Test 1 tag:diveintomark.org,2003:14.2427 2003-08-18T15:13:11-05:00 2003-08-18T19:13:11Z This is what you get 2003-08-18T19:13:11Z When you do unit testing. Unit Test 1 tag:diveintomark.org,2003:14.2426 2003-08-18T15:12:31-05:00 2003-08-18T19:12:31Z This is what you get 2003-08-18T19:12:31Z When you do unit testing. Unit Test 1 tag:diveintomark.org,2003:14.2425 2003-08-18T15:11:56-05:00 2003-08-18T19:11:56Z This is what you get 2003-08-18T19:11:56Z When you do unit testing. Unit Test 1 tag:diveintomark.org,2003:14.2424 2003-08-18T15:11:21-05:00 2003-08-18T19:11:21Z This is what you get 2003-08-18T19:11:21Z When you do unit testing. Unit Test 1 tag:diveintomark.org,2003:14.2423 2003-08-18T15:10:50-05:00 2003-08-18T19:10:50Z This is what you get 2003-08-18T19:10:50Z When you do unit testing. Unit Test 1 tag:diveintomark.org,2003:14.2421 2003-08-18T15:07:58-05:00 2003-08-18T19:07:58Z This is what you get 2003-08-18T19:07:58Z When you do unit testing. Unit Test 1 tag:diveintomark.org,2003:14.2420 2003-08-18T14:59:24-05:00 2003-08-18T18:59:24Z This is what you get 2003-08-18T18:59:24Z When you do unit testing.
XML-Atom-0.42/t/samples/lifeblog-atom.xml000644 000765 000024 00000017441 13105244427 021122 0ustar00miyagawastaff000000 000000 me.jpg /9j/4AAQSkZJRgABAgEASABIAAD/7QE0UGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEAAgBIAAAAAQACOEJJTQPzAAAAAAAIAAAAAAAAAAA4QklNJxAAAAAAAAoAAQAAAAAAAAACOEJJTQP1AAAAAABIAC9mZgABAGxmZgAGAAAAAAABAC9mZgABAKGZmgAGAAAAAAABADIAAAABAFoAAAAGAAAAAAABADUAAAABAC0AAAAGAAAAAAABOEJJTQP4AAAAAABwAAD/////////////////////////////A+gAAAAA/////////////////////////////wPoAAAAAP////////////////////////////8D6AAAAAD/////////////////////////////A+gAADhCSU0EBgAAAAAAAgAC/+4ADkFkb2JlAGSAAAAAAf/bAIQADAgICAkIDAkJDBELCgsRFQ8MDA8VGBMTFRMTGBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAENCwsNDg0QDg4QFA4ODhQUDg4ODhQRDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM/8AAEQgAyACWAwEiAAIRAQMRAf/EAT8AAAEFAQEBAQEBAAAAAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAABBAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHxY3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9jdHV2d3h5ent8fX5/cRAAICAQIEBAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS0fAzJGLhcoKSQ1MVY3M08SUGFqKygwcmNcLSRJNUoxdkRVU2dGXi8rOEw9N14/NGlKSFtJXE1OT0pbXF1eX1VmZ2hpamtsbW5vYnN0dXZ3eHl6e3x//dAAQACv/aAAwDAQACEQMRAD8A8qSSSSUpJJJJSkkkklKSSSSUpJJJJSkkkklKSSSSUpJJJJSkkkklKSSSSU//0PKkkkklKSSSSUpJJJJS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 1 XML-Atom-0.42/t/samples/me.jpg000644 000765 000024 00000013115 13105244427 016754 0ustar00miyagawastaff000000 000000 JFIFHH4Photoshop 3.08BIMHH8BIM8BIM' 8BIMH/fflff/ff2Z5-8BIMp8BIMAdobed            "?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?I%)$IJI$RI$I%)$IJI$RI$I%)$IOI%)$IJI$RI$$g{_m1|˟#3\{i{3a痋5|Gx/-uV{L5(7bLIJ&=RI$I$$8j8dz"$$VI%)$IJI%&5pkD`)(,A4OUhO`6'ViM$:f_6DgTǧKw{.}8euK[4V p/?' rֺͭookmx?ފ.I5TyP/<-FH+|Ǯ˺f.g$Ndž"=5sr%W#:ĤI9u&3B#ZU_-%}FV _5ُ !v}?ݦf'SZyF^Kӿ=bNڄ֟D[ZxGu 2=jjnַңpdF:o%/[c[G+FEe@kw欮v ]_ܚ͘ꈝZ.~˅Ý]m3oix3rt+WYms2I xgڹnl;$d̹_[3wG`0$r߮ǾUq;E1 ho\S2'HѾ}Sc`V#pOo:OeU7Jhu AV־;c~ ,LZ6,{l:9sŗ&N6:D%d==xcN_h)8L5Nɡ] ߲ r9UFVk(k@<`s}ܶyP`O Ӆz~qtʱ'S\L66C]v1/N{9$@Xq޲_͏V|REIP=>{I2I)7i\ׁ^UjFq-OS}K׿hs/=mp k5?Ssaй 'HdÔO*ݸMu߁+KCw{]>W$-ShOc7Ҫ8xYy!aSLrt&/cs辆b>^TZ{]o=?2ηwK}Tbَ#~Kk6l}*ų]ޡP:ʷsKk-Xz[:~N_W sUDXo.IIC$$X dHFz/_⛪t6W  qYYXTl-h{ []\n6=b:2\@4c;׏k6/G?U~ugc'1:\Ch 5z[O{z#}ca iun{k ,unkmO@vEz/զM4u5}&/9 &cױkÚ`ǂԔ% pGA[F227~9aK[m{؀dGrڪZ@^+9at]OZ&evOnի.bʇYIr!%W9/|~G!oɪfѫk<$)$JRI$ߪ=//u'!kWK6}^3}ÍnmUxw+ѯDWِUMhM+0mk@ h?ŏI}^u[˫5WS6v "<2o_yG践ZK+{]gzfE$hzKoY虝=s~7TpWb ݌6=tպ=eYך#M>[#"ߑcYcsO.sYM[en,{O!;\ئ06 UޕޡwUݏyC}/v+3DZ3VWEGw4pGt9jTX2=;zcIcC̀c],sMelh#_o$vIy<!)=.=I%)n}]UfޣhὍR)oU z^>M6ZqOakgzu+꣦[q1o]z\PՍDkʽuX/ӫen]zv%z#-]5HV({\vϩN{gt !;{~)n5RYC}noqsW7aSN@ݔ;#nL dAV.!ա2#] Ogh~=R=-{,/.:O֋m1EgCGw\\4:@ 9/!wqNktU7_H9޼BH N=,[mvH~ $a-̜kqm6ѿոMpszm*S$=T$?I%)$IJ^[od Lʹ zV6yƳ_u_GccWf5DVzaA ڍzOdco'yhısv+j۠꭭Ů?neWzS貫huMoJv;ӱmkC2)} Wk)0-3{QSehձ~`5<*jwBʫ%H(N;d;~%v\!O*4zt=,ugXs?KujȻig~#PV "Wc۳cA-pw{\a]FN;lֺuN{6)!bX1c3=]WanUNeX] \ /Xwjk ZaUg-rg, [E]'Mwnܱ<}9cK.ɮ"ֈe n۹wz]-I$aRI$I$I%)$IOM.1FW&!ן ͵ߝg!=Kq^R΢#} }UZWW'~#K!XyNͶ'Xϫ>JCVr^}OstkU$έy Qsԗ;vC޽1xnUXKVbj6?OIs>l++H׾Բ1}$ Lr[wezXFrqKj.5i i[GMkAoñivݞv6opwpĞ/^`n5ZMOkFTíJՁ.e) 2&IeN/F%Z'=ω1qv,#pRVjr3:uw_d6=l`[U{@sNa,QTy#-4,$4q'H+ 5R-#o,/؟I)I%)$IOFcȭXWC[Z]έ7!&&[cnȥy $A5-Χv6];yZ\FP}&?4cFxlx 5y`c>oV߭x֦=2^> ܮOhN+TI))i:WǪ K+v}b˿>=f-ʓb:@5^w ҏ^>I^>'fTѳ,ˋյZֿ _&^^`l 7w"'OQv+%m}teb/ IX<ɍSI] kfC{RI%?򤓩Vi"gRSR4D~ $ 4]? Vu6;A X60376݋{7Sgh*ٮwb^[v ,`6 CRKc,}pAUx7Jy>ܳ{/&KM1i{U^ZJCĮI (%I1ढ?wU>>>PyN/2 Testing atom:source Example Entry Frank's JiveBlog
XML-Atom-0.42/t/samples/vox.xml000644 000765 000024 00000063700 13105244427 017214 0ustar00miyagawastaff000000 000000 miyagawa's blog Vox 2006-07-18T07:02:12Z miyagawa http://bulknews.vox.com/ tag:vox.com,2006:6p00b8ea067a57dece/ Pirates of Caribbean - Dead Man's Chest tag:vox.com,2006-07-18:asset-6a00b8ea067a57dece00c2251d59be549d 2006-07-18T03:00:19Z 2006-07-18T07:02:12Z

Last night I went to the preview show of "Pirates of Caribbean - Dead Man's Chest" in Roppongi Hills. The movie was fun but all I remember is Keira Knightley's jaw!

She was so cute in Love Actually but these days she's been getting probably thin and that makes her jaw's edge sharp and awful. Hmm ...

 

Ellegarden - Riot on the Grill tag:vox.com,2006-07-16:asset-6a00b8ea067a57dece00c2251d0fdff219 2006-07-16T11:23:11Z 2006-07-17T07:15:11Z

Ellegarden has been on my antenna for a while, whenever I listen to their song on cable TV stations like MTV Japan. They're a Japanese alternative rock band (kind of emo + punk) and does really great tunes. I just downloaded their (probably first) major album "Riot on the Grill" from iTMS Japan and it surely rocks.

If you like New Found Glory, the Ataris or Blink-182, you'll definitely like ELLEGARDEN as well. Check out Last.fm artist page for more.

Mocha frapp tag:vox.com,2006-07-16:asset-6a00b8ea067a57dece00c2251dfed68e1d 2006-07-16T06:43:41Z 2006-07-16T06:43:41Z

Rock'n Roll

Vox tag:vox.com,2006-07-16:asset-6a00b8ea067a57dece00c2251d0b7b8fdb 2006-07-16T02:51:51Z 2006-07-16T02:51:51Z
Vox cafe found in Boston.
Way too HOT tag:vox.com,2006-07-15:asset-6a00b8ea067a57dece00c2251d04798fdb 2006-07-15T08:53:25Z 2006-07-16T19:49:16Z

Tokyo is again getting its craziness to become the hottest place in the world. Today it was up to 95 F (or 36 C) in the daytime. Way too hot.

Fireworks in New York tag:vox.com,2006-07-11:asset-6a00b8ea067a57dece00c2251cb644604a 2006-07-11T06:29:23Z 2006-07-11T06:36:09Z
Here's the video I took on the Ferry.
Westside story tag:vox.com,2006-07-11:asset-6a00b8ea067a57dece00c2251cb4cb604a 2006-07-11T04:03:56Z 2006-07-11T04:03:56Z

coming to Japan this fall

Materazzi is an idiot tag:vox.com,2006-07-10:asset-6a00b8ea067a57dece00c2251cab768fdb 2006-07-10T09:26:10Z 2006-07-11T01:36:25Z
He's an asshole.
Johnny Depp tag:vox.com,2006-07-10:asset-6a00b8ea067a57dece00c2251ca6158fdb 2006-07-10T04:01:25Z 2006-07-10T04:01:25Z

is here but i cant see

This is good vs. This is awful tag:vox.com,2006-07-09:asset-6a00b8ea067a57dece00c2251d90098e1d 2006-07-09T05:26:05Z 2006-07-09T16:19:30Z

[this is good] is a great feature and it's funny to see the coincidence with the funniest tag in Japanese social bookmarking site.

See posts tagged これはひどい (this-is-awful) on Hatena Bookmark. Consider it as del.icio.us/tag/thisisawful or something like that. This page lists blog posts and/or news items which are awful, bad, stupid and ridiculous. Especially a good page to start surfing on the net when you're bored.

XML-Atom-0.42/lib/XML/000755 000765 000024 00000000000 13105244427 015147 5ustar00miyagawastaff000000 000000 XML-Atom-0.42/lib/XML/Atom/000755 000765 000024 00000000000 13105244427 016047 5ustar00miyagawastaff000000 000000 XML-Atom-0.42/lib/XML/Atom.pm000644 000765 000024 00000004315 13105244427 016410 0ustar00miyagawastaff000000 000000 # $Id$ package XML::Atom; use strict; use 5.008_001; our $VERSION = '0.42'; BEGIN { @XML::Atom::EXPORT = qw( LIBXML DATETIME); if (eval { require XML::LibXML }) { *{XML::Atom::LIBXML} = sub() {1}; } else { require XML::XPath; *{XML::Atom::LIBXML} = sub() {0}; } if (eval { require DateTime::Format::Atom }) { *{XML::Atom::DATETIME} = sub() {1}; } else { *{XML::Atom::DATETIME} = sub() {0}; } local $^W = 0; *XML::XPath::Function::namespace_uri = sub { my $self = shift; my($node, @params) = @_; my $ns = $node->getNamespace($node->getPrefix); if (!$ns) { $ns = ($node->getNamespaces)[0]; } XML::XPath::Literal->new($ns ? $ns->getExpanded : ''); }; $XML::Atom::ForceUnicode = 0; $XML::Atom::DefaultVersion = 0.3; } sub libxml_parser { ## uses old XML::LibXML < 1.70 interface for compat reasons return XML::LibXML->new( #no_network => 1, # v1.63+ expand_xinclude => 0, expand_entities => 1, load_ext_dtd => 0, ext_ent_handler => sub { warn "External entities disabled."; '' }, ); } sub expat_parser { return XML::Parser->new( Handlers => { ExternEnt => sub { warn "External Entities disabled."; '' }, ExternEntFin => sub {}, }, ); } use base qw( XML::Atom::ErrorHandler Exporter ); package XML::Atom::Namespace; use strict; sub new { my $class = shift; my($prefix, $uri) = @_; bless { prefix => $prefix, uri => $uri }, $class; } sub DESTROY { } use vars qw( $AUTOLOAD ); sub AUTOLOAD { (my $var = $AUTOLOAD) =~ s!.+::!!; no strict 'refs'; ($_[0], $var); } 1; __END__ =head1 NAME XML::Atom - Atom feed and API implementation =head1 SYNOPSIS use XML::Atom; =head1 DESCRIPTION Atom is a syndication, API, and archiving format for weblogs and other data. I implements the feed format as well as a client for the API. =head1 LICENSE I is free software; you may redistribute it and/or modify it under the same terms as Perl itself. =head1 AUTHOR Benjamin Trott, Tatsuhiko Miyagawa =head1 COPYRIGHT All rights reserved. =cut XML-Atom-0.42/lib/XML/Atom/Base.pm000644 000765 000024 00000024015 13105244427 017261 0ustar00miyagawastaff000000 000000 # $Id$ package XML::Atom::Base; use strict; use base qw( XML::Atom::ErrorHandler Class::Data::Inheritable ); use Encode; use XML::Atom; use XML::Atom::Util qw( set_ns first nodelist childlist create_element ); __PACKAGE__->mk_classdata('__attributes', []); sub new { my $class = shift; my $obj = bless {}, $class; $obj->init(@_) or return $class->error($obj->errstr); $obj; } sub init { my $obj = shift; my %param = @_; if (!exists $param{Namespace} and my $ns = $obj->element_ns) { $param{Namespace} = $ns; } $obj->set_ns(\%param); my $elem; unless ($elem = $param{Elem}) { if (LIBXML) { my $doc = XML::LibXML::Document->createDocument('1.0', 'UTF-8'); my $ns = $obj->ns; my ($ns_uri, $ns_prefix); if ( ref $ns and $ns->isa('XML::Atom::Namespace') ) { $ns_uri = $ns->{uri}; $ns_prefix = $ns->{prefix}; } else { $ns_uri = $ns; } if ( $ns_uri and $ns_prefix ) { $elem = $doc->createElement($obj->element_name); $elem->setNamespace( $ns_uri, $ns_prefix, 1 ); } else { $elem = $doc->createElementNS($obj->ns, $obj->element_name); } $doc->setDocumentElement($elem); } else { $elem = XML::XPath::Node::Element->new($obj->element_name); my $ns = XML::XPath::Node::Namespace->new('#default' => $obj->ns); $elem->appendNamespace($ns); } } $obj->{elem} = $elem; $obj; } sub element_name { } sub element_ns { } sub ns { $_[0]->{ns} } sub elem { $_[0]->{elem} } sub version { my $atom = shift; XML::Atom::Util::ns_to_version($atom->ns); } sub content_type { my $atom = shift; if ($atom->version >= 1.0) { return "application/atom+xml"; } else { return "application/x.atom+xml"; } } sub get { my $obj = shift; my($ns, $name) = @_; my @list = $obj->getlist($ns, $name); return $list[0]; } sub getlist { my $obj = shift; my($ns, $name) = @_; my $ns_uri = ref($ns) eq 'XML::Atom::Namespace' ? $ns->{uri} : $ns; my @node = childlist($obj->elem, $ns_uri, $name); return map { my $val = LIBXML ? $_->textContent : $_->string_value; if ($] >= 5.008) { require Encode; Encode::_utf8_off($val) unless $XML::Atom::ForceUnicode; } $val; } @node; } sub add { my $obj = shift; my($ns, $name, $val, $attr) = @_; return $obj->set($ns, $name, $val, $attr, 1); } sub set { my $obj = shift; my($ns, $name, $val, $attr, $add) = @_; my $ns_uri = ref $ns eq 'XML::Atom::Namespace' ? $ns->{uri} : $ns; my @elem = childlist($obj->elem, $ns_uri, $name); if (!$add && @elem) { $obj->elem->removeChild($_) for @elem; } my $elem = create_element($ns, $name); if (UNIVERSAL::isa($val, 'XML::Atom::Base')) { if (LIBXML) { for my $child ($val->elem->childNodes) { $elem->appendChild($child->cloneNode(1)); } for my $attr ($val->elem->attributes) { next unless ref($attr) eq 'XML::LibXML::Attr'; $elem->setAttribute($attr->getName, $attr->getValue); } } else { for my $child ($val->elem->getChildNodes) { $elem->appendChild($child); } for my $attr ($val->elem->getAttributes) { $elem->appendAttribute($attr); } } } elsif (DATETIME && UNIVERSAL::isa($val, "DateTime")) { return $obj->set($ns, $name, DateTime::Format::Atom->format_datetime($val), $attr, $add); } else { if (LIBXML) { $elem->appendChild(XML::LibXML::Text->new($val)); } else { $elem->appendChild(XML::XPath::Node::Text->new($val)); } } $obj->elem->appendChild($elem); if ($attr) { while (my($k, $v) = each %$attr) { $elem->setAttribute($k, $v); } } return $val; } sub get_attr { my $obj = shift; my($attr) = @_; my $val = $obj->elem->getAttribute($attr); if ($] >= 5.008) { require Encode; Encode::_utf8_off($val) unless $XML::Atom::ForceUnicode; } $val; } sub set_attr { my $obj = shift; if (@_ == 2) { my($attr, $val) = @_; $obj->elem->setAttribute($attr => $val); } elsif (@_ == 3) { my($ns, $attr, $val) = @_; my $attribute = "$ns->{prefix}:$attr"; if (LIBXML) { $obj->elem->setAttributeNS($ns->{uri}, $attribute, $val); } else { my $ns = XML::XPath::Node::Namespace->new( $ns->{prefix} => $ns->{uri} ); $obj->elem->appendNamespace($ns); $obj->elem->setAttribute($attribute => $val); } } } sub get_object { my $obj = shift; my($ns, $name, $class) = @_; my $ns_uri = ref($ns) eq 'XML::Atom::Namespace' ? $ns->{uri} : $ns; my @elem = childlist($obj->elem, $ns_uri, $name) or return; my @obj = map { $class->new( Elem => $_, Namespace => $ns ) } @elem; return wantarray ? @obj : $obj[0]; } sub mk_elem_accessors { my $class = shift; my (@list) = @_; my $override_ns; if ( ref $list[-1] ) { my $ns_list = pop @list; if ( ref $ns_list eq 'ARRAY' ) { $ns_list = $ns_list->[0]; } if ( ref($ns_list) =~ /Namespace/ ) { $override_ns = $ns_list; } else { if ( ref $ns_list eq 'HASH' ) { $override_ns = XML::Atom::Namespace->new(%$ns_list); } elsif ( not ref $ns_list and $ns_list ) { $override_ns = $ns_list; } } } no strict 'refs'; for my $elem ( @list ) { (my $meth = $elem) =~ tr/\-/_/; *{"${class}::$meth"} = sub { my $obj = shift; if (@_) { return $obj->set( $override_ns || $obj->ns, $elem, $_[0]); } else { return $obj->get( $override_ns || $obj->ns, $elem); } }; } } sub mk_attr_accessors { my $class = shift; my(@list) = @_; no strict 'refs'; for my $attr (@list) { (my $meth = $attr) =~ tr/\-/_/; *{"${class}::$meth"} = sub { my $obj = shift; if (@_) { return $obj->set_attr($attr => $_[0]); } else { return $obj->get_attr($attr); } }; $class->_add_attribute($attr); } } sub _add_attribute { my($class, $attr) = @_; push @{$class->__attributes}, $attr; } sub attributes { my $class = shift; @{ $class->__attributes }; } sub mk_xml_attr_accessors { my($class, @list) = @_; no strict 'refs'; for my $attr (@list) { (my $meth = $attr) =~ tr/\-/_/; *{"${class}::$meth"} = sub { my $obj = shift; if (LIBXML) { my $elem = $obj->elem; if (@_) { $elem->setAttributeNS('http://www.w3.org/XML/1998/namespace', $attr, $_[0]); } return $elem->getAttribute("xml:$attr"); } else { if (@_) { $obj->elem->setAttribute("xml:$attr", $_[0]); } return $obj->elem->getAttribute("xml:$attr"); } }; } } sub mk_object_accessor { my $class = shift; my($name, $ext_class) = @_; no strict 'refs'; (my $meth = $name) =~ tr/\-/_/; *{"${class}::$meth"} = sub { my $obj = shift; my $ns_uri = $ext_class->element_ns || $obj->ns; if (@_) { return $obj->set($ns_uri, $name, $_[0]); } else { return $obj->get_object($ns_uri, $name, $ext_class); } }; } sub mk_object_list_accessor { my $class = shift; my($name, $ext_class, $moniker) = @_; no strict 'refs'; *{"$class\::$name"} = sub { my $obj = shift; my $ns_uri = $ext_class->element_ns || $obj->ns; if (@_) { # setter: clear existent elements first my @elem = childlist($obj->elem, $ns_uri, $name); for my $el (@elem) { $obj->elem->removeChild($el); } # add the new elements for each my $adder = "add_$name"; for my $add_elem (@_) { $obj->$adder($add_elem); } } else { # getter: just call get_object which is a context aware return $obj->get_object($ns_uri, $name, $ext_class); } }; # moniker returns always list: array ref in a scalar context if ($moniker) { *{"$class\::$moniker"} = sub { my $obj = shift; if (@_) { return $obj->$name(@_); } else { my @obj = $obj->$name; return wantarray ? @obj : \@obj; } }; } # add_$name *{"$class\::add_$name"} = sub { my $obj = shift; my($stuff) = @_; my $ns_uri = $ext_class->element_ns || $obj->ns; my $elem = (ref $stuff && UNIVERSAL::isa($stuff, $ext_class)) ? $stuff->elem : create_element($ns_uri, $name); $obj->elem->appendChild($elem); if (ref($stuff) eq 'HASH') { for my $k ( $ext_class->attributes ) { defined $stuff->{$k} or next; $elem->setAttribute($k, $stuff->{$k}); } } }; } sub as_xml { my $obj = shift; if (LIBXML) { my $doc = XML::LibXML::Document->new('1.0', 'UTF-8'); $doc->setDocumentElement($obj->elem->cloneNode(1)); return $doc->toString(1); } else { return '' . "\n" . $obj->elem->toString; } } sub as_xml_utf8 { my $obj = shift; my $xml = $obj->as_xml; if (utf8::is_utf8($xml)) { return Encode::encode_utf8($xml); } return $xml; } 1; XML-Atom-0.42/lib/XML/Atom/Category.pm000644 000765 000024 00000000444 13105244427 020164 0ustar00miyagawastaff000000 000000 # $Id$ package XML::Atom::Category; use strict; use base qw( XML::Atom::Base ); use XML::Atom; __PACKAGE__->mk_attr_accessors(qw( term scheme label )); sub element_name { 'category' } ## Maintain backwards compatibility with the old Link->set method. sub set { shift->set_attr(@_) } 1; XML-Atom-0.42/lib/XML/Atom/Client.pm000644 000765 000024 00000022555 13105244427 017634 0ustar00miyagawastaff000000 000000 # $Id$ package XML::Atom::Client; use strict; use XML::Atom; use base qw( XML::Atom::ErrorHandler ); use LWP::UserAgent; use XML::Atom::Entry; use XML::Atom::Feed; use XML::Atom::Util qw( first textValue ); use Digest::SHA1 qw( sha1 ); use MIME::Base64 qw( encode_base64 ); use DateTime; use constant NS_SOAP => 'http://schemas.xmlsoap.org/soap/envelope/'; sub new { my $class = shift; my $client = bless { }, $class; $client->init(@_) or return $class->error($client->errstr); $client; } sub init { my $client = shift; my %param = @_; $client->{ua} = LWP::UserAgent::AtomClient->new($client); $client->{ua}->agent('XML::Atom/' . XML::Atom->VERSION); $client->{ua}->parse_head(0); $client; } sub username { my $client = shift; $client->{username} = shift if @_; $client->{username}; } sub password { my $client = shift; $client->{password} = shift if @_; $client->{password}; } sub use_soap { my $client = shift; $client->{use_soap} = shift if @_; $client->{use_soap}; } sub auth_digest { my $client = shift; $client->{auth_digest} = shift if @_; $client->{auth_digest}; } sub getEntry { my $client = shift; my($url) = @_; my $req = HTTP::Request->new(GET => $url); my $res = $client->make_request($req); return $client->error("Error on GET $url: " . $res->status_line) unless $res->code == 200; XML::Atom::Entry->new(Stream => \$res->content); } sub createEntry { my $client = shift; my($uri, $entry) = @_; return $client->error("Must pass a PostURI before posting") unless $uri; my $req = HTTP::Request->new(POST => $uri); $req->content_type($entry->content_type); my $xml = $entry->as_xml; _utf8_off($xml); $req->content_length(length $xml); $req->content($xml); my $res = $client->make_request($req); return $client->error("Error on POST $uri: " . $res->status_line) unless $res->code == 201; $res->header('Location') || 1; } sub updateEntry { my $client = shift; my($url, $entry) = @_; my $req = HTTP::Request->new(PUT => $url); $req->content_type($entry->content_type); my $xml = $entry->as_xml; _utf8_off($xml); $req->content_length(length $xml); $req->content($xml); my $res = $client->make_request($req); return $client->error("Error on PUT $url: " . $res->status_line) unless $res->code == 200; 1; } sub deleteEntry { my $client = shift; my($url) = @_; my $req = HTTP::Request->new(DELETE => $url); my $res = $client->make_request($req); return $client->error("Error on DELETE $url: " . $res->status_line) unless $res->code == 200; 1; } sub getFeed { my $client = shift; my($uri) = @_; return $client->error("Must pass a FeedURI before retrieving feed") unless $uri; my $req = HTTP::Request->new(GET => $uri); my $res = $client->make_request($req); return $client->error("Error on GET $uri: " . $res->status_line) unless $res->code == 200; my $feed = XML::Atom::Feed->new(Stream => \$res->content) or return $client->error(XML::Atom::Feed->errstr); $feed; } sub make_request { my $client = shift; my($req) = @_; $client->munge_request($req); my $res = $client->{ua}->request($req); $client->munge_response($res); $client->{response} = $res; $res; } sub munge_request { my $client = shift; my($req) = @_; $req->header( Accept => 'application/atom+xml, application/x.atom+xml, application/xml, text/xml, */*', ); my $nonce = $client->make_nonce; my $nonce_enc = encode_base64($nonce, ''); my $now = DateTime->now->iso8601 . 'Z'; my $digest = encode_base64(sha1($nonce . $now . ($client->password || '')), ''); if ($client->use_soap) { my $xml = $req->content || ''; $xml =~ s!^(<\?xml.*?\?>)!!; my $method = $req->method; $xml = ($1 || '') . < @{[ $client->username || '' ]} $digest $nonce_enc $now <$method xmlns="http://schemas.xmlsoap.org/wsdl/http/"> $xml SOAP $req->content($xml); $req->content_length(length $xml); $req->header('SOAPAction', 'http://schemas.xmlsoap.org/wsdl/http/' . $method); $req->method('POST'); $req->content_type('text/xml'); } else { if ($client->username) { $req->header('X-WSSE', sprintf qq(UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"), $client->username || '', $digest, $nonce_enc, $now); $req->header('Authorization', 'WSSE profile="UsernameToken"'); } } } sub munge_response { my $client = shift; my($res) = @_; if ($client->use_soap && (my $xml = $res->content)) { my $doc; if (LIBXML) { my $parser = $client->libxml_parser; $doc = $parser->parse_string($xml); } else { my $xp = XML::XPath->new(xml => $xml); $doc = ($xp->find('/')->get_nodelist)[0]; } my $body = first($doc, NS_SOAP, 'Body'); if (my $fault = first($body, NS_SOAP, 'Fault')) { $res->code(textValue($fault, undef, 'faultcode')); $res->message(textValue($fault, undef, 'faultstring')); $res->content(''); $res->content_length(0); } else { $xml = join '', map $_->toString(LIBXML ? 1 : 0), LIBXML ? $body->childNodes : $body->getChildNodes; $res->content($xml); $res->content_length(1); } } } sub make_nonce { sha1(sha1(time() . {} . rand() . $$)) } sub _utf8_off { if ($] >= 5.008) { require Encode; Encode::_utf8_off($_[0]); } } sub libxml_parser { XML::Atom->libxml_parser } package LWP::UserAgent::AtomClient; use strict; use Scalar::Util; use base qw( LWP::UserAgent ); my %ClientOf; sub new { my($class, $client) = @_; my $ua = $class->SUPER::new; $ClientOf{$ua} = $client; Scalar::Util::weaken($ClientOf{$ua}); $ua; } sub get_basic_credentials { my($ua, $realm, $url, $proxy) = @_; my $client = $ClientOf{$ua} or die "Cannot find $ua"; return $client->username, $client->password; } sub DESTROY { my $self = shift; delete $ClientOf{$self}; } 1; __END__ =head1 NAME XML::Atom::Client - A client for the Atom API =head1 SYNOPSIS use XML::Atom::Client; use XML::Atom::Entry; my $api = XML::Atom::Client->new; $api->username('Melody'); $api->password('Nelson'); my $entry = XML::Atom::Entry->new; $entry->title('New Post'); $entry->content('Content of my post.'); my $EditURI = $api->createEntry($PostURI, $entry); my $feed = $api->getFeed($FeedURI); my @entries = $feed->entries; my $entry = $api->getEntry($EditURI); =head1 DESCRIPTION I implements a client for the Atom API described at I, with the authentication scheme described at I. B the API, and particularly the authentication scheme, are still in flux. =head1 USAGE =head2 XML::Atom::Client->new(%param) =head2 $api->use_soap([ 0 | 1 ]) I supports both the REST and SOAP-wrapper versions of the Atom API. By default, the REST version of the API will be used, but you can turn on the SOAP wrapper--for example, if you need to connect to a server that supports only the SOAP wrapper--by calling I with a value of C<1>: $api->use_soap(1); If called without arguments, returns the current value of the flag. =head2 $api->username([ $username ]) If called with an argument, sets the username for login to I<$username>. Returns the current username that will be used when logging in to the Atom server. =head2 $api->password([ $password ]) If called with an argument, sets the password for login to I<$password>. Returns the current password that will be used when logging in to the Atom server. =head2 $api->createEntry($PostURI, $entry) Creates a new entry. I<$entry> must be an I object. =head2 $api->getEntry($EditURI) Retrieves the entry with the given URL I<$EditURI>. Returns an I object. =head2 $api->updateEntry($EditURI, $entry) Updates the entry at URL I<$EditURI> with the entry I<$entry>, which must be an I object. Returns true on success, false otherwise. =head2 $api->deleteEntry($EditURI) Deletes the entry at URL I<$EditURI>. =head2 $api->getFeed($FeedURI) Retrieves the feed at I<$FeedURI>. Returns an I object representing the feed returned from the server. =head2 ERROR HANDLING Methods return C on error, and the error message can be retrieved using the I method. =head1 AUTHOR & COPYRIGHT Please see the I manpage for author, copyright, and license information. =cut XML-Atom-0.42/lib/XML/Atom/Content.pm000644 000765 000024 00000012207 13105244427 020021 0ustar00miyagawastaff000000 000000 # $Id$ package XML::Atom::Content; use strict; use base qw( XML::Atom::Base ); __PACKAGE__->mk_attr_accessors(qw( type mode )); __PACKAGE__->mk_xml_attr_accessors(qw( lang base )); use Encode; use XML::Atom; use MIME::Base64 qw( encode_base64 decode_base64 ); sub element_name { 'content' } sub init { my $content = shift; my %param = @_ == 1 ? (Body => $_[0]) : @_; $content->SUPER::init(%param); if ($param{Body}) { $content->body($param{Body}); } if ($param{Type}) { $content->type($param{Type}); } return $content; } sub body { my $content = shift; my $elem = $content->elem; if (@_) { my $data = shift; if (LIBXML) { $elem->removeChildNodes; } else { $elem->removeChild($_) for $elem->getChildNodes; } if (!_is_printable($data)) { Encode::_utf8_off($data); if (LIBXML) { $elem->appendChild(XML::LibXML::Text->new(encode_base64($data, ''))); } else { $elem->appendChild(XML::XPath::Node::Text->new(encode_base64($data, ''))); } if ($content->version == 0.3) { $content->mode('base64'); } } else { my $copy = '
' . $data . '
'; my $node; eval { if (LIBXML) { my $parser = XML::Atom->libxml_parser; my $tree = $parser->parse_string($copy); $node = $tree->getDocumentElement; } else { my $parser = XML::Atom->expat_parser; my $xp = XML::XPath->new(xml => $copy, parser => $parser); $node = (($xp->find('/')->get_nodelist)[0]->getChildNodes)[0] if $xp; } }; if (!$@ && $node) { $elem->appendChild($node); if ($content->version == 0.3) { $content->mode('xml'); } else { $content->type('xhtml'); } } else { if (LIBXML) { $elem->appendChild(XML::LibXML::Text->new($data)); } else { $elem->appendChild(XML::XPath::Node::Text->new($data)); } if ($content->version == 0.3) { $content->mode('escaped'); } else { $content->type($data =~ /^\s*{__body}) { my $mode; if ($content->version == 0.3) { $mode = $content->mode || 'xml'; } else { $mode = $content->type eq 'xhtml' ? 'xml' : $content->type =~ m![/\+]xml$! ? 'xml' : $content->type eq 'html' ? 'escaped' : $content->type eq 'text' ? 'escaped' : $content->type =~ m!^text/! ? 'escaped' : 'base64'; } if ($mode eq 'xml') { my @children = grep ref($_) =~ /Element/, LIBXML ? $elem->childNodes : $elem->getChildNodes; if (@children) { if (@children == 1 && $children[0]->getLocalName eq 'div') { @children = LIBXML ? $children[0]->childNodes : $children[0]->getChildNodes } $content->{__body} = ''; for my $n (@children) { $content->{__body} .= $n->toString(LIBXML ? 1 : 0); } } else { $content->{__body} = LIBXML ? $elem->textContent : $elem->string_value; } if ($] >= 5.008) { Encode::_utf8_off($content->{__body}) unless $XML::Atom::ForceUnicode; } } elsif ($mode eq 'base64') { my $raw = decode_base64(LIBXML ? $elem->textContent : $elem->string_value); if ($content->type && $content->type =~ m!^text/!) { $content->{__body} = eval { Encode::decode("utf-8", $raw) } || $raw; Encode::_utf8_off($content->{__body}) unless $XML::Atom::ForceUnicode; } else { $content->{__body} = $raw; } } elsif ($mode eq 'escaped') { $content->{__body} = LIBXML ? $elem->textContent : $elem->string_value; } else { $content->{__body} = undef; } } } $content->{__body}; } sub _is_printable { my $data = shift; local $@; # try decoding this $data with UTF-8 my $decoded = ( Encode::is_utf8($data) ? $data : eval { Encode::decode("utf-8", $data, Encode::FB_CROAK) } ); return ! $@ && $decoded =~ /^[\p{IsPrint}\s]*$/; } 1; XML-Atom-0.42/lib/XML/Atom/Entry.pm000644 000765 000024 00000007627 13105244427 017522 0ustar00miyagawastaff000000 000000 # $Id$ package XML::Atom::Entry; use strict; use XML::Atom; use base qw( XML::Atom::Thing ); use MIME::Base64 qw( encode_base64 decode_base64 ); use XML::Atom::Person; use XML::Atom::Content; use XML::Atom::Util qw( first ); sub element_name { 'entry' } sub content { my $entry = shift; if (my @arg = @_) { if (ref($arg[0]) ne 'XML::Atom::Content') { $arg[0] = XML::Atom::Content->new(Body => $arg[0], Version => $entry->version); } $entry->set($entry->ns, 'content', @arg); } else { return $entry->get_object($entry->ns, 'content', 'XML::Atom::Content'); } } __PACKAGE__->mk_elem_accessors(qw( summary )); __PACKAGE__->mk_xml_attr_accessors(qw( lang base )); __PACKAGE__->_rename_elements('issued' => 'published'); __PACKAGE__->_rename_elements('modified' => 'updated'); # OMG 0.3 elements ... to be backward compatible __PACKAGE__->mk_elem_accessors(qw( created )); __PACKAGE__->mk_object_accessor( source => 'XML::Atom::Feed' ); 1; __END__ =head1 NAME XML::Atom::Entry - Atom entry =head1 SYNOPSIS use XML::Atom::Entry; my $entry = XML::Atom::Entry->new; $entry->title('My Post'); $entry->content('The content of my post.'); my $xml = $entry->as_xml; my $dc = XML::Atom::Namespace->new(dc => 'http://purl.org/dc/elements/1.1/'); $entry->set($dc, 'subject', 'Food & Drink'); =head1 USAGE =head2 XML::Atom::Entry->new([ $stream ]) Creates a new entry object, and if I<$stream> is supplied, fills it with the data specified by I<$stream>. Automatically handles autodiscovery if I<$stream> is a URI (see below). Returns the new I object. On failure, returns C. I<$stream> can be any one of the following: =over 4 =item * Reference to a scalar This is treated as the XML body of the entry. =item * Scalar This is treated as the name of a file containing the entry XML. =item * Filehandle This is treated as an open filehandle from which the entry XML can be read. =back =head2 $entry->content([ $content ]) Returns the content of the entry. If I<$content> is given, sets the content of the entry. Automatically handles all necessary escaping. =head2 $entry->author([ $author ]) Returns an I object representing the author of the entry, or C if there is no author information present. If I<$author> is supplied, it should be an I object representing the author. For example: my $author = XML::Atom::Person->new; $author->name('Foo Bar'); $author->email('foo@bar.com'); $entry->author($author); =head2 $entry->link If called in scalar context, returns an I object corresponding to the first IlinkE> tag found in the entry. If called in list context, returns a list of I objects corresponding to all of the IlinkE> tags found in the entry. =head2 $entry->add_link($link) Adds the link I<$link>, which must be an I object, to the entry as a new IlinkE> tag. For example: my $link = XML::Atom::Link->new; $link->type('text/html'); $link->rel('alternate'); $link->href('http://www.example.com/2003/12/post.html'); $entry->add_link($link); =head2 $entry->get($ns, $element) Given an I element I<$ns> and an element name I<$element>, retrieves the value for the element in that namespace. This is useful for retrieving the value of elements not in the main Atom namespace, like categories. For example: my $dc = XML::Atom::Namespace->new(dc => 'http://purl.org/dc/elements/1.1/'); my $subj = $entry->get($dc, 'subject'); =head2 $entry->getlist($ns, $element) Just like I<$entry-Eget>, but if there are multiple instances of the element I<$element> in the namespace I<$ns>, returns all of them. I will return only the first. =head1 AUTHOR & COPYRIGHT Please see the I manpage for author, copyright, and license information. =cut XML-Atom-0.42/lib/XML/Atom/ErrorHandler.pm000644 000765 000024 00000000635 13105244427 021000 0ustar00miyagawastaff000000 000000 # $Id: ErrorHandler.pm,v 1.1 2003/09/08 00:00:50 btrott Exp $ package XML::Atom::ErrorHandler; use strict; use vars qw( $ERROR ); sub new { bless {}, shift } sub error { my $msg = $_[1] || ''; $msg .= "\n" unless $msg =~ /\n$/; if (ref($_[0])) { $_[0]->{_errstr} = $msg; } else { $ERROR = $msg; } return; } sub errstr { ref($_[0]) ? $_[0]->{_errstr} : $ERROR } 1; XML-Atom-0.42/lib/XML/Atom/Feed.pm000644 000765 000024 00000023574 13105244427 017263 0ustar00miyagawastaff000000 000000 # $Id$ package XML::Atom::Feed; use strict; use base qw( XML::Atom::Thing ); use XML::Atom; use XML::Atom::Entry; BEGIN { if (LIBXML) { *entries = \&entries_libxml; *add_entry = \&add_entry_libxml; } else { *entries = \&entries_xpath; *add_entry = \&add_entry_xpath; } } sub init { my $atom = shift; my %param = @_ == 1 ? (Stream => $_[0]) : @_; if (UNIVERSAL::isa($param{Stream}, 'URI')) { my @feeds = __PACKAGE__->find_feeds($param{Stream}); return $atom->error("Can't find Atom file") unless @feeds; my $ua = LWP::UserAgent->new; my $req = HTTP::Request->new(GET => $feeds[0]); my $res = $ua->request($req); if ($res->is_success) { $param{Stream} = \$res->content; } } $atom->SUPER::init(%param); } sub find_feeds { my $class = shift; my($uri) = @_; my $ua = LWP::UserAgent->new; my $req = HTTP::Request->new(GET => $uri); my $res = $ua->request($req); return unless $res->is_success; my @feeds; if ($res->content_type eq 'text/html' || $res->content_type eq 'application/xhtml+xml') { my $base_uri = $uri; my $find_links = sub { my($tag, $attr) = @_; if ($tag eq 'link') { return unless $attr->{rel}; my %rel = map { $_ => 1 } split /\s+/, lc($attr->{rel}); (my $type = lc $attr->{type}) =~ s/^\s*//; $type =~ s/\s*$//; push @feeds, URI->new_abs($attr->{href}, $base_uri)->as_string if $rel{alternate} && $type eq 'application/atom+xml'; } elsif ($tag eq 'base') { $base_uri = $attr->{href}; } }; require HTML::Parser; my $p = HTML::Parser->new(api_version => 3, start_h => [ $find_links, "tagname, attr" ]); $p->parse($res->content); } else { @feeds = ($uri); } @feeds; } sub element_name { 'feed' } *language = \⟨ # legacy sub version { my $feed = shift; my $elem = $feed->elem; if (@_) { $elem->setAttribute('version', $_[0]); } $elem->getAttribute('version') || $feed->SUPER::version(@_); } sub entries_libxml { my $feed = shift; my @res = $feed->elem->getElementsByTagNameNS($feed->ns, 'entry') or return; my @entries; for my $res (@res) { my $entry = XML::Atom::Entry->new(Elem => $res->cloneNode(1)); push @entries, $entry; } @entries; } sub entries_xpath { my $feed = shift; my $set = $feed->elem->find("descendant-or-self::*[local-name()='entry' and namespace-uri()='" . $feed->ns . "']"); my @entries; for my $elem ($set->get_nodelist) { ## Delete the link to the parent (feed) element, and append ## the default Atom namespace. $elem->del_parent_link; my $ns = XML::XPath::Node::Namespace->new('#default' => $feed->ns); $elem->appendNamespace($ns); my $entry = XML::Atom::Entry->new(Elem => $elem); push @entries, $entry; } @entries; } sub add_entry_libxml { my $feed = shift; my($entry, $opt) = @_; $opt ||= {}; # When doing an insert, we try to insert before the first so # that we don't screw up any preamble. If there are no existing # 's, then fall back to appending, which should be # semantically identical. my ($first_entry) = $feed->elem->getChildrenByTagNameNS($entry->ns, 'entry'); if ($opt->{mode} && $opt->{mode} eq 'insert' && $first_entry) { $feed->elem->insertBefore($entry->elem, $first_entry); } else { $feed->elem->appendChild($entry->elem); } } sub add_entry_xpath { my $feed = shift; my($entry, $opt) = @_; $opt ||= {}; my $set = $feed->elem->find("*[local-name()='entry' and namespace-uri()='" . $entry->ns . "']"); my $first_entry = $set ? ($set->get_nodelist)[0] : undef; if ($opt->{mode} && $opt->{mode} eq 'insert' && $first_entry) { $feed->elem->insertBefore($entry->elem, $first_entry); } else { $feed->elem->appendChild($entry->elem); } } __PACKAGE__->mk_elem_accessors(qw( generator )); __PACKAGE__->mk_xml_attr_accessors(qw( lang base )); __PACKAGE__->_rename_elements('modified' => 'updated'); __PACKAGE__->_rename_elements('tagline' => 'subtitle'); 1; __END__ =head1 NAME XML::Atom::Feed - Atom feed =head1 SYNOPSIS use XML::Atom::Feed; use XML::Atom::Entry; my $feed = XML::Atom::Feed->new; $feed->title('My Weblog'); $feed->id('tag:example.com,2006:feed-id'); my $entry = XML::Atom::Entry->new; $entry->title('First Post'); $entry->id('tag:example.com,2006:entry-id'); $entry->content('Post Body'); $feed->add_entry($entry); $feed->add_entry($entry, { mode => 'insert' }); my @entries = $feed->entries; my $xml = $feed->as_xml; ## Get a list of the tags in the feed. my $links = $feed->link; ## Find all of the Atom feeds on a given page, using auto-discovery. my @uris = XML::Atom::Feed->find_feeds('http://www.example.com/'); ## Use auto-discovery to load the first Atom feed on a given page. my $feed = XML::Atom::Feed->new(URI->new('http://www.example.com/')); =head1 USAGE =head2 XML::Atom::Feed->new([ $stream ]) Creates a new feed object, and if I<$stream> is supplied, fills it with the data specified by I<$stream>. Automatically handles autodiscovery if I<$stream> is a URI (see below). Returns the new I object. On failure, returns C. I<$stream> can be any one of the following: =over 4 =item * Reference to a scalar This is treated as the XML body of the feed. =item * Scalar This is treated as the name of a file containing the feed XML. =item * Filehandle This is treated as an open filehandle from which the feed XML can be read. =item * URI object This is treated as a URI, and the feed XML will be retrieved from the URI. If the content type returned from fetching the content at URI is I, this method will automatically try to perform auto-discovery by looking for a IlinkE> tag describing the feed URL. If such a URL is found, the feed XML will be automatically retrieved. If the URI is already of a feed, no auto-discovery is necessary, and the feed XML will be retrieved and parsed as normal. =back =head2 XML::Atom::Feed->find_feeds($uri) Given a URI I<$uri>, use auto-discovery to find all of the Atom feeds linked from that page (using IlinkE> tags). Returns a list of feed URIs. =head2 $feed->link If called in scalar context, returns an I object corresponding to the first IlinkE> tag found in the feed. If called in list context, returns a list of I objects corresponding to all of the IlinkE> tags found in the feed. =head2 $feed->add_link($link) Adds the link I<$link>, which must be an I object, to the feed as a new IlinkE> tag. For example: my $link = XML::Atom::Link->new; $link->type('text/html'); $link->rel('alternate'); $link->href('http://www.example.com/'); $feed->add_link($link); =head2 $feed->add_entry($entry) Adds the entry I<$entry>, which must be an I object, to the feed. If you want to add an entry before existent entries, you can pass optional hash reference containing C value set to C. $feed->add_entry($entry, { mode => 'insert' }); =head2 $feed->entries Returns list of XML::Atom::Entry objects contained in the feed. =head2 $feed->language Returns the language of the feed, from I. =head2 $feed->author([ $author ]) Returns an I object representing the author of the entry, or C if there is no author information present. If I<$author> is supplied, it should be an I object representing the author. For example: my $author = XML::Atom::Person->new; $author->name('Foo Bar'); $author->email('foo@bar.com'); $feed->author($author); =head2 $feed->id([ $id ]) Returns an id for the feed. If I<$id> is supplied, set the id. When generating the new feed, it is your responsibility to generate unique ID for the feed and set to XML::Atom::Feed object. You can use I permalink, I URI scheme or I for handy. =head1 UNICODE FLAGS By default, XML::Atom takes off all the Unicode flag from the feed content. For example, my $title = $feed->title; the variable C<$title> contains UTF-8 bytes without Unicode flag set, even if the feed title contains some multibyte characters. If you don't like this behaviour and wants to handle everything as Unicode characters (rather than UTF-8 bytes), set C<$XML::Atom::ForceUnicode> flag to 1. $XML::Atom::ForceUnicode = 1; then all the data returned from XML::Atom::Feed object and XML::Atom::Entry object etc., will have Unicode flag set. The only exception will be C<< $entry->content->body >>, if content type is not text/* (e.g. image/gif). In that case, the content body is still binary data, without Unicode flag set. =head1 CREATING ATOM 1.0 FEEDS By default, XML::Atom::Feed and other classes (Entry, Link and Content) will create entities using Atom 0.3 namespaces. In order to create 1.0 feed and entry elements, you can set I as a parameter, like: $feed = XML::Atom::Feed->new(Version => 1.0); $entry = XML::Atom::Entry->new(Version => 1.0); Setting those Version to every element would be sometimes painful. In that case, you can override the default version number by setting C<$XML::Atom::DefaultVersion> global variable to "1.0". use XML::Atom; $XML::Atom::DefaultVersion = "1.0"; my $feed = XML::Atom::Feed->new; $feed->title("blah"); my $entry = XML::Atom::Entry->new; $feed->add_entry($entry); $feed->version; # 1.0 =head1 AUTHOR & COPYRIGHT Please see the I manpage for author, copyright, and license information. =cut XML-Atom-0.42/lib/XML/Atom/Link.pm000644 000765 000024 00000000456 13105244427 017307 0ustar00miyagawastaff000000 000000 # $Id$ package XML::Atom::Link; use strict; use base qw( XML::Atom::Base ); use XML::Atom; __PACKAGE__->mk_attr_accessors(qw( rel href hreflang title type length )); sub element_name { 'link' } ## Maintain backwards compatibility with the old Link->set method. sub set { shift->set_attr(@_) } 1; XML-Atom-0.42/lib/XML/Atom/Person.pm000644 000765 000024 00000001616 13105244427 017657 0ustar00miyagawastaff000000 000000 # $Id$ package XML::Atom::Person; use strict; use base qw( XML::Atom::Base ); use XML::Atom; use XML::Atom::Feed; use XML::Atom::Entry; __PACKAGE__->mk_elem_accessors(qw( email name uri url homepage )); for my $class (qw( XML::Atom::Feed XML::Atom::Entry )) { $class->mk_object_accessor( author => __PACKAGE__ ); $class->mk_object_accessor( contributor => __PACKAGE__ ); } sub element_name { 'author' } 1; __END__ =head1 NAME XML::Atom::Person - Author or contributor object =head1 SYNOPSIS my $person = XML::Atom::Person->new; $person->email('foo@example.com'); $person->name('Foo Bar'); $entry->author($person); =head1 DESCRIPTION I represents an author or contributor element in an Atom feed or entry. =head1 USAGE =head2 XML::Atom::Person->new =head2 $person->email([ $email ]) =head2 $person->name([ $name ]) =head2 $person->uri([ $uri ]) =cut XML-Atom-0.42/lib/XML/Atom/Server.pm000644 000765 000024 00000035060 13105244427 017657 0ustar00miyagawastaff000000 000000 # $Id$ package XML::Atom::Server; use strict; use XML::Atom; use base qw( XML::Atom::ErrorHandler ); use MIME::Base64 qw( encode_base64 decode_base64 ); use Digest::SHA1 qw( sha1 ); use XML::Atom::Util qw( first encode_xml textValue ); use XML::Atom::Entry; use constant NS_SOAP => 'http://schemas.xmlsoap.org/soap/envelope/'; use constant NS_WSSE => 'http://schemas.xmlsoap.org/ws/2002/07/secext'; use constant NS_WSU => 'http://schemas.xmlsoap.org/ws/2002/07/utility'; sub handler ($$) { my $class = shift; my($r) = @_; require Apache::Constants; if (lc($r->dir_config('Filter') || '') eq 'on') { $r = $r->filter_register; } my $server = $class->new or die $class->errstr; $server->{apache} = $r; $server->run; return Apache::Constants::OK(); } sub new { my $class = shift; my $server = bless { }, $class; $server->init(@_) or return $class->error($server->errstr); $server; } sub init { my $server = shift; $server->{param} = {}; unless ($ENV{MOD_PERL}) { require CGI; $server->{cgi} = CGI->new({}); } $server; } sub run { my $server = shift; (my $pi = $server->path_info) =~ s!^/!!; my @args = split /\//, $pi; for my $arg (@args) { my($k, $v) = split /=/, $arg, 2; $server->request_param($k, $v); } if (my $action = $server->request_header('SOAPAction')) { $server->{is_soap} = 1; $action =~ s/"//g; my($method) = $action =~ m!/([^/]+)$!; $server->request_method($method); } my $out; eval { defined($out = $server->handle_request) or die $server->errstr; if (defined $out && $server->{is_soap}) { $out =~ s!^(<\?xml.*?\?>)!!; $out = < $out SOAP } }; if ($@) { $out = $server->show_error($@); } $server->send_http_header; $server->print($out); 1; } sub handle_request; sub password_for_user; sub uri { my $server = shift; $ENV{MOD_PERL} ? $server->{apache}->uri : $server->{cgi}->url; } sub path_info { my $server = shift; return $server->{__path_info} if exists $server->{__path_info}; my $path_info; if ($ENV{MOD_PERL}) { ## mod_perl often leaves part of the script name (Location) ## in the path info, for some reason. This should remove it. $path_info = $server->{apache}->path_info; if ($path_info) { my($script_last) = $server->{apache}->location =~ m!/([^/]+)$!; $path_info =~ s!^/$script_last!!; } } else { $path_info = $server->{cgi}->path_info; } $server->{__path_info} = $path_info; } sub request_header { my $server = shift; my($key) = @_; if ($ENV{MOD_PERL}) { return $server->{apache}->header_in($key); } else { ($key = uc($key)) =~ tr/-/_/; return $ENV{'HTTP_' . $key}; } } sub request_method { my $server = shift; if (@_) { $server->{request_method} = shift; } elsif (!exists $server->{request_method}) { $server->{request_method} = $ENV{MOD_PERL} ? $server->{apache}->method : $ENV{REQUEST_METHOD}; } $server->{request_method}; } sub request_content { my $server = shift; unless (exists $server->{request_content}) { if ($ENV{MOD_PERL}) { ## Read from $server->{apache} my $r = $server->{apache}; my $len = $server->request_header('Content-length'); $r->read($server->{request_content}, $len); } else { ## Read from STDIN my $len = $ENV{CONTENT_LENGTH} || 0; read STDIN, $server->{request_content}, $len; } } $server->{request_content}; } sub request_param { my $server = shift; my $k = shift; $server->{param}{$k} = shift if @_; $server->{param}{$k}; } sub response_header { my $server = shift; my($key, $val) = @_; if ($ENV{MOD_PERL}) { $server->{apache}->header_out($key, $val); } else { unless ($key =~ /^-/) { ($key = lc($key)) =~ tr/-/_/; $key = '-' . $key; } $server->{cgi_headers}{$key} = $val; } } sub response_code { my $server = shift; $server->{response_code} = shift if @_; $server->{response_code}; } sub response_content_type { my $server = shift; $server->{response_content_type} = shift if @_; $server->{response_content_type}; } sub send_http_header { my $server = shift; my $type = $server->response_content_type || 'application/x.atom+xml'; if ($ENV{MOD_PERL}) { $server->{apache}->status($server->response_code || 200); $server->{apache}->send_http_header($type); } else { $server->{cgi_headers}{-status} = $server->response_code || 200; $server->{cgi_headers}{-type} = $type; print $server->{cgi}->header(%{ $server->{cgi_headers} }); } } sub print { my $server = shift; if ($ENV{MOD_PERL}) { $server->{apache}->print(@_); } else { CORE::print(@_); } } sub error { my $server = shift; my($code, $msg) = @_; $server->response_code($code) if ref($server); return $server->SUPER::error($msg); } sub show_error { my $server = shift; my($err) = @_; chomp($err = encode_xml($err)); if ($server->{is_soap}) { my $code = $server->response_code; if ($code >= 400) { $server->response_code(500); } return < $code $err FAULT } else { return < $err ERR } } sub get_auth_info { my $server = shift; my %param; if ($server->{is_soap}) { my $xml = $server->xml_body; my $auth = first($xml, NS_WSSE, 'UsernameToken'); $param{Username} = textValue($auth, NS_WSSE, 'Username'); $param{PasswordDigest} = textValue($auth, NS_WSSE, 'Password'); $param{Nonce} = textValue($auth, NS_WSSE, 'Nonce'); $param{Created} = textValue($auth, NS_WSSE, 'Created'); } else { my $req = $server->request_header('X-WSSE') or return $server->auth_failure(401, 'X-WSSE authentication required'); $req =~ s/^(?:WSSE|UsernameToken) //; for my $i (split /,\s*/, $req) { my($k, $v) = split /=/, $i, 2; $v =~ s/^"//; $v =~ s/"$//; $param{$k} = $v; } } \%param; } sub authenticate { my $server = shift; my $auth = $server->get_auth_info or return; for my $f (qw( Username PasswordDigest Nonce Created )) { return $server->auth_failure(400, "X-WSSE requires $f") unless $auth->{$f}; } my $password = $server->password_for_user($auth->{Username}); defined($password) or return $server->auth_failure(403, 'Invalid login'); my $expected = encode_base64(sha1( decode_base64($auth->{Nonce}) . $auth->{Created} . $password ), ''); return $server->auth_failure(403, 'Invalid login') unless $expected eq $auth->{PasswordDigest}; return 1; } sub auth_failure { my $server = shift; $server->response_header('WWW-Authenticate', 'WSSE profile="UsernameToken"'); return $server->error(@_); } sub xml_body { my $server = shift; unless (exists $server->{xml_body}) { if (LIBXML) { my $parser = $server->libxml_parser; $server->{xml_body} = $parser->parse_string($server->request_content); } else { $server->{xml_body} = XML::XPath->new(xml => $server->request_content); } } $server->{xml_body}; } sub atom_body { my $server = shift; my $atom; if ($server->{is_soap}) { my $xml = $server->xml_body; $atom = XML::Atom::Entry->new(Doc => first($xml, NS_SOAP, 'Body')) or return $server->error(500, XML::Atom::Entry->errstr); } else { $atom = XML::Atom::Entry->new(Stream => \$server->request_content) or return $server->error(500, XML::Atom::Entry->errstr); } $atom; } sub libxml_parser { XML::Atom->libxml_parser } 1; __END__ =head1 NAME XML::Atom::Server - A server for the Atom API =head1 SYNOPSIS package My::Server; use base qw( XML::Atom::Server ); sub handle_request { my $server = shift; $server->authenticate or return; my $method = $server->request_method; if ($method eq 'POST') { return $server->new_post; } ... } my %Passwords; sub password_for_user { my $server = shift; my($username) = @_; $Passwords{$username}; } sub new_post { my $server = shift; my $entry = $server->atom_body or return; ## $entry is an XML::Atom::Entry object. ## ... Save the new entry ... } package main; my $server = My::Server->new; $server->run; =head1 DESCRIPTION I provides a base class for Atom API servers. It handles all core server processing, both the SOAP and REST formats of the protocol, and WSSE authentication. It can also run as either a mod_perl handler or as part of a CGI program. It does not provide functions specific to any particular implementation, such as posting an entry, retrieving a list of entries, deleting an entry, etc. Implementations should subclass I, overriding the I method, and handle all functions such as this themselves. =head1 SUBCLASSING =head2 Request Handling Subclasses of I must override the I method to perform all request processing. The implementation must set all response headers, including the response code and any relevant HTTP headers, and should return a scalar representing the response body to be sent back to the client. For example: sub handle_request { my $server = shift; my $method = $server->request_method; if ($method eq 'POST') { return $server->new_post; } ## ... handle GET, PUT, etc } sub new_post { my $server = shift; my $entry = $server->atom_body or return; my $id = save_this_entry($entry); ## Implementation-specific $server->response_header(Location => $server->uri . '/entry_id=' . $id); $server->response_code(201); $server->response_content_type('application/x.atom+xml'); return serialize_entry($entry); ## Implementation-specific } =head2 Authentication Servers that require authentication for posting or retrieving entries or feeds should override the I method. Given a username (from the WSSE header), I should return that user's password in plaintext. This will then be combined with the nonce and the creation time to generate the digest, which will be compared with the digest sent in the WSSE header. If the supplied username doesn't exist in your user database or alike, just return C. For example: my %Passwords = ( foo => 'bar' ); ## The password for "foo" is "bar". sub password_for_user { my $server = shift; my($username) = @_; $Passwords{$username}; } =head1 METHODS I provides a variety of methods to be used by subclasses for retrieving headers, content, and other request information, and for setting the same on the response. =head2 Client Request Parameters =over 4 =item * $server->uri Returns the URI of the Atom server implementation. =item * $server->request_method Returns the name of the request method sent to the server from the client (for example, C, C, etc). Note that if the client sent the request in a SOAP envelope, the method is obtained from the I HTTP header. =item * $server->request_header($header) Retrieves the value of the HTTP request header I<$header>. =item * $server->request_content Returns a scalar containing the contents of a POST or PUT request from the client. =item * $server->request_param($param) I automatically parses the PATH_INFO sent in the request and breaks it up into key-value pairs. This can be used to pass parameters. For example, in the URI http://localhost/atom-server/entry_id=1 the I parameter would be set to C<1>. I returns the value of the value of the parameter I<$param>. =back =head2 Setting up the Response =over 4 =item * $server->response_header($header, $value) Sets the value of the HTTP response header I<$header> to I<$value>. =item * $server->response_code([ $code ]) Returns the current response code to be sent back to the client, and if I<$code> is given, sets the response code. =item * $server->response_content_type([ $type ]) Returns the current I header to be sent back to the client, and I<$type> is given, sets the value for that header. =back =head2 Processing the Request =over 4 =item * $server->authenticate Attempts to authenticate the request based on the authentication information present in the request (currently just WSSE). This will call the I method in the subclass to obtain the cleartext password for the username given in the request. =item * $server->atom_body Returns an I object containing the entry sent in the request. =back =head1 USAGE Once you have defined your server subclass, you can set it up either as a CGI program or as a mod_perl handler. A simple CGI program would look something like this: #!/usr/bin/perl -w use strict; use My::Server; my $server = My::Server->new; $server->run; A simple mod_perl handler configuration would look something like this: PerlModule My::Server SetHandler perl-script PerlHandler My::Server =head1 ERROR HANDLING If you wish to return an error from I, you can use the built-in I method: sub handle_request { my $server = shift; ... return $server->error(500, "Something went wrong"); } This will be returned to the client with a response code of 500 and an error string of C. Errors are automatically serialized into SOAP faults if the incoming request is enclosed in a SOAP envelope. =head1 AUTHOR & COPYRIGHT Please see the I manpage for author, copyright, and license information. =cut XML-Atom-0.42/lib/XML/Atom/Thing.pm000644 000765 000024 00000007140 13105244427 017460 0ustar00miyagawastaff000000 000000 # $Id$ package XML::Atom::Thing; use strict; use base qw( XML::Atom::Base ); use XML::Atom; use base qw( XML::Atom::ErrorHandler ); use XML::Atom::Util qw( first nodelist childlist create_element ); use XML::Atom::Category; use XML::Atom::Link; use LWP::UserAgent; BEGIN { if (LIBXML) { *init = \&init_libxml; } else { *init = \&init_xpath; } } sub init_libxml { my $atom = shift; my %param = @_ == 1 ? (Stream => $_[0]) : @_; if (my $stream = delete $param{Stream}) { my $parser = delete $param{Parser} || XML::Atom->libxml_parser; my $doc; if (ref($stream) eq 'SCALAR') { $doc = $parser->parse_string($$stream); } elsif (ref($stream)) { $doc = $parser->parse_fh($stream); } else { $doc = $parser->parse_file($stream); } $param{Elem} = $doc->getDocumentElement; } elsif (my $doc = delete $param{Doc}) { $param{Elem} = $doc->getDocumentElement; } $atom->SUPER::init(%param); $atom->fixup_ns; return $atom; } sub fixup_ns { my $obj = shift; $obj->{ns} = $obj->elem->namespaceURI; } sub init_xpath { my $atom = shift; my %param = @_ == 1 ? (Stream => $_[0]) : @_; my $elem_name = $atom->element_name; if (my $stream = delete $param{Stream}) { my $parser = delete $param{Parser} || XML::Atom->expat_parser; my $xp; if (ref($stream) eq 'SCALAR') { $xp = XML::XPath->new(xml => $$stream, parser => $parser); } elsif (ref($stream)) { $xp = XML::XPath->new(ioref => $stream, parser => $parser); } else { $xp = XML::XPath->new(filename => $stream, parser => $parser); } my $set = $xp->find('/' . $elem_name); unless ($set && $set->size) { $set = $xp->find('/'); } $param{Elem} = ($set->get_nodelist)[0]; } elsif (my $doc = delete $param{Doc}) { $param{Elem} = $doc; } elsif (my $elem = $param{Elem}) { my $xp = XML::XPath->new(context => $elem); my $set = $xp->find('/' . $elem_name); unless ($set && $set->size) { $set = $xp->find('/'); } $param{Elem} = ($set->get_nodelist)[0]; } $atom->SUPER::init(%param); $atom; } sub set { my $atom = shift; my($ns, $name, $val, $attr, $add) = @_; if (ref($val) =~ /Element$/) { $atom->elem->appendChild($val); return $val; } else { return $atom->SUPER::set(@_); } } # common elements __PACKAGE__->mk_elem_accessors(qw( icon id logo title )); # updated & rights are in renamed # common multiple elements __PACKAGE__->mk_object_list_accessor('link' => 'XML::Atom::Link', 'links'); __PACKAGE__->mk_object_list_accessor('category' => 'XML::Atom::Category', 'categories'); __PACKAGE__->mk_object_list_accessor('author' => 'XML::Atom::Person', 'authors'); __PACKAGE__->mk_object_list_accessor('contributor' => 'XML::Atom::Person', 'contributors'); __PACKAGE__->_rename_elements('copyright' => 'rights'); # 0.3 -> 1.0 elements aliasing sub _rename_elements { my($class, $atom03, $atom10) = @_; no strict 'refs'; *{"$class\::$atom03"} = sub { my $self = shift; if ($self->version eq "1.0") { return $self->$atom10(@_); } @_ > 0 ? $self->set($self->ns, $atom03, @_) : $self->get($self->ns, $atom03); }; *{"$class\::$atom10"} = sub { my $self = shift; if ($self->version eq "0.3") { return $self->$atom03(@_); } @_ > 0 ? $self->set($self->ns, $atom10, @_) : $self->get($self->ns, $atom10); }; } 1; XML-Atom-0.42/lib/XML/Atom/Util.pm000644 000765 000024 00000007676 13105244427 017342 0ustar00miyagawastaff000000 000000 # $Id$ package XML::Atom::Util; use strict; use XML::Atom; use vars qw( @EXPORT_OK @ISA ); use Encode; use Exporter; @EXPORT_OK = qw( set_ns first nodelist childlist textValue iso2dt encode_xml create_element ); @ISA = qw( Exporter ); our %NS_MAP = ( '0.3' => 'http://purl.org/atom/ns#', '1.0' => 'http://www.w3.org/2005/Atom', ); our %NS_VERSION = reverse %NS_MAP; sub set_ns { my $thing = shift; my($param) = @_; if (my $ns = delete $param->{Namespace}) { $thing->{ns} = $ns; $thing->{version} = $NS_VERSION{$ns}; } else { my $version = delete $param->{Version} || $XML::Atom::DefaultVersion; $version = '1.0' if $version == 1; my $ns = $NS_MAP{$version} or $thing->error("Unknown version: $version"); $thing->{ns} = $ns; $thing->{version} = $version; } } sub ns_to_version { my $ns = shift; $NS_VERSION{$ns}; } sub first { my @nodes = nodelist(@_); return unless @nodes; return $nodes[0]; } sub nodelist { if (LIBXML) { return $_[1] ? $_[0]->getElementsByTagNameNS($_[1], $_[2]) : $_[0]->getElementsByTagName($_[2]); } else { my $set = $_[1] ? $_[0]->find("descendant::*[local-name()='$_[2]' and namespace-uri()='$_[1]']") : $_[0]->find("descendant::$_[2]"); return unless $set && $set->isa('XML::XPath::NodeSet'); return $set->get_nodelist; } } sub childlist { if (LIBXML) { return $_[1] ? $_[0]->getChildrenByTagNameNS($_[1], $_[2]) : $_[0]->getChildrenByTagName($_[2]); } else { my $set = $_[1] ? $_[0]->find("*[local-name()='$_[2]' and namespace-uri()='$_[1]']") : $_[0]->find($_[2]); return unless $set && $set->isa('XML::XPath::NodeSet'); return $set->get_nodelist; } } sub textValue { my $node = first(@_) or return; LIBXML ? $node->textContent : $node->string_value; } sub iso2dt { my($iso) = @_; return unless $iso =~ /^(\d{4})(?:-?(\d{2})(?:-?(\d\d?)(?:T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(?:Z|([+-]\d{2}:\d{2}))?)?)?)?/; my($y, $mo, $d, $h, $m, $s, $zone) = ($1, $2 || 1, $3 || 1, $4 || 0, $5 || 0, $6 || 0, $7); require DateTime; my $dt = DateTime->new( year => $y, month => $mo, day => $d, hour => $h, minute => $m, second => $s, time_zone => 'UTC', ); if ($zone && $zone ne 'Z') { my $seconds = DateTime::TimeZone::offset_as_seconds($zone); $dt->subtract(seconds => $seconds); } $dt; } my %Map = ('&' => '&', '"' => '"', '<' => '<', '>' => '>', '\'' => '''); my $RE = join '|', keys %Map; sub encode_xml { my($str) = @_; $str =~ s!($RE)!$Map{$1}!g; $str; } sub create_element { my($ns, $name) = @_; my($ns_uri, $ns_prefix); if (ref $ns eq 'XML::Atom::Namespace') { $ns_uri = $ns->{uri}; $ns_prefix = $ns->{prefix}; } else { $ns_uri = $ns; } my $elem; if (LIBXML) { $elem = XML::LibXML::Element->new($name); $elem->setNamespace($ns_uri, $ns_prefix ? $ns_prefix : ()); } else { $ns_prefix ||= '#default'; $elem = XML::XPath::Node::Element->new($name); my $ns = XML::XPath::Node::Namespace->new($ns_prefix => $ns_uri); $elem->appendNamespace($ns); } return $elem; } 1; __END__ =head1 NAME XML::Atom::Util - Utility functions =head1 SYNOPSIS use XML::Atom::Util qw( iso2dt ); my $dt = iso2dt($entry->issued); =head1 USAGE =head2 iso2dt($iso) Transforms the ISO-8601 date I<$iso> into a I object and returns the I object. =head2 encode_xml($str) Encodes characters with special meaning in XML into entities and returns the encoded string. =head1 AUTHOR & COPYRIGHT Please see the I manpage for author, copyright, and license information. =cut