From: Andrea Zagli Date: Sat, 6 Jan 2007 14:42:33 +0000 (+0000) Subject: Initial import. X-Git-Url: https://saetta.ns0.it/gitweb?a=commitdiff_plain;h=1d37506a9eb1b824465f450d18cfc31dad0828be;p=libgfeed Initial import. git-svn-id: http://saetta.homelinux.org/svn/libgfeed/trunk@1 766e3509-7fc5-439a-ae96-336fe19d476f --- 1d37506a9eb1b824465f450d18cfc31dad0828be diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..948556f --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Andrea Zagli diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..5ab7695 --- /dev/null +++ b/COPYING @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser 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 Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +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 + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. 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 LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. 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) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; 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. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..b93368d --- /dev/null +++ b/ChangeLog @@ -0,0 +1,28 @@ +2006-09-05 Andrea Zagli + + * rss.c: + * rss.h: added rss_new_from_buffer() + * test/Makefile.am: + * test/test_rss_load_buffer: new test + +2006-09-03 Andrea Zagli + + * src/Makefile.am: changed $(includedir) + * libgfeed.pc.in: changed Cflags + * atom.c: + * atom.h: added atom_new_from_buffer() + * test/Makefile.am: + * test/test_atom_load_buffer: new test + +2006-08-23 Andrea Zagli + + * changed license headers on source code from GPL to LGPL + * COPYING now is the LGLP's text + +2006-06-10 Andrea Zagli + + * added more api documentation + +2006-05-18 Andrea Zagli + + * added support for Atom file v1.0 based on http://www.ietf.org/rfc/rfc4287.txt diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..4c0b500 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,7 @@ +SUBDIRS = src test docs + +EXTRA_DIST = libgfeed.pc.in + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libgfeed.pc + diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/README b/README new file mode 100644 index 0000000..e69de29 diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..8622f26 --- /dev/null +++ b/config.h.in @@ -0,0 +1,71 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#undef HAVE_MALLOC + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strftime' function. */ +#undef HAVE_STRFTIME + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if your declares `struct tm'. */ +#undef TM_IN_SYS_TIME + +/* Version number of package */ +#undef VERSION + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to rpl_malloc if the replacement function should be used. */ +#undef malloc diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..7d51124 --- /dev/null +++ b/configure.ac @@ -0,0 +1,52 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.59) +AC_INIT([libgfeed], [0.1.1], [azagli@inwind.it]) +AC_CONFIG_SRCDIR([src/rss.c]) +AC_CONFIG_HEADER([config.h]) + +AM_INIT_AUTOMAKE +AM_MAINTAINER_MODE +AC_LIBTOOL_WIN32_DLL + +AC_CANONICAL_SYSTEM + +# Checks for programs. +AC_PROG_CC +AC_PROG_CXX +AC_PROG_CPP +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_PROG_LIBTOOL +GTK_DOC_CHECK + +# Checks for libraries. +PKG_CHECK_MODULES([GFEED], [glib-2.0 >= 2.6.0 + gobject-2.0 >= 2.6.0 + libxml-2.0 >= 2.6.0]) + +AC_SUBST(GFEED_CFLAGS) +AC_SUBST(GFEED_LIBS) + +# Checks for header files. + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_STRUCT_TM + +# Checks for library functions. +AC_FUNC_MALLOC +AC_FUNC_STRFTIME + +AC_CONFIG_FILES([ + libgfeed.pc + Makefile + src/Makefile + test/Makefile + docs/Makefile + docs/reference/Makefile + docs/reference/version.xml +]) +AC_OUTPUT diff --git a/docs/Makefile.am b/docs/Makefile.am new file mode 100644 index 0000000..f3ddc22 --- /dev/null +++ b/docs/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = reference diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am new file mode 100644 index 0000000..09f8c12 --- /dev/null +++ b/docs/reference/Makefile.am @@ -0,0 +1,78 @@ +## Process this file with automake to produce Makefile.in + +# We require automake 1.6 at least. +AUTOMAKE_OPTIONS = 1.6 + +# This is a blank Makefile.am for using gtk-doc. +# Copy this to your project's API docs directory and modify the variables to +# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples +# of using the various options. + +# The name of the module, e.g. 'glib'. +DOC_MODULE = libgfeed + +# The top-level SGML file. You can change this if you want to. +DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml + +# The directory containing the source code. Relative to $(srcdir). +# gtk-doc will search all .c & .h files beneath here for inline comments +# documenting the functions and macros. +# e.g. DOC_SOURCE_DIR=../../../gtk +DOC_SOURCE_DIR = ../../src + +# Extra options to pass to gtkdoc-scangobj. Not normally needed. +SCANGOBJ_OPTIONS= + +# Extra options to supply to gtkdoc-scan. +# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" +SCAN_OPTIONS= + +# Extra options to supply to gtkdoc-mkdb. +# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml +MKDB_OPTIONS=--sgml-mode --output-format=xml + +# Extra options to supply to gtkdoc-mktmpl +# e.g. MKTMPL_OPTIONS=--only-section-tmpl +MKTMPL_OPTIONS= + +# Extra options to supply to gtkdoc-fixref. Not normally needed. +# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html +FIXXREF_OPTIONS= + +# Used for dependencies. The docs will be rebuilt if any of these change. +# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h +# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c +HFILE_GLOB = $(top_srcdir)/src/*.h +CFILE_GLOB = $(top_srcdir)/src/*.c + +# Header files to ignore when scanning. +# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h +IGNORE_HFILES= + +# Images to copy into HTML directory. +# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png +HTML_IMAGES= + +# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). +# e.g. content_files=running.sgml building.sgml changes-2.0.sgml +content_files = version.xml + +# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded +# These files must be listed here *and* in content_files +# e.g. expand_content_files=running.sgml +expand_content_files= + +# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. +# Only needed if you are using gtkdoc-scangobj to dynamically query widget +# signals and properties. +# e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) +# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) +INCLUDES = -I$(top_srcdir)/src $(GFEED_CFLAGS) +GTKDOC_LIBS = $(top_builddir)/src/libgfeed.la $(GFEED_LIBS) + +# This includes the standard gtk-doc make rules, copied by gtkdocize. +include $(top_srcdir)/gtk-doc.make + +# Other files to distribute +# e.g. EXTRA_DIST += version.xml.in +EXTRA_DIST += version.xml.in diff --git a/docs/reference/libgfeed-docs.sgml b/docs/reference/libgfeed-docs.sgml new file mode 100644 index 0000000..e61d1da --- /dev/null +++ b/docs/reference/libgfeed-docs.sgml @@ -0,0 +1,41 @@ + + +]> + + + LibGFeed Reference Manual + for LibGFeed &version; + + + + RSS API reference + + + + + + + + + + + + + + ATOM API reference + + + + + + + + + + + + + + diff --git a/docs/reference/libgfeed-overrides.txt b/docs/reference/libgfeed-overrides.txt new file mode 100644 index 0000000..e69de29 diff --git a/docs/reference/libgfeed-sections.txt b/docs/reference/libgfeed-sections.txt new file mode 100644 index 0000000..111ce6d --- /dev/null +++ b/docs/reference/libgfeed-sections.txt @@ -0,0 +1,241 @@ +
+rss +Rss +Rss +rss_new +rss_new_from_file +rss_new_from_buffer +rss_get_xml_doc +rss_save_file +
+ +
+rsschannel +RSSCHANNEL_DAY_MONDAY +RSSCHANNEL_DAY_TUESDAY +RSSCHANNEL_DAY_WEDNESDAY +RSSCHANNEL_DAY_THURSDAY +RSSCHANNEL_DAY_FRIDAY +RSSCHANNEL_DAY_SATURDAY +RSSCHANNEL_DAY_SUNDAY +RSSCHANNEL_HOUR_0 +RSSCHANNEL_HOUR_1 +RSSCHANNEL_HOUR_2 +RSSCHANNEL_HOUR_3 +RSSCHANNEL_HOUR_4 +RSSCHANNEL_HOUR_5 +RSSCHANNEL_HOUR_6 +RSSCHANNEL_HOUR_7 +RSSCHANNEL_HOUR_8 +RSSCHANNEL_HOUR_9 +RSSCHANNEL_HOUR_10 +RSSCHANNEL_HOUR_11 +RSSCHANNEL_HOUR_12 +RSSCHANNEL_HOUR_13 +RSSCHANNEL_HOUR_14 +RSSCHANNEL_HOUR_15 +RSSCHANNEL_HOUR_16 +RSSCHANNEL_HOUR_17 +RSSCHANNEL_HOUR_18 +RSSCHANNEL_HOUR_19 +RSSCHANNEL_HOUR_20 +RSSCHANNEL_HOUR_21 +RSSCHANNEL_HOUR_22 +RSSCHANNEL_HOUR_23 +RssChannel +RssChannel +rss_channel_new +rss_channel_new_from_xml +rss_channel_add_category +rss_channel_get_categories +rss_channel_add_item +rss_channel_remove_item +rss_channel_get_xml +
+ +
+rsschannelitem +RssChannelItem +RssChannelItem +rss_channel_item_new +rss_channel_item_new_from_xml +rss_channel_item_add_category +rss_channel_item_get_categories +rss_channel_item_get_xml +
+ +
+rssimage +RssImage +RssImage +rss_image_new +rss_image_new_from_xml +rss_image_get_xml +
+ +
+rssguid +RssGuid +RssGuid +rss_guid_new +rss_guid_new_from_xml +rss_guid_get_xml +
+ +
+atom +Atom +Atom +atom_new +atom_new_from_file +atom_new_from_buffer +atom_get_xml_doc +atom_save_file +
+ +
+rsstextinput +RssTextInput +RssTextInput +rss_text_input_new +rss_text_input_new_from_xml +rss_text_input_get_xml +
+ +
+rsscloud +RssCloud +RssCloud +rss_cloud_new +rss_cloud_new_from_xml +rss_cloud_get_xml +
+ +
+rsscategory +RssCategory +RssCategory +rss_category_new +rss_category_new_from_xml +rss_category_get_xml +
+ +
+rsssource +RssSource +RssSource +rss_source_new +rss_source_new_from_xml +rss_source_get_xml +
+ +
+rssenclosure +RssEnclosure +RssEnclosure +rss_enclosure_new +rss_enclosure_new_from_xml +rss_enclosure_get_xml +
+ +
+atomcommon +AtomCommon +AtomCommon +atom_common_new +atom_common_set_properties_from_xml +atom_common_get_xml +
+ +
+atomdate +AtomDate +AtomDate +atom_date_new +atom_date_new_from_xml +atom_date_get_xml +
+ +
+atomid +AtomID +AtomID +atom_id_new +atom_id_new_from_xml +atom_id_get_xml +
+ +
+atomcontent +AtomContent +AtomContent +AtomContentType +atom_content_new +atom_content_new_from_xml +atom_content_get_xml +
+ +
+atomperson +AtomPerson +AtomPerson +atom_person_new +atom_person_new_from_xml +atom_person_get_xml +
+ +
+atomtext +AtomText +AtomText +AtomTextType +atom_text_new +atom_text_new_from_xml +atom_text_get_xml +
+ +
+atomcategory +AtomCategory +AtomCategory +atom_category_new +atom_category_new_from_xml +atom_category_get_xml +
+ +
+atomgenerator +AtomGenerator +AtomGenerator +atom_generator_new +atom_generator_new_from_xml +atom_generator_get_xml +
+ +
+atomlink +AtomLink +AtomLink +atom_link_new +atom_link_new_from_xml +atom_link_get_xml +
+ +
+atomentry +AtomEntry +AtomEntry +atom_entry_new +atom_entry_new_from_xml +atom_entry_get_xml +
+ +
+atomsource +AtomSource +AtomSource +atom_source_new +atom_source_new_from_xml +atom_source_get_xml +
+ diff --git a/docs/reference/libgfeed-undocumented.txt b/docs/reference/libgfeed-undocumented.txt new file mode 100644 index 0000000..69b2fdf --- /dev/null +++ b/docs/reference/libgfeed-undocumented.txt @@ -0,0 +1,168 @@ +44% symbol docs coverage. +128 symbols documented. +0 symbols incomplete. +160 not documented. + + +Atom +AtomCategory +AtomCommon +AtomContent +AtomContentType +AtomDate +AtomEntry +AtomGenerator +AtomID +AtomLink +AtomPerson +AtomSource +AtomText +AtomTextType +RSSCHANNEL_DAY_FRIDAY +RSSCHANNEL_DAY_MONDAY +RSSCHANNEL_DAY_SATURDAY +RSSCHANNEL_DAY_SUNDAY +RSSCHANNEL_DAY_THURSDAY +RSSCHANNEL_DAY_TUESDAY +RSSCHANNEL_DAY_WEDNESDAY +RSSCHANNEL_HOUR_0 +RSSCHANNEL_HOUR_1 +RSSCHANNEL_HOUR_10 +RSSCHANNEL_HOUR_11 +RSSCHANNEL_HOUR_12 +RSSCHANNEL_HOUR_13 +RSSCHANNEL_HOUR_14 +RSSCHANNEL_HOUR_15 +RSSCHANNEL_HOUR_16 +RSSCHANNEL_HOUR_17 +RSSCHANNEL_HOUR_18 +RSSCHANNEL_HOUR_19 +RSSCHANNEL_HOUR_2 +RSSCHANNEL_HOUR_20 +RSSCHANNEL_HOUR_21 +RSSCHANNEL_HOUR_22 +RSSCHANNEL_HOUR_23 +RSSCHANNEL_HOUR_3 +RSSCHANNEL_HOUR_4 +RSSCHANNEL_HOUR_5 +RSSCHANNEL_HOUR_6 +RSSCHANNEL_HOUR_7 +RSSCHANNEL_HOUR_8 +RSSCHANNEL_HOUR_9 +Rss +RssCategory +RssChannel +RssChannelItem +RssCloud +RssEnclosure +RssGuid +RssImage +RssSource +RssTextInput +atom_category_get_xml +atom_category_new +atom_category_new_from_xml +atom_common_get_xml +atom_common_new +atom_common_set_properties_from_xml +atom_content_get_xml +atom_content_new +atom_content_new_from_xml +atom_date_get_xml +atom_date_new +atom_date_new_from_xml +atom_entry_get_xml +atom_entry_new +atom_entry_new_from_xml +atom_generator_get_xml +atom_generator_new +atom_generator_new_from_xml +atom_get_xml_doc +atom_id_get_xml +atom_id_new +atom_id_new_from_xml +atom_link_get_xml +atom_link_new +atom_link_new_from_xml +atom_new +atom_new_from_buffer +atom_new_from_file +atom_person_get_xml +atom_person_new +atom_person_new_from_xml +atom_save_file +atom_source_get_xml +atom_source_new +atom_source_new_from_xml +atom_text_get_xml +atom_text_new +atom_text_new_from_xml +rss_category_get_xml +rss_category_new +rss_category_new_from_xml +rss_channel_add_category +rss_channel_add_item +rss_channel_get_categories +rss_channel_get_xml +rss_channel_item_add_category +rss_channel_item_get_categories +rss_channel_item_get_xml +rss_channel_item_new +rss_channel_item_new_from_xml +rss_channel_new +rss_channel_new_from_xml +rss_channel_remove_item +rss_cloud_get_xml +rss_cloud_new +rss_cloud_new_from_xml +rss_enclosure_get_xml +rss_enclosure_new +rss_enclosure_new_from_xml +rss_get_xml_doc +rss_guid_get_xml +rss_guid_new +rss_guid_new_from_xml +rss_image_get_xml +rss_image_new +rss_image_new_from_xml +rss_new +rss_new_from_buffer +rss_new_from_file +rss_save_file +rss_source_get_xml +rss_source_new +rss_source_new_from_xml +rss_text_input_get_xml +rss_text_input_new +rss_text_input_new_from_xml + + +atom:Long_Description +atom:Short_Description +atomcategory:Long_Description +atomcommon:Long_Description +atomcommon:Short_Description +atomcontent:Long_Description +atomdate:Long_Description +atomdate:Short_Description +atomentry:Long_Description +atomgenerator:Long_Description +atomid:Long_Description +atomlink:Long_Description +atomperson:Long_Description +atomsource:Short_Description +atomtext:Long_Description +atomtext:Short_Description +rss:Long_Description +rss:Short_Description +rsscategory:Long_Description +rsschannel:Long_Description +rsschannel:Short_Description +rsschannelitem:Long_Description +rsschannelitem:Short_Description +rsscloud:Long_Description +rssenclosure:Long_Description +rssguid:Long_Description +rssimage:Long_Description +rsssource:Long_Description +rsstextinput:Long_Description diff --git a/docs/reference/libgfeed.types b/docs/reference/libgfeed.types new file mode 100644 index 0000000..9fbf79e --- /dev/null +++ b/docs/reference/libgfeed.types @@ -0,0 +1,24 @@ +#include + +rss_get_type +rss_channel_get_type +rss_channel_item_get_type +rss_category_get_type +rss_cloud_get_type +rss_guid_get_type +rss_enclosure_get_type +rss_source_get_type +rss_image_get_type +rss_text_input_get_type +atom_get_type +atom_category_get_type +atom_common_get_type +atom_content_get_type +atom_date_get_type +atom_entry_get_type +atom_generator_get_type +atom_id_get_type +atom_link_get_type +atom_person_get_type +atom_source_get_type +atom_text_get_type diff --git a/docs/reference/tmpl/atom.sgml b/docs/reference/tmpl/atom.sgml new file mode 100644 index 0000000..65c2957 --- /dev/null +++ b/docs/reference/tmpl/atom.sgml @@ -0,0 +1,138 @@ + +Atom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@id: +@title: +@updated: +@Returns: + + + + + + + +@filename: +@Returns: + + + + + + + +@buffer: +@Returns: + + + + + + + +@atom: +@Returns: + + + + + + + +@atom: +@filename: +@Returns: + + diff --git a/docs/reference/tmpl/atomcategory.sgml b/docs/reference/tmpl/atomcategory.sgml new file mode 100644 index 0000000..fe99b5f --- /dev/null +++ b/docs/reference/tmpl/atomcategory.sgml @@ -0,0 +1,67 @@ + +AtomCategory + + +Conveys information about a category associated with an entry or feed. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@term: +@Returns: + + + + + + + +@xnode: +@Returns: + + + + + + + +@atom_category: +@xnode: + + diff --git a/docs/reference/tmpl/atomcommon.sgml b/docs/reference/tmpl/atomcommon.sgml new file mode 100644 index 0000000..5e9748a --- /dev/null +++ b/docs/reference/tmpl/atomcommon.sgml @@ -0,0 +1,61 @@ + +AtomCommon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Returns: + + + + + + + +@atom_common: +@xnode: + + + + + + + +@atom_common: +@xnode: + + diff --git a/docs/reference/tmpl/atomcontent.sgml b/docs/reference/tmpl/atomcontent.sgml new file mode 100644 index 0000000..a767f20 --- /dev/null +++ b/docs/reference/tmpl/atomcontent.sgml @@ -0,0 +1,82 @@ + +AtomContent + + +Contains or links to the content of the entry. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@ATOM_CONTENT_TEXT: +@ATOM_CONTENT_HTML: +@ATOM_CONTENT_XHTML: +@ATOM_CONTENT_MEDIA: + + + + + + +@type: +@Returns: + + + + + + + +@xnode: +@Returns: + + + + + + + +@atom_content: +@xnode: + + diff --git a/docs/reference/tmpl/atomdate.sgml b/docs/reference/tmpl/atomdate.sgml new file mode 100644 index 0000000..e63e656 --- /dev/null +++ b/docs/reference/tmpl/atomdate.sgml @@ -0,0 +1,57 @@ + +AtomDate + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@dateTime: +@Returns: + + + + + + + +@xnode: +@Returns: + + + + + + + +@atom_date: +@xnode: + + diff --git a/docs/reference/tmpl/atomentry.sgml b/docs/reference/tmpl/atomentry.sgml new file mode 100644 index 0000000..69bbe7a --- /dev/null +++ b/docs/reference/tmpl/atomentry.sgml @@ -0,0 +1,114 @@ + +AtomEntry + + +An individual entry, acting as a container for metadata and data associated with the entry. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@id: +@title: +@updated: +@Returns: + + + + + + + +@xnode: +@Returns: + + + + + + + +@atom_entry: +@xnode: + + diff --git a/docs/reference/tmpl/atomgenerator.sgml b/docs/reference/tmpl/atomgenerator.sgml new file mode 100644 index 0000000..4cf0a26 --- /dev/null +++ b/docs/reference/tmpl/atomgenerator.sgml @@ -0,0 +1,67 @@ + +AtomGenerator + + +Identifies the agent used to generate a feed, for debugging and other purposes. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@text: +@Returns: + + + + + + + +@xnode: +@Returns: + + + + + + + +@atom_generator: +@xnode: + + diff --git a/docs/reference/tmpl/atomid.sgml b/docs/reference/tmpl/atomid.sgml new file mode 100644 index 0000000..af30ca8 --- /dev/null +++ b/docs/reference/tmpl/atomid.sgml @@ -0,0 +1,57 @@ + +AtomID + + +A permanent, universally unique identifier for an entry or feed. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@uri: +@Returns: + + + + + + + +@xnode: +@Returns: + + + + + + + +@atom_id: +@xnode: + + diff --git a/docs/reference/tmpl/atomlink.sgml b/docs/reference/tmpl/atomlink.sgml new file mode 100644 index 0000000..e2b355f --- /dev/null +++ b/docs/reference/tmpl/atomlink.sgml @@ -0,0 +1,82 @@ + +AtomLink + + +A reference from an entry or feed to a Web resource. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@href: +@Returns: + + + + + + + +@xnode: +@Returns: + + + + + + + +@atom_link: +@xnode: + + diff --git a/docs/reference/tmpl/atomperson.sgml b/docs/reference/tmpl/atomperson.sgml new file mode 100644 index 0000000..ce83d54 --- /dev/null +++ b/docs/reference/tmpl/atomperson.sgml @@ -0,0 +1,67 @@ + +AtomPerson + + +Describes a person, corporation, or similar entity (hereafter, 'person'). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@name: +@Returns: + + + + + + + +@xnode: +@Returns: + + + + + + + +@atom_person: +@xnode: + + diff --git a/docs/reference/tmpl/atomsource.sgml b/docs/reference/tmpl/atomsource.sgml new file mode 100644 index 0000000..cc5a8e0 --- /dev/null +++ b/docs/reference/tmpl/atomsource.sgml @@ -0,0 +1,111 @@ + +AtomSource + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Returns: + + + + + + + +@xnode: +@Returns: + + + + + + + +@atom_source: +@xnode: + + diff --git a/docs/reference/tmpl/atomtext.sgml b/docs/reference/tmpl/atomtext.sgml new file mode 100644 index 0000000..312f713 --- /dev/null +++ b/docs/reference/tmpl/atomtext.sgml @@ -0,0 +1,72 @@ + +AtomText + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@ATOM_TEXT_TEXT: +@ATOM_TEXT_HTML: +@ATOM_TEXT_XHTML: + + + + + + +@type: +@text: +@Returns: + + + + + + + +@xnode: +@Returns: + + + + + + + +@atom_text: +@xnode: + + diff --git a/docs/reference/tmpl/gfeed.sgml b/docs/reference/tmpl/gfeed.sgml new file mode 100644 index 0000000..927dd25 --- /dev/null +++ b/docs/reference/tmpl/gfeed.sgml @@ -0,0 +1,21 @@ + +gfeed + + + + + + + + + + + + + + + + + + + diff --git a/docs/reference/tmpl/libgfeed-unused.sgml b/docs/reference/tmpl/libgfeed-unused.sgml new file mode 100644 index 0000000..fcfcca8 --- /dev/null +++ b/docs/reference/tmpl/libgfeed-unused.sgml @@ -0,0 +1,1080 @@ + + + + + + + + + + + + + + + + + + + + + +gfeed + + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + +@klass: + + + + + + +@obj: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Returns: + + + + + + +@Returns: + + + + + + +@Returns: + + + + + + +@Returns: + + + + + + +@Returns: + + + + + + +@Returns: + + + + + + +@Returns: + + + + + + +@Returns: + + + + + + +@Returns: + + + + + + +@Returns: + + + + + + +@Returns: + + + + + + +@Returns: + + + + + + +@Returns: + + + + + + +@Returns: + + + + + + +@Returns: + + + + + + +@Returns: + + + + + + +@Returns: + + + + + + +@Returns: + + + + + + +@Returns: + + + + + + +@Returns: + + + + + + +@Returns: + + + + + + +@Returns: + diff --git a/docs/reference/tmpl/rss.sgml b/docs/reference/tmpl/rss.sgml new file mode 100644 index 0000000..65306a8 --- /dev/null +++ b/docs/reference/tmpl/rss.sgml @@ -0,0 +1,75 @@ + +Rss + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Returns: + + + + + + + +@filename: +@Returns: + + + + + + + +@buffer: +@Returns: + + + + + + + +@rss: +@Returns: + + + + + + + +@rss: +@filename: +@Returns: + + diff --git a/docs/reference/tmpl/rsscategory.sgml b/docs/reference/tmpl/rsscategory.sgml new file mode 100644 index 0000000..5bf4aba --- /dev/null +++ b/docs/reference/tmpl/rsscategory.sgml @@ -0,0 +1,62 @@ + +RssCategory + + +Specify one or more categories that the channel belongs to. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@location: +@Returns: + + + + + + + +@xnode: +@Returns: + + + + + + + +@rss_category: +@Returns: + + diff --git a/docs/reference/tmpl/rsschannel.sgml b/docs/reference/tmpl/rsschannel.sgml new file mode 100644 index 0000000..7ee0c19 --- /dev/null +++ b/docs/reference/tmpl/rsschannel.sgml @@ -0,0 +1,395 @@ + +RssChannel + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@title: +@link: +@description: +@Returns: + + + + + + + +@xnode: +@Returns: + + + + + + + +@rss_channel: +@rss_category: +@Returns: + + + + + + + +@rss_channel: +@Returns: + + + + + + + +@rss_channel: +@rss_channel_item: +@Returns: + + + + + + + +@rss_channel: +@rss_channel_item: +@Returns: + + + + + + + +@rss_channel: +@Returns: + + diff --git a/docs/reference/tmpl/rsschannelitem.sgml b/docs/reference/tmpl/rsschannelitem.sgml new file mode 100644 index 0000000..b73655a --- /dev/null +++ b/docs/reference/tmpl/rsschannelitem.sgml @@ -0,0 +1,117 @@ + +RssChannelItem + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@title: +@description: +@Returns: + + + + + + + +@xnode: +@Returns: + + + + + + + +@rss_channel_item: +@rss_category: +@Returns: + + + + + + + +@rss_channel_item: +@Returns: + + + + + + + +@rss_channel_item: +@Returns: + + diff --git a/docs/reference/tmpl/rsscloud.sgml b/docs/reference/tmpl/rsscloud.sgml new file mode 100644 index 0000000..f5e27ca --- /dev/null +++ b/docs/reference/tmpl/rsscloud.sgml @@ -0,0 +1,81 @@ + +RssCloud + + +Allows processes to register with a cloud to be notified of updates to the channel, implementing a lightweight publish-subscribe protocol for RSS feeds. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@domain: +@port: +@path: +@registerProcedure: +@protocol: +@Returns: + + + + + + + +@xnode: +@Returns: + + + + + + + +@rss_cloud: +@Returns: + + diff --git a/docs/reference/tmpl/rssenclosure.sgml b/docs/reference/tmpl/rssenclosure.sgml new file mode 100644 index 0000000..8d63b91 --- /dev/null +++ b/docs/reference/tmpl/rssenclosure.sgml @@ -0,0 +1,69 @@ + +RssEnclosure + + +Describes a media object that is attached to the item. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@url: +@length: +@type: +@Returns: + + + + + + + +@xnode: +@Returns: + + + + + + + +@rss_enclosure: +@Returns: + + diff --git a/docs/reference/tmpl/rssguid.sgml b/docs/reference/tmpl/rssguid.sgml new file mode 100644 index 0000000..44933c6 --- /dev/null +++ b/docs/reference/tmpl/rssguid.sgml @@ -0,0 +1,62 @@ + +RssGuid + + +A string that uniquely identifies the item (Globally Unique Identifier). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@guid: +@Returns: + + + + + + + +@xnode: +@Returns: + + + + + + + +@rss_guid: +@Returns: + + diff --git a/docs/reference/tmpl/rssimage.sgml b/docs/reference/tmpl/rssimage.sgml new file mode 100644 index 0000000..bd17c55 --- /dev/null +++ b/docs/reference/tmpl/rssimage.sgml @@ -0,0 +1,84 @@ + +RssImage + + +Specifies a GIF, JPEG or PNG image that can be displayed with the channel. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@url: +@title: +@link: +@Returns: + + + + + + + +@xnode: +@Returns: + + + + + + + +@rss_image: +@Returns: + + diff --git a/docs/reference/tmpl/rsssource.sgml b/docs/reference/tmpl/rsssource.sgml new file mode 100644 index 0000000..9eb3461 --- /dev/null +++ b/docs/reference/tmpl/rsssource.sgml @@ -0,0 +1,63 @@ + +RssSource + + +The RSS channel that the item came from. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@title: +@url: +@Returns: + + + + + + + +@xnode: +@Returns: + + + + + + + +@rss_source: +@Returns: + + diff --git a/docs/reference/tmpl/rsstextinput.sgml b/docs/reference/tmpl/rsstextinput.sgml new file mode 100644 index 0000000..ffab614 --- /dev/null +++ b/docs/reference/tmpl/rsstextinput.sgml @@ -0,0 +1,75 @@ + +RssTextInput + + +Specifies a text input box that can be displayed with the channel. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@title: +@description: +@name: +@link: +@Returns: + + + + + + + +@xnode: +@Returns: + + + + + + + +@rss_text_input: +@Returns: + + diff --git a/docs/reference/version.xml.in b/docs/reference/version.xml.in new file mode 100644 index 0000000..c5d0fd6 --- /dev/null +++ b/docs/reference/version.xml.in @@ -0,0 +1,2 @@ +@PACKAGE_VERSION@ + diff --git a/libgfeed.pc.in b/libgfeed.pc.in new file mode 100644 index 0000000..8aa176d --- /dev/null +++ b/libgfeed.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: @PACKAGE_NAME@ +Description: Library to create RSS and Atom feed +Version: @PACKAGE_VERSION@ +Requires: glib-2.0 gobject-2.0 libxml-2.0 +Libs: -L${libdir} -lgfeed +Cflags: -I${includedir}/libgfeed diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..c7eb240 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,56 @@ +LIBS = $(GFEED_LIBS) + +AM_CPPFLAGS = $(GFEED_CFLAGS) + +lib_LTLIBRARIES = libgfeed.la + +libgfeed_la_SOURCES = rss.c \ + rsschannel.c \ + rsschannelitem.c \ + rsscategory.c \ + rsscloud.c \ + rssimage.c \ + rsstextinput.c \ + rssenclosure.c \ + rssguid.c \ + rsssource.c \ + atom.c \ + atomcommon.c \ + atomtext.c \ + atomperson.c \ + atomdate.c \ + atomid.c \ + atomcategory.c \ + atomgenerator.c \ + atomlink.c \ + atomsource.c \ + atomentry.c \ + atomcontent.c + +libgfeed_la_LDFLAGS = -no-undefined + +libgfeed_include_HEADERS = gfeed.h \ + rss.h \ + rsschannel.h \ + rsschannelitem.h \ + rsscategory.h \ + rsscloud.h \ + rssimage.h \ + rsstextinput.h \ + rssenclosure.h \ + rssguid.h \ + rsssource.h \ + atom.h \ + atomcommon.h \ + atomtext.h \ + atomperson.h \ + atomdate.h \ + atomid.h \ + atomcategory.h \ + atomgenerator.h \ + atomlink.h \ + atomsource.h \ + atomentry.h \ + atomcontent.h + +libgfeed_includedir = $(includedir)/libgfeed diff --git a/src/atom.c b/src/atom.c new file mode 100644 index 0000000..c008568 --- /dev/null +++ b/src/atom.c @@ -0,0 +1,810 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#include "atom.h" +#include "atomperson.h" +#include "atomcategory.h" +#include "atomgenerator.h" +#include "atomlink.h" +#include "atomentry.h" + +enum +{ + PROP_0, + PROP_AUTHOR, + PROP_CATEGORY, + PROP_CONTRIBUTOR, + PROP_GENERATOR, + PROP_ICON, + PROP_ID, + PROP_LINK, + PROP_LOGO, + PROP_RIGHTS, + PROP_SUBTITLE, + PROP_TITLE, + PROP_UPDATED, + PROP_ENTRY +}; + +static void atom_class_init (AtomClass *klass); +static void atom_init (Atom *atom); + +static void atom_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void atom_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static Atom *parse_xml (xmlDoc *xdoc); + + +#define ATOM_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_ATOM, AtomPrivate)) + +typedef struct _AtomPrivate AtomPrivate; +struct _AtomPrivate + { + GList *author, + *category, + *contributor, + *entry; + AtomGenerator *generator; + AtomID *icon, + *id, + *logo; + AtomLink *link; + AtomText *title, + *rights, + *subtitle; + AtomDate *updated; + }; + +GType +atom_get_type (void) +{ + static GType atom_type = 0; + + if (!atom_type) + { + static const GTypeInfo atom_info = + { + sizeof (AtomClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) atom_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (Atom), + 0, /* n_preallocs */ + (GInstanceInitFunc) atom_init, + NULL + }; + + atom_type = g_type_register_static (TYPE_ATOM_COMMON, "Atom", + &atom_info, 0); + } + + return atom_type; +} + +static void +atom_class_init (AtomClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (AtomPrivate)); + + object_class->set_property = atom_set_property; + object_class->get_property = atom_get_property; + + g_object_class_install_property (object_class, PROP_AUTHOR, + g_param_spec_pointer ("author", + "Author", + "A #GList of #AtomPerson objects that indicates the author of the entry or feed.", + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_CATEGORY, + g_param_spec_pointer ("category", + "Category", + "A #GList of #AtomCategory objects convey information about a category associated with an entry or feed.", + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_CONTRIBUTOR, + g_param_spec_pointer ("contributor", + "Contributor", + "A #GList of #AtomPerson objects that indicate a person or other entity who contributed to the entry or feed.", + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_GENERATOR, + g_param_spec_object ("generator", + "Generato", + "An #AtomGenerator object that identifies the agent used to generate a feed, for debugging and other purposes.", + TYPE_ATOM_GENERATOR, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_ICON, + g_param_spec_object ("icon", + "Icon", + "An #AtomID object that contains an IRI reference [RFC3987] that identifies an image that provides iconic visual identification for a feed.", + TYPE_ATOM_ID, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_ID, + g_param_spec_object ("id", + "Id", + "An #AtomID object that conveys a permanent, universally unique identifier for an entry or feed.", + TYPE_ATOM_ID, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_LINK, + g_param_spec_object ("link", + "Link", + "An #AtomLink object that defines a reference from an entry or feed to a Web resource.", + TYPE_ATOM_LINK, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_LOGO, + g_param_spec_object ("logo", + "Logo", + "An #AtonID object that contains an IRI reference [RFC3987] that identifies an image that provides visual identification for a feed.", + TYPE_ATOM_ID, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_RIGHTS, + g_param_spec_object ("rights", + "Rights", + "An #AtomText object that conveys information about rights held in and over an entry or feed.", + TYPE_ATOM_TEXT, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_SUBTITLE, + g_param_spec_object ("subtitle", + "Subtitle", + "An #AtomText object that conveys a human-readable description or subtitle for a feed.", + TYPE_ATOM_TEXT, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_TITLE, + g_param_spec_object ("title", + "Title", + "An #AtomText object that conveys a human-readable title for an entry or feed.", + TYPE_ATOM_TEXT, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_UPDATED, + g_param_spec_object ("updated", + "Updated", + "An #AtomDate object indicating the most recent instant in time when an entry or feed was modified in a way the publisher considers significant.", + TYPE_ATOM_DATE, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_ENTRY, + g_param_spec_pointer ("entry", + "Entry", + "A #GList of #AtomEntry.", + G_PARAM_READWRITE)); +} + +static void +atom_init (Atom *atom) +{ +} + +/** + * atom_new: + * @id: an #AtomID object that conveys a permanent, universally unique identifier for an entry or feed. + * @title: an #AtomText object that conveys a human-readable title for an entry or feed. + * @updated: an #AtomDate object indicating the most recent instant in time when an entry or feed was modified in a way the publisher considers significant. + * + * Returns: the newly created #Atom object. + */ +Atom +*atom_new (AtomID *id, AtomText *title, AtomDate *updated) +{ + Atom *atom = ATOM (g_object_new (atom_get_type (), NULL)); + + g_object_set (G_OBJECT (atom), + "id", id, + "title", title, + "updated", updated, + NULL); + + return atom; +} + +/** + * atom_new_from_file: + * @filename: + * + * Returns: the newly created #Atom object. + */ +Atom +*atom_new_from_file (const gchar *filename) +{ + Atom *atom = NULL; + + xmlDoc *xdoc = xmlParseFile (filename); + + atom = parse_xml (xdoc); + + return atom; +} + +/** + * atom_new_from_buffer: + * @buffer: a pointer to an array of #gchar. + * + * Returns: the newly created #Atom object. + */ +Atom +*atom_new_from_buffer (const gchar *buffer) +{ + Atom *atom = NULL; + + xmlDoc *xdoc = xmlParseDoc (buffer); + + atom = parse_xml (xdoc); + + return atom; +} + +/** + * atom_get_xml_doc: + * @atom: an #Atom object. + * + * Returns: the #xmlDoc correspondent to the entire #Atom object. + */ +xmlDoc +*atom_get_xml_doc (Atom *atom) +{ + xmlNode *xnode; + GList *lst; + + AtomPrivate *priv = ATOM_GET_PRIVATE (atom); + + xmlDoc *xdoc = xmlNewDoc ((const xmlChar *)"1.0"); + xmlNode *xroot = xmlNewNode (NULL, (const xmlChar *)"feed"); + + /* adding root element */ + if (xroot == NULL) return NULL; + + xmlSetProp (xroot, (const xmlChar *)"xmlns", (const xmlChar *)"http://www.w3.org/2005/Atom"); + xmlDocSetRootElement (xdoc, xroot); + + lst = g_list_first (priv->author); + while (lst != NULL) + { + if (IS_ATOM_PERSON (lst->data)) + { + xnode = xmlNewNode (NULL, (const xmlChar *)"author"); + xmlAddChild (xroot, xnode); + atom_person_get_xml (ATOM_PERSON (lst->data), xnode); + } + + lst = g_list_next (lst); + } + + lst = g_list_first (priv->category); + while (lst != NULL) + { + if (IS_ATOM_CATEGORY (lst->data)) + { + xnode = xmlNewNode (NULL, (const xmlChar *)"category"); + xmlAddChild (xroot, xnode); + atom_category_get_xml (ATOM_CATEGORY (lst->data), xnode); + } + + lst = g_list_next (lst); + } + + lst = g_list_first (priv->contributor); + while (lst != NULL) + { + if (IS_ATOM_PERSON (lst->data)) + { + xnode = xmlNewNode (NULL, (const xmlChar *)"contributor"); + xmlAddChild (xroot, xnode); + atom_person_get_xml (ATOM_PERSON (lst->data), xnode); + } + + lst = g_list_next (lst); + } + + if (priv->generator != NULL) + { + xnode = xmlNewNode (NULL, (const xmlChar *)"generator"); + xmlAddChild (xroot, xnode); + atom_generator_get_xml (priv->generator, xnode); + } + + if (priv->icon != NULL) + { + xnode = xmlNewNode (NULL, (const xmlChar *)"icon"); + xmlAddChild (xroot, xnode); + atom_id_get_xml (priv->icon, xnode); + } + + if (priv->id != NULL) + { + xnode = xmlNewNode (NULL, (const xmlChar *)"id"); + xmlAddChild (xroot, xnode); + atom_id_get_xml (priv->id, xnode); + } + else + { + /* TO DO */ + return NULL; + } + + if (priv->link != NULL) + { + xnode = xmlNewNode (NULL, (const xmlChar *)"link"); + xmlAddChild (xroot, xnode); + atom_link_get_xml (priv->link, xnode); + } + + if (priv->logo != NULL) + { + xnode = xmlNewNode (NULL, (const xmlChar *)"logo"); + xmlAddChild (xroot, xnode); + atom_id_get_xml (priv->logo, xnode); + } + + if (priv->rights != NULL) + { + xnode = xmlNewNode (NULL, (const xmlChar *)"rights"); + xmlAddChild (xroot, xnode); + atom_text_get_xml (priv->rights, xnode); + } + + if (priv->subtitle != NULL) + { + xnode = xmlNewNode (NULL, (const xmlChar *)"subtitle"); + xmlAddChild (xroot, xnode); + atom_text_get_xml (priv->subtitle, xnode); + } + + if (priv->title != NULL) + { + xnode = xmlNewNode (NULL, (const xmlChar *)"title"); + xmlAddChild (xroot, xnode); + atom_text_get_xml (priv->title, xnode); + } + else + { + /* TO DO */ + return NULL; + } + + if (priv->updated != NULL) + { + xnode = xmlNewNode (NULL, (const xmlChar *)"updated"); + xmlAddChild (xroot, xnode); + atom_date_get_xml (priv->updated, xnode); + } + else + { + /* TO DO */ + return NULL; + } + + lst = g_list_first (priv->entry); + while (lst != NULL) + { + if (IS_ATOM_ENTRY (lst->data)) + { + xnode = xmlNewNode (NULL, (const xmlChar *)"entry"); + xmlAddChild (xroot, xnode); + atom_entry_get_xml (ATOM_ENTRY (lst->data), xnode); + } + + lst = g_list_next (lst); + } + + return xdoc; +} + +/** + * atom_save_file: + * @atom: an #Atom object. + * @filename: + * + */ +gboolean +atom_save_file (Atom *atom, const gchar *filename) +{ + return (xmlSaveFileEnc (filename, atom_get_xml_doc (atom), "utf-8") > -1); +} + +static void +atom_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + GObject *obj; + + Atom *atom = ATOM (object); + + AtomPrivate *priv = ATOM_GET_PRIVATE (atom); + + switch (property_id) + { + case PROP_AUTHOR: + if (g_value_get_pointer (value) != NULL) + { + priv->author = (GList *)g_memdup ((gconstpointer)g_value_get_pointer (value), sizeof (GList)); + } + break; + + case PROP_CATEGORY: + if (g_value_get_pointer (value) != NULL) + { + priv->category = (GList *)g_memdup ((gconstpointer)g_value_get_pointer (value), sizeof (GList)); + } + break; + + case PROP_CONTRIBUTOR: + if (g_value_get_pointer (value) != NULL) + { + priv->contributor = (GList *)g_memdup ((gconstpointer)g_value_get_pointer (value), sizeof (GList)); + } + break; + + case PROP_GENERATOR: + if (g_value_get_object (value) != NULL && IS_ATOM_GENERATOR (g_value_get_object (value))) + { + priv->generator = (AtomGenerator *)g_value_dup_object (value); + } + break; + + case PROP_ICON: + if (g_value_get_object (value) != NULL && IS_ATOM_ID (g_value_get_object (value))) + { + priv->icon = (AtomID *)g_value_dup_object (value); + } + break; + + case PROP_ID: + if (g_value_get_object (value) != NULL && IS_ATOM_ID (g_value_get_object (value))) + { + priv->id = (AtomID *)g_value_dup_object (value); + } + break; + + case PROP_LINK: + if (g_value_get_object (value) != NULL && IS_ATOM_LINK (g_value_get_object (value))) + { + priv->link = (AtomLink *)g_value_dup_object (value); + } + break; + + case PROP_LOGO: + if (g_value_get_object (value) != NULL && IS_ATOM_ID (g_value_get_object (value))) + { + priv->logo = (AtomID *)g_value_dup_object (value); + } + break; + + case PROP_RIGHTS: + if (g_value_get_object (value) != NULL && IS_ATOM_TEXT (g_value_get_object (value))) + { + priv->rights = (AtomText *)g_value_dup_object (value); + } + break; + + case PROP_SUBTITLE: + if (g_value_get_object (value) != NULL && IS_ATOM_TEXT (g_value_get_object (value))) + { + priv->subtitle = (AtomText *)g_value_dup_object (value); + } + break; + + case PROP_TITLE: + if (g_value_get_object (value) != NULL && IS_ATOM_TEXT (g_value_get_object (value))) + { + priv->title = (AtomText *)g_value_dup_object (value); + } + break; + + case PROP_UPDATED: + if (g_value_get_object (value) != NULL && IS_ATOM_DATE (g_value_get_object (value))) + { + priv->updated = (AtomDate *)g_value_dup_object (value); + } + break; + + case PROP_ENTRY: + if (g_value_get_pointer (value) != NULL) + { + priv->entry = (GList *)g_memdup ((gconstpointer)g_value_get_pointer (value), sizeof (GList)); + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +atom_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + Atom *atom = ATOM (object); + + AtomPrivate *priv = ATOM_GET_PRIVATE (atom); + + switch (property_id) + { + case PROP_AUTHOR: + g_value_set_pointer (value, priv->author); + break; + + case PROP_CATEGORY: + g_value_set_pointer (value, priv->category); + break; + + case PROP_CONTRIBUTOR: + g_value_set_pointer (value, priv->contributor); + break; + + case PROP_GENERATOR: + g_value_set_pointer (value, priv->generator); + break; + + case PROP_ICON: + g_value_set_object (value, priv->icon); + break; + + case PROP_ID: + g_value_set_object (value, priv->id); + break; + + case PROP_LINK: + g_value_set_object (value, priv->link); + break; + + case PROP_LOGO: + g_value_set_object (value, priv->logo); + break; + + case PROP_RIGHTS: + g_value_set_object (value, priv->rights); + break; + + case PROP_SUBTITLE: + g_value_set_object (value, priv->subtitle); + break; + + case PROP_TITLE: + g_value_set_object (value, priv->title); + break; + + case PROP_UPDATED: + g_value_set_object (value, priv->updated); + break; + + case PROP_ENTRY: + g_value_set_object (value, priv->entry); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static Atom +*parse_xml (xmlDoc *xdoc) +{ + Atom *atom; + + if (xdoc != NULL) + { + xmlNode *cur = xmlDocGetRootElement (xdoc); + if (cur != NULL) + { + if (xmlStrcmp (cur->name, (const xmlChar *)"feed") == 0) + { + xmlNsPtr *xmlns = xmlGetNsList (xdoc, cur); + if (xmlns != NULL && xmlStrcmp (xmlns[0]->href, (const xmlChar *)"http://www.w3.org/2005/Atom") == 0) + { + if (cur->children != NULL) + { + AtomID *id = NULL; + AtomText *title = NULL; + AtomDate *updated = NULL; + + xmlXPathObjectPtr xpresult; + xmlXPathContextPtr xpcontext = xmlXPathNewContext (xdoc); + + xmlXPathRegisterNs (xpcontext, (const xmlChar *)"atom", xmlns[0]->href); + + /* searching for id */ + xpcontext->node = cur; + xpresult = xmlXPathEvalExpression ((const xmlChar *)"child::atom:id", xpcontext); + if (xpresult == NULL || xpresult->nodesetval == NULL || xpresult->nodesetval->nodeNr != 1) + { + g_critical ("Atom document must contain one and only id element."); + } + else + { + id = atom_id_new_from_xml (xpresult->nodesetval->nodeTab[0]); + if (id == NULL) + { + g_critical ("Invalid id element."); + } + } + + /* searching for title */ + xpcontext->node = cur; + xpresult = xmlXPathEvalExpression ((const xmlChar *)"child::atom:title", xpcontext); + if (xpresult == NULL || xpresult->nodesetval == NULL || xpresult->nodesetval->nodeNr != 1) + { + g_critical ("Atom document must contain one and only title element."); + } + else + { + title = atom_text_new_from_xml (xpresult->nodesetval->nodeTab[0]); + if (title == NULL) + { + g_critical ("Invalid title element."); + } + } + + /* searching for updated */ + xpcontext->node = cur; + xpresult = xmlXPathEvalExpression ((const xmlChar *)"child::atom:updated", xpcontext); + if (xpresult == NULL || xpresult->nodesetval == NULL || xpresult->nodesetval->nodeNr != 1) + { + g_critical ("Atom document must contain one and only updated element."); + } + else + { + updated = atom_date_new_from_xml (xpresult->nodesetval->nodeTab[0]); + if (updated == NULL) + { + g_critical ("Invalid updated element."); + } + } + + if (id != NULL && title != NULL && updated != NULL) + { + atom = atom_new (id, title, updated); + + AtomPrivate *priv = ATOM_GET_PRIVATE (atom); + + cur = cur->children; + while (cur != NULL) + { + if (xmlStrcmp (cur->name, (const xmlChar *)"author") == 0) + { + AtomPerson *ap = atom_person_new_from_xml (cur); + if (ap != NULL) + { + priv->author = g_list_append (priv->author, ap); + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"category") == 0) + { + AtomCategory *ac = atom_category_new_from_xml (cur); + if (ac != NULL) + { + priv->category = g_list_append (priv->category, ac); + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"contributor") == 0) + { + AtomPerson *ap = atom_person_new_from_xml (cur); + if (ap != NULL) + { + priv->contributor = g_list_append (priv->contributor, ap); + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"generator") == 0) + { + AtomGenerator *ag = atom_generator_new_from_xml (cur); + if (ag != NULL) + { + priv->generator = ag; + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"icon") == 0) + { + AtomID *icon = atom_id_new_from_xml (cur); + if (icon == NULL) + { + priv->icon = icon; + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"link") == 0) + { + AtomLink *link = atom_link_new_from_xml (cur); + if (link == NULL) + { + priv->link = link; + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"logo") == 0) + { + AtomID *logo = atom_id_new_from_xml (cur); + if (logo == NULL) + { + priv->logo = logo; + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"rights") == 0) + { + AtomText *rights = atom_text_new_from_xml (cur); + if (rights != NULL) + { + priv->rights = rights; + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"subtitle") == 0) + { + AtomText *subtitle = atom_text_new_from_xml (cur); + if (subtitle != NULL) + { + priv->subtitle = subtitle; + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"entry") == 0) + { + AtomEntry *ae = atom_entry_new_from_xml (cur); + if (ae != NULL) + { + priv->entry = g_list_append (priv->entry, ae); + } + } + + cur = cur->next; + } + } + } + else + { + g_critical ("Empty atom document."); + } + } + else + { + g_critical ("Wrong atom version."); + } + } + else + { + g_critical ("XML document is not an atom feed document."); + } + } + else + { + g_critical ("Empty document."); + } + } + + return atom; +} diff --git a/src/atom.h b/src/atom.h new file mode 100644 index 0000000..19247db --- /dev/null +++ b/src/atom.h @@ -0,0 +1,70 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __ATOM_H__ +#define __ATOM_H__ + +#include +#include +#include + +#include "atomcommon.h" +#include "atomid.h" +#include "atomtext.h" +#include "atomdate.h" + +G_BEGIN_DECLS + + +#define TYPE_ATOM (atom_get_type ()) +#define ATOM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_ATOM, Atom)) +#define ATOM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_ATOM, AtomClass)) +#define IS_ATOM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_ATOM)) +#define IS_ATOM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_ATOM)) +#define ATOM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_ATOM, AtomClass)) + + +typedef struct _Atom Atom; +typedef struct _AtomClass AtomClass; + +struct _Atom + { + AtomCommon parent; + }; + +struct _AtomClass + { + AtomCommonClass parent_class; + }; + +GType atom_get_type (void) G_GNUC_CONST; + +Atom *atom_new (AtomID *id, AtomText *title, AtomDate *updated); +Atom *atom_new_from_file (const gchar *filename); +Atom *atom_new_from_buffer (const gchar *buffer); + +xmlDoc *atom_get_xml_doc (Atom *atom); +gboolean atom_save_file (Atom *atom, const gchar *filename); + + +G_END_DECLS + +#endif /* __ATOM_H__ */ diff --git a/src/atomcategory.c b/src/atomcategory.c new file mode 100644 index 0000000..c986d0d --- /dev/null +++ b/src/atomcategory.c @@ -0,0 +1,269 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#include "atomcategory.h" + +enum +{ + PROP_0, + PROP_TERM, + PROP_SCHEME, + PROP_LABEL, +}; + +static void atom_category_class_init (AtomCategoryClass *klass); +static void atom_category_init (AtomCategory *atom_category); + +static void atom_category_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void atom_category_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +#define ATOM_CATEGORY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_ATOM_CATEGORY, AtomCategoryPrivate)) + +typedef struct _AtomCategoryPrivate AtomCategoryPrivate; +struct _AtomCategoryPrivate + { + gchar *term, + *scheme, + *label; + }; + +GType +atom_category_get_type (void) +{ + static GType atom_category_type = 0; + + if (!atom_category_type) + { + static const GTypeInfo atom_category_info = + { + sizeof (AtomCategoryClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) atom_category_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (AtomCategory), + 0, /* n_preallocs */ + (GInstanceInitFunc) atom_category_init, + NULL + }; + + atom_category_type = g_type_register_static (TYPE_ATOM_COMMON, "AtomCategory", + &atom_category_info, 0); + } + + return atom_category_type; +} + +static void +atom_category_class_init (AtomCategoryClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (AtomCategoryPrivate)); + + object_class->set_property = atom_category_set_property; + object_class->get_property = atom_category_get_property; + + g_object_class_install_property (object_class, PROP_TERM, + g_param_spec_string ("term", + "Term", + "A string that identifies the category to which the entry or feed belongs.", + "", + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_SCHEME, + g_param_spec_string ("scheme", + "Scheme", + "An IRI that identifies a categorization scheme.", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, PROP_LABEL, + g_param_spec_string ("label", + "Label", + "A human-readable label for display in end-user applications.", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); +} + +static void +atom_category_init (AtomCategory *atom_category) +{ +} + +/** + * atom_category_new: + * @term: a string that identifies the category to which the entry or feed belongs. + * + * Returns: the newly created #AtomCategory object. + */ +AtomCategory +*atom_category_new (const gchar *term) +{ + AtomCategory *atom_category = ATOM_CATEGORY (g_object_new (atom_category_get_type (), NULL)); + + g_object_set (G_OBJECT (atom_category), + "term", term, + NULL); + + return atom_category; +} + +/** + * atom_category_new_from_xml: + * @xnode: an #xmlNode. + * + * Returns: the newly created #AtomCategory object. + */ +AtomCategory +*atom_category_new_from_xml (xmlNode *xnode) +{ + AtomCategory *atom_category = NULL; + + gchar *term = (gchar *)xmlGetProp (xnode, (const xmlChar *)"term"); + if (term == NULL || strcmp (g_strstrip (term), "") == 0) + { + g_critical ("AtomCategory must have a term attribute."); + return NULL; + } + else + { + atom_category = atom_category_new (term); + if (atom_category != NULL) + { + atom_common_set_properties_from_xml (ATOM_COMMON (atom_category), xnode); + + term = (gchar *)xmlGetProp (xnode, (const xmlChar *)"scheme"); + if (term != NULL && strcmp (g_strstrip (term), "") != 0) + { + g_object_set (G_OBJECT (atom_category), + "scheme", term, + NULL); + } + + term = (gchar *)xmlGetProp (xnode, (const xmlChar *)"label"); + if (term != NULL && strcmp (g_strstrip (term), "") != 0) + { + g_object_set (G_OBJECT (atom_category), + "label", term, + NULL); + } + } + } + + return atom_category; +} + +/** + * atom_category_get_xml: + * @atom_category: an #AtomCategory object. + * @xnode: an #xmlNode. + * + */ +void +atom_category_get_xml (AtomCategory *atom_category, xmlNode *xnode) +{ + AtomCategoryPrivate *priv = ATOM_CATEGORY_GET_PRIVATE (atom_category); + + atom_common_get_xml (ATOM_COMMON (atom_category), xnode); + + xmlSetProp (xnode, (const xmlChar *)"term", (const xmlChar *)priv->term); + + if (strcmp (priv->scheme, "") != 0) + { + xmlSetProp (xnode, (const xmlChar *)"scheme", (const xmlChar *)priv->scheme); + } + if (strcmp (priv->label, "") != 0) + { + xmlSetProp (xnode, (const xmlChar *)"label", (const xmlChar *)priv->label); + } +} + +static void +atom_category_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + AtomCategory *atom_category = ATOM_CATEGORY (object); + + AtomCategoryPrivate *priv = ATOM_CATEGORY_GET_PRIVATE (atom_category); + + switch (property_id) + { + case PROP_TERM: + { + gchar *term = g_strstrip (g_value_dup_string (value)); + if (strcmp (term, "") == 0) + { + g_warning ("Property term must not be empty."); + } + else + { + priv->term = term; + } + break; + } + + case PROP_SCHEME: + priv->scheme = g_strstrip (g_value_dup_string (value)); + break; + + case PROP_LABEL: + priv->label = g_strstrip (g_value_dup_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +atom_category_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + AtomCategory *atom_category = ATOM_CATEGORY (object); + + AtomCategoryPrivate *priv = ATOM_CATEGORY_GET_PRIVATE (atom_category); + + switch (property_id) + { + case PROP_TERM: + g_value_set_string (value, priv->term); + break; + + case PROP_SCHEME: + g_value_set_string (value, priv->scheme); + break; + + case PROP_LABEL: + g_value_set_string (value, priv->label); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} diff --git a/src/atomcategory.h b/src/atomcategory.h new file mode 100644 index 0000000..630f3db --- /dev/null +++ b/src/atomcategory.h @@ -0,0 +1,64 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __ATOM_CATEGORY_H__ +#define __ATOM_CATEGORY_H__ + +#include +#include + +#include "atomcommon.h" + +G_BEGIN_DECLS + + +#define TYPE_ATOM_CATEGORY (atom_category_get_type ()) +#define ATOM_CATEGORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_ATOM_CATEGORY, AtomCategory)) +#define ATOM_CATEGORY_COMMON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_ATOM_CATEGORY, AtomCategoryClass)) +#define IS_ATOM_CATEGORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_ATOM_CATEGORY)) +#define IS_ATOM_CATEGORY_COMMON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_ATOM_CATEGORY)) +#define ATOM_CATEGORY_COMMON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_ATOM_CATEGORY, AtomCategoryClass)) + + +typedef struct _AtomCategory AtomCategory; +typedef struct _AtomCategoryClass AtomCategoryClass; + +struct _AtomCategory + { + AtomCommon parent; + }; + +struct _AtomCategoryClass + { + AtomCommonClass parent_class; + }; + +GType atom_category_get_type (void) G_GNUC_CONST; + +AtomCategory *atom_category_new (const gchar *term); +AtomCategory *atom_category_new_from_xml (xmlNode *xnode); + +void atom_category_get_xml (AtomCategory *atom_category, xmlNode *xnode); + + +G_END_DECLS + +#endif /* __ATOM_CATEGORY_H__ */ diff --git a/src/atomcommon.c b/src/atomcommon.c new file mode 100644 index 0000000..8368a88 --- /dev/null +++ b/src/atomcommon.c @@ -0,0 +1,226 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#include "atomcommon.h" + +enum +{ + PROP_0, + PROP_BASE, + PROP_LANG +}; + +static void atom_common_class_init (AtomCommonClass *klass); +static void atom_common_init (AtomCommon *atom_common); + +static void atom_common_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void atom_common_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +#define ATOM_COMMON_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_ATOM_COMMON, AtomCommonPrivate)) + +typedef struct _AtomCommonPrivate AtomCommonPrivate; +struct _AtomCommonPrivate + { + gchar *base, + *lang; + }; + +GType +atom_common_get_type (void) +{ + static GType atom_common_type = 0; + + if (!atom_common_type) + { + static const GTypeInfo atom_common_info = + { + sizeof (AtomCommonClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) atom_common_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (AtomCommon), + 0, /* n_preallocs */ + (GInstanceInitFunc) atom_common_init, + NULL + }; + + atom_common_type = g_type_register_static (G_TYPE_OBJECT, "AtomCommon", + &atom_common_info, 0); + } + + return atom_common_type; +} + +static void +atom_common_class_init (AtomCommonClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (AtomCommonPrivate)); + + object_class->set_property = atom_common_set_property; + object_class->get_property = atom_common_get_property; + + g_object_class_install_property (object_class, PROP_BASE, + g_param_spec_string ("base", + "Base", + "Base", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, PROP_LANG, + g_param_spec_string ("lang", + "Lang", + "Lang", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); +} + +static void +atom_common_init (AtomCommon *atom_common) +{ +} + +/** + * atom_common_new: + * + * Returns: the newly created #AtomCommon object. + */ +AtomCommon +*atom_common_new () +{ + return ATOM_COMMON (g_object_new (atom_common_get_type (), NULL)); +} + +/** + * atom_common_set_properties_from_xml: + * @atom_common: an #AtomCommon object. + * #xnode: the #xmlNode from which to get properties. + * + */ +void +atom_common_set_properties_from_xml (AtomCommon *atom_common, xmlNode *xnode) +{ + g_object_set (G_OBJECT (atom_common), + "base", xmlGetProp (xnode, (const xmlChar *)"base"), + "lang", xmlGetProp (xnode, (const xmlChar *)"lang"), + NULL); +} + +/** + * atom_common_get_xml: + * @atom_common: an #AtomCommon object. + * @xnode: the #xmlNode to fill. + * + */ +void +atom_common_get_xml (AtomCommon *atom_common, xmlNode *xnode) +{ + AtomCommonPrivate *priv = ATOM_COMMON_GET_PRIVATE (atom_common); + + xmlChar *prop = (xmlChar *)g_strstrip (priv->base); + if (!xmlStrEqual (prop, (const xmlChar *)"")) + { + xmlSetProp (xnode, (const xmlChar *)"xml:base", prop); + } + + prop = (xmlChar *)g_strstrip (priv->lang); + if (!xmlStrEqual (prop, (const xmlChar *)"")) + { + xmlSetProp (xnode, (const xmlChar *)"xml:lang", prop); + } +} + +static void +atom_common_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + AtomCommon *atom_common = ATOM_COMMON (object); + + AtomCommonPrivate *priv = ATOM_COMMON_GET_PRIVATE (atom_common); + + switch (property_id) + { + case PROP_BASE: + if (value != NULL) + { + gchar *str = g_value_dup_string (value); + if (str == NULL) + { + priv->base = g_strdup (""); + } + else + { + priv->base = g_strstrip (str); + } + } + break; + + case PROP_LANG: + if (value != NULL) + { + gchar *str = g_value_dup_string (value); + if (str == NULL) + { + priv->lang = g_strdup (""); + } + else + { + priv->lang = g_strstrip (str); + } + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +atom_common_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + AtomCommon *atom_common = ATOM_COMMON (object); + + AtomCommonPrivate *priv = ATOM_COMMON_GET_PRIVATE (atom_common); + + switch (property_id) + { + case PROP_BASE: + g_value_set_string (value, priv->base); + break; + + case PROP_LANG: + g_value_set_string (value, priv->lang); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} diff --git a/src/atomcommon.h b/src/atomcommon.h new file mode 100644 index 0000000..b5e7cd3 --- /dev/null +++ b/src/atomcommon.h @@ -0,0 +1,64 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __ATOM_COMMON_H__ +#define __ATOM_COMMON_H__ + +#include +#include +#include + +G_BEGIN_DECLS + + +#define TYPE_ATOM_COMMON (atom_common_get_type ()) +#define ATOM_COMMON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_ATOM_COMMON, AtomCommon)) +#define ATOM_COMMON_COMMON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_ATOM_COMMON, AtomCommonClass)) +#define IS_ATOM_COMMON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_ATOM_COMMON)) +#define IS_ATOM_COMMON_COMMON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_ATOM_COMMON)) +#define ATOM_COMMON_COMMON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_ATOM_COMMON, AtomCommonClass)) + + +typedef struct _AtomCommon AtomCommon; +typedef struct _AtomCommonClass AtomCommonClass; + +struct _AtomCommon + { + GObject parent; + }; + +struct _AtomCommonClass + { + GObjectClass parent_class; + }; + +GType atom_common_get_type (void) G_GNUC_CONST; + +AtomCommon *atom_common_new (void); + +void atom_common_set_properties_from_xml (AtomCommon *atom_common, xmlNode *xnode); + +void atom_common_get_xml (AtomCommon *atom_common, xmlNode *xnode); + + +G_END_DECLS + +#endif /* __ATOM_COMMON_H__ */ diff --git a/src/atomcontent.c b/src/atomcontent.c new file mode 100644 index 0000000..deaa20a --- /dev/null +++ b/src/atomcontent.c @@ -0,0 +1,344 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#include + +#include "atomcontent.h" + +enum +{ + PROP_0, + PROP_TYPE, + PROP_MEDIA_TYPE, + PROP_SRC, + PROP_TEXT +}; + +static void atom_content_class_init (AtomContentClass *klass); +static void atom_content_init (AtomContent *atom_content); + +static void atom_content_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void atom_content_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +#define ATOM_CONTENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_ATOM_CONTENT, AtomContentPrivate)) + +typedef struct _AtomContentPrivate AtomContentPrivate; +struct _AtomContentPrivate + { + AtomContentType type; + gchar *media_type, + *src, + *text; + }; + +GType +atom_content_get_type (void) +{ + static GType atom_content_type = 0; + + if (!atom_content_type) + { + static const GTypeInfo atom_content_info = + { + sizeof (AtomContentClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) atom_content_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (AtomContent), + 0, /* n_preallocs */ + (GInstanceInitFunc) atom_content_init, + NULL + }; + + atom_content_type = g_type_register_static (TYPE_ATOM_COMMON, "AtomContent", + &atom_content_info, 0); + } + + return atom_content_type; +} + +static void +atom_content_class_init (AtomContentClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (AtomContentPrivate)); + + object_class->set_property = atom_content_set_property; + object_class->get_property = atom_content_get_property; + + g_object_class_install_property (object_class, PROP_TYPE, + g_param_spec_uint ("type", + "Type", + "Type", + 0, 2, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, PROP_MEDIA_TYPE, + g_param_spec_string ("media-type", + "Media Type", + "Media Type", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, PROP_SRC, + g_param_spec_string ("src", + "Src", + "Src", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, PROP_TEXT, + g_param_spec_string ("text", + "Text", + "Text", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); +} + +static void +atom_content_init (AtomContent *atom_content) +{ +} + +/** + * atom_content_new: + * + * Returns: the newly created #AtomContent object. + */ +AtomContent +*atom_content_new (AtomContentType type) +{ + AtomContent *atomtext = ATOM_CONTENT (g_object_new (atom_content_get_type (), NULL)); + + g_object_set (G_OBJECT (atomtext), + "type", type, + NULL); + + return atomtext; +} + +/** + * atom_content_new_from_xml: + * @xnode: an #xmlNode. + * + * Returns: the newly created #AtomContent object. + */ +AtomContent +*atom_content_new_from_xml (xmlNode *xnode) +{ + AtomContent *atom_content = NULL; + AtomContentType atomtype; + gchar *text; + + gchar *type = g_strstrip ((gchar *)xmlGetProp ((xmlNodePtr)xnode, (const xmlChar *)"type")); + if (type == NULL || strcmp (type, "") == 0 || strcmp (type, "text") == 0) + { + atomtype = ATOM_CONTENT_TEXT; + } + else if (strcmp (type, "html") == 0) + { + atomtype = ATOM_CONTENT_HTML; + } + else if (strcmp (type, "xhtml") == 0) + { + atomtype = ATOM_CONTENT_XHTML; + } + else + { + atomtype = ATOM_CONTENT_MEDIA; + } + + if (atomtype == ATOM_CONTENT_TEXT || atomtype == ATOM_CONTENT_HTML || atomtype == ATOM_CONTENT_MEDIA) + { + text = (gchar *)xmlNodeGetContent ((xmlNodePtr)xnode); + } + else if (atomtype == ATOM_CONTENT_XHTML) + { + xmlXPathObjectPtr xpresult; + xmlXPathContextPtr xpcontext = xmlXPathNewContext (xnode->doc); + + xmlXPathRegisterNs (xpcontext, (const xmlChar *)"xhtml", (const xmlChar *)"http://www.w3.org/1999/xhtml"); + + xpcontext->node = xnode; + xpresult = xmlXPathEvalExpression ((const xmlChar *)"child::xhtml:div", xpcontext); + if (xpresult == NULL || xpresult->nodesetval == NULL || xpresult->nodesetval->nodeNr != 1) + { + g_critical ("Invalid AtomContent type xhtml."); + return NULL; + } + else + { + text = (gchar *)xmlNodeGetContent ((xmlNodePtr)xpresult->nodesetval->nodeTab[0]); + } + } + + atom_content = atom_content_new (atomtype); + + if (atomtype == ATOM_CONTENT_MEDIA) + { + gchar *src = (gchar *)xmlGetProp (xnode, (const xmlChar *)"src"); + if (src != NULL) + { + text = NULL; + g_object_set (G_OBJECT (atom_content), + "src", src, + NULL); + } + } + + if (atom_content != NULL) + { + atom_common_set_properties_from_xml (ATOM_COMMON (atom_content), xnode); + + if (text != NULL) + { + g_object_set (G_OBJECT (atom_content), + "text", text, + NULL); + } + } + + return atom_content; +} + +/** + * atom_content_get_xml: + * @atom_content: an #AtomContent object. + * @xnode: an #xmlNode. + * + */ +void +atom_content_get_xml (AtomContent *atom_content, xmlNode *xnode) +{ + gchar *type; + + AtomContentPrivate *priv = ATOM_CONTENT_GET_PRIVATE (atom_content); + + atom_common_get_xml (ATOM_COMMON (atom_content), xnode); + + switch (priv->type) + { + case ATOM_CONTENT_TEXT: + type = g_strdup ("text"); + break; + + case ATOM_CONTENT_HTML: + type = g_strdup ("html"); + break; + + case ATOM_CONTENT_XHTML: + type = g_strdup ("xhtml"); + break; + + case ATOM_CONTENT_MEDIA: + type = g_strdup (priv->media_type); + break; + } + + xmlSetProp (xnode, (const xmlChar *)"type", (const xmlChar *)type); + + if (priv->type == ATOM_CONTENT_MEDIA && strcmp (priv->src, "") != 0) + { + xmlSetProp (xnode, (const xmlChar *)"src", (const xmlChar *)priv->src); + } + else if (priv->type == ATOM_CONTENT_XHTML) + { + xmlNode *new_xnode = xmlNewNode (NULL, (const xmlChar *)"xhtml:div"); + xmlNewNs (new_xnode, (const xmlChar *)"http://www.w3.org/1999/xhtml", (const xmlChar *)"xhtml"); + xmlNodeSetContent (new_xnode, (const xmlChar *)priv->text); + xmlAddChild (xnode, new_xnode); + } + else + { + xmlNodeSetContent (xnode, (const xmlChar *)priv->text); + } +} + +static void +atom_content_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + AtomContent *atom_content = ATOM_CONTENT (object); + + AtomContentPrivate *priv = ATOM_CONTENT_GET_PRIVATE (atom_content); + + switch (property_id) + { + case PROP_TYPE: + priv->type = g_value_get_uint (value); + break; + + case PROP_MEDIA_TYPE: + priv->media_type = g_strstrip (g_value_dup_string (value)); + break; + + case PROP_SRC: + priv->src = g_strstrip (g_value_dup_string (value)); + break; + + case PROP_TEXT: + priv->text = g_strstrip (g_value_dup_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +atom_content_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + AtomContent *atom_content = ATOM_CONTENT (object); + + AtomContentPrivate *priv = ATOM_CONTENT_GET_PRIVATE (atom_content); + + switch (property_id) + { + case PROP_TYPE: + g_value_set_int (value, priv->type); + break; + + case PROP_MEDIA_TYPE: + g_value_set_string (value, priv->media_type); + break; + + case PROP_SRC: + g_value_set_string (value, priv->src); + break; + + case PROP_TEXT: + g_value_set_string (value, priv->text); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} diff --git a/src/atomcontent.h b/src/atomcontent.h new file mode 100644 index 0000000..df160e2 --- /dev/null +++ b/src/atomcontent.h @@ -0,0 +1,72 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __ATOM_CONTENT_H__ +#define __ATOM_CONTENT_H__ + +#include +#include + +#include "atomcommon.h" + +G_BEGIN_DECLS + + +#define TYPE_ATOM_CONTENT (atom_content_get_type ()) +#define ATOM_CONTENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_ATOM_CONTENT, AtomContent)) +#define ATOM_CONTENT_COMMON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_ATOM_CONTENT, AtomContentClass)) +#define IS_ATOM_CONTENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_ATOM_CONTENT)) +#define IS_ATOM_CONTENT_COMMON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_ATOM_CONTENT)) +#define ATOM_CONTENT_COMMON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_ATOM_CONTENT, AtomContentClass)) + + +typedef struct _AtomContent AtomContent; +typedef struct _AtomContentClass AtomContentClass; + +struct _AtomContent + { + AtomCommon parent; + }; + +struct _AtomContentClass + { + AtomCommonClass parent_class; + }; + +typedef enum +{ + ATOM_CONTENT_TEXT, + ATOM_CONTENT_HTML, + ATOM_CONTENT_XHTML, + ATOM_CONTENT_MEDIA +} AtomContentType; + +GType atom_content_get_type (void) G_GNUC_CONST; + +AtomContent *atom_content_new (AtomContentType type); +AtomContent *atom_content_new_from_xml (xmlNode *xnode); + +void atom_content_get_xml (AtomContent *atom_content, xmlNode *xnode); + + +G_END_DECLS + +#endif /* __ATOM_CONTENT_H__ */ diff --git a/src/atomdate.c b/src/atomdate.c new file mode 100644 index 0000000..ec82b15 --- /dev/null +++ b/src/atomdate.c @@ -0,0 +1,217 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#include "atomdate.h" + +enum +{ + PROP_0, + PROP_DATE +}; + +static void atom_date_class_init (AtomDateClass *klass); +static void atom_date_init (AtomDate *atom_date); + +static void atom_date_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void atom_date_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +#define ATOM_DATE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_ATOM_DATE, AtomDatePrivate)) + +typedef struct _AtomDatePrivate AtomDatePrivate; +struct _AtomDatePrivate + { + struct tm *dateTime; + }; + +GType +atom_date_get_type (void) +{ + static GType atom_date_type = 0; + + if (!atom_date_type) + { + static const GTypeInfo atom_date_info = + { + sizeof (AtomDateClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) atom_date_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (AtomDate), + 0, /* n_preallocs */ + (GInstanceInitFunc) atom_date_init, + NULL + }; + + atom_date_type = g_type_register_static (TYPE_ATOM_COMMON, "AtomDate", + &atom_date_info, 0); + } + + return atom_date_type; +} + +static void +atom_date_class_init (AtomDateClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (AtomDatePrivate)); + + object_class->set_property = atom_date_set_property; + object_class->get_property = atom_date_get_property; + + g_object_class_install_property (object_class, PROP_DATE, + g_param_spec_pointer ("date", + "Date", + "Date", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); +} + +static void +atom_date_init (AtomDate *atom_date) +{ +} + +/** + * atom_date_new: + * @dateTime: a tm struct. + * + * Returns: the newly created #AtomDate object. + */ +AtomDate +*atom_date_new (struct tm dateTime) +{ + AtomDate *atomdate = ATOM_DATE (g_object_new (atom_date_get_type (), NULL)); + + g_object_set (G_OBJECT (atomdate), + "date", &dateTime, + NULL); + + return atomdate; +} + +/** + * atom_date_new_from_xml: + * @xnode: an #xmlNode. + * + * Returns: the newly created #AtomDate object. + */ +AtomDate +*atom_date_new_from_xml (xmlNode *xnode) +{ + AtomDate *atom_date = NULL; + + gchar *date = (gchar *)xmlNodeGetContent ((xmlNodePtr)xnode); + if (date == NULL) + { + g_critical ("Invalid date content."); + } + else + { + struct tm dateTime; + + gchar *ret = (gchar *)strptime (g_strstrip (date), "%Y-%m-%dT%H:%M:%SZ", &dateTime); + if (ret != NULL) + { + atom_date = atom_date_new (dateTime); + if (atom_date != NULL) + { + atom_common_set_properties_from_xml (ATOM_COMMON (atom_date), xnode); + } + } + } + + return atom_date; +} + +/** + * atom_date_get_xml: + * @atom_date: an #AtomDate object. + * @xnode: the #xmlNode to fill. + * + */ +void +atom_date_get_xml (AtomDate *atom_date, xmlNode *xnode) +{ + gchar *buf; + + AtomDatePrivate *priv = ATOM_DATE_GET_PRIVATE (atom_date); + + atom_common_get_xml (ATOM_COMMON (atom_date), xnode); + + buf = g_strdup_printf ("%04d-%02d-%02dT%02d:%02d:%02dZ", + priv->dateTime->tm_year + 1900, + priv->dateTime->tm_mon + 1, + priv->dateTime->tm_mday, + priv->dateTime->tm_hour, + priv->dateTime->tm_min, + priv->dateTime->tm_sec); + + xmlNodeSetContent (xnode, (const xmlChar *)buf); +} + +static void +atom_date_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + AtomDate *atom_date = ATOM_DATE (object); + + AtomDatePrivate *priv = ATOM_DATE_GET_PRIVATE (atom_date); + + switch (property_id) + { + case PROP_DATE: + if (g_value_get_pointer (value) != NULL) + { + priv->dateTime = (struct tm *)g_memdup ((gconstpointer)g_value_get_pointer (value), sizeof (struct tm)); + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +atom_date_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + AtomDate *atom_date = ATOM_DATE (object); + + AtomDatePrivate *priv = ATOM_DATE_GET_PRIVATE (atom_date); + + switch (property_id) + { + case PROP_DATE: + g_value_set_pointer (value, priv->dateTime); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} diff --git a/src/atomdate.h b/src/atomdate.h new file mode 100644 index 0000000..ab13d9b --- /dev/null +++ b/src/atomdate.h @@ -0,0 +1,66 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __ATOM_DATE_H__ +#define __ATOM_DATE_H__ + +#include + +#include +#include + +#include "atomcommon.h" + +G_BEGIN_DECLS + + +#define TYPE_ATOM_DATE (atom_date_get_type ()) +#define ATOM_DATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_ATOM_DATE, AtomDate)) +#define ATOM_DATE_COMMON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_ATOM_DATE, AtomDateClass)) +#define IS_ATOM_DATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_ATOM_DATE)) +#define IS_ATOM_DATE_COMMON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_ATOM_DATE)) +#define ATOM_DATE_COMMON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_ATOM_DATE, AtomDateClass)) + + +typedef struct _AtomDate AtomDate; +typedef struct _AtomDateClass AtomDateClass; + +struct _AtomDate + { + AtomCommon parent; + }; + +struct _AtomDateClass + { + AtomCommonClass parent_class; + }; + +GType atom_date_get_type (void) G_GNUC_CONST; + +AtomDate *atom_date_new (struct tm dateTime); +AtomDate *atom_date_new_from_xml (xmlNode *xnode); + +void atom_date_get_xml (AtomDate *atom_date, xmlNode *xnode); + + +G_END_DECLS + +#endif /* __ATOM_DATE_H__ */ diff --git a/src/atomentry.c b/src/atomentry.c new file mode 100644 index 0000000..19d67b5 --- /dev/null +++ b/src/atomentry.c @@ -0,0 +1,680 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#include + +#include "atomentry.h" +#include "atomperson.h" +#include "atomcategory.h" +#include "atomcontent.h" +#include "atomlink.h" +#include "atomsource.h" + +enum +{ + PROP_0, + PROP_AUTHOR, + PROP_CATEGORY, + PROP_CONTENT, + PROP_CONTRIBUTOR, + PROP_ID, + PROP_LINK, + PROP_PUBLISHED, + PROP_RIGHTS, + PROP_SOURCE, + PROP_SUMMARY, + PROP_TITLE, + PROP_UPDATED +}; + +static void atom_entry_class_init (AtomEntryClass *klass); +static void atom_entry_init (AtomEntry *atome); + +static void atom_entry_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void atom_entry_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +#define ATOM_ENTRY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_ATOM_ENTRY, AtomEntryPrivate)) + +typedef struct _AtomEntryPrivate AtomEntryPrivate; +struct _AtomEntryPrivate + { + GList *author, + *category, + *contributor; + AtomContent *content; + AtomID *id; + AtomLink *link; + AtomText *title, + *rights, + *summary; + AtomDate *published, + *updated; + AtomSource *source; + }; + +GType +atom_entry_get_type (void) +{ + static GType atom_entry_type = 0; + + if (!atom_entry_type) + { + static const GTypeInfo atom_entry_info = + { + sizeof (AtomEntryClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) atom_entry_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (AtomEntry), + 0, /* n_preallocs */ + (GInstanceInitFunc) atom_entry_init, + NULL + }; + + atom_entry_type = g_type_register_static (TYPE_ATOM_COMMON, "AtomEntry", + &atom_entry_info, 0); + } + + return atom_entry_type; +} + +static void +atom_entry_class_init (AtomEntryClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (AtomEntryPrivate)); + + object_class->set_property = atom_entry_set_property; + object_class->get_property = atom_entry_get_property; + + g_object_class_install_property (object_class, PROP_AUTHOR, + g_param_spec_pointer ("author", + "Author", + "An #AtomPerson object that indicates the author of the entry.", + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_CATEGORY, + g_param_spec_pointer ("category", + "Category", + "Information about a category associated with an entry.", + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_CONTENT, + g_param_spec_object ("content", + "Content", + "Either contains or links to the content of the entry.", + TYPE_ATOM_CONTENT, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_CONTRIBUTOR, + g_param_spec_pointer ("contributor", + "Contributor", + "Indicates a person or other entity who contributed to the entry or feed.", + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_ID, + g_param_spec_object ("id", + "Id", + "A permanent, universally unique identifier for an entry.", + TYPE_ATOM_ID, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_LINK, + g_param_spec_object ("link", + "Link", + "An #AtomLink defines a reference from an entry or feed to a Web resource.", + TYPE_ATOM_LINK, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_PUBLISHED, + g_param_spec_object ("published", + "Published", + "An #AtomDate object indicating an instant in time associated with an event early in the life cycle of the entry.", + TYPE_ATOM_DATE, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_RIGHTS, + g_param_spec_object ("rights", + "Rights", + "Conveys information about rights held in and over an entry.", + TYPE_ATOM_TEXT, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_SOURCE, + g_param_spec_object ("source", + "Source", + "Source", + TYPE_ATOM_SOURCE, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_SUMMARY, + g_param_spec_object ("summary", + "Summary", + "Conveys a short summary, abstract, or excerpt of an entry.", + TYPE_ATOM_TEXT, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_TITLE, + g_param_spec_object ("title", + "Title", + "A human-readable title for the entry.", + TYPE_ATOM_TEXT, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_UPDATED, + g_param_spec_object ("updated", + "Updated", + "The most recent instant in time when the entry was modified in a way the publisher considers significant.", + TYPE_ATOM_DATE, + G_PARAM_READWRITE)); +} + +static void +atom_entry_init (AtomEntry *atome) +{ +} + +/** + * atom_entry_new: + * @id: a permanent, universally unique identifier for an entry or feed. + * @title: a human-readable title for an entry or feed. + * @updated: the most recent instant in time when an entry or feed was modified in a way the publisher considers significant. + * + * Returns: the newly created #AtomEntry object. + */ +AtomEntry +*atom_entry_new (AtomID *id, AtomText *title, AtomDate *updated) +{ + AtomEntry *atom_entry = ATOM_ENTRY (g_object_new (atom_entry_get_type (), NULL)); + + g_object_set (G_OBJECT (atom_entry), + "id", id, + "title", title, + "updated", updated, + NULL); + + return atom_entry; +} + +/** + * atom_entry_new_from_xml: + * @xnode: an #xmlNode. + * + * Returns: the newly created #AtomEntry object. + */ +AtomEntry +*atom_entry_new_from_xml (xmlNode *xnode) +{ + AtomEntry *atom_entry = NULL; + + AtomID *id = NULL; + AtomText *title = NULL; + AtomDate *updated = NULL; + + xmlXPathObjectPtr xpresult; + xmlXPathContextPtr xpcontext = xmlXPathNewContext (xnode->doc); + + xmlXPathRegisterNs (xpcontext, (const xmlChar *)"atom", (const xmlChar *)"http://www.w3.org/2005/Atom"); + + /* searching for id */ + xpcontext->node = xnode; + xpresult = xmlXPathEvalExpression ((const xmlChar *)"child::atom:id", xpcontext); + if (xpresult == NULL || xpresult->nodesetval == NULL || xpresult->nodesetval->nodeNr != 1) + { + g_critical ("Atom entry must contain one and only id element."); + } + else + { + id = atom_id_new_from_xml (xpresult->nodesetval->nodeTab[0]); + if (id == NULL) + { + g_critical ("Invalid id element."); + } + } + + /* searching for title */ + xpcontext->node = xnode; + xpresult = xmlXPathEvalExpression ((const xmlChar *)"child::atom:title", xpcontext); + if (xpresult == NULL || xpresult->nodesetval == NULL || xpresult->nodesetval->nodeNr != 1) + { + g_critical ("Atom entry must contain one and only title element."); + } + else + { + title = atom_text_new_from_xml (xpresult->nodesetval->nodeTab[0]); + if (title == NULL) + { + g_critical ("Invalid title element."); + } + } + + /* searching for updated */ + xpcontext->node = xnode; + xpresult = xmlXPathEvalExpression ((const xmlChar *)"child::atom:updated", xpcontext); + if (xpresult == NULL || xpresult->nodesetval == NULL || xpresult->nodesetval->nodeNr != 1) + { + g_critical ("Atom entry must contain one and only updated element."); + } + else + { + updated = atom_date_new_from_xml (xpresult->nodesetval->nodeTab[0]); + if (updated == NULL) + { + g_critical ("Invalid updated element."); + } + } + + if (id != NULL && title != NULL && updated != NULL) + { + atom_entry = atom_entry_new (id, title, updated); + + AtomEntryPrivate *priv = ATOM_ENTRY_GET_PRIVATE (atom_entry); + + atom_common_set_properties_from_xml (ATOM_COMMON (atom_entry), xnode); + + xmlNode *cur = xnode->children; + + while (cur != NULL) + { + if (xmlStrcmp (cur->name, (const xmlChar *)"author") == 0) + { + AtomPerson *ap = atom_person_new_from_xml (cur); + if (ap != NULL) + { + priv->author = g_list_append (priv->author, ap); + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"category") == 0) + { + AtomCategory *ac = atom_category_new_from_xml (cur); + if (ac != NULL) + { + priv->category = g_list_append (priv->category, ac); + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"content") == 0) + { + AtomContent *ac = atom_content_new_from_xml (cur); + if (ac != NULL) + { + priv->content = ac; + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"contributor") == 0) + { + AtomPerson *ap = atom_person_new_from_xml (cur); + if (ap != NULL) + { + priv->contributor = g_list_append (priv->contributor, ap); + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"id") == 0) + { + AtomID *id = atom_id_new_from_xml (cur); + if (id == NULL) + { + priv->id = id; + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"link") == 0) + { + AtomLink *link = atom_link_new_from_xml (cur); + if (link == NULL) + { + priv->link = link; + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"published") == 0) + { + AtomDate *published = atom_date_new_from_xml (cur); + if (published != NULL) + { + priv->published = published; + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"rights") == 0) + { + AtomText *rights = atom_text_new_from_xml (cur); + if (rights != NULL) + { + priv->rights = rights; + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"source") == 0) + { + AtomSource *source = atom_source_new_from_xml (cur); + if (source != NULL) + { + priv->source = source; + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"summary") == 0) + { + AtomText *summary = atom_text_new_from_xml (cur); + if (summary != NULL) + { + priv->summary = summary; + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"title") == 0) + { + AtomText *title = atom_text_new_from_xml (cur); + if (title != NULL) + { + priv->title = title; + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"updated") == 0) + { + AtomDate *updated = atom_date_new_from_xml (cur); + if (updated != NULL) + { + priv->updated = updated; + } + } + + cur = cur->next; + } + } + + return atom_entry; +} + +/** + * atatom_entry_get_xml: + * @atom_entry: an #AtomEntry object. + * @xnode: an #xmlNode. + * + */ +void +atom_entry_get_xml (AtomEntry *atom_entry, xmlNode *xnode) +{ + xmlNode *xnodenew; + GList *lst; + + AtomEntryPrivate *priv = ATOM_ENTRY_GET_PRIVATE (atom_entry); + + atom_common_get_xml (ATOM_COMMON (atom_entry), xnode); + + lst = g_list_first (priv->author); + while (lst != NULL) + { + if (IS_ATOM_PERSON (lst->data)) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"author"); + xmlAddChild (xnode, xnodenew); + atom_person_get_xml (ATOM_PERSON (lst->data), xnodenew); + } + + lst = g_list_next (lst); + } + + lst = g_list_first (priv->category); + while (lst != NULL) + { + if (IS_ATOM_CATEGORY (lst->data)) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"category"); + xmlAddChild (xnode, xnodenew); + atom_category_get_xml (ATOM_CATEGORY (lst->data), xnodenew); + } + + lst = g_list_next (lst); + } + + if (priv->content != NULL) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"content"); + xmlAddChild (xnode, xnodenew); + atom_content_get_xml (priv->content, xnodenew); + } + + lst = g_list_first (priv->contributor); + while (lst != NULL) + { + if (IS_ATOM_PERSON (lst->data)) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"contributor"); + xmlAddChild (xnode, xnodenew); + atom_person_get_xml (ATOM_PERSON (lst->data), xnodenew); + } + + lst = g_list_next (lst); + } + + if (priv->id != NULL) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"id"); + xmlAddChild (xnode, xnodenew); + atom_id_get_xml (priv->id, xnodenew); + } + + if (priv->link != NULL) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"link"); + xmlAddChild (xnode, xnodenew); + atom_link_get_xml (priv->link, xnodenew); + } + + if (priv->published != NULL) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"published"); + xmlAddChild (xnode, xnodenew); + atom_date_get_xml (priv->published, xnodenew); + } + + if (priv->rights != NULL) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"rights"); + xmlAddChild (xnode, xnodenew); + atom_text_get_xml (priv->rights, xnodenew); + } + + if (priv->source != NULL) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"source"); + xmlAddChild (xnode, xnodenew); + atom_source_get_xml (priv->source, xnodenew); + } + + if (priv->summary != NULL) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"summary"); + xmlAddChild (xnode, xnodenew); + atom_text_get_xml (priv->summary, xnodenew); + } + + if (priv->title != NULL) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"title"); + xmlAddChild (xnode, xnodenew); + atom_text_get_xml (priv->title, xnodenew); + } + + if (priv->updated != NULL) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"updated"); + xmlAddChild (xnode, xnodenew); + atom_date_get_xml (priv->updated, xnodenew); + } +} + +static void +atom_entry_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + GObject *obj; + + AtomEntry *atome = ATOM_ENTRY (object); + + AtomEntryPrivate *priv = ATOM_ENTRY_GET_PRIVATE (atome); + + switch (property_id) + { + case PROP_AUTHOR: + if (g_value_get_pointer (value) != NULL) + { + priv->author = (GList *)g_memdup ((gconstpointer)g_value_get_pointer (value), sizeof (GList)); + } + break; + + case PROP_CATEGORY: + if (g_value_get_pointer (value) != NULL) + { + priv->category = (GList *)g_memdup ((gconstpointer)g_value_get_pointer (value), sizeof (GList)); + } + break; + + case PROP_CONTENT: + if (g_value_get_object (value) != NULL && IS_ATOM_CONTENT (g_value_get_object (value))) + { + priv->content = (AtomContent *)g_value_dup_object (value); + } + break; + + case PROP_CONTRIBUTOR: + if (g_value_get_pointer (value) != NULL) + { + priv->contributor = (GList *)g_memdup ((gconstpointer)g_value_get_pointer (value), sizeof (GList)); + } + break; + + case PROP_ID: + if (g_value_get_object (value) != NULL && IS_ATOM_ID (g_value_get_object (value))) + { + priv->id = (AtomID *)g_value_dup_object (value); + } + break; + + case PROP_LINK: + if (g_value_get_object (value) != NULL && IS_ATOM_LINK (g_value_get_object (value))) + { + priv->link = (AtomLink *)g_value_dup_object (value); + } + break; + + case PROP_RIGHTS: + if (g_value_get_object (value) != NULL && IS_ATOM_TEXT (g_value_get_object (value))) + { + priv->rights = (AtomText *)g_value_dup_object (value); + } + break; + + case PROP_SOURCE: + if (g_value_get_object (value) != NULL && IS_ATOM_SOURCE (g_value_get_object (value))) + { + priv->source = (AtomSource *)g_value_dup_object (value); + } + break; + + case PROP_SUMMARY: + if (g_value_get_object (value) != NULL && IS_ATOM_TEXT (g_value_get_object (value))) + { + priv->summary = (AtomText *)g_value_dup_object (value); + } + break; + + case PROP_TITLE: + if (g_value_get_object (value) != NULL && IS_ATOM_TEXT (g_value_get_object (value))) + { + priv->title = (AtomText *)g_value_dup_object (value); + } + break; + + case PROP_UPDATED: + if (g_value_get_object (value) != NULL && IS_ATOM_DATE (g_value_get_object (value))) + { + priv->updated = (AtomDate *)g_value_dup_object (value); + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +atom_entry_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + AtomEntry *atome = ATOM_ENTRY (object); + + AtomEntryPrivate *priv = ATOM_ENTRY_GET_PRIVATE (atome); + + switch (property_id) + { + case PROP_AUTHOR: + g_value_set_pointer (value, priv->author); + break; + + case PROP_CATEGORY: + g_value_set_pointer (value, priv->category); + break; + + case PROP_CONTENT: + g_value_set_object (value, priv->content); + break; + + case PROP_CONTRIBUTOR: + g_value_set_pointer (value, priv->contributor); + break; + + case PROP_ID: + g_value_set_object (value, priv->id); + break; + + case PROP_LINK: + g_value_set_object (value, priv->link); + break; + + case PROP_SOURCE: + g_value_set_object (value, priv->source); + break; + + case PROP_RIGHTS: + g_value_set_object (value, priv->rights); + break; + + case PROP_SUMMARY: + g_value_set_object (value, priv->summary); + break; + + case PROP_TITLE: + g_value_set_object (value, priv->title); + break; + + case PROP_UPDATED: + g_value_set_object (value, priv->updated); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} diff --git a/src/atomentry.h b/src/atomentry.h new file mode 100644 index 0000000..90e0654 --- /dev/null +++ b/src/atomentry.h @@ -0,0 +1,68 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __ATOM_ENTRY_H__ +#define __ATOM_ENTRY_H__ + +#include +#include +#include + +#include "atomcommon.h" +#include "atomid.h" +#include "atomtext.h" +#include "atomdate.h" + +G_BEGIN_DECLS + + +#define TYPE_ATOM_ENTRY (atom_entry_get_type ()) +#define ATOM_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_ATOM_ENTRY, AtomEntry)) +#define ATOM_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_ATOM_ENTRY, AtomEntryClass)) +#define IS_ATOM_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_ATOM_ENTRY)) +#define IS_ATOM_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_ATOM_ENTRY)) +#define ATOM_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_ATOM_ENTRY, AtomEntryClass)) + + +typedef struct _AtomEntry AtomEntry; +typedef struct _AtomEntryClass AtomEntryClass; + +struct _AtomEntry + { + AtomCommon parent; + }; + +struct _AtomEntryClass + { + AtomCommonClass parent_class; + }; + +GType atom_entry_get_type (void) G_GNUC_CONST; + +AtomEntry *atom_entry_new (AtomID *id, AtomText *title, AtomDate *updated); +AtomEntry *atom_entry_new_from_xml (xmlNode *xnode); + +void atom_entry_get_xml (AtomEntry *atom_entry, xmlNode *xnode); + + +G_END_DECLS + +#endif /* __ATOM_ENTRY_H__ */ diff --git a/src/atomgenerator.c b/src/atomgenerator.c new file mode 100644 index 0000000..a8236b4 --- /dev/null +++ b/src/atomgenerator.c @@ -0,0 +1,271 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#include "atomgenerator.h" + +enum +{ + PROP_0, + PROP_URI, + PROP_VERSION, + PROP_TEXT +}; + +static void atom_generator_class_init (AtomGeneratorClass *klass); +static void atom_generator_init (AtomGenerator *atom_generator); + +static void atom_generator_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void atom_generator_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +#define ATOM_GENERATOR_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_ATOM_GENERATOR, AtomGeneratorPrivate)) + +typedef struct _AtomGeneratorPrivate AtomGeneratorPrivate; +struct _AtomGeneratorPrivate + { + gchar *uri, + *version, + *text; + }; + +GType +atom_generator_get_type (void) +{ + static GType atom_generator_type = 0; + + if (!atom_generator_type) + { + static const GTypeInfo atom_generator_info = + { + sizeof (AtomGeneratorClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) atom_generator_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (AtomGenerator), + 0, /* n_preallocs */ + (GInstanceInitFunc) atom_generator_init, + NULL + }; + + atom_generator_type = g_type_register_static (TYPE_ATOM_COMMON, "AtomGenerator", + &atom_generator_info, 0); + } + + return atom_generator_type; +} + +static void +atom_generator_class_init (AtomGeneratorClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (AtomGeneratorPrivate)); + + object_class->set_property = atom_generator_set_property; + object_class->get_property = atom_generator_get_property; + + g_object_class_install_property (object_class, PROP_URI, + g_param_spec_string ("uri", + "URI", + "URI", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, PROP_VERSION, + g_param_spec_string ("version", + "Version", + "The version of the generating agent.", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, PROP_TEXT, + g_param_spec_string ("text", + "Text", + "A string that is a human-readable name for the generating agent.", + "", + G_PARAM_READWRITE)); +} + +static void +atom_generator_init (AtomGenerator *atom_generator) +{ +} + +/** + * atom_generator_new: + * @text: a string that is a human-readable name for the generating agent. + * + * Returns: the newly created #AtomGenerator object. + */ +AtomGenerator +*atom_generator_new (const gchar *text) +{ + AtomGenerator *atom_generator = ATOM_GENERATOR (g_object_new (atom_generator_get_type (), NULL)); + + g_object_set (G_OBJECT (atom_generator), + "text", text, + NULL); + + return atom_generator; +} + +/** + * atom_generator_new_from_xml: + * @xnode: an #xmlNode. + * + * Returns: the newly created #AtomGenerator object. + */ +AtomGenerator +*atom_generator_new_from_xml (xmlNode *xnode) +{ + AtomGenerator *atom_generator = NULL; + + gchar *text = (gchar *)xmlNodeGetContent (xnode); + if (text != NULL && strcmp (g_strstrip (text), "") == 0) + { + g_critical ("AtomGenerator must have a text content."); + return NULL; + } + + atom_generator = atom_generator_new (text); + if (atom_generator != NULL) + { + atom_common_set_properties_from_xml (ATOM_COMMON (atom_generator), xnode); + + text = (gchar *)xmlGetProp (xnode, (const xmlChar *)"uri"); + if (text != NULL && strcmp (g_strstrip (text), "") != 0) + { + g_object_set (G_OBJECT (atom_generator), + "uri", text, + NULL); + } + + text = (gchar *)xmlGetProp (xnode, (const xmlChar *)"version"); + if (text != NULL && strcmp (g_strstrip (text), "") != 0) + { + g_object_set (G_OBJECT (atom_generator), + "version", text, + NULL); + } + } + + return atom_generator; +} + +/** + * atom_generator_get_xml: + * @atom_generator: an #AtomGenerator object. + * @xnode: an #xmlNode. + * + */ +void +atom_generator_get_xml (AtomGenerator *atom_generator, xmlNode *xnode) +{ + xmlNode *new_xnode; + + AtomGeneratorPrivate *priv = ATOM_GENERATOR_GET_PRIVATE (atom_generator); + + atom_common_get_xml (ATOM_COMMON (atom_generator), xnode); + + if (strcmp (priv->uri, "") != 0) + { + xmlSetProp (xnode, (const xmlChar *)"uri", (const xmlChar *)priv->uri); + } + if (strcmp (priv->version, "") != 0) + { + xmlSetProp (xnode, (const xmlChar *)"version", (const xmlChar *)priv->version); + } + + new_xnode = xmlNewNode (NULL, (const xmlChar *)"text"); + xmlNodeSetContent (new_xnode, (const xmlChar *)priv->text); + xmlAddChild (xnode, new_xnode); +} + +static void +atom_generator_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + AtomGenerator *atom_generator = ATOM_GENERATOR (object); + + AtomGeneratorPrivate *priv = ATOM_GENERATOR_GET_PRIVATE (atom_generator); + + switch (property_id) + { + case PROP_URI: + priv->uri = g_strstrip (g_value_dup_string (value)); + break; + + case PROP_VERSION: + priv->version = g_strstrip (g_value_dup_string (value)); + break; + + case PROP_TEXT: + { + gchar *text = g_strstrip (g_value_dup_string (value)); + if (strcmp (text, "") == 0) + { + g_warning ("Property text must not be empty."); + } + else + { + priv->text = text; + } + break; + } + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +atom_generator_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + AtomGenerator *atom_generator = ATOM_GENERATOR (object); + + AtomGeneratorPrivate *priv = ATOM_GENERATOR_GET_PRIVATE (atom_generator); + + switch (property_id) + { + case PROP_URI: + g_value_set_string (value, priv->uri); + break; + + case PROP_VERSION: + g_value_set_string (value, priv->version); + break; + + case PROP_TEXT: + g_value_set_string (value, priv->text); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} diff --git a/src/atomgenerator.h b/src/atomgenerator.h new file mode 100644 index 0000000..246ec98 --- /dev/null +++ b/src/atomgenerator.h @@ -0,0 +1,64 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __ATOM_GENERATOR_H__ +#define __ATOM_GENERATOR_H__ + +#include +#include + +#include "atomcommon.h" + +G_BEGIN_DECLS + + +#define TYPE_ATOM_GENERATOR (atom_generator_get_type ()) +#define ATOM_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_ATOM_GENERATOR, AtomGenerator)) +#define ATOM_GENERATOR_COMMON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_ATOM_GENERATOR, AtomGeneratorClass)) +#define IS_ATOM_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_ATOM_GENERATOR)) +#define IS_ATOM_GENERATOR_COMMON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_ATOM_GENERATOR)) +#define ATOM_GENERATOR_COMMON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_ATOM_GENERATOR, AtomGeneratorClass)) + + +typedef struct _AtomGenerator AtomGenerator; +typedef struct _AtomGeneratorClass AtomGeneratorClass; + +struct _AtomGenerator + { + AtomCommon parent; + }; + +struct _AtomGeneratorClass + { + AtomCommonClass parent_class; + }; + +GType atom_generator_get_type (void) G_GNUC_CONST; + +AtomGenerator *atom_generator_new (const gchar *text); +AtomGenerator *atom_generator_new_from_xml (xmlNode *xnode); + +void atom_generator_get_xml (AtomGenerator *atom_generator, xmlNode *xnode); + + +G_END_DECLS + +#endif /* __ATOM_GENERATOR_H__ */ diff --git a/src/atomid.c b/src/atomid.c new file mode 100644 index 0000000..1dcbfff --- /dev/null +++ b/src/atomid.c @@ -0,0 +1,211 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#include "atomid.h" + +enum +{ + PROP_0, + PROP_URI +}; + +static void atom_id_class_init (AtomIDClass *klass); +static void atom_id_init (AtomID *atom_id); + +static void atom_id_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void atom_id_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +#define ATOM_ID_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_ATOM_ID, AtomIDPrivate)) + +typedef struct _AtomIDPrivate AtomIDPrivate; +struct _AtomIDPrivate + { + gchar *uri; + }; + +GType +atom_id_get_type (void) +{ + static GType atom_id_type = 0; + + if (!atom_id_type) + { + static const GTypeInfo atom_id_info = + { + sizeof (AtomIDClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) atom_id_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (AtomID), + 0, /* n_preallocs */ + (GInstanceInitFunc) atom_id_init, + NULL + }; + + atom_id_type = g_type_register_static (TYPE_ATOM_COMMON, "AtomID", + &atom_id_info, 0); + } + + return atom_id_type; +} + +static void +atom_id_class_init (AtomIDClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (AtomIDPrivate)); + + object_class->set_property = atom_id_set_property; + object_class->get_property = atom_id_get_property; + + g_object_class_install_property (object_class, PROP_URI, + g_param_spec_string ("uri", + "URI", + "URI", + "", + G_PARAM_READWRITE)); +} + +static void +atom_id_init (AtomID *atom_id) +{ +} + +/** + * atom_id_new: + * @uri: + * + * Returns: the newly created #AtomID object. + */ +AtomID +*atom_id_new (const gchar *uri) +{ + gchar *uri_new = ""; + AtomID *atomid = ATOM_ID (g_object_new (atom_id_get_type (), NULL)); + + g_object_set (G_OBJECT (atomid), + "uri", uri, + NULL); + + g_object_get (G_OBJECT (atomid), + "uri", &uri_new, + NULL); + + return (strcmp (uri_new, "") != 0 ? atomid : NULL); +} + +/** + * atom_id_new_from_xml: + * @xnode: an #xmlNode. + * + * Returns: the newly created #AtomID object. + */ +AtomID +*atom_id_new_from_xml (xmlNode *xnode) +{ + AtomID *atom_id = NULL; + + gchar *uri = (gchar *)xmlNodeGetContent ((xmlNodePtr)xnode); + if (uri != NULL) + { + atom_id = atom_id_new (uri); + if (atom_id != NULL) + { + atom_common_set_properties_from_xml (ATOM_COMMON (atom_id), xnode); + } + } + + return atom_id; +} + +/** + * atom_id_get_xml: + * @atom_id: #AtomID object. + * @xnode: an #xmlNode. + * + */ +void +atom_id_get_xml (AtomID *atom_id, xmlNode *xnode) +{ + AtomIDPrivate *priv = ATOM_ID_GET_PRIVATE (atom_id); + + atom_common_get_xml (ATOM_COMMON (atom_id), xnode); + + xmlNodeSetContent (xnode, (const xmlChar *)priv->uri); +} + +static void +atom_id_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + AtomID *atom_id = ATOM_ID (object); + + AtomIDPrivate *priv = ATOM_ID_GET_PRIVATE (atom_id); + + switch (property_id) + { + case PROP_URI: + { + gchar *uri = g_value_dup_string (value); + if (strcmp (g_strstrip (uri), "") != 0) + { + priv->uri = g_strdup (uri); + } + else + { + g_warning ("Property uri must not be empty."); + } + g_free (uri); + break; + } + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +atom_id_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + AtomID *atom_id = ATOM_ID (object); + + AtomIDPrivate *priv = ATOM_ID_GET_PRIVATE (atom_id); + + switch (property_id) + { + case PROP_URI: + g_value_set_string (value, priv->uri); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} diff --git a/src/atomid.h b/src/atomid.h new file mode 100644 index 0000000..999c311 --- /dev/null +++ b/src/atomid.h @@ -0,0 +1,64 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __ATOM_ID_H__ +#define __ATOM_ID_H__ + +#include +#include + +#include "atomcommon.h" + +G_BEGIN_DECLS + + +#define TYPE_ATOM_ID (atom_id_get_type ()) +#define ATOM_ID(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_ATOM_ID, AtomID)) +#define ATOM_ID_COMMON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_ATOM_ID, AtomIDClass)) +#define IS_ATOM_ID(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_ATOM_ID)) +#define IS_ATOM_ID_COMMON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_ATOM_ID)) +#define ATOM_ID_COMMON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_ATOM_ID, AtomIDClass)) + + +typedef struct _AtomID AtomID; +typedef struct _AtomIDClass AtomIDClass; + +struct _AtomID + { + AtomCommon parent; + }; + +struct _AtomIDClass + { + AtomCommonClass parent_class; + }; + +GType atom_id_get_type (void) G_GNUC_CONST; + +AtomID *atom_id_new (const gchar *uri); +AtomID *atom_id_new_from_xml (xmlNode *xnode); + +void atom_id_get_xml (AtomID *atom_id, xmlNode *xnode); + + +G_END_DECLS + +#endif /* __ATOM_ID_H__ */ diff --git a/src/atomlink.c b/src/atomlink.c new file mode 100644 index 0000000..3b37482 --- /dev/null +++ b/src/atomlink.c @@ -0,0 +1,360 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#include "atomlink.h" + +enum +{ + PROP_0, + PROP_HREF, + PROP_REL, + PROP_TYPE, + PROP_HREFLANG, + PROP_TITLE, + PROP_LENGTH +}; + +static void atom_link_class_init (AtomLinkClass *klass); +static void atom_link_init (AtomLink *atom_link); + +static void atom_link_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void atom_link_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +#define ATOM_LINK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_ATOM_LINK, AtomLinkPrivate)) + +typedef struct _AtomLinkPrivate AtomLinkPrivate; +struct _AtomLinkPrivate + { + gchar *href, + *rel, + *type, + *hreflang, + *title, + *length; + }; + +GType +atom_link_get_type (void) +{ + static GType atom_link_type = 0; + + if (!atom_link_type) + { + static const GTypeInfo atom_link_info = + { + sizeof (AtomLinkClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) atom_link_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (AtomLink), + 0, /* n_preallocs */ + (GInstanceInitFunc) atom_link_init, + NULL + }; + + atom_link_type = g_type_register_static (TYPE_ATOM_COMMON, "AtomLink", + &atom_link_info, 0); + } + + return atom_link_type; +} + +static void +atom_link_class_init (AtomLinkClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (AtomLinkPrivate)); + + object_class->set_property = atom_link_set_property; + object_class->get_property = atom_link_get_property; + + g_object_class_install_property (object_class, PROP_HREF, + g_param_spec_string ("href", + "Href", + "Href", + "", + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_REL, + g_param_spec_string ("rel", + "Rel", + "Indicates the link relation type.", + "", + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_TYPE, + g_param_spec_string ("type", + "Type", + "An advisory media type: it is a hint about the type of the representation that is expected to be returned when the value of the href attribute is dereferenced.", + "", + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_HREFLANG, + g_param_spec_string ("hreflang", + "Hreflang", + "Describes the language of the resource pointed to by the href attribute.", + "", + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_TITLE, + g_param_spec_string ("title", + "Title", + "A human-readable information about the link.", + "", + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_LENGTH, + g_param_spec_string ("length", + "Length", + "An advisory length of the linked content in octets; it is a hint about the content length of the representation returned when the IRI in the href attribute is mapped to a URI and dereferenced.", + "", + G_PARAM_READWRITE)); +} + +static void +atom_link_init (AtomLink *atom_link) +{ +} + +/** + * atom_link_new: + * @href: + * + * Returns: the newly created #AtomLink object. + */ +AtomLink +*atom_link_new (const gchar *href) +{ + AtomLink *atom_link = ATOM_LINK (g_object_new (atom_link_get_type (), NULL)); + + g_object_set (G_OBJECT (atom_link), + "href", href, + NULL); + + return atom_link; +} + +/** + * atom_link_new_from_xml: + * @xnode: an #xmlNode. + * + * Returns: the newly created #AtomLink object. + */ +AtomLink +*atom_link_new_from_xml (xmlNode *xnode) +{ + AtomLink *atom_link = NULL; + + gchar *href = (gchar *)xmlGetProp (xnode, (const xmlChar *)"href"); + if (href == NULL || strcmp (g_strstrip (href), "") == 0) + { + g_critical ("AtomLink must have an href attribute."); + return NULL; + } + else + { + atom_link = atom_link_new (href); + if (atom_link != NULL) + { + atom_common_set_properties_from_xml (ATOM_COMMON (atom_link), xnode); + + href = (gchar *)xmlGetProp (xnode, (const xmlChar *)"rel"); + if (href != NULL && strcmp (g_strstrip (href), "") != 0) + { + g_object_set (G_OBJECT (atom_link), + "rel", href, + NULL); + } + + href = (gchar *)xmlGetProp (xnode, (const xmlChar *)"type"); + if (href != NULL && strcmp (g_strstrip (href), "") != 0) + { + g_object_set (G_OBJECT (atom_link), + "type", href, + NULL); + } + + href = (gchar *)xmlGetProp (xnode, (const xmlChar *)"hreflang"); + if (href != NULL && strcmp (g_strstrip (href), "") != 0) + { + g_object_set (G_OBJECT (atom_link), + "hreflang", href, + NULL); + } + + href = (gchar *)xmlGetProp (xnode, (const xmlChar *)"title"); + if (href != NULL && strcmp (g_strstrip (href), "") != 0) + { + g_object_set (G_OBJECT (atom_link), + "title", href, + NULL); + } + + href = (gchar *)xmlGetProp (xnode, (const xmlChar *)"length"); + if (href != NULL && strcmp (g_strstrip (href), "") != 0) + { + g_object_set (G_OBJECT (atom_link), + "length", href, + NULL); + } + } + } + + return atom_link; +} + +/** + * atom_link_get_xml: + * @atom_link: an #AtomLink object. + * @xnode: an #xmlNode. + * + */ +void +atom_link_get_xml (AtomLink *atom_link, xmlNode *xnode) +{ + xmlNode *new_xnode; + + AtomLinkPrivate *priv = ATOM_LINK_GET_PRIVATE (atom_link); + + atom_common_get_xml (ATOM_COMMON (atom_link), xnode); + + if (strcmp (priv->href, "") != 0) + { + xmlSetProp (xnode, (const xmlChar *)"href", (const xmlChar *)priv->href); + } + if (strcmp (priv->rel, "") != 0) + { + xmlSetProp (xnode, (const xmlChar *)"rel", (const xmlChar *)priv->rel); + } + if (strcmp (priv->type, "") != 0) + { + xmlSetProp (xnode, (const xmlChar *)"type", (const xmlChar *)priv->type); + } + if (strcmp (priv->hreflang, "") != 0) + { + xmlSetProp (xnode, (const xmlChar *)"hreflang", (const xmlChar *)priv->hreflang); + } + if (strcmp (priv->title, "") != 0) + { + xmlSetProp (xnode, (const xmlChar *)"title", (const xmlChar *)priv->title); + } + if (strcmp (priv->length, "") != 0) + { + xmlSetProp (xnode, (const xmlChar *)"length", (const xmlChar *)priv->length); + } +} + +static void +atom_link_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + AtomLink *atom_link = ATOM_LINK (object); + + AtomLinkPrivate *priv = ATOM_LINK_GET_PRIVATE (atom_link); + + switch (property_id) + { + case PROP_HREF: + { + gchar *href = g_strstrip (g_value_dup_string (value)); + if (strcmp (href, "") == 0) + { + g_warning ("Property href must not be empty."); + } + else + { + priv->href = href; + } + break; + } + + case PROP_REL: + priv->rel = g_strstrip (g_value_dup_string (value)); + break; + + case PROP_TYPE: + priv->type = g_strstrip (g_value_dup_string (value)); + break; + + case PROP_HREFLANG: + priv->hreflang = g_strstrip (g_value_dup_string (value)); + break; + + case PROP_TITLE: + priv->title = g_strstrip (g_value_dup_string (value)); + break; + + case PROP_LENGTH: + priv->length = g_strstrip (g_value_dup_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +atom_link_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + AtomLink *atom_link = ATOM_LINK (object); + + AtomLinkPrivate *priv = ATOM_LINK_GET_PRIVATE (atom_link); + + switch (property_id) + { + case PROP_HREF: + g_value_set_string (value, priv->href); + break; + + case PROP_REL: + g_value_set_string (value, priv->rel); + break; + + case PROP_TYPE: + g_value_set_string (value, priv->type); + break; + + case PROP_HREFLANG: + g_value_set_string (value, priv->hreflang); + break; + + case PROP_TITLE: + g_value_set_string (value, priv->title); + break; + + case PROP_LENGTH: + g_value_set_string (value, priv->length); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} diff --git a/src/atomlink.h b/src/atomlink.h new file mode 100644 index 0000000..a7c1e5f --- /dev/null +++ b/src/atomlink.h @@ -0,0 +1,64 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __ATOM_LINK_H__ +#define __ATOM_LINK_H__ + +#include +#include + +#include "atomcommon.h" + +G_BEGIN_DECLS + + +#define TYPE_ATOM_LINK (atom_link_get_type ()) +#define ATOM_LINK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_ATOM_LINK, AtomLink)) +#define ATOM_LINK_COMMON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_ATOM_LINK, AtomLinkClass)) +#define IS_ATOM_LINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_ATOM_LINK)) +#define IS_ATOM_LINK_COMMON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_ATOM_LINK)) +#define ATOM_LINK_COMMON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_ATOM_LINK, AtomLinkClass)) + + +typedef struct _AtomLink AtomLink; +typedef struct _AtomLinkClass AtomLinkClass; + +struct _AtomLink + { + AtomCommon parent; + }; + +struct _AtomLinkClass + { + AtomCommonClass parent_class; + }; + +GType atom_link_get_type (void) G_GNUC_CONST; + +AtomLink *atom_link_new (const gchar *href); +AtomLink *atom_link_new_from_xml (xmlNode *xnode); + +void atom_link_get_xml (AtomLink *atom_link, xmlNode *xnode); + + +G_END_DECLS + +#endif /* __ATOM_LINK_H__ */ diff --git a/src/atomperson.c b/src/atomperson.c new file mode 100644 index 0000000..26529f2 --- /dev/null +++ b/src/atomperson.c @@ -0,0 +1,296 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#include + +#include "atomperson.h" + +enum +{ + PROP_0, + PROP_NAME, + PROP_URI, + PROP_EMAIL +}; + +static void atom_person_class_init (AtomPersonClass *klass); +static void atom_person_init (AtomPerson *atom_person); + +static void atom_person_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void atom_person_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +#define ATOM_PERSON_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_ATOM_PERSON, AtomPersonPrivate)) + +typedef struct _AtomPersonPrivate AtomPersonPrivate; +struct _AtomPersonPrivate + { + gchar *name, + *uri, + *email; + }; + +GType +atom_person_get_type (void) +{ + static GType atom_person_type = 0; + + if (!atom_person_type) + { + static const GTypeInfo atom_person_info = + { + sizeof (AtomPersonClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) atom_person_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (AtomPerson), + 0, /* n_preallocs */ + (GInstanceInitFunc) atom_person_init, + NULL + }; + + atom_person_type = g_type_register_static (TYPE_ATOM_COMMON, "AtomPerson", + &atom_person_info, 0); + } + + return atom_person_type; +} + +static void +atom_person_class_init (AtomPersonClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (AtomPersonPrivate)); + + object_class->set_property = atom_person_set_property; + object_class->get_property = atom_person_get_property; + + g_object_class_install_property (object_class, PROP_NAME, + g_param_spec_string ("name", + "Name", + "Conveys a human-readable name for the person.", + "", + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_URI, + g_param_spec_string ("uri", + "URI", + "Conveys an IRI associated with the person.", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, PROP_EMAIL, + g_param_spec_string ("email", + "EMail", + "Conveys an e-mail address associated with the person.", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); +} + +static void +atom_person_init (AtomPerson *atom_person) +{ +} + +/** + * atom_person_new: + * @name: a string with a human-readable name for the person. + * + * Returns: the newly created #AtomPerson object. + */ +AtomPerson +*atom_person_new (const gchar *name) +{ + AtomPerson *atom_person = ATOM_PERSON (g_object_new (atom_person_get_type (), NULL)); + + g_object_set (G_OBJECT (atom_person), + "name", name, + NULL); + + return atom_person; +} + +/** + * atom_person_new_from_xml: + * @xnode: an #xmlNode. + * + * Returns: the newly created #AtomPerson object. + */ +AtomPerson +*atom_person_new_from_xml (xmlNode *xnode) +{ + gchar *name; + + AtomPerson *atom_person = NULL; + + xmlXPathObjectPtr xpresult; + xmlXPathContextPtr xpcontext = xmlXPathNewContext (xnode->doc); + + xmlXPathRegisterNs (xpcontext, (const xmlChar *)"atom", (const xmlChar *)"http://www.w3.org/2005/Atom"); + + xpcontext->node = xnode; + xpresult = xmlXPathEvalExpression ((const xmlChar *)"child::atom:name", xpcontext); + if (xpresult == NULL || xpresult->nodesetval == NULL || xpresult->nodesetval->nodeNr != 1) + { + g_critical ("AtomPerson must have a name element."); + return NULL; + } + else + { + name = (gchar *)xmlNodeGetContent ((xmlNodePtr)xpresult->nodesetval->nodeTab[0]); + if (strcmp (g_strstrip (name), "") == 0) + { + g_critical ("Element name must be filled."); + return NULL; + } + } + + atom_person = atom_person_new (name); + if (atom_person != NULL) + { + atom_common_set_properties_from_xml (ATOM_COMMON (atom_person), xnode); + + xpcontext->node = xnode; + xpresult = xmlXPathEvalExpression ((const xmlChar *)"child::atom:uri", xpcontext); + if (xpresult != NULL && xpresult->nodesetval != NULL && xpresult->nodesetval->nodeNr != 0) + { + g_object_set (G_OBJECT (atom_person), + "uri", (gchar *)xmlNodeGetContent ((xmlNodePtr)xpresult->nodesetval->nodeTab[0]), + NULL); + } + + xpcontext->node = xnode; + xpresult = xmlXPathEvalExpression ((const xmlChar *)"child::atom:email", xpcontext); + if (xpresult != NULL && xpresult->nodesetval != NULL && xpresult->nodesetval->nodeNr != 0) + { + g_object_set (G_OBJECT (atom_person), + "email", (gchar *)xmlNodeGetContent ((xmlNodePtr)xpresult->nodesetval->nodeTab[0]), + NULL); + } + } + + return atom_person; +} + +/** + * atom_person_get_xml: + * @atom_person: an #AtomPerson object. + * @xnode: an #xmlNode. + * + */ +void +atom_person_get_xml (AtomPerson *atom_person, xmlNode *xnode) +{ + xmlNode *new_xnode; + + AtomPersonPrivate *priv = ATOM_PERSON_GET_PRIVATE (atom_person); + + atom_common_get_xml (ATOM_COMMON (atom_person), xnode); + + new_xnode = xmlNewNode (NULL, (const xmlChar *)"name"); + xmlNodeSetContent (new_xnode, (const xmlChar *)priv->name); + xmlAddChild (xnode, new_xnode); + + if (strcmp (priv->uri, "") != 0) + { + new_xnode = xmlNewNode (NULL, (const xmlChar *)"uri"); + xmlNodeSetContent (new_xnode, (const xmlChar *)priv->uri); + xmlAddChild (xnode, new_xnode); + } + if (strcmp (priv->email, "") != 0) + { + new_xnode = xmlNewNode (NULL, (const xmlChar *)"email"); + xmlNodeSetContent (new_xnode, (const xmlChar *)priv->email); + xmlAddChild (xnode, new_xnode); + } +} + +static void +atom_person_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + AtomPerson *atom_person = ATOM_PERSON (object); + + AtomPersonPrivate *priv = ATOM_PERSON_GET_PRIVATE (atom_person); + + switch (property_id) + { + case PROP_NAME: + { + gchar *name = g_strstrip (g_value_dup_string (value)); + if (strcmp (name, "") == 0) + { + g_warning ("Property name must not be empty."); + } + else + { + priv->name = name; + } + break; + } + + case PROP_URI: + priv->uri = g_strstrip (g_value_dup_string (value)); + break; + + case PROP_EMAIL: + priv->email = g_strstrip (g_value_dup_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +atom_person_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + AtomPerson *atom_person = ATOM_PERSON (object); + + AtomPersonPrivate *priv = ATOM_PERSON_GET_PRIVATE (atom_person); + + switch (property_id) + { + case PROP_NAME: + g_value_set_string (value, priv->name); + break; + + case PROP_URI: + g_value_set_string (value, priv->uri); + break; + + case PROP_EMAIL: + g_value_set_string (value, priv->email); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} diff --git a/src/atomperson.h b/src/atomperson.h new file mode 100644 index 0000000..975d261 --- /dev/null +++ b/src/atomperson.h @@ -0,0 +1,64 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __ATOM_PERSON_H__ +#define __ATOM_PERSON_H__ + +#include +#include + +#include "atomcommon.h" + +G_BEGIN_DECLS + + +#define TYPE_ATOM_PERSON (atom_person_get_type ()) +#define ATOM_PERSON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_ATOM_PERSON, AtomPerson)) +#define ATOM_PERSON_COMMON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_ATOM_PERSON, AtomPersonClass)) +#define IS_ATOM_PERSON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_ATOM_PERSON)) +#define IS_ATOM_PERSON_COMMON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_ATOM_PERSON)) +#define ATOM_PERSON_COMMON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_ATOM_PERSON, AtomPersonClass)) + + +typedef struct _AtomPerson AtomPerson; +typedef struct _AtomPersonClass AtomPersonClass; + +struct _AtomPerson + { + AtomCommon parent; + }; + +struct _AtomPersonClass + { + AtomCommonClass parent_class; + }; + +GType atom_person_get_type (void) G_GNUC_CONST; + +AtomPerson *atom_person_new (const gchar *name); +AtomPerson *atom_person_new_from_xml (xmlNode *xnode); + +void atom_person_get_xml (AtomPerson *atom_person, xmlNode *xnode); + + +G_END_DECLS + +#endif /* __ATOM_PERSON_H__ */ diff --git a/src/atomsource.c b/src/atomsource.c new file mode 100644 index 0000000..9cd1e45 --- /dev/null +++ b/src/atomsource.c @@ -0,0 +1,590 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#include "atomsource.h" +#include "atomperson.h" +#include "atomcategory.h" +#include "atomgenerator.h" +#include "atomlink.h" + +enum +{ + PROP_0, + PROP_AUTHOR, + PROP_CATEGORY, + PROP_CONTRIBUTOR, + PROP_GENERATOR, + PROP_ICON, + PROP_ID, + PROP_LINK, + PROP_LOGO, + PROP_RIGHTS, + PROP_SUBTITLE, + PROP_TITLE, + PROP_UPDATED +}; + +static void atom_source_class_init (AtomSourceClass *klass); +static void atom_source_init (AtomSource *atome); + +static void atom_source_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void atom_source_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +#define ATOM_SOURCE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_ATOM_SOURCE, AtomSourcePrivate)) + +typedef struct _AtomSourcePrivate AtomSourcePrivate; +struct _AtomSourcePrivate + { + GList *author, + *category, + *contributor; + AtomGenerator *generator; + AtomID *icon, + *id, + *logo; + AtomLink *link; + AtomText *title, + *rights, + *subtitle; + AtomDate *updated; + }; + +GType +atom_source_get_type (void) +{ + static GType atom_source_type = 0; + + if (!atom_source_type) + { + static const GTypeInfo atom_source_info = + { + sizeof (AtomSourceClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) atom_source_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (AtomSource), + 0, /* n_preallocs */ + (GInstanceInitFunc) atom_source_init, + NULL + }; + + atom_source_type = g_type_register_static (TYPE_ATOM_COMMON, "AtomSource", + &atom_source_info, 0); + } + + return atom_source_type; +} + +static void +atom_source_class_init (AtomSourceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (AtomSourcePrivate)); + + object_class->set_property = atom_source_set_property; + object_class->get_property = atom_source_get_property; + + g_object_class_install_property (object_class, PROP_AUTHOR, + g_param_spec_pointer ("author", + "Author", + "A #GList of #AtomPerson objects that indicates the author of the entry or feed.", + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_CATEGORY, + g_param_spec_pointer ("category", + "Category", + "A #GList of #AtomCategory objects convey information about a category associated with an entry or feed.", + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_CONTRIBUTOR, + g_param_spec_pointer ("contributor", + "Contributor", + "A #GList of #AtomPerson objects that indicate a person or other entity who contributed to the entry or feed.", + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_GENERATOR, + g_param_spec_object ("generator", + "Generato", + "An #AtomGenerator object that identifies the agent used to generate a feed, for debugging and other purposes.", + TYPE_ATOM_GENERATOR, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_ICON, + g_param_spec_object ("icon", + "Icon", + "An #AtomID object that contains an IRI reference [RFC3987] that identifies an image that provides iconic visual identification for a feed.", + TYPE_ATOM_ID, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_ID, + g_param_spec_object ("id", + "Id", + "An #AtomID object that conveys a permanent, universally unique identifier for an entry or feed.", + TYPE_ATOM_ID, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_LINK, + g_param_spec_object ("link", + "Link", + "An #AtomLink object that defines a reference from an entry or feed to a Web resource.", + TYPE_ATOM_LINK, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_LOGO, + g_param_spec_object ("logo", + "Logo", + "An #AtonID object that contains an IRI reference [RFC3987] that identifies an image that provides visual identification for a feed.", + TYPE_ATOM_ID, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_RIGHTS, + g_param_spec_object ("rights", + "Rights", + "An #AtomText object that conveys information about rights held in and over an entry or feed.", + TYPE_ATOM_TEXT, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_SUBTITLE, + g_param_spec_object ("subtitle", + "Subtitle", + "An #AtomText object that conveys a human-readable description or subtitle for a feed.", + TYPE_ATOM_TEXT, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_TITLE, + g_param_spec_object ("title", + "Title", + "An #AtomText object that conveys a human-readable title for an entry or feed.", + TYPE_ATOM_TEXT, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_UPDATED, + g_param_spec_object ("updated", + "Updated", + "An #AtomDate object indicating the most recent instant in time when an entry or feed was modified in a way the publisher considers significant.", + TYPE_ATOM_DATE, + G_PARAM_READWRITE)); +} + +static void +atom_source_init (AtomSource *atome) +{ +} + +/** + * atom_source_new: + * + * Returns: the newly created #AtomSource object. + */ +AtomSource +*atom_source_new () +{ + return ATOM_SOURCE (g_object_new (atom_source_get_type (), NULL)); +} + +/** + * atom_source_new_from_xml: + * @xnode: an #xmlNode. + * + * Returns: the newly created #AtomSource object. + */ +AtomSource +*atom_source_new_from_xml (xmlNode *xnode) +{ + AtomSource *atom_source = atom_source_new (); + + AtomSourcePrivate *priv = ATOM_SOURCE_GET_PRIVATE (atom_source); + + atom_common_set_properties_from_xml (ATOM_COMMON (atom_source), xnode); + + xmlNode *cur = xnode->children; + + while (cur != NULL) + { + if (xmlStrcmp (cur->name, (const xmlChar *)"author") == 0) + { + AtomPerson *ap = atom_person_new_from_xml (cur); + if (ap != NULL) + { + priv->author = g_list_append (priv->author, ap); + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"category") == 0) + { + AtomCategory *ac = atom_category_new_from_xml (cur); + if (ac != NULL) + { + priv->category = g_list_append (priv->category, ac); + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"contributor") == 0) + { + AtomPerson *ap = atom_person_new_from_xml (cur); + if (ap != NULL) + { + priv->contributor = g_list_append (priv->contributor, ap); + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"generator") == 0) + { + AtomGenerator *ag = atom_generator_new_from_xml (cur); + if (ag != NULL) + { + priv->generator = ag; + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"icon") == 0) + { + AtomID *icon = atom_id_new_from_xml (cur); + if (icon == NULL) + { + priv->icon = icon; + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"link") == 0) + { + AtomLink *link = atom_link_new_from_xml (cur); + if (link == NULL) + { + priv->link = link; + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"logo") == 0) + { + AtomID *logo = atom_id_new_from_xml (cur); + if (logo == NULL) + { + priv->logo = logo; + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"rights") == 0) + { + AtomText *rights = atom_text_new_from_xml (cur); + if (rights != NULL) + { + priv->rights = rights; + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"subtitle") == 0) + { + AtomText *subtitle = atom_text_new_from_xml (cur); + if (subtitle != NULL) + { + priv->subtitle = subtitle; + } + } + + cur = cur->next; + } + + return atom_source; +} + +/** + * atatom_source_get_xml: + * @atom_source: an #AtomSource object. + * + */ +void +atom_source_get_xml (AtomSource *atom_source, xmlNode *xnode) +{ + xmlNode *xnodenew; + GList *lst; + + AtomSourcePrivate *priv = ATOM_SOURCE_GET_PRIVATE (atom_source); + + atom_common_get_xml (ATOM_COMMON (atom_source), xnodenew); + + lst = g_list_first (priv->author); + while (lst != NULL) + { + if (IS_ATOM_PERSON (lst->data)) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"author"); + xmlAddChild (xnode, xnodenew); + atom_person_get_xml (ATOM_PERSON (lst->data), xnodenew); + } + + lst = g_list_next (lst); + } + + lst = g_list_first (priv->category); + while (lst != NULL) + { + if (IS_ATOM_CATEGORY (lst->data)) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"category"); + xmlAddChild (xnode, xnodenew); + atom_category_get_xml (ATOM_CATEGORY (lst->data), xnodenew); + } + + lst = g_list_next (lst); + } + + lst = g_list_first (priv->contributor); + while (lst != NULL) + { + if (IS_ATOM_PERSON (lst->data)) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"contributor"); + xmlAddChild (xnode, xnodenew); + atom_person_get_xml (ATOM_PERSON (lst->data), xnodenew); + } + + lst = g_list_next (lst); + } + + if (priv->generator != NULL) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"generator"); + xmlAddChild (xnode, xnodenew); + atom_generator_get_xml (priv->generator, xnodenew); + } + + if (priv->icon != NULL) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"icon"); + xmlAddChild (xnode, xnodenew); + atom_id_get_xml (priv->icon, xnodenew); + } + + if (priv->id != NULL) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"id"); + xmlAddChild (xnode, xnodenew); + atom_id_get_xml (priv->id, xnodenew); + } + + if (priv->link != NULL) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"link"); + xmlAddChild (xnode, xnodenew); + atom_link_get_xml (priv->link, xnodenew); + } + + if (priv->logo != NULL) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"logo"); + xmlAddChild (xnode, xnodenew); + atom_id_get_xml (priv->logo, xnodenew); + } + + if (priv->rights != NULL) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"rights"); + xmlAddChild (xnode, xnodenew); + atom_text_get_xml (priv->rights, xnodenew); + } + + if (priv->subtitle != NULL) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"subtitle"); + xmlAddChild (xnode, xnodenew); + atom_text_get_xml (priv->subtitle, xnodenew); + } + + if (priv->title != NULL) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"title"); + xmlAddChild (xnode, xnodenew); + atom_text_get_xml (priv->title, xnodenew); + } + + if (priv->updated != NULL) + { + xnodenew = xmlNewNode (NULL, (const xmlChar *)"updated"); + xmlAddChild (xnode, xnodenew); + atom_date_get_xml (priv->updated, xnodenew); + } +} + +static void +atom_source_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + GObject *obj; + + AtomSource *atome = ATOM_SOURCE (object); + + AtomSourcePrivate *priv = ATOM_SOURCE_GET_PRIVATE (atome); + + switch (property_id) + { + case PROP_AUTHOR: + if (g_value_get_pointer (value) != NULL) + { + priv->author = (GList *)g_memdup ((gconstpointer)g_value_get_pointer (value), sizeof (GList)); + } + break; + + case PROP_CATEGORY: + if (g_value_get_pointer (value) != NULL) + { + priv->category = (GList *)g_memdup ((gconstpointer)g_value_get_pointer (value), sizeof (GList)); + } + break; + + case PROP_CONTRIBUTOR: + if (g_value_get_pointer (value) != NULL) + { + priv->contributor = (GList *)g_memdup ((gconstpointer)g_value_get_pointer (value), sizeof (GList)); + } + break; + + case PROP_GENERATOR: + if (g_value_get_object (value) != NULL && IS_ATOM_GENERATOR (g_value_get_object (value))) + { + priv->generator = (AtomGenerator *)g_value_dup_object (value); + } + break; + + case PROP_ICON: + if (g_value_get_object (value) != NULL && IS_ATOM_ID (g_value_get_object (value))) + { + priv->icon = (AtomID *)g_value_dup_object (value); + } + break; + + case PROP_ID: + if (g_value_get_object (value) != NULL && IS_ATOM_ID (g_value_get_object (value))) + { + priv->id = (AtomID *)g_value_dup_object (value); + } + break; + + case PROP_LINK: + if (g_value_get_object (value) != NULL && IS_ATOM_LINK (g_value_get_object (value))) + { + priv->link = (AtomLink *)g_value_dup_object (value); + } + break; + + case PROP_LOGO: + if (g_value_get_object (value) != NULL && IS_ATOM_ID (g_value_get_object (value))) + { + priv->logo = (AtomID *)g_value_dup_object (value); + } + break; + + case PROP_RIGHTS: + if (g_value_get_object (value) != NULL && IS_ATOM_TEXT (g_value_get_object (value))) + { + priv->rights = (AtomText *)g_value_dup_object (value); + } + break; + + case PROP_SUBTITLE: + if (g_value_get_object (value) != NULL && IS_ATOM_TEXT (g_value_get_object (value))) + { + priv->subtitle = (AtomText *)g_value_dup_object (value); + } + break; + + case PROP_TITLE: + if (g_value_get_object (value) != NULL && IS_ATOM_TEXT (g_value_get_object (value))) + { + priv->title = (AtomText *)g_value_dup_object (value); + } + break; + + case PROP_UPDATED: + if (g_value_get_object (value) != NULL && IS_ATOM_DATE (g_value_get_object (value))) + { + priv->updated = (AtomDate *)g_value_dup_object (value); + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +atom_source_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + AtomSource *atome = ATOM_SOURCE (object); + + AtomSourcePrivate *priv = ATOM_SOURCE_GET_PRIVATE (atome); + + switch (property_id) + { + case PROP_AUTHOR: + g_value_set_pointer (value, priv->author); + break; + + case PROP_CATEGORY: + g_value_set_pointer (value, priv->category); + break; + + case PROP_CONTRIBUTOR: + g_value_set_pointer (value, priv->contributor); + break; + + case PROP_GENERATOR: + g_value_set_pointer (value, priv->generator); + break; + + case PROP_ICON: + g_value_set_object (value, priv->icon); + break; + + case PROP_ID: + g_value_set_object (value, priv->id); + break; + + case PROP_LINK: + g_value_set_object (value, priv->link); + break; + + case PROP_LOGO: + g_value_set_object (value, priv->logo); + break; + + case PROP_RIGHTS: + g_value_set_object (value, priv->rights); + break; + + case PROP_SUBTITLE: + g_value_set_object (value, priv->subtitle); + break; + + case PROP_TITLE: + g_value_set_object (value, priv->title); + break; + + case PROP_UPDATED: + g_value_set_object (value, priv->updated); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} diff --git a/src/atomsource.h b/src/atomsource.h new file mode 100644 index 0000000..e6eeb45 --- /dev/null +++ b/src/atomsource.h @@ -0,0 +1,68 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __ATOM_SOURCE_H__ +#define __ATOM_SOURCE_H__ + +#include +#include +#include + +#include "atomcommon.h" +#include "atomid.h" +#include "atomtext.h" +#include "atomdate.h" + +G_BEGIN_DECLS + + +#define TYPE_ATOM_SOURCE (atom_source_get_type ()) +#define ATOM_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_ATOM_SOURCE, AtomSource)) +#define ATOM_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_ATOM_SOURCE, AtomSourceClass)) +#define IS_ATOM_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_ATOM_SOURCE)) +#define IS_ATOM_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_ATOM_SOURCE)) +#define ATOM_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_ATOM_SOURCE, AtomSourceClass)) + + +typedef struct _AtomSource AtomSource; +typedef struct _AtomSourceClass AtomSourceClass; + +struct _AtomSource + { + AtomCommon parent; + }; + +struct _AtomSourceClass + { + AtomCommonClass parent_class; + }; + +GType atom_source_get_type (void) G_GNUC_CONST; + +AtomSource *atom_source_new (void); +AtomSource *atom_source_new_from_xml (xmlNode *xnode); + +void atom_source_get_xml (AtomSource *atom_source, xmlNode *xnode); + + +G_END_DECLS + +#endif /* __ATOM_SOURCE_H__ */ diff --git a/src/atomtext.c b/src/atomtext.c new file mode 100644 index 0000000..79387ca --- /dev/null +++ b/src/atomtext.c @@ -0,0 +1,287 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#include + +#include "atomtext.h" + +enum +{ + PROP_0, + PROP_TYPE, + PROP_TEXT +}; + +static void atom_text_class_init (AtomTextClass *klass); +static void atom_text_init (AtomText *atom_text); + +static void atom_text_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void atom_text_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +#define ATOM_TEXT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_ATOM_TEXT, AtomTextPrivate)) + +typedef struct _AtomTextPrivate AtomTextPrivate; +struct _AtomTextPrivate + { + AtomTextType type; + gchar *text; + }; + +GType +atom_text_get_type (void) +{ + static GType atom_text_type = 0; + + if (!atom_text_type) + { + static const GTypeInfo atom_text_info = + { + sizeof (AtomTextClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) atom_text_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (AtomText), + 0, /* n_preallocs */ + (GInstanceInitFunc) atom_text_init, + NULL + }; + + atom_text_type = g_type_register_static (TYPE_ATOM_COMMON, "AtomText", + &atom_text_info, 0); + } + + return atom_text_type; +} + +static void +atom_text_class_init (AtomTextClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (AtomTextPrivate)); + + object_class->set_property = atom_text_set_property; + object_class->get_property = atom_text_get_property; + + g_object_class_install_property (object_class, PROP_TYPE, + g_param_spec_uint ("type", + "Type", + "Type", + 0, 2, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, PROP_TEXT, + g_param_spec_string ("text", + "Text", + "Text", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); +} + +static void +atom_text_init (AtomText *atom_text) +{ +} + +/** + * atom_text_new: + * + * Returns: the newly created #AtomText object. + */ +AtomText +*atom_text_new (AtomTextType type, const gchar *text) +{ + AtomText *atomtext = ATOM_TEXT (g_object_new (atom_text_get_type (), NULL)); + + g_object_set (G_OBJECT (atomtext), + "type", type, + "text", text, + NULL); + + return atomtext; +} + +/** + * atom_text_new_from_xml: + * @xnode: an #xmlNode. + * + * Returns: the newly created #AtomText object. + */ +AtomText +*atom_text_new_from_xml (xmlNode *xnode) +{ + AtomText *atom_text = NULL; + AtomTextType atomtype; + gchar *text; + + gchar *type = (gchar *)xmlGetProp ((xmlNodePtr)xnode, (const xmlChar *)"type"); + if (type == NULL || strcmp (type, "text") == 0) + { + atomtype = ATOM_TEXT_TEXT; + } + else if (strcmp (type, "html") == 0) + { + atomtype = ATOM_TEXT_HTML; + } + else if (strcmp (type, "xhtml") == 0) + { + atomtype = ATOM_TEXT_XHTML; + } + else + { + g_critical ("Invalid AtomText type."); + return NULL; + } + + if (atomtype == ATOM_TEXT_TEXT || atomtype == ATOM_TEXT_HTML) + { + text = (gchar *)xmlNodeGetContent ((xmlNodePtr)xnode); + } + else if (atomtype == ATOM_TEXT_XHTML) + { + xmlXPathObjectPtr xpresult; + xmlXPathContextPtr xpcontext = xmlXPathNewContext (xnode->doc); + + xmlXPathRegisterNs (xpcontext, (const xmlChar *)"xhtml", (const xmlChar *)"http://www.w3.org/1999/xhtml"); + + xpcontext->node = xnode; + xpresult = xmlXPathEvalExpression ((const xmlChar *)"child::xhtml:div", xpcontext); + if (xpresult == NULL || xpresult->nodesetval->nodeNr != 1) + { + g_critical ("Invalid AtomText type xhtml."); + return NULL; + } + else + { + text = (gchar *)xmlNodeGetContent ((xmlNodePtr)xpresult->nodesetval->nodeTab[0]); + } + } + + if (text != NULL) + { + atom_text = atom_text_new (atomtype, g_strstrip (text)); + if (atom_text != NULL) + { + atom_common_set_properties_from_xml (ATOM_COMMON (atom_text), xnode); + } + } + + return atom_text; +} + +/** + * atom_text_get_xml: + * @atom_text: #AtomText object. + * @xnode: + * + */ +void +atom_text_get_xml (AtomText *atom_text, xmlNode *xnode) +{ + gchar *type; + + AtomTextPrivate *priv = ATOM_TEXT_GET_PRIVATE (atom_text); + + atom_common_get_xml (ATOM_COMMON (atom_text), xnode); + + switch (priv->type) + { + case ATOM_TEXT_TEXT: + type = g_strdup ("text"); + break; + + case ATOM_TEXT_HTML: + type = g_strdup ("html"); + break; + + case ATOM_TEXT_XHTML: + type = g_strdup ("xhtml"); + break; + } + + xmlSetProp (xnode, (const xmlChar *)"type", (const xmlChar *)type); + + if (priv->type == ATOM_TEXT_XHTML) + { + xmlNode *new_xnode = xmlNewNode (NULL, (const xmlChar *)"xhtml:div"); + xmlNewNs (new_xnode, (const xmlChar *)"http://www.w3.org/1999/xhtml", (const xmlChar *)"xhtml"); + xmlNodeSetContent (new_xnode, (const xmlChar *)priv->text); + xmlAddChild (xnode, new_xnode); + } + else + { + xmlNodeSetContent (xnode, (const xmlChar *)priv->text); + } +} + +static void +atom_text_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + AtomText *atom_text = ATOM_TEXT (object); + + AtomTextPrivate *priv = ATOM_TEXT_GET_PRIVATE (atom_text); + + switch (property_id) + { + case PROP_TYPE: + priv->type = g_value_get_uint (value); + break; + + case PROP_TEXT: + priv->text = g_value_dup_string (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +atom_text_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + AtomText *atom_text = ATOM_TEXT (object); + + AtomTextPrivate *priv = ATOM_TEXT_GET_PRIVATE (atom_text); + + switch (property_id) + { + case PROP_TYPE: + g_value_set_int (value, priv->type); + break; + + case PROP_TEXT: + g_value_set_string (value, priv->text); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} diff --git a/src/atomtext.h b/src/atomtext.h new file mode 100644 index 0000000..bbeb761 --- /dev/null +++ b/src/atomtext.h @@ -0,0 +1,71 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __ATOM_TEXT_H__ +#define __ATOM_TEXT_H__ + +#include +#include + +#include "atomcommon.h" + +G_BEGIN_DECLS + + +#define TYPE_ATOM_TEXT (atom_text_get_type ()) +#define ATOM_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_ATOM_TEXT, AtomText)) +#define ATOM_TEXT_COMMON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_ATOM_TEXT, AtomTextClass)) +#define IS_ATOM_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_ATOM_TEXT)) +#define IS_ATOM_TEXT_COMMON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_ATOM_TEXT)) +#define ATOM_TEXT_COMMON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_ATOM_TEXT, AtomTextClass)) + + +typedef struct _AtomText AtomText; +typedef struct _AtomTextClass AtomTextClass; + +struct _AtomText + { + AtomCommon parent; + }; + +struct _AtomTextClass + { + AtomCommonClass parent_class; + }; + +typedef enum +{ + ATOM_TEXT_TEXT, + ATOM_TEXT_HTML, + ATOM_TEXT_XHTML +} AtomTextType; + +GType atom_text_get_type (void) G_GNUC_CONST; + +AtomText *atom_text_new (AtomTextType type, const gchar *text); +AtomText *atom_text_new_from_xml (xmlNode *xnode); + +void atom_text_get_xml (AtomText *atom_text, xmlNode *xnode); + + +G_END_DECLS + +#endif /* __ATOM_TEXT_H__ */ diff --git a/src/gfeed.h b/src/gfeed.h new file mode 100644 index 0000000..6400319 --- /dev/null +++ b/src/gfeed.h @@ -0,0 +1,41 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __GFEED_H__ +#define __GFEED_H__ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#endif /* __GFEED_H__ */ diff --git a/src/rss.c b/src/rss.c new file mode 100644 index 0000000..cf0208e --- /dev/null +++ b/src/rss.c @@ -0,0 +1,293 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include "rss.h" + +enum +{ + PROP_0, + PROP_CHANNEL, +}; + +static void rss_class_init (RssClass *klass); +static void rss_init (Rss *rss); + +static void rss_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void rss_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static Rss *parse_xml (xmlDoc *xdoc); + +#define RSS_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_RSS, RssPrivate)) + +typedef struct _RssPrivate RssPrivate; +struct _RssPrivate + { + RssChannel *channel; + }; + +GType +rss_get_type (void) +{ + static GType rss_type = 0; + + if (!rss_type) + { + static const GTypeInfo rss_info = + { + sizeof (RssClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) rss_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (Rss), + 0, /* n_preallocs */ + (GInstanceInitFunc) rss_init, + NULL + }; + + rss_type = g_type_register_static (G_TYPE_OBJECT, "Rss", + &rss_info, 0); + } + + return rss_type; +} + +static void +rss_class_init (RssClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (RssPrivate)); + + object_class->set_property = rss_set_property; + object_class->get_property = rss_get_property; + + g_object_class_install_property (object_class, PROP_CHANNEL, + g_param_spec_object ("channel", + "Channel", + "The channel node", + TYPE_RSSCHANNEL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); +} + +static void +rss_init (Rss *rss) +{ +} + +/** + * rss_new: + * + * Returns: the newly created #Rss object. + */ +Rss +*rss_new () +{ + return RSS (g_object_new (rss_get_type (), NULL)); +} + +/** + * rss_new_from_file: + * @filename: + * + * Returns: the newly created #Rss object. + */ +Rss +*rss_new_from_file (const gchar *filename) +{ + Rss *rss; + + xmlDoc *xdoc = xmlParseFile (filename); + + rss = parse_xml (xdoc); + + return rss; +} + +/** + * rss_new_from_buffer: + * @buffer: a pointer to an array of #gchar. + * + * Returns: the newly created #Rss object. + */ +Rss +*rss_new_from_buffer (const gchar *buffer) +{ + Rss *rss; + + xmlDoc *xdoc = xmlParseDoc (buffer); + + rss = parse_xml (xdoc); + + return rss; +} + +/** + * rss_get_xml_doc: + * @rss: a #Rss object. + * + * Returns: the #xmlDoc correspondent to the entire rss file. + */ +xmlDoc +*rss_get_xml_doc (Rss *rss) +{ + RssPrivate *priv = RSS_GET_PRIVATE (rss); + + xmlDoc *xdoc = xmlNewDoc ((const xmlChar *)"1.0"); + xmlNode *xroot = xmlNewNode (NULL, (const xmlChar *)"rss"); + + /* adding root element */ + if (xroot == NULL) return NULL; + + xmlSetProp (xroot, (const xmlChar *)"version", (const xmlChar *)"2.0"); + xmlDocSetRootElement (xdoc, xroot); + + if (priv->channel != NULL) + { + xmlAddChild (xroot, rss_channel_get_xml (priv->channel)); + } + else + { + g_warning ("Node «channel» not present."); + } + + return xdoc; +} + +/** + * rss_save_file: + * @rss: a #Rss object. + * @filename: + * + */ +gboolean +rss_save_file (Rss *rss, const gchar *filename) +{ + return (xmlSaveFileEnc (filename, rss_get_xml_doc (rss), "iso-8859-1") > -1); +} + +static void +rss_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + Rss *rss = RSS (object); + + RssPrivate *priv = RSS_GET_PRIVATE (rss); + + switch (property_id) + { + case PROP_CHANNEL: + if (g_value_get_object (value) != NULL) + { + priv->channel = (RssChannel *)g_value_dup_object (value); + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +rss_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + Rss *rss = RSS (object); + + RssPrivate *priv = RSS_GET_PRIVATE (rss); + + switch (property_id) + { + case PROP_CHANNEL: + g_value_set_object (value, priv->channel); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static Rss +*parse_xml (xmlDoc *xdoc) +{ + Rss *rss = rss_new (); + + if (xdoc != NULL) + { + xmlNode *cur = xmlDocGetRootElement (xdoc); + if (cur != NULL) + { + if (xmlStrcmp (cur->name, (const xmlChar *)"rss") == 0) + { + if (xmlStrcmp (xmlGetProp (cur, (const xmlChar *)"version"), (const xmlChar *)"2.0") == 0) + { + cur = cur->xmlChildrenNode; + if (cur != NULL) + { + if (xmlStrcmp (cur->name, (const xmlChar *)"channel") == 0) + { + RssChannel *rssc = rss_channel_new_from_xml (cur); + if (rssc != NULL) + { + g_object_set (G_OBJECT (rss), + "channel", rssc, + NULL); + } + } + else + { + g_critical ("The unique first element must be «channel»"); + } + } + else + { + g_critical ("Empty rss document."); + } + } + else + { + g_critical ("Wrong rss version."); + } + } + else + { + g_critical ("XML document is not a rss feed."); + } + } + else + { + g_critical ("Empty document."); + } + } + + return rss; +} diff --git a/src/rss.h b/src/rss.h new file mode 100644 index 0000000..a381b28 --- /dev/null +++ b/src/rss.h @@ -0,0 +1,67 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __RSS_H__ +#define __RSS_H__ + +#include +#include +#include + +#include "rsschannel.h" + +G_BEGIN_DECLS + + +#define TYPE_RSS (rss_get_type ()) +#define RSS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_RSS, Rss)) +#define RSS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_RSS, RssClass)) +#define IS_RSS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_RSS)) +#define IS_RSS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_RSS)) +#define RSS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_RSS, RssClass)) + + +typedef struct _Rss Rss; +typedef struct _RssClass RssClass; + +struct _Rss + { + GObject parent; + }; + +struct _RssClass + { + GObjectClass parent_class; + }; + +GType rss_get_type (void) G_GNUC_CONST; + +Rss *rss_new (void); +Rss *rss_new_from_file (const gchar *filename); +Rss *rss_new_from_buffer (const gchar *buffer); + +xmlDoc *rss_get_xml_doc (Rss *rss); +gboolean rss_save_file (Rss *rss, const gchar *filename); + + +G_END_DECLS + +#endif /* __RSS_H__ */ diff --git a/src/rsscategory.c b/src/rsscategory.c new file mode 100644 index 0000000..0bdf99d --- /dev/null +++ b/src/rsscategory.c @@ -0,0 +1,242 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#include + +#include + +#include "rsscategory.h" + +enum +{ + PROP_0, + PROP_LOCATION, + PROP_DOMAIN +}; + +static void rss_category_class_init (RssCategoryClass *klass); +static void rss_category_init (RssCategory *rss); + +static void rss_category_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void rss_category_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +#define RSSCATEGORY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_RSSCATEGORY, RssCategoryPrivate)) + +typedef struct _RssCategoryPrivate RssCategoryPrivate; +struct _RssCategoryPrivate + { + gchar *location, + *domain; + }; + +GType +rss_category_get_type (void) +{ + static GType rss_category_type = 0; + + if (!rss_category_type) + { + static const GTypeInfo rss_category_info = + { + sizeof (RssCategoryClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) rss_category_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (RssCategory), + 0, /* n_preallocs */ + (GInstanceInitFunc) rss_category_init, + NULL + }; + + rss_category_type = g_type_register_static (G_TYPE_OBJECT, "RssCategory", + &rss_category_info, 0); + } + + return rss_category_type; +} + +static void +rss_category_class_init (RssCategoryClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (RssCategoryPrivate)); + + object_class->set_property = rss_category_set_property; + object_class->get_property = rss_category_get_property; + + g_object_class_install_property (object_class, PROP_LOCATION, + g_param_spec_string ("location", + "Location", + "A forward-slash-separated string that identifies a hierarchic location in the indicated taxonomy.", + "default", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_DOMAIN, + g_param_spec_string ("domain", + "Domain", + "A string that identifies a categorization taxonomy.", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); +} + +static void +rss_category_init (RssCategory *rss) +{ +} + +/** + * rss_category_new: + * @location: A forward-slash-separated string that identifies a hierarchic location in the indicated taxonomy. + * + * Returns: the newly created #RssCategory object. + */ +RssCategory +*rss_category_new (const gchar *location) +{ + g_return_val_if_fail (location != NULL, NULL); + + gchar *_location = g_strstrip (g_strdup (location)); + + if (strcmp (_location, "") == 0) + { + g_critical ("rss_category_new: location cannot be an empty string"); + return NULL; + } + + RssCategory *rssc = RSSCATEGORY (g_object_new (rss_category_get_type (), NULL)); + + g_object_set (G_OBJECT (rssc), + "location", _location, + NULL); + + return rssc; +} + +/** + * rss_category_new_from_xml: + * @xnode: an #xmlNode. + * + */ +RssCategory +*rss_category_new_from_xml (xmlNode *xnode) +{ + g_return_val_if_fail (xnode != NULL, NULL); + + RssCategory *rssc = rss_category_new ("location"); + gboolean location = FALSE; + + xmlChar *prop; + + if ((prop = xmlGetProp (xnode, (const xmlChar *)"domain")) != NULL) + { + g_object_set (G_OBJECT (rssc), + "domain", (gchar *)prop, + NULL); + } + + gchar *text = (gchar *)xmlNodeGetContent (xnode); + if (strcmp (g_strstrip (text), "") != 0) + { + location = TRUE; + g_object_set (G_OBJECT (rssc), + "location", text, + NULL); + } + + return (!location ? NULL : rssc); +} + +/** + * rss_category_get_xml: + * @rss_category: a #RssCategory object + * + * Returns: the #xmlNode correspondent to the item. + */ +xmlNode +*rss_category_get_xml (RssCategory *rss_category) +{ + RssCategoryPrivate *priv = RSSCATEGORY_GET_PRIVATE (rss_category); + + xmlNode *xnode = xmlNewNode (NULL, (const xmlChar *)"category"); + + xmlAddChild (xnode, xmlNewText ((const xmlChar *)priv->location)); + + if (strcmp (priv->domain, "") != 0) + { + xmlSetProp (xnode, (const xmlChar *)"domain", (const xmlChar *)priv->domain); + } + + return xnode; +} + +static void +rss_category_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + RssCategory *rssc = RSSCATEGORY (object); + + RssCategoryPrivate *priv = RSSCATEGORY_GET_PRIVATE (rssc); + + switch (property_id) + { + case PROP_LOCATION: + priv->location = g_strdup (g_value_get_string (value)); + break; + + case PROP_DOMAIN: + priv->domain = g_strdup (g_value_get_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +rss_category_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + RssCategory *rssc = RSSCATEGORY (object); + + RssCategoryPrivate *priv = RSSCATEGORY_GET_PRIVATE (rssc); + + switch (property_id) + { + case PROP_LOCATION: + g_value_set_string (value, priv->location); + break; + + case PROP_DOMAIN: + g_value_set_string (value, priv->domain); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} diff --git a/src/rsscategory.h b/src/rsscategory.h new file mode 100644 index 0000000..abd3b00 --- /dev/null +++ b/src/rsscategory.h @@ -0,0 +1,63 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __RSSCATEGORY_H__ +#define __RSSCATEGORY_H__ + +#include +#include +#include + +G_BEGIN_DECLS + + +#define TYPE_RSSCATEGORY (rss_category_get_type ()) +#define RSSCATEGORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_RSSCATEGORY, RssCategory)) +#define RSSCATEGORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_RSSCATEGORY, RssCategoryClass)) +#define IS_RSSCATEGORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_RSSCATEGORY)) +#define IS_RSSCATEGORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_RSSCATEGORY)) +#define RSSCATEGORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_RSSCATEGORY, RssCategoryClass)) + + +typedef struct _RssCategory RssCategory; +typedef struct _RssCategoryClass RssCategoryClass; + +struct _RssCategory + { + GObject parent; + }; + +struct _RssCategoryClass + { + GObjectClass parent_class; + }; + +GType rss_category_get_type (void) G_GNUC_CONST; + +RssCategory *rss_category_new (const gchar *location); +RssCategory *rss_category_new_from_xml (xmlNode *xnode); + +xmlNode *rss_category_get_xml (RssCategory *rss_category); + + +G_END_DECLS + +#endif /* __RSSCATEGORY_H__ */ diff --git a/src/rsschannel.c b/src/rsschannel.c new file mode 100644 index 0000000..6f762fa --- /dev/null +++ b/src/rsschannel.c @@ -0,0 +1,1095 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#include +#include + +#include "rsschannel.h" +#include "rssimage.h" +#include "rsstextinput.h" +#include "rsscloud.h" + +enum +{ + PROP_0, + PROP_TITLE, + PROP_LINK, + PROP_DESCRIPTION, + PROP_LANGUAGE, + PROP_COPYRIGHT, + PROP_MANAGING_EDITOR, + PROP_WEBMASTER, + PROP_PUB_DATE, + PROP_LAST_BUILD_DATE, + PROP_GENERATOR, + PROP_DOCS, + PROP_CLOUD, + PROP_TTL, + PROP_IMAGE, + PROP_TEXT_INPUT, + PROP_SKIP_HOURS, + PROP_SKIP_DAYS +}; + +static void rss_channel_class_init (RssChannelClass *klass); +static void rss_channel_init (RssChannel *rss); + +static void rss_channel_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void rss_channel_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +#define RSSCHANNEL_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_RSSCHANNEL, RssChannelPrivate)) + +typedef struct _RssChannelPrivate RssChannelPrivate; +struct _RssChannelPrivate + { + gchar *title, + *link, + *description, + *language, + *copyright, + *managingEditor, + *webMaster, + *generator, + *docs; + struct tm *pubDate, + *lastBuildDate; + guint ttl, + skipHours, + skipDays; + RssCloud *cloud; + RssImage *image; + RssTextInput *textInput; + + GList *categories, *items; + }; + +GType +rss_channel_get_type (void) +{ + static GType rss_channel_type = 0; + + if (!rss_channel_type) + { + static const GTypeInfo rss_channel_info = + { + sizeof (RssChannelClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) rss_channel_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (RssChannel), + 0, /* n_preallocs */ + (GInstanceInitFunc) rss_channel_init, + NULL + }; + + rss_channel_type = g_type_register_static (G_TYPE_OBJECT, "RssChannel", + &rss_channel_info, 0); + } + + return rss_channel_type; +} + +static void +rss_channel_class_init (RssChannelClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (RssChannelPrivate)); + + object_class->set_property = rss_channel_set_property; + object_class->get_property = rss_channel_get_property; + + g_object_class_install_property (object_class, PROP_TITLE, + g_param_spec_string ("title", + "Title", + "The name of the channel", + "default", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_LINK, + g_param_spec_string ("link", + "Link", + "The URL to the HTML website corresponding to the channel", + "default", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_DESCRIPTION, + g_param_spec_string ("description", + "Description", + "Phrase or sentence describing the channel", + "default", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_LANGUAGE, + g_param_spec_string ("language", + "Language", + "The language the channel is written in", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_COPYRIGHT, + g_param_spec_string ("copyright", + "Copyright", + "Copyright notice for content in the channel", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_MANAGING_EDITOR, + g_param_spec_string ("managing-editor", + "Managing editor", + "Email address for person responsible for editorial content", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_WEBMASTER, + g_param_spec_string ("webmaster", + "Webmaster", + "Email address for person responsible for technical issues relating to channel", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_PUB_DATE, + g_param_spec_pointer ("pub-date", + "Publication date", + "The publication date for the content in the channel", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_LAST_BUILD_DATE, + g_param_spec_pointer ("last-build-date", + "Last build date", + "The last time the content of the channel changed", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_GENERATOR, + g_param_spec_string ("generator", + "Generator", + "A string indicating the program used to generate the channel", + "libgfeed v0.0.1", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_DOCS, + g_param_spec_string ("docs", + "Docs", + "A URL that points to the documentation for the format used in the RSS file", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_CLOUD, + g_param_spec_object ("cloud", + "Cloud", + "Allows processes to register with a cloud to be notified of updates to the channel, implementing a lightweight publish-subscribe protocol for RSS feeds.", + TYPE_RSSCLOUD, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_TTL, + g_param_spec_uint ("ttl", + "TTL", + "Time To Live", + 0, + UINT_MAX, + 0, + G_PARAM_READWRITE)); + g_object_class_install_property (object_class, PROP_IMAGE, + g_param_spec_object ("image", + "Image", + "Specifies a GIF, JPEG or PNG image that can be displayed with the channel.", + TYPE_RSSIMAGE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_TEXT_INPUT, + g_param_spec_object ("text-input", + "Text Input", + "Specifies a text input box that can be displayed with the channel.", + TYPE_RSSTEXTINPUT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_SKIP_HOURS, + g_param_spec_uint ("skip-hours", + "Skip hours", + "A hint for aggregators telling them which hours they can skip", + 0, + 16777215, + 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_SKIP_DAYS, + g_param_spec_uint ("skip-days", + "Skip days", + "A hint for aggregators telling them which days they can skip", + 0, + 127, + 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); +} + +static void +rss_channel_init (RssChannel *rss_channel) +{ + RssChannelPrivate *priv = RSSCHANNEL_GET_PRIVATE (rss_channel); + + priv->ttl = 0; +} + +/** + * rss_channel_new: + * @title: The name of the channel. It's how people refer to your service. + * @link: The URL to the HTML website corresponding to the channel. + * @description: Phrase or sentence describing the channel. + * + * Returns: the newly created #RssChannel object. + */ +RssChannel +*rss_channel_new (const gchar *title, const gchar *link, const gchar *description) +{ + g_return_val_if_fail (title != NULL, NULL); + g_return_val_if_fail (link != NULL, NULL); + g_return_val_if_fail (description != NULL, NULL); + + gchar *_title = g_strstrip (g_strdup (title)), + *_link = g_strstrip (g_strdup (link)), + *_description = g_strstrip (g_strdup (description)); + + if (strcmp (_title, "") == 0) + { + g_critical ("rss_channel_new: title cannot be an empty string"); + return NULL; + } + if (strcmp (_link, "") == 0) + { + g_critical ("rss_channel_new: link cannot be an empty string"); + return NULL; + } + if (strcmp (_description, "") == 0) + { + g_critical ("rss_channel_new: description cannot be an empty string"); + return NULL; + } + + RssChannel *rssc = RSSCHANNEL (g_object_new (rss_channel_get_type (), NULL)); + + g_object_set (G_OBJECT (rssc), + "title", _title, + "link", _link, + "description", _description, + NULL); + + return rssc; +} + +/** + * rss_channel_new_from_xml: + * @xnode: a #xmlNode to parse. + * + * Returns: the newly created #RssChannel object. + */ +RssChannel +*rss_channel_new_from_xml (xmlNode *xnode) +{ + /* creating a temporary rss_channel */ + RssChannel *rssc = rss_channel_new ("title", "link", "description"); + gboolean title = FALSE, link = FALSE, description = FALSE; + + xmlNode *cur = xnode->xmlChildrenNode; + while (cur != NULL) + { + if (xmlStrcmp (cur->name, (const xmlChar *)"title") == 0) + { + title = TRUE; + g_object_set (G_OBJECT (rssc), + "title", (gchar *)xmlNodeGetContent (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"link") == 0) + { + link = TRUE; + g_object_set (G_OBJECT (rssc), + "link", (gchar *)xmlNodeGetContent (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"description") == 0) + { + description = TRUE; + g_object_set (G_OBJECT (rssc), + "description", (gchar *)xmlNodeGetContent (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"language") == 0) + { + g_object_set (G_OBJECT (rssc), + "language", (gchar *)xmlNodeGetContent (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"copyright") == 0) + { + g_object_set (G_OBJECT (rssc), + "copyright", (gchar *)xmlNodeGetContent (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"managingEditor") == 0) + { + g_object_set (G_OBJECT (rssc), + "managing-editor", (gchar *)xmlNodeGetContent (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"webmaster") == 0) + { + g_object_set (G_OBJECT (rssc), + "webmaster", (gchar *)xmlNodeGetContent (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"pubDate") == 0) + { + struct tm tm; + gchar *ret, *text = (gchar *)xmlNodeGetContent (cur); + ret = (gchar *)strptime (text, "%a, %d %b %Y %T GMT", &tm); + if (ret != NULL) + { + g_object_set (G_OBJECT (rssc), + "pub-date", &tm, + NULL); + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"lastBuildDate") == 0) + { + struct tm tm; + gchar *ret, *text = (gchar *)xmlNodeGetContent (cur); + ret = (gchar *)strptime (text, "%a, %d %b %Y %T GMT", &tm); + if (ret != NULL) + { + g_object_set (G_OBJECT (rssc), + "last-build-date", &tm, + NULL); + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"category") == 0) + { + rss_channel_add_category (rssc, rss_category_new_from_xml (cur)); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"generator") == 0) + { + g_object_set (G_OBJECT (rssc), + "generator", (gchar *)xmlNodeGetContent (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"docs") == 0) + { + g_object_set (G_OBJECT (rssc), + "docs", (gchar *)xmlNodeGetContent (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"cloud") == 0) + { + g_object_set (G_OBJECT (rssc), + "cloud", rss_cloud_new_from_xml (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"ttl") == 0) + { + g_object_set (G_OBJECT (rssc), + "ttl", atol ((char *)xmlNodeGetContent (cur)), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"image") == 0) + { + g_object_set (G_OBJECT (rssc), + "image", rss_image_new_from_xml (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"textInput") == 0) + { + g_object_set (G_OBJECT (rssc), + "text-input", rss_text_input_new_from_xml (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"skipHours") == 0) + { + xmlNode *xhours = cur->xmlChildrenNode; + guint hours = 0; + while (xhours != NULL) + { + if (xmlStrcmp (xhours->name, (const xmlChar *)"hour") == 0) + { + if (atol ((char *)xmlNodeGetContent (xhours)) == 0) + { + hours |= RSSCHANNEL_HOUR_0; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 1) + { + hours |= RSSCHANNEL_HOUR_1; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 2) + { + hours |= RSSCHANNEL_HOUR_2; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 3) + { + hours |= RSSCHANNEL_HOUR_3; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 4) + { + hours |= RSSCHANNEL_HOUR_4; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 5) + { + hours |= RSSCHANNEL_HOUR_5; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 6) + { + hours |= RSSCHANNEL_HOUR_6; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 7) + { + hours |= RSSCHANNEL_HOUR_7; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 8) + { + hours |= RSSCHANNEL_HOUR_8; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 9) + { + hours |= RSSCHANNEL_HOUR_9; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 10) + { + hours |= RSSCHANNEL_HOUR_10; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 11) + { + hours |= RSSCHANNEL_HOUR_11; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 12) + { + hours |= RSSCHANNEL_HOUR_12; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 13) + { + hours |= RSSCHANNEL_HOUR_13; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 14) + { + hours |= RSSCHANNEL_HOUR_14; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 15) + { + hours |= RSSCHANNEL_HOUR_15; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 16) + { + hours |= RSSCHANNEL_HOUR_16; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 17) + { + hours |= RSSCHANNEL_HOUR_17; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 18) + { + hours |= RSSCHANNEL_HOUR_18; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 19) + { + hours |= RSSCHANNEL_HOUR_19; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 20) + { + hours |= RSSCHANNEL_HOUR_20; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 21) + { + hours |= RSSCHANNEL_HOUR_21; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 22) + { + hours |= RSSCHANNEL_HOUR_22; + } + else if (atol ((char *)xmlNodeGetContent (xhours)) == 23) + { + hours |= RSSCHANNEL_HOUR_23; + } + } + + xhours = xhours->next; + } + + if (hours > 0) + { + g_object_set (G_OBJECT (rssc), + "skip-hours", hours, + NULL); + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"skipDays") == 0) + { + xmlNode *xdays = cur->xmlChildrenNode; + guint days = 0; + while (xdays != NULL) + { + if (xmlStrcmp (xdays->name, (const xmlChar *)"day") == 0) + { + if (xmlStrcasestr (xmlNodeGetContent (xdays), (xmlChar *)"Monday") != NULL) + { + days |= RSSCHANNEL_DAY_MONDAY; + } + else if (xmlStrcasestr (xmlNodeGetContent (xdays), (xmlChar *)"Tuesday") != NULL) + { + days |= RSSCHANNEL_DAY_TUESDAY; + } + else if (xmlStrcasestr (xmlNodeGetContent (xdays), (xmlChar *)"Wednesday") != NULL) + { + days |= RSSCHANNEL_DAY_WEDNESDAY; + } + else if (xmlStrcasestr (xmlNodeGetContent (xdays), (xmlChar *)"Thursday") != NULL) + { + days |= RSSCHANNEL_DAY_THURSDAY; + } + else if (xmlStrcasestr (xmlNodeGetContent (xdays), (xmlChar *)"Friday") != NULL) + { + days |= RSSCHANNEL_DAY_FRIDAY; + } + else if (xmlStrcasestr (xmlNodeGetContent (xdays), (xmlChar *)"Saturday") != NULL) + { + days |= RSSCHANNEL_DAY_SATURDAY; + } + else if (xmlStrcasestr (xmlNodeGetContent (xdays), (xmlChar *)"Sunday") != NULL) + { + days |= RSSCHANNEL_DAY_SUNDAY; + } + } + + xdays = xdays->next; + } + + if (days > 0) + { + g_object_set (G_OBJECT (rssc), + "skip-days", days, + NULL); + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"item") == 0) + { + rss_channel_add_item (rssc, rss_channel_item_new_from_xml (cur)); + } + + cur = cur->next; + } + + return (!title || !link || !description ? NULL : rssc); +} + +/** + * rss_channel_add_category: + * @rss_channel: a #RssChannel object. + * @rss_category: a #RssCategory object. + * + */ +gboolean +rss_channel_add_category (RssChannel *rss_channel, RssCategory *rss_category) +{ + g_return_val_if_fail (rss_category != NULL, FALSE); + + RssChannelPrivate *priv = RSSCHANNEL_GET_PRIVATE (rss_channel); + + priv->categories = g_list_append (priv->categories, rss_category); + + return TRUE; +} + +/** + * rss_channel_get_categories: + * @rss_channel: a #RssChannel object. + * + */ +GList +*rss_channel_get_categories (RssChannel *rss_channel) +{ + RssChannelPrivate *priv = RSSCHANNEL_GET_PRIVATE (rss_channel); + + return priv->categories; +} + +/** + * rss_channel_add_item: + * @rss_channel: a #RssChannel object. + * @rss_channel_item: a #RssChannelItem object. + * + */ +gboolean +rss_channel_add_item (RssChannel *rss_channel, RssChannelItem *rss_channel_item) +{ + RssChannelPrivate *priv = RSSCHANNEL_GET_PRIVATE (rss_channel); + + priv->items = g_list_append (priv->items, rss_channel_item); + + return TRUE; +} + +/** + * rss_channel_remove_item: + * @rss_channel: a #RssChannel object. + * @rss_channel_item: a #RssChannelItem object. + * + */ +gboolean +rss_channel_remove_item (RssChannel *rss_channel, RssChannelItem *rss_channel_item) +{ + RssChannelPrivate *priv = RSSCHANNEL_GET_PRIVATE (rss_channel); + + priv->items = g_list_remove (priv->items, (gconstpointer)rss_channel_item); + + return TRUE; +} + +/** + * rss_channel_get_xml: + * @rss_channel: a #RssChannel object. + * + * Returns: the #xmlNode correspondent to the channel and its items. + */ +xmlNode +*rss_channel_get_xml (RssChannel *rss_channel) +{ + char pd[256]; + GList *categories, *items; + RssChannelPrivate *priv = RSSCHANNEL_GET_PRIVATE (rss_channel); + + xmlNode *xnode = xmlNewNode (NULL, (const xmlChar *)"channel"); + + xmlNewTextChild (xnode, NULL, (const xmlChar *)"title", (const xmlChar *)priv->title); + xmlNewTextChild (xnode, NULL, (const xmlChar *)"link", (const xmlChar *)priv->link); + xmlNewTextChild (xnode, NULL, (const xmlChar *)"description", (const xmlChar *)priv->description); + + if (strcmp (priv->language, "") != 0) + { + xmlNewTextChild (xnode, NULL, (const xmlChar *)"language", (const xmlChar *)priv->language); + } + if (strcmp (priv->copyright, "") != 0) + { + xmlNewTextChild (xnode, NULL, (const xmlChar *)"copyright", (const xmlChar *)priv->copyright); + } + if (strcmp (priv->managingEditor, "") != 0) + { + xmlNewTextChild (xnode, NULL, (const xmlChar *)"managingEditor", (const xmlChar *)priv->managingEditor); + } + if (strcmp (priv->webMaster, "") != 0) + { + xmlNewTextChild (xnode, NULL, (const xmlChar *)"webMaster", (const xmlChar *)priv->webMaster); + } + + if (priv->pubDate != NULL) + { + strftime (pd, 256, "%a, %d %b %Y %T GMT", (const struct tm *)priv->pubDate); + xmlNewTextChild (xnode, NULL, (const xmlChar *)"pubDate", (const xmlChar *)pd); + } + if (priv->lastBuildDate != NULL) + { + strftime (pd, 256, "%a, %d %b %Y %T GMT", (const struct tm *)priv->lastBuildDate); + xmlNewTextChild (xnode, NULL, (const xmlChar *)"lastBuildDate", (const xmlChar *)pd); + } + + categories = priv->categories; + while (categories != NULL) + { + xmlAddChild (xnode, rss_category_get_xml ((RssCategory *)categories->data)); + + categories = g_list_next (categories); + } + + if (strcmp (priv->generator, "") != 0) + { + xmlNewTextChild (xnode, NULL, (const xmlChar *)"generator", (const xmlChar *)priv->generator); + } + if (strcmp (priv->docs, "") != 0) + { + xmlNewTextChild (xnode, NULL, (const xmlChar *)"docs", (const xmlChar *)priv->docs); + } + + if (priv->cloud != NULL) + { + xmlAddChild (xnode, rss_cloud_get_xml (priv->cloud)); + } + + if (priv->ttl > 0) + { + xmlNewTextChild (xnode, NULL, (const xmlChar *)"ttl", (const xmlChar *)g_strdup_printf ("%d", priv->ttl)); + } + + if (priv->image != NULL) + { + xmlAddChild (xnode, rss_image_get_xml (priv->image)); + } + + if (priv->textInput!= NULL) + { + xmlAddChild (xnode, rss_text_input_get_xml (priv->textInput)); + } + + if (priv->skipHours > 0) + { + xmlNode *xnodeh = xmlNewNode (NULL, (const xmlChar *)"skipHours"); + if (priv->skipHours & RSSCHANNEL_HOUR_0) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"0"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_1) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"1"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_2) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"2"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_3) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"3"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_4) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"4"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_5) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"5"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_6) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"6"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_7) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"7"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_8) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"8"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_9) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"9"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_10) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"10"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_11) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"11"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_12) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"12"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_13) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"13"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_14) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"14"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_15) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"15"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_16) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"16"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_17) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"17"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_18) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"18"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_19) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"19"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_20) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"20"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_21) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"21"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_22) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"22"); + } + if (priv->skipHours & RSSCHANNEL_HOUR_23) + { + xmlNewTextChild (xnodeh, NULL, (const xmlChar *)"hour", (const xmlChar *)"23"); + } + + xmlAddChild (xnode, xnodeh); + } + + if (priv->skipDays > 0) + { + xmlNode *xnoded = xmlNewNode (NULL, (const xmlChar *)"skipDays"); + if (priv->skipDays & RSSCHANNEL_DAY_MONDAY) + { + xmlNewTextChild (xnoded, NULL, (const xmlChar *)"day", (const xmlChar *)"Monday"); + } + if (priv->skipDays & RSSCHANNEL_DAY_TUESDAY) + { + xmlNewTextChild (xnoded, NULL, (const xmlChar *)"day", (const xmlChar *)"Tuesday"); + } + if (priv->skipDays & RSSCHANNEL_DAY_WEDNESDAY) + { + xmlNewTextChild (xnoded, NULL, (const xmlChar *)"day", (const xmlChar *)"Wednesday"); + } + if (priv->skipDays & RSSCHANNEL_DAY_THURSDAY) + { + xmlNewTextChild (xnoded, NULL, (const xmlChar *)"day", (const xmlChar *)"Thursday"); + } + if (priv->skipDays & RSSCHANNEL_DAY_FRIDAY) + { + xmlNewTextChild (xnoded, NULL, (const xmlChar *)"day", (const xmlChar *)"Friday"); + } + if (priv->skipDays & RSSCHANNEL_DAY_SATURDAY) + { + xmlNewTextChild (xnoded, NULL, (const xmlChar *)"day", (const xmlChar *)"Saturday"); + } + if (priv->skipDays & RSSCHANNEL_DAY_SUNDAY) + { + xmlNewTextChild (xnoded, NULL, (const xmlChar *)"day", (const xmlChar *)"Sunday"); + } + + xmlAddChild (xnode, xnoded); + } + + items = priv->items; + while (items != NULL) + { + xmlAddChild (xnode, rss_channel_item_get_xml ((RssChannelItem *)items->data)); + + items = g_list_next (items); + } + + return xnode; +} + +static void +rss_channel_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + RssChannel *rssc = RSSCHANNEL (object); + + RssChannelPrivate *priv = RSSCHANNEL_GET_PRIVATE (rssc); + + switch (property_id) + { + case PROP_TITLE: + { + gchar *prop = g_strdup (g_value_get_string (value)); + if (strcmp (g_strstrip (prop), "") == 0) + { + g_critical ("rss_channel_set_property: title cannot be an empty string"); + } + else + { + priv->title = prop; + } + } + break; + + case PROP_LINK: + { + gchar *prop = g_strdup (g_value_get_string (value)); + if (strcmp (g_strstrip (prop), "") == 0) + { + g_critical ("rss_channel_set_property: link cannot be an empty string"); + } + else + { + priv->link = prop; + } + } + break; + + case PROP_DESCRIPTION: + { + gchar *prop = g_strdup (g_value_get_string (value)); + if (strcmp (g_strstrip (prop), "") == 0) + { + g_critical ("rss_channel_set_property: description cannot be an empty string"); + } + else + { + priv->description = prop; + } + } + break; + + case PROP_LANGUAGE: + priv->language = g_strdup (g_value_get_string (value)); + break; + + case PROP_COPYRIGHT: + priv->copyright = g_strdup (g_value_get_string (value)); + break; + + case PROP_MANAGING_EDITOR: + priv->managingEditor = g_strdup (g_value_get_string (value)); + break; + + case PROP_WEBMASTER: + priv->webMaster = g_strdup (g_value_get_string (value)); + break; + + case PROP_PUB_DATE: + if (g_value_get_pointer (value) != NULL) + { + priv->pubDate = g_memdup ((gconstpointer)g_value_get_pointer (value), sizeof (struct tm)); + } + break; + + case PROP_LAST_BUILD_DATE: + if (g_value_get_pointer (value) != NULL) + { + priv->lastBuildDate = g_memdup ((gconstpointer)g_value_get_pointer (value), sizeof (struct tm)); + } + break; + + case PROP_GENERATOR: + priv->generator = g_strdup (g_value_get_string (value)); + break; + + case PROP_DOCS: + priv->docs = g_strdup (g_value_get_string (value)); + break; + + case PROP_CLOUD: + if (g_value_get_object (value) != NULL) + { + priv->cloud = (RssCloud *)g_value_dup_object (value); + } + break; + + case PROP_TTL: + priv->ttl = g_value_get_uint (value); + break; + + case PROP_IMAGE: + if (g_value_get_object (value) != NULL) + { + priv->image = (RssImage *)g_value_dup_object (value); + } + break; + + case PROP_TEXT_INPUT: + if (g_value_get_object (value) != NULL) + { + priv->textInput = (RssTextInput *)g_value_dup_object (value); + } + break; + + case PROP_SKIP_HOURS: + priv->skipHours = g_value_get_uint (value); + break; + + case PROP_SKIP_DAYS: + priv->skipDays = g_value_get_uint (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +rss_channel_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + RssChannel *rssc = RSSCHANNEL (object); + + RssChannelPrivate *priv = RSSCHANNEL_GET_PRIVATE (rssc); + + switch (property_id) + { + case PROP_TITLE: + g_value_set_string (value, priv->title); + break; + + case PROP_LINK: + g_value_set_string (value, priv->link); + break; + + case PROP_DESCRIPTION: + g_value_set_string (value, priv->description); + break; + + case PROP_LANGUAGE: + g_value_set_string (value, priv->language); + break; + + case PROP_COPYRIGHT: + g_value_set_string (value, priv->copyright); + break; + + case PROP_MANAGING_EDITOR: + g_value_set_string (value, priv->managingEditor); + break; + + case PROP_WEBMASTER: + g_value_set_string (value, priv->webMaster); + break; + + case PROP_PUB_DATE: + g_value_set_pointer (value, priv->pubDate); + break; + + case PROP_LAST_BUILD_DATE: + g_value_set_pointer (value, priv->lastBuildDate); + break; + + case PROP_GENERATOR: + g_value_set_string (value, priv->generator); + break; + + case PROP_DOCS: + g_value_set_string (value, priv->docs); + break; + + case PROP_CLOUD: + g_value_set_object (value, priv->cloud); + break; + + case PROP_TTL: + g_value_set_uint (value, priv->ttl); + break; + + case PROP_IMAGE: + g_value_set_object (value, priv->image); + break; + + case PROP_TEXT_INPUT: + g_value_set_object (value, priv->textInput); + break; + + case PROP_SKIP_HOURS: + g_value_set_uint (value, priv->skipHours); + break; + + case PROP_SKIP_DAYS: + g_value_set_uint (value, priv->skipDays); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} diff --git a/src/rsschannel.h b/src/rsschannel.h new file mode 100644 index 0000000..f70af3e --- /dev/null +++ b/src/rsschannel.h @@ -0,0 +1,105 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __RSSCHANNEL_H__ +#define __RSSCHANNEL_H__ + +#include +#include +#include + +#include "rsscategory.h" +#include "rsschannelitem.h" + +G_BEGIN_DECLS + + +#define TYPE_RSSCHANNEL (rss_channel_get_type ()) +#define RSSCHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_RSSCHANNEL, RssChannel)) +#define RSSCHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_RSSCHANNEL, RssChannelClass)) +#define IS_RSSCHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_RSSCHANNEL)) +#define IS_RSSCHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_RSSCHANNEL)) +#define RSSCHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_RSSCHANNEL, RssChannelClass)) + + +#define RSSCHANNEL_DAY_MONDAY 1 << 0 +#define RSSCHANNEL_DAY_TUESDAY 1 << 1 +#define RSSCHANNEL_DAY_WEDNESDAY 1 << 2 +#define RSSCHANNEL_DAY_THURSDAY 1 << 3 +#define RSSCHANNEL_DAY_FRIDAY 1 << 4 +#define RSSCHANNEL_DAY_SATURDAY 1 << 5 +#define RSSCHANNEL_DAY_SUNDAY 1 << 6 + +#define RSSCHANNEL_HOUR_0 1 << 0 +#define RSSCHANNEL_HOUR_1 1 << 1 +#define RSSCHANNEL_HOUR_2 1 << 2 +#define RSSCHANNEL_HOUR_3 1 << 3 +#define RSSCHANNEL_HOUR_4 1 << 4 +#define RSSCHANNEL_HOUR_5 1 << 5 +#define RSSCHANNEL_HOUR_6 1 << 6 +#define RSSCHANNEL_HOUR_7 1 << 7 +#define RSSCHANNEL_HOUR_8 1 << 8 +#define RSSCHANNEL_HOUR_9 1 << 9 +#define RSSCHANNEL_HOUR_10 1 << 10 +#define RSSCHANNEL_HOUR_11 1 << 11 +#define RSSCHANNEL_HOUR_12 1 << 12 +#define RSSCHANNEL_HOUR_13 1 << 13 +#define RSSCHANNEL_HOUR_14 1 << 14 +#define RSSCHANNEL_HOUR_15 1 << 15 +#define RSSCHANNEL_HOUR_16 1 << 16 +#define RSSCHANNEL_HOUR_17 1 << 17 +#define RSSCHANNEL_HOUR_18 1 << 18 +#define RSSCHANNEL_HOUR_19 1 << 19 +#define RSSCHANNEL_HOUR_20 1 << 20 +#define RSSCHANNEL_HOUR_21 1 << 21 +#define RSSCHANNEL_HOUR_22 1 << 22 +#define RSSCHANNEL_HOUR_23 1 << 23 + +typedef struct _RssChannel RssChannel; +typedef struct _RssChannelClass RssChannelClass; + +struct _RssChannel + { + GObject parent; + }; + +struct _RssChannelClass + { + GObjectClass parent_class; + }; + +GType rss_channel_get_type (void) G_GNUC_CONST; + +RssChannel *rss_channel_new (const gchar *title, const gchar *link, const gchar *description); +RssChannel *rss_channel_new_from_xml (xmlNode *xnode); + +gboolean rss_channel_add_category (RssChannel *rss_channel, RssCategory *rss_category); +GList *rss_channel_get_categories (RssChannel *rss_channel); + +gboolean rss_channel_add_item (RssChannel *rss_channel, RssChannelItem *rss_channel_item); +gboolean rss_channel_remove_item (RssChannel *rss_channel, RssChannelItem *rss_channel_item); + +xmlNode *rss_channel_get_xml (RssChannel *rss_channel); + + +G_END_DECLS + +#endif /* __RSSCHANNEL_H__ */ diff --git a/src/rsschannelitem.c b/src/rsschannelitem.c new file mode 100644 index 0000000..4b69553 --- /dev/null +++ b/src/rsschannelitem.c @@ -0,0 +1,502 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#include + +#include + +#include "rsschannelitem.h" +#include "rssenclosure.h" +#include "rssguid.h" +#include "rsssource.h" + +enum +{ + PROP_0, + PROP_TITLE, + PROP_LINK, + PROP_DESCRIPTION, + PROP_AUTHOR, + PROP_COMMENTS, + PROP_ENCLOSURE, + PROP_GUID, + PROP_PUB_DATE, + PROP_SOURCE +}; + +static void rss_channel_item_class_init (RssChannelItemClass *klass); +static void rss_channel_item_init (RssChannelItem *rss); + +static void rss_channel_item_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void rss_channel_item_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +#define RSSCHANNELITEM_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_RSSCHANNELITEM, RssChannelItemPrivate)) + +typedef struct _RssChannelItemPrivate RssChannelItemPrivate; +struct _RssChannelItemPrivate + { + gchar *title, + *link, + *description, + *author, + *category, + *comments; + RssEnclosure *enclosure; + RssGuid *guid; + struct tm *pubDate; + GList *categories; + RssSource *source; + }; + +GType +rss_channel_item_get_type (void) +{ + static GType rss_channel_item_type = 0; + + if (!rss_channel_item_type) + { + static const GTypeInfo rss_channel_item_info = + { + sizeof (RssChannelItemClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) rss_channel_item_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (RssChannelItem), + 0, /* n_preallocs */ + (GInstanceInitFunc) rss_channel_item_init, + NULL + }; + + rss_channel_item_type = g_type_register_static (G_TYPE_OBJECT, "RssChannelItem", + &rss_channel_item_info, 0); + } + + return rss_channel_item_type; +} + +static void +rss_channel_item_class_init (RssChannelItemClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (RssChannelItemPrivate)); + + object_class->set_property = rss_channel_item_set_property; + object_class->get_property = rss_channel_item_get_property; + + g_object_class_install_property (object_class, PROP_TITLE, + g_param_spec_string ("title", + "Title", + "The title of the item.", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_LINK, + g_param_spec_string ("link", + "Link", + "The URL of the item.", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_DESCRIPTION, + g_param_spec_string ("description", + "Description", + "The item synopsis.", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_AUTHOR, + g_param_spec_string ("author", + "Author", + "Email address of the author of the item.", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_COMMENTS, + g_param_spec_string ("comments", + "Comments", + "URL of a page for comments relating to the item.", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_ENCLOSURE, + g_param_spec_object ("enclosure", + "Enclosure", + "Describes a media object that is attached to the item.", + TYPE_RSSENCLOSURE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_GUID, + g_param_spec_object ("guid", + "GUID", + "A string that uniquely identifies the item.", + TYPE_RSSGUID, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_PUB_DATE, + g_param_spec_pointer ("pub-date", + "Publication date", + "Indicates when the item was published.", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_SOURCE, + g_param_spec_object ("source", + "Source", + "The RSS channel that the item came from.", + TYPE_RSSSOURCE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); +} + +static void +rss_channel_item_init (RssChannelItem *rss) +{ +} + +/** + * rss_channel_item_new: + * @title: the title of the item. + * @description: the item synopsis. + * + * Returns: the newly created #RssChannelItem object. + */ +RssChannelItem +*rss_channel_item_new (const gchar *title, const gchar *description) +{ + g_return_val_if_fail (title != NULL && description != NULL, NULL); + + gchar *_title = g_strstrip (g_strdup (title)), + *_description = g_strstrip (g_strdup (description)); + + if (strcmp (_title, "") == 0 && strcmp (_description, "") == 0) + { + g_critical ("rss_channel_item_new: one of title or description must be present"); + return NULL; + } + + RssChannelItem *rssci = RSSCHANNELITEM (g_object_new (rss_channel_item_get_type (), NULL)); + + g_object_set (G_OBJECT (rssci), + "title", _title, + "description", _description, + NULL); + + return rssci; +} + +/** + * rss_channel_item_new_from_xml: + * @xnode: an #xmlNode. + * + */ +RssChannelItem +*rss_channel_item_new_from_xml (xmlNode *xnode) +{ + g_return_val_if_fail (xnode != NULL, NULL); + + RssChannelItem *rssci = rss_channel_item_new ("title", "description"); + gboolean title = FALSE, description = FALSE; + + xmlNode *cur = xnode->xmlChildrenNode; + while (cur != NULL) + { + if (xmlStrcmp (cur->name, (const xmlChar *)"title") == 0) + { + title = TRUE; + g_object_set (G_OBJECT (rssci), + "title", (gchar *)xmlNodeGetContent (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"link") == 0) + { + g_object_set (G_OBJECT (rssci), + "link", (gchar *)xmlNodeGetContent (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"description") == 0) + { + description = TRUE; + g_object_set (G_OBJECT (rssci), + "description", (gchar *)xmlNodeGetContent (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"author") == 0) + { + g_object_set (G_OBJECT (rssci), + "author", (gchar *)xmlNodeGetContent (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"category") == 0) + { + rss_channel_item_add_category (rssci, rss_category_new_from_xml (cur)); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"comments") == 0) + { + g_object_set (G_OBJECT (rssci), + "comments", (gchar *)xmlNodeGetContent (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"enclosure") == 0) + { + g_object_set (G_OBJECT (rssci), + "enclosure", rss_enclosure_new_from_xml (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"guid") == 0) + { + g_object_set (G_OBJECT (rssci), + "guid", rss_guid_new_from_xml (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"pubDate") == 0) + { + struct tm tm; + gchar *ret, *text = (gchar *)xmlNodeGetContent (cur); + ret = (gchar *)strptime (text, "%a, %d %b %Y %T GMT", &tm); + if (ret != NULL) + { + g_object_set (G_OBJECT (rssci), + "pub-date", &tm, + NULL); + } + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"image") == 0) + { + g_object_set (G_OBJECT (rssci), + "image", rss_image_new_from_xml (cur), + NULL); + } + + cur = cur->next; + } + + return (!title || !description ? NULL : rssci); +} + +/** + * rss_channel_item_add_category: + * @rss_channel_item: + * @rss_category: + * + */ +gboolean +rss_channel_item_add_category (RssChannelItem *rss_channel_item, RssCategory *rss_category) +{ + RssChannelItemPrivate *priv = RSSCHANNELITEM_GET_PRIVATE (rss_channel_item); + + priv->categories = g_list_append (priv->categories, rss_category); + + return TRUE; +} + +/** + * rss_channel_item_get_categories: + * @rss_channel_item: + * + */ +GList +*rss_channel_item_get_categories (RssChannelItem *rss_channel_item) +{ + RssChannelItemPrivate *priv = RSSCHANNELITEM_GET_PRIVATE (rss_channel_item); + + return priv->categories; +} + +/** + * rss_channel_item_get_xml: + * @rss_channel_item: a #RssChannelItem object + * + * Returns: the #xmlNode correspondent to the item. + */ +xmlNode +*rss_channel_item_get_xml (RssChannelItem *rss_channel_item) +{ + char pd[256]; + GList *categories; + RssChannelItemPrivate *priv = RSSCHANNELITEM_GET_PRIVATE (rss_channel_item); + + xmlNode *xnode = xmlNewNode (NULL, (const xmlChar *)"item"); + + if (strcmp (priv->title, "") != 0) + { + xmlNewTextChild (xnode, NULL, (const xmlChar *)"title", (const xmlChar *)priv->title); + } + if (strcmp (priv->link, "") != 0) + { + xmlNewTextChild (xnode, NULL, (const xmlChar *)"link", (const xmlChar *)priv->link); + } + if (strcmp (priv->description, "") != 0) + { + xmlNewTextChild (xnode, NULL, (const xmlChar *)"description", (const xmlChar *)priv->description); + } + if (strcmp (priv->author, "") != 0) + { + xmlNewTextChild (xnode, NULL, (const xmlChar *)"author", (const xmlChar *)priv->author); + } + + categories = priv->categories; + while (categories != NULL) + { + xmlAddChild (xnode, rss_category_get_xml ((RssCategory *)categories->data)); + + categories = g_list_next (categories); + } + + if (strcmp (priv->comments, "") != 0) + { + xmlNewTextChild (xnode, NULL, (const xmlChar *)"comments", (const xmlChar *)priv->comments); + } + + if (priv->enclosure != NULL) + { + xmlAddChild (xnode, rss_enclosure_get_xml (priv->enclosure)); + } + if (priv->guid != NULL) + { + xmlAddChild (xnode, rss_guid_get_xml (priv->guid)); + } + + if (priv->pubDate != NULL) + { + strftime (pd, 256, "%a, %d %b %Y %T GMT", (const struct tm *)priv->pubDate); + xmlNewTextChild (xnode, NULL, (const xmlChar *)"pubDate", (const xmlChar *)pd); + } + + if (priv->source != NULL) + { + xmlAddChild (xnode, rss_source_get_xml (priv->source)); + } + + return xnode; +} + +static void +rss_channel_item_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + RssChannelItem *rssci = RSSCHANNELITEM (object); + + RssChannelItemPrivate *priv = RSSCHANNELITEM_GET_PRIVATE (rssci); + + switch (property_id) + { + case PROP_TITLE: + priv->title = g_strdup (g_value_get_string (value)); + break; + + case PROP_LINK: + priv->link = g_strdup (g_value_get_string (value)); + break; + + case PROP_DESCRIPTION: + priv->description = g_strdup (g_value_get_string (value)); + break; + + case PROP_AUTHOR: + priv->author = g_strdup (g_value_get_string (value)); + break; + + case PROP_COMMENTS: + priv->comments = g_strdup (g_value_get_string (value)); + break; + + case PROP_ENCLOSURE: + if (g_value_get_object (value) != NULL) + { + priv->enclosure = (RssEnclosure *)g_value_dup_object (value); + } + break; + + case PROP_GUID: + if (g_value_get_object (value) != NULL) + { + priv->guid = (RssGuid *)g_value_dup_object (value); + } + break; + + case PROP_PUB_DATE: + if (g_value_get_pointer (value) != NULL) + { + priv->pubDate = g_memdup ((gconstpointer)g_value_get_pointer (value), sizeof (struct tm)); + } + break; + + case PROP_SOURCE: + if (g_value_get_object (value) != NULL) + { + priv->source = (RssSource *)g_value_dup_object (value); + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +rss_channel_item_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + RssChannelItem *rssci = RSSCHANNELITEM (object); + + RssChannelItemPrivate *priv = RSSCHANNELITEM_GET_PRIVATE (rssci); + + switch (property_id) + { + case PROP_TITLE: + g_value_set_string (value, priv->title); + break; + + case PROP_LINK: + g_value_set_string (value, priv->link); + break; + + case PROP_DESCRIPTION: + g_value_set_string (value, priv->description); + break; + + case PROP_AUTHOR: + g_value_set_string (value, priv->author); + break; + + case PROP_COMMENTS: + g_value_set_string (value, priv->comments); + break; + + case PROP_ENCLOSURE: + g_value_set_object (value, priv->enclosure); + break; + + case PROP_GUID: + g_value_set_object (value, priv->guid); + break; + + case PROP_PUB_DATE: + g_value_set_pointer (value, priv->pubDate); + break; + + case PROP_SOURCE: + g_value_set_object (value, priv->source); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} diff --git a/src/rsschannelitem.h b/src/rsschannelitem.h new file mode 100644 index 0000000..2bf9f16 --- /dev/null +++ b/src/rsschannelitem.h @@ -0,0 +1,68 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __RSSCHANNELITEMITEM_H__ +#define __RSSCHANNELITEMITEM_H__ + +#include +#include +#include + +#include "rsscategory.h" + +G_BEGIN_DECLS + + +#define TYPE_RSSCHANNELITEM (rss_channel_item_get_type ()) +#define RSSCHANNELITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_RSSCHANNELITEM, RssChannelItem)) +#define RSSCHANNELITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_RSSCHANNELITEM, RssChannelItemClass)) +#define IS_RSSCHANNELITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_RSSCHANNELITEM)) +#define IS_RSSCHANNELITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_RSSCHANNELITEM)) +#define RSSCHANNELITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_RSSCHANNELITEM, RssChannelItemClass)) + + +typedef struct _RssChannelItem RssChannelItem; +typedef struct _RssChannelItemClass RssChannelItemClass; + +struct _RssChannelItem + { + GObject parent; + }; + +struct _RssChannelItemClass + { + GObjectClass parent_class; + }; + +GType rss_channel_item_get_type (void) G_GNUC_CONST; + +RssChannelItem *rss_channel_item_new (const gchar *title, const gchar *description); +RssChannelItem *rss_channel_item_new_from_xml (xmlNode *xnode); + +gboolean rss_channel_item_add_category (RssChannelItem *rss_channel_item, RssCategory *rss_category); +GList *rss_channel_item_get_categories (RssChannelItem *rss_channel_item); + +xmlNode *rss_channel_item_get_xml (RssChannelItem *rss_channel_item); + + +G_END_DECLS + +#endif /* __RSSCHANNELITEM_H__ */ diff --git a/src/rsscloud.c b/src/rsscloud.c new file mode 100644 index 0000000..064f57f --- /dev/null +++ b/src/rsscloud.c @@ -0,0 +1,346 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#include + +#include + +#include "rsscloud.h" + +enum +{ + PROP_0, + PROP_DOMAIN, + PROP_PORT, + PROP_PATH, + PROP_REGISTER_PROCEDURE, + PROP_PROTOCOL +}; + +static void rss_cloud_class_init (RssCloudClass *klass); +static void rss_cloud_init (RssCloud *rss); + +static void rss_cloud_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void rss_cloud_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +#define RSSCLOUD_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_RSSCLOUD, RssCloudPrivate)) + +typedef struct _RssCloudPrivate RssCloudPrivate; +struct _RssCloudPrivate + { + gchar *domain, + *path, + *registerProcedure, + *protocol; + guint port; + }; + +GType +rss_cloud_get_type (void) +{ + static GType rss_cloud_type = 0; + + if (!rss_cloud_type) + { + static const GTypeInfo rss_cloud_info = + { + sizeof (RssCloudClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) rss_cloud_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (RssCloud), + 0, /* n_preallocs */ + (GInstanceInitFunc) rss_cloud_init, + NULL + }; + + rss_cloud_type = g_type_register_static (G_TYPE_OBJECT, "RssCloud", + &rss_cloud_info, 0); + } + + return rss_cloud_type; +} + +static void +rss_cloud_class_init (RssCloudClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (RssCloudPrivate)); + + object_class->set_property = rss_cloud_set_property; + object_class->get_property = rss_cloud_get_property; + + g_object_class_install_property (object_class, PROP_DOMAIN, + g_param_spec_string ("domain", + "Domain", + "Domain", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_PORT, + g_param_spec_uint ("port", + "Port", + "Port", + 1, + 65565, + 80, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_PATH, + g_param_spec_string ("path", + "Path", + "Path", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_REGISTER_PROCEDURE, + g_param_spec_string ("register-procedure", + "Register Procedure", + "Register Procedure", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_PROTOCOL, + g_param_spec_string ("protocol", + "Protocol", + "Protocol", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); +} + +static void +rss_cloud_init (RssCloud *rss) +{ +} + +/** + * rss_cloud_new: + * @domain: + * @port: + * @path: + * @registerProcedure: + * @protocol: + * + * Returns: the newly created #RssCloud object. + */ +RssCloud +*rss_cloud_new (const gchar *domain, + guint port, + const gchar *path, + const gchar *registerProcedure, + const gchar *protocol) +{ + g_return_val_if_fail (domain != NULL, NULL); + g_return_val_if_fail (port > 0 && port < 65565, NULL); + g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (registerProcedure != NULL, NULL); + g_return_val_if_fail (protocol != NULL, NULL); + + gchar *_domain = g_strstrip (g_strdup (domain)), + *_path = g_strstrip (g_strdup (path)), + *_registerProcedure = g_strstrip (g_strdup (registerProcedure)), + *_protocol = g_strstrip (g_strdup (protocol)); + + if (strcmp (_domain, "") == 0) + { + g_critical ("rss_cloud_new: domain cannot be an empty string"); + return NULL; + } + if (strcmp (_path, "") == 0) + { + g_critical ("rss_cloud_new: path cannot be an empty string"); + return NULL; + } + if (strcmp (_registerProcedure, "") == 0) + { + g_critical ("rss_cloud_new: registerProcedure cannot be an empty string"); + return NULL; + } + if (strcmp (_protocol, "") == 0) + { + g_critical ("rss_cloud_new: protocol cannot be an empty string"); + return NULL; + } + + RssCloud *rssc = RSSCLOUD (g_object_new (rss_cloud_get_type (), NULL)); + + g_object_set (G_OBJECT (rssc), + "domain", _domain, + "port", port, + "path", _path, + "register-procedure", _registerProcedure, + "protocol", _protocol, + NULL); + + return rssc; +} + +/** + * rss_cloud_new_from_xml: + * @xnode: an #xmlNode. + * + */ +RssCloud +*rss_cloud_new_from_xml (xmlNode *xnode) +{ + g_return_val_if_fail (xnode != NULL, NULL); + + RssCloud *rssc = rss_cloud_new ("domain", 80, "path", "register-procedure", "protocol"); + gboolean domain = FALSE, port = FALSE, path = FALSE, + registerProcedure = FALSE, protocol = FALSE; + + xmlChar *prop; + + if ((prop = xmlGetProp (xnode, (const xmlChar *)"domain")) != NULL) + { + domain = TRUE; + g_object_set (G_OBJECT (rssc), + "domain", (gchar *)prop, + NULL); + } + if ((prop = xmlGetProp (xnode, (const xmlChar *)"port")) != NULL) + { + port = TRUE; + g_object_set (G_OBJECT (rssc), + "port", atol ((char *)prop), + NULL); + } + if ((prop = xmlGetProp (xnode, (const xmlChar *)"path")) != NULL) + { + path = TRUE; + g_object_set (G_OBJECT (rssc), + "path", (gchar *)prop, + NULL); + } + if ((prop = xmlGetProp (xnode, (const xmlChar *)"registerProcedure")) != NULL) + { + registerProcedure = TRUE; + g_object_set (G_OBJECT (rssc), + "register-procedure", (gchar *)prop, + NULL); + } + if ((prop = xmlGetProp (xnode, (const xmlChar *)"protocol")) != NULL) + { + protocol = TRUE; + g_object_set (G_OBJECT (rssc), + "protocol", (gchar *)prop, + NULL); + } + + return (!domain || !port || !path || !registerProcedure || !protocol ? NULL : rssc); +} + +/** + * rss_cloud_get_xml: + * @rss_cloud: a #RssCloud object + * + * Returns: the #xmlNode correspondent to the item. + */ +xmlNode +*rss_cloud_get_xml (RssCloud *rss_cloud) +{ + RssCloudPrivate *priv = RSSCLOUD_GET_PRIVATE (rss_cloud); + + xmlNode *xnode = xmlNewNode (NULL, (const xmlChar *)"cloud"); + + xmlSetProp (xnode, (const xmlChar *)"domain", (const xmlChar *)priv->domain); + xmlSetProp (xnode, (const xmlChar *)"port", (const xmlChar *)g_strdup_printf ("%d", priv->port)); + xmlSetProp (xnode, (const xmlChar *)"path", (const xmlChar *)priv->path); + xmlSetProp (xnode, (const xmlChar *)"registerProcedure", (const xmlChar *)priv->registerProcedure); + xmlSetProp (xnode, (const xmlChar *)"protocol", (const xmlChar *)priv->protocol); + + return xnode; +} + +static void +rss_cloud_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + RssCloud *rssc = RSSCLOUD (object); + + RssCloudPrivate *priv = RSSCLOUD_GET_PRIVATE (rssc); + + switch (property_id) + { + case PROP_DOMAIN: + priv->domain = g_strdup (g_value_get_string (value)); + break; + + case PROP_PORT: + priv->port = g_value_get_uint (value); + break; + + case PROP_PATH: + priv->path = g_strdup (g_value_get_string (value)); + break; + + case PROP_REGISTER_PROCEDURE: + priv->registerProcedure = g_strdup (g_value_get_string (value)); + break; + + case PROP_PROTOCOL: + priv->protocol = g_strdup (g_value_get_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +rss_cloud_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + RssCloud *rssc = RSSCLOUD (object); + + RssCloudPrivate *priv = RSSCLOUD_GET_PRIVATE (rssc); + + switch (property_id) + { + case PROP_DOMAIN: + g_value_set_string (value, priv->domain); + break; + + case PROP_PORT: + g_value_set_uint (value, priv->port); + break; + + case PROP_PATH: + g_value_set_string (value, priv->path); + break; + + case PROP_REGISTER_PROCEDURE: + g_value_set_string (value, priv->registerProcedure); + break; + + case PROP_PROTOCOL: + g_value_set_string (value, priv->protocol); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} diff --git a/src/rsscloud.h b/src/rsscloud.h new file mode 100644 index 0000000..f84590a --- /dev/null +++ b/src/rsscloud.h @@ -0,0 +1,67 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __RSSCLOUD_H__ +#define __RSSCLOUD_H__ + +#include +#include +#include + +G_BEGIN_DECLS + + +#define TYPE_RSSCLOUD (rss_cloud_get_type ()) +#define RSSCLOUD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_RSSCLOUD, RssCloud)) +#define RSSCLOUD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_RSSCLOUD, RssCloudClass)) +#define IS_RSSCLOUD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_RSSCLOUD)) +#define IS_RSSCLOUD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_RSSCLOUD)) +#define RSSCLOUD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_RSSCLOUD, RssCloudClass)) + + +typedef struct _RssCloud RssCloud; +typedef struct _RssCloudClass RssCloudClass; + +struct _RssCloud + { + GObject parent; + }; + +struct _RssCloudClass + { + GObjectClass parent_class; + }; + +GType rss_cloud_get_type (void) G_GNUC_CONST; + +RssCloud *rss_cloud_new (const gchar *domain, + guint port, + const gchar *path, + const gchar *registerProcedure, + const gchar *protocol); +RssCloud *rss_cloud_new_from_xml (xmlNode *xnode); + +xmlNode *rss_cloud_get_xml (RssCloud *rss_cloud); + + +G_END_DECLS + +#endif /* __RSSCLOUD_H__ */ diff --git a/src/rssenclosure.c b/src/rssenclosure.c new file mode 100644 index 0000000..a819b70 --- /dev/null +++ b/src/rssenclosure.c @@ -0,0 +1,274 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#include + +#include + +#include "rssenclosure.h" + +enum +{ + PROP_0, + PROP_URL, + PROP_PORT, + PROP_LENGTH, + PROP_TYPE +}; + +static void rss_enclosure_class_init (RssEnclosureClass *klass); +static void rss_enclosure_init (RssEnclosure *rss); + +static void rss_enclosure_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void rss_enclosure_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +#define RSSENCLOSURE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_RSSENCLOSURE, RssEnclosurePrivate)) + +typedef struct _RssEnclosurePrivate RssEnclosurePrivate; +struct _RssEnclosurePrivate + { + gchar *url, + *type; + gulong length; + }; + +GType +rss_enclosure_get_type (void) +{ + static GType rss_enclosure_type = 0; + + if (!rss_enclosure_type) + { + static const GTypeInfo rss_enclosure_info = + { + sizeof (RssEnclosureClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) rss_enclosure_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (RssEnclosure), + 0, /* n_preallocs */ + (GInstanceInitFunc) rss_enclosure_init, + NULL + }; + + rss_enclosure_type = g_type_register_static (G_TYPE_OBJECT, "RssEnclosure", + &rss_enclosure_info, 0); + } + + return rss_enclosure_type; +} + +static void +rss_enclosure_class_init (RssEnclosureClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (RssEnclosurePrivate)); + + object_class->set_property = rss_enclosure_set_property; + object_class->get_property = rss_enclosure_get_property; + + g_object_class_install_property (object_class, PROP_URL, + g_param_spec_string ("url", + "URL", + "Where the enclosure is located.", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_LENGTH, + g_param_spec_ulong ("length", + "Length", + "How big it is in bytes.", + 0, + ULONG_MAX, + 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_TYPE, + g_param_spec_string ("type", + "Type", + "What its type is, a standard MIME type.", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); +} + +static void +rss_enclosure_init (RssEnclosure *rss) +{ +} + +/** + * rss_enclosure_new: + * @url: Where the enclosure is located. + * @length: How big it is in bytes. + * @type: What its type is, a standard MIME type. + * + * Returns: the newly created #RssEnclosure object. + */ +RssEnclosure +*rss_enclosure_new (const gchar *url, + gulong length, + const gchar *type) +{ + g_return_val_if_fail (url != NULL, NULL); + g_return_val_if_fail (type != NULL, NULL); + + gchar *_url = g_strstrip (g_strdup (url)), + *_type = g_strstrip (g_strdup (type)); + + if (strcmp (_url, "") == 0) + { + g_critical ("rss_enclosure_new: url cannot be an empty string"); + return NULL; + } + if (strcmp (_type, "") == 0) + { + g_critical ("rss_enclosure_new: type cannot be an empty string"); + return NULL; + } + + RssEnclosure *rsse = RSSENCLOSURE (g_object_new (rss_enclosure_get_type (), NULL)); + + g_object_set (G_OBJECT (rsse), + "url", _url, + "length", length, + "type", _type, + NULL); + + return rsse; +} + +/** + * rss_enclosure_new_from_xml: + * @xnode: an #xmlNode. + * + */ +RssEnclosure +*rss_enclosure_new_from_xml (xmlNode *xnode) +{ + g_return_val_if_fail (xnode != NULL, NULL); + + RssEnclosure *rsse = rss_enclosure_new ("url", 1, "type"); + gboolean url = FALSE, length = FALSE, type = FALSE; + + xmlChar *prop; + + if ((prop = xmlGetProp (xnode, (const xmlChar *)"url")) != NULL) + { + g_object_set (G_OBJECT (rsse), + "url", (gchar *)prop, + NULL); + } + if ((prop = xmlGetProp (xnode, (const xmlChar *)"length")) != NULL) + { + g_object_set (G_OBJECT (rsse), + "length", atol ((char *)prop), + NULL); + } + if ((prop = xmlGetProp (xnode, (const xmlChar *)"type")) != NULL) + { + g_object_set (G_OBJECT (rsse), + "type", (gchar *)prop, + NULL); + } + + return (!url || !length || !type ? NULL : rsse); +} + +/** + * rss_enclosure_get_xml: + * @rss_enclosure: a #RssEnclosure object + * + * Returns: the #xmlNode correspondent to the item. + */ +xmlNode +*rss_enclosure_get_xml (RssEnclosure *rss_enclosure) +{ + RssEnclosurePrivate *priv = RSSENCLOSURE_GET_PRIVATE (rss_enclosure); + + xmlNode *xnode = xmlNewNode (NULL, (const xmlChar *)"enclosure"); + + xmlSetProp (xnode, (const xmlChar *)"url", (const xmlChar *)priv->url); + xmlSetProp (xnode, (const xmlChar *)"length", (const xmlChar *)g_strdup_printf ("%d", priv->length)); + xmlSetProp (xnode, (const xmlChar *)"type", (const xmlChar *)priv->type); + + return xnode; +} + +static void +rss_enclosure_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + RssEnclosure *rsse = RSSENCLOSURE (object); + + RssEnclosurePrivate *priv = RSSENCLOSURE_GET_PRIVATE (rsse); + + switch (property_id) + { + case PROP_URL: + priv->url = g_strdup (g_value_get_string (value)); + break; + + case PROP_LENGTH: + priv->length = g_value_get_ulong (value); + break; + + case PROP_TYPE: + priv->type = g_strdup (g_value_get_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +rss_enclosure_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + RssEnclosure *rsse = RSSENCLOSURE (object); + + RssEnclosurePrivate *priv = RSSENCLOSURE_GET_PRIVATE (rsse); + + switch (property_id) + { + case PROP_URL: + g_value_set_string (value, priv->url); + break; + + case PROP_LENGTH: + g_value_set_ulong (value, priv->length); + break; + + case PROP_TYPE: + g_value_set_string (value, priv->type); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} diff --git a/src/rssenclosure.h b/src/rssenclosure.h new file mode 100644 index 0000000..f6bdde8 --- /dev/null +++ b/src/rssenclosure.h @@ -0,0 +1,65 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __RSSENCLOSURE_H__ +#define __RSSENCLOSURE_H__ + +#include +#include +#include + +G_BEGIN_DECLS + + +#define TYPE_RSSENCLOSURE (rss_enclosure_get_type ()) +#define RSSENCLOSURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_RSSENCLOSURE, RssEnclosure)) +#define RSSENCLOSURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_RSSENCLOSURE, RssEnclosureClass)) +#define IS_RSSENCLOSURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_RSSENCLOSURE)) +#define IS_RSSENCLOSURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_RSSENCLOSURE)) +#define RSSENCLOSURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_RSSENCLOSURE, RssEnclosureClass)) + + +typedef struct _RssEnclosure RssEnclosure; +typedef struct _RssEnclosureClass RssEnclosureClass; + +struct _RssEnclosure + { + GObject parent; + }; + +struct _RssEnclosureClass + { + GObjectClass parent_class; + }; + +GType rss_enclosure_get_type (void) G_GNUC_CONST; + +RssEnclosure *rss_enclosure_new (const gchar *url, + gulong length, + const gchar *type); +RssEnclosure *rss_enclosure_new_from_xml (xmlNode *xnode); + +xmlNode *rss_enclosure_get_xml (RssEnclosure *rss_enclosure); + + +G_END_DECLS + +#endif /* __RSSENCLOSURE_H__ */ diff --git a/src/rssguid.c b/src/rssguid.c new file mode 100644 index 0000000..5d64806 --- /dev/null +++ b/src/rssguid.c @@ -0,0 +1,243 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#include + +#include + +#include "rssguid.h" + +enum +{ + PROP_0, + PROP_GUID, + PROP_IS_PERMALINK +}; + +static void rss_guid_class_init (RssGuidClass *klass); +static void rss_guid_init (RssGuid *rss); + +static void rss_guid_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void rss_guid_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +#define RSSGUID_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_RSSGUID, RssGuidPrivate)) + +typedef struct _RssGuidPrivate RssGuidPrivate; +struct _RssGuidPrivate + { + gchar *guid; + gboolean isPermaLink; + }; + +GType +rss_guid_get_type (void) +{ + static GType rss_guid_type = 0; + + if (!rss_guid_type) + { + static const GTypeInfo rss_guid_info = + { + sizeof (RssGuidClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) rss_guid_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (RssGuid), + 0, /* n_preallocs */ + (GInstanceInitFunc) rss_guid_init, + NULL + }; + + rss_guid_type = g_type_register_static (G_TYPE_OBJECT, "RssGuid", + &rss_guid_info, 0); + } + + return rss_guid_type; +} + +static void +rss_guid_class_init (RssGuidClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (RssGuidPrivate)); + + object_class->set_property = rss_guid_set_property; + object_class->get_property = rss_guid_get_property; + + g_object_class_install_property (object_class, PROP_GUID, + g_param_spec_string ("guid", + "GUID", + "A string that uniquely identifies the item (Global Unique Identifier).", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_IS_PERMALINK, + g_param_spec_boolean ("is-permalink", + "Is PermaLink", + "True if GUID is a url that can be opened in a Web browser.", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); +} + +static void +rss_guid_init (RssGuid *rss) +{ +} + +/** + * rss_guid_new: + * @guid: A string that uniquely identifies the item (Global Unique Identifier). + * + * Returns: the newly created #RssGuid object. + */ +RssGuid +*rss_guid_new (const gchar *guid) +{ + g_return_val_if_fail (guid != NULL, NULL); + + gchar *_guid = g_strstrip (g_strdup (guid)); + + if (strcmp (_guid, "") == 0) + { + g_critical ("rss_guid_new: guid cannot be an empty string"); + return NULL; + } + + RssGuid *rssg = RSSGUID (g_object_new (rss_guid_get_type (), NULL)); + + g_object_set (G_OBJECT (rssg), + "guid", _guid, + NULL); + + return rssg; +} + +/** + * rss_guid_new_from_xml: + * @xnode: an #xmlNode. + * + * Returns: the newly created #RssGuid object. + */ +RssGuid +*rss_guid_new_from_xml (xmlNode *xnode) +{ + g_return_val_if_fail (xnode != NULL, NULL); + + RssGuid *rssg = rss_guid_new ("guid"); + gboolean guid = FALSE; + + xmlChar *prop; + + if ((prop = xmlGetProp (xnode, (const xmlChar *)"isPermaLink")) != NULL) + { + g_object_set (G_OBJECT (rssg), + "is-permalink", (gchar *)prop, + NULL); + } + + gchar *text = (gchar *)xmlNodeGetContent (xnode); + if (strcmp (g_strstrip (text), "") != 0) + { + guid = TRUE; + g_object_set (G_OBJECT (rssg), + "guid", text, + NULL); + } + + return (!guid ? NULL : rssg); +} + +/** + * rss_guid_get_xml: + * @rss_guid: a #RssGuid object. + * + * Returns: the #xmlNode correspondent to the item. + */ +xmlNode +*rss_guid_get_xml (RssGuid *rss_guid) +{ + RssGuidPrivate *priv = RSSGUID_GET_PRIVATE (rss_guid); + + xmlNode *xnode = xmlNewNode (NULL, (const xmlChar *)"guid"); + + xmlAddChild (xnode, xmlNewText ((const xmlChar *)priv->guid)); + + if (!priv->isPermaLink) + { + xmlSetProp (xnode, (const xmlChar *)"isPermaLink", (const xmlChar *)"false"); + } + + return xnode; +} + +static void +rss_guid_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + RssGuid *rssc = RSSGUID (object); + + RssGuidPrivate *priv = RSSGUID_GET_PRIVATE (rssc); + + switch (property_id) + { + case PROP_GUID: + priv->guid = g_strdup (g_value_get_string (value)); + break; + + case PROP_IS_PERMALINK: + priv->isPermaLink = g_value_get_boolean (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +rss_guid_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + RssGuid *rssc = RSSGUID (object); + + RssGuidPrivate *priv = RSSGUID_GET_PRIVATE (rssc); + + switch (property_id) + { + case PROP_GUID: + g_value_set_string (value, priv->guid); + break; + + case PROP_IS_PERMALINK: + g_value_set_boolean (value, priv->isPermaLink); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} diff --git a/src/rssguid.h b/src/rssguid.h new file mode 100644 index 0000000..8c7bcec --- /dev/null +++ b/src/rssguid.h @@ -0,0 +1,63 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __RSSGUID_H__ +#define __RSSGUID_H__ + +#include +#include +#include + +G_BEGIN_DECLS + + +#define TYPE_RSSGUID (rss_cloud_get_type ()) +#define RSSGUID(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_RSSGUID, RssGuid)) +#define RSSGUID_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_RSSGUID, RssGuidClass)) +#define IS_RSSGUID(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_RSSGUID)) +#define IS_RSSGUID_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_RSSGUID)) +#define RSSGUID_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_RSSGUID, RssGuidClass)) + + +typedef struct _RssGuid RssGuid; +typedef struct _RssGuidClass RssGuidClass; + +struct _RssGuid + { + GObject parent; + }; + +struct _RssGuidClass + { + GObjectClass parent_class; + }; + +GType rss_guid_get_type (void) G_GNUC_CONST; + +RssGuid *rss_guid_new (const gchar *guid); +RssGuid *rss_guid_new_from_xml (xmlNode *xnode); + +xmlNode *rss_guid_get_xml (RssGuid *rss_guid); + + +G_END_DECLS + +#endif /* __RSSGUID_H__ */ diff --git a/src/rssimage.c b/src/rssimage.c new file mode 100644 index 0000000..f3eae4e --- /dev/null +++ b/src/rssimage.c @@ -0,0 +1,363 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#include + +#include + +#include "rssimage.h" + +enum +{ + PROP_0, + PROP_URL, + PROP_TITLE, + PROP_LINK, + PROP_WIDTH, + PROP_HEIGHT, + PROP_DESCRIPTION +}; + +static void rss_image_class_init (RssImageClass *klass); +static void rss_image_init (RssImage *rss); + +static void rss_image_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void rss_image_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +#define RSSIMAGE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_RSSIMAGE, RssImagePrivate)) + +typedef struct _RssImagePrivate RssImagePrivate; +struct _RssImagePrivate + { + gchar *url, + *title, + *link, + *description; + guint width, height; + }; + +GType +rss_image_get_type (void) +{ + static GType rss_image_type = 0; + + if (!rss_image_type) + { + static const GTypeInfo rss_image_info = + { + sizeof (RssImageClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) rss_image_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (RssImage), + 0, /* n_preallocs */ + (GInstanceInitFunc) rss_image_init, + NULL + }; + + rss_image_type = g_type_register_static (G_TYPE_OBJECT, "RssImage", + &rss_image_info, 0); + } + + return rss_image_type; +} + +static void +rss_image_class_init (RssImageClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (RssImagePrivate)); + + object_class->set_property = rss_image_set_property; + object_class->get_property = rss_image_get_property; + + g_object_class_install_property (object_class, PROP_URL, + g_param_spec_string ("url", + "URL", + "The URL of a GIF, JPEG or PNG image", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_TITLE, + g_param_spec_string ("title", + "Title", + "Describes the image, it is used in the ALT attribute of the HTML img tag when the channel is rendered in HTML", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_LINK, + g_param_spec_string ("link", + "Link", + "Is the URL of the site, when the channel is rendered, the image is a link to the site", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_WIDTH, + g_param_spec_uint ("width", + "Width", + "The width of the image in pixels", + 0, + 144, + 88, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_HEIGHT, + g_param_spec_uint ("height", + "Height", + "The height of the image in pixels", + 0, + 400, + 31, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_DESCRIPTION, + g_param_spec_string ("description", + "Description", + "Contains text that is included in the TITLE attribute of the link formed around the image in the HTML rendering", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); +} + +static void +rss_image_init (RssImage *rss) +{ +} + +/** + * rss_image_new: + * @url: the URL of a GIF, JPEG or PNG image. + * @title: describes the image, it is used in the ALT attribute of the HTML img tag when the channel is rendered in HTML. + * @link: iIs the URL of the site, when the channel is rendered, the image is a link to the site. + * + * Returns: the newly created #RssImage object. + */ +RssImage +*rss_image_new (const gchar *url, const gchar *title, const gchar *link) +{ + g_return_val_if_fail (url != NULL, NULL); + g_return_val_if_fail (title != NULL, NULL); + g_return_val_if_fail (link != NULL, NULL); + + gchar *_url = g_strstrip (g_strdup (url)), + *_title = g_strstrip (g_strdup (title)), + *_link = g_strstrip (g_strdup (link)); + + if (strcmp (_url, "") == 0) + { + g_critical ("rss_image_new: url cannot be an empty string"); + return NULL; + } + if (strcmp (_title, "") == 0) + { + g_critical ("rss_image_new: title cannot be an empty string"); + return NULL; + } + if (strcmp (_link, "") == 0) + { + g_critical ("rss_image_new: link cannot be an empty string"); + return NULL; + } + + RssImage *rssi = RSSIMAGE (g_object_new (rss_image_get_type (), NULL)); + + g_object_set (G_OBJECT (rssi), + "url", _url, + "title", _title, + "link", _link, + NULL); + + return rssi; +} + +/** + * rss_image_new_from_xml: + * @xnode: an #xmlNode. + * + */ +RssImage +*rss_image_new_from_xml (xmlNode *xnode) +{ + RssImage *rssi = rss_image_new ("url", "title", "link"); + gboolean url = FALSE, title = FALSE, link = FALSE; + + xmlNode *cur = xnode->xmlChildrenNode; + while (cur != NULL) + { + if (xmlStrcmp (cur->name, (const xmlChar *)"url") == 0) + { + url = TRUE; + g_object_set (G_OBJECT (rssi), + "url", (gchar *)xmlNodeGetContent (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"title") == 0) + { + title = TRUE; + g_object_set (G_OBJECT (rssi), + "title", (gchar *)xmlNodeGetContent (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"link") == 0) + { + link = TRUE; + g_object_set (G_OBJECT (rssi), + "link", (gchar *)xmlNodeGetContent (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"width") == 0) + { + g_object_set (G_OBJECT (rssi), + "width", atol ((char *)xmlNodeGetContent (cur)), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"height") == 0) + { + g_object_set (G_OBJECT (rssi), + "height", atol ((char *)xmlNodeGetContent (cur)), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"description") == 0) + { + g_object_set (G_OBJECT (rssi), + "description", (gchar *)xmlNodeGetContent (cur), + NULL); + } + + cur = cur->next; + } + + return (!url || !title || !link ? NULL : rssi); +} + +/** + * rss_image_get_xml: + * @rss_image: a #RssImage object. + * + * Returns: the #xmlNode correspondent to the item. + */ +xmlNode +*rss_image_get_xml (RssImage *rss_image) +{ + RssImagePrivate *priv = RSSIMAGE_GET_PRIVATE (rss_image); + + xmlNode *xnode = xmlNewNode (NULL, (const xmlChar *)"image"); + + xmlNewTextChild (xnode, NULL, (const xmlChar *)"url", (const xmlChar *)priv->url); + xmlNewTextChild (xnode, NULL, (const xmlChar *)"title", (const xmlChar *)priv->title); + xmlNewTextChild (xnode, NULL, (const xmlChar *)"link", (const xmlChar *)priv->link); + + if (priv->width != 88) + { + xmlNewTextChild (xnode, NULL, (const xmlChar *)"width", (const xmlChar *)g_strdup_printf ("%d", priv->width)); + } + if (priv->height != 31) + { + xmlNewTextChild (xnode, NULL, (const xmlChar *)"height", (const xmlChar *)g_strdup_printf ("%d", priv->height)); + } + if (strcmp (priv->description, "") != 0) + { + xmlNewTextChild (xnode, NULL, (const xmlChar *)"description", (const xmlChar *)priv->description); + } + + return xnode; +} + +static void +rss_image_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + RssImage *rssi = RSSIMAGE (object); + + RssImagePrivate *priv = RSSIMAGE_GET_PRIVATE (rssi); + + switch (property_id) + { + case PROP_URL: + priv->url = g_strdup (g_value_get_string (value)); + break; + + case PROP_TITLE: + priv->title = g_strdup (g_value_get_string (value)); + break; + + case PROP_LINK: + priv->link = g_strdup (g_value_get_string (value)); + break; + + case PROP_WIDTH: + priv->width = g_value_get_uint (value); + break; + + case PROP_HEIGHT: + priv->height = g_value_get_uint (value); + break; + + case PROP_DESCRIPTION: + priv->description = g_strdup (g_value_get_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +rss_image_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + RssImage *rssi = RSSIMAGE (object); + + RssImagePrivate *priv = RSSIMAGE_GET_PRIVATE (rssi); + + switch (property_id) + { + case PROP_URL: + g_value_set_string (value, priv->url); + break; + + case PROP_TITLE: + g_value_set_string (value, priv->title); + break; + + case PROP_LINK: + g_value_set_string (value, priv->link); + break; + + case PROP_WIDTH: + g_value_set_uint (value, priv->width); + break; + + case PROP_HEIGHT: + g_value_set_uint (value, priv->height); + break; + + case PROP_DESCRIPTION: + g_value_set_string (value, priv->description); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} diff --git a/src/rssimage.h b/src/rssimage.h new file mode 100644 index 0000000..c11d791 --- /dev/null +++ b/src/rssimage.h @@ -0,0 +1,63 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __RSSIMAGE_H__ +#define __RSSIMAGE_H__ + +#include +#include +#include + +G_BEGIN_DECLS + + +#define TYPE_RSSIMAGE (rss_image_get_type ()) +#define RSSIMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_RSSIMAGE, RssImage)) +#define RSSIMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_RSSIMAGE, RssImageClass)) +#define IS_RSSIMAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_RSSIMAGE)) +#define IS_RSSIMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_RSSIMAGE)) +#define RSSIMAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_RSSIMAGE, RssImageClass)) + + +typedef struct _RssImage RssImage; +typedef struct _RssImageClass RssImageClass; + +struct _RssImage + { + GObject parent; + }; + +struct _RssImageClass + { + GObjectClass parent_class; + }; + +GType rss_image_get_type (void) G_GNUC_CONST; + +RssImage *rss_image_new (const gchar *url, const gchar *title, const gchar *link); +RssImage *rss_image_new_from_xml (xmlNode *xnode); + +xmlNode *rss_image_get_xml (RssImage *rss_image); + + +G_END_DECLS + +#endif /* __RSSIMAGE_H__ */ diff --git a/src/rsssource.c b/src/rsssource.c new file mode 100644 index 0000000..c8082c1 --- /dev/null +++ b/src/rsssource.c @@ -0,0 +1,247 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#include + +#include + +#include "rsssource.h" + +enum +{ + PROP_0, + PROP_TITLE, + PROP_URL +}; + +static void rss_source_class_init (RssSourceClass *klass); +static void rss_source_init (RssSource *rss); + +static void rss_source_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void rss_source_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +#define RSSSOURCE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_RSSSOURCE, RssSourcePrivate)) + +typedef struct _RssSourcePrivate RssSourcePrivate; +struct _RssSourcePrivate + { + gchar *title, + *url; + }; + +GType +rss_source_get_type (void) +{ + static GType rss_source_type = 0; + + if (!rss_source_type) + { + static const GTypeInfo rss_source_info = + { + sizeof (RssSourceClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) rss_source_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (RssSource), + 0, /* n_preallocs */ + (GInstanceInitFunc) rss_source_init, + NULL + }; + + rss_source_type = g_type_register_static (G_TYPE_OBJECT, "RssSource", + &rss_source_info, 0); + } + + return rss_source_type; +} + +static void +rss_source_class_init (RssSourceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (RssSourcePrivate)); + + object_class->set_property = rss_source_set_property; + object_class->get_property = rss_source_get_property; + + g_object_class_install_property (object_class, PROP_TITLE, + g_param_spec_string ("title", + "Title", + "Title of the source which the item came from.", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_URL, + g_param_spec_string ("url", + "URL", + "Links to the XMLization of the source.", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); +} + +static void +rss_source_init (RssSource *rss) +{ +} + +/** + * rss_source_new: + * @title: Title of the source which the item came from. + * @url: Links to the XMLization of the source. + * + * Returns: the newly created #RssSource object. + */ +RssSource +*rss_source_new (const gchar *title, const gchar *url) +{ + g_return_val_if_fail (title != NULL, NULL); + g_return_val_if_fail (url != NULL, NULL); + + gchar *_title = g_strstrip (g_strdup (title)), + *_url = g_strstrip (g_strdup (url)); + + if (strcmp (_title, "") == 0) + { + g_critical ("rss_source_new: title cannot be an empty string"); + return NULL; + } + if (strcmp (_url, "") == 0) + { + g_critical ("rss_source_new: url cannot be an empty string"); + return NULL; + } + + RssSource *rsss = RSSSOURCE (g_object_new (rss_source_get_type (), NULL)); + + g_object_set (G_OBJECT (rsss), + "title", _title, + "url", _url, + NULL); + + return rsss; +} + +/** + * rss_source_new_from_xml: + * @xnode: an #xmlNode. + * + */ +RssSource +*rss_source_new_from_xml (xmlNode *xnode) +{ + RssSource *rsss = rss_source_new ("title", "url"); + gboolean title = FALSE, url = FALSE; + gchar *str_title, *str_url; + + str_url = (gchar *)xmlGetProp (xnode, (const xmlChar *)"url"); + if (str_url != NULL || strcmp (g_strstrip (str_url), "") != 0) + { + url = TRUE; + g_object_set (G_OBJECT (rsss), + "url", str_url, + NULL); + } + + str_title = (gchar *)xmlNodeGetContent ((xmlNodePtr)xnode); + if (str_title != NULL && strcmp (g_strstrip (str_title), "") != 0) + { + title = TRUE; + g_object_set (G_OBJECT (rsss), + "title", str_title, + NULL); + } + + return (!title || !url ? NULL : rsss); +} + +/** + * rss_source_get_xml: + * @rss_source: a #RssSource object + * + * Returns: the #xmlNode correspondent to the item. + */ +xmlNode +*rss_source_get_xml (RssSource *rss_source) +{ + RssSourcePrivate *priv = RSSSOURCE_GET_PRIVATE (rss_source); + + xmlNode *xnode = xmlNewNode (NULL, (const xmlChar *)"source"); + + xmlAddChild (xnode, xmlNewText ((const xmlChar *)priv->title)); + + xmlSetProp (xnode, (const xmlChar *)"url", (const xmlChar *)priv->url); + + return xnode; +} + +static void +rss_source_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + RssSource *rsss = RSSSOURCE (object); + + RssSourcePrivate *priv = RSSSOURCE_GET_PRIVATE (rsss); + + switch (property_id) + { + case PROP_TITLE: + priv->title = g_strdup (g_value_get_string (value)); + break; + + case PROP_URL: + priv->url = g_strdup (g_value_get_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +rss_source_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + RssSource *rsss = RSSSOURCE (object); + + RssSourcePrivate *priv = RSSSOURCE_GET_PRIVATE (rsss); + + switch (property_id) + { + case PROP_TITLE: + g_value_set_string (value, priv->title); + break; + + case PROP_URL: + g_value_set_string (value, priv->url); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} diff --git a/src/rsssource.h b/src/rsssource.h new file mode 100644 index 0000000..b66315a --- /dev/null +++ b/src/rsssource.h @@ -0,0 +1,63 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __RSSSOURCE_H__ +#define __RSSSOURCE_H__ + +#include +#include +#include + +G_BEGIN_DECLS + + +#define TYPE_RSSSOURCE (rss_cloud_get_type ()) +#define RSSSOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_RSSSOURCE, RssSource)) +#define RSSSOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_RSSSOURCE, RssSourceClass)) +#define IS_RSSSOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_RSSSOURCE)) +#define IS_RSSSOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_RSSSOURCE)) +#define RSSSOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_RSSSOURCE, RssSourceClass)) + + +typedef struct _RssSource RssSource; +typedef struct _RssSourceClass RssSourceClass; + +struct _RssSource + { + GObject parent; + }; + +struct _RssSourceClass + { + GObjectClass parent_class; + }; + +GType rss_source_get_type (void) G_GNUC_CONST; + +RssSource *rss_source_new (const gchar *title, const gchar *url); +RssSource *rss_source_new_from_xml (xmlNode *xnode); + +xmlNode *rss_source_get_xml (RssSource *rss_source); + + +G_END_DECLS + +#endif /* __RSSSOURCE_H__ */ diff --git a/src/rsstextinput.c b/src/rsstextinput.c new file mode 100644 index 0000000..0e7c39a --- /dev/null +++ b/src/rsstextinput.c @@ -0,0 +1,317 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#include + +#include + +#include "rsstextinput.h" + +enum +{ + PROP_0, + PROP_TITLE, + PROP_DESCRIPTION, + PROP_NAME, + PROP_LINK +}; + +static void rss_text_input_class_init (RssTextInputClass *klass); +static void rss_text_input_init (RssTextInput *rss); + +static void rss_text_input_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void rss_text_input_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +#define RSSTEXTINPUT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_RSSTEXTINPUT, RssTextInputPrivate)) + +typedef struct _RssTextInputPrivate RssTextInputPrivate; +struct _RssTextInputPrivate + { + gchar *title, + *description, + *name, + *link; + }; + +GType +rss_text_input_get_type (void) +{ + static GType rss_text_input_type = 0; + + if (!rss_text_input_type) + { + static const GTypeInfo rss_text_input_info = + { + sizeof (RssTextInputClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) rss_text_input_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (RssTextInput), + 0, /* n_preallocs */ + (GInstanceInitFunc) rss_text_input_init, + NULL + }; + + rss_text_input_type = g_type_register_static (G_TYPE_OBJECT, "RssTextInput", + &rss_text_input_info, 0); + } + + return rss_text_input_type; +} + +static void +rss_text_input_class_init (RssTextInputClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (RssTextInputPrivate)); + + object_class->set_property = rss_text_input_set_property; + object_class->get_property = rss_text_input_get_property; + + g_object_class_install_property (object_class, PROP_TITLE, + g_param_spec_string ("title", + "Title", + "The label of the Submit button in the text input area", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_DESCRIPTION, + g_param_spec_string ("description", + "Description", + "Explains the text input area", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_NAME, + g_param_spec_string ("name", + "Name", + "The name of the text object in the text input area", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_LINK, + g_param_spec_string ("link", + "Link", + "The URL of the CGI script that processes text input requests", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); +} + +static void +rss_text_input_init (RssTextInput *rss) +{ +} + +/** + * rss_text_input_new: + * @title: + * @description: + * @name: + * @link: + * + * Returns: the newly created #RssTextInput object. + */ +RssTextInput +*rss_text_input_new (const gchar *title, + const gchar *description, + const gchar *name, + const gchar *link) +{ + g_return_val_if_fail (title != NULL, NULL); + g_return_val_if_fail (description!= NULL, NULL); + g_return_val_if_fail (name!= NULL, NULL); + g_return_val_if_fail (link != NULL, NULL); + + gchar *_title = g_strstrip (g_strdup (title)), + *_description = g_strstrip (g_strdup (description)), + *_name = g_strstrip (g_strdup (name)), + *_link = g_strstrip (g_strdup (link)); + + if (strcmp (_title, "") == 0) + { + g_critical ("rss_text_input_new: title cannot be an empty string"); + return NULL; + } + if (strcmp (_description, "") == 0) + { + g_critical ("rss_text_input_new: description cannot be an empty string"); + return NULL; + } + if (strcmp (_name, "") == 0) + { + g_critical ("rss_text_input_new: name cannot be an empty string"); + return NULL; + } + if (strcmp (_link, "") == 0) + { + g_critical ("rss_text_input_new: link cannot be an empty string"); + return NULL; + } + + RssTextInput *rssti = RSSTEXTINPUT (g_object_new (rss_text_input_get_type (), NULL)); + + g_object_set (G_OBJECT (rssti), + "title", _title, + "description", _description, + "name", _name, + "link", _link, + NULL); + + return rssti; +} + +/** + * rss_text_input_new_from_xml: + * @xnode: an #xmlNode. + * + */ +RssTextInput +*rss_text_input_new_from_xml (xmlNode *xnode) +{ + RssTextInput *rssti = rss_text_input_new ("title", "description", "name", "link"); + gboolean title = FALSE, description = FALSE, name = FALSE, link = FALSE; + + xmlNode *cur = xnode->xmlChildrenNode; + while (cur != NULL) + { + if (xmlStrcmp (cur->name, (const xmlChar *)"title") == 0) + { + title = TRUE; + g_object_set (G_OBJECT (rssti), + "title", (gchar *)xmlNodeGetContent (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"description") == 0) + { + description = TRUE; + g_object_set (G_OBJECT (rssti), + "description", (gchar *)xmlNodeGetContent (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"name") == 0) + { + name = TRUE; + g_object_set (G_OBJECT (rssti), + "name", (gchar *)xmlNodeGetContent (cur), + NULL); + } + else if (xmlStrcmp (cur->name, (const xmlChar *)"link") == 0) + { + link = TRUE; + g_object_set (G_OBJECT (rssti), + "link", (gchar *)xmlNodeGetContent (cur), + NULL); + } + + cur = cur->next; + } + + return (!title || !description || !name || !link ? NULL : rssti); +} + +/** + * rss_text_input_get_xml: + * @rss_text_input: a #RssTextInput object + * + * Returns: the #xmlNode correspondent to the item. + */ +xmlNode +*rss_text_input_get_xml (RssTextInput *rss_text_input) +{ + RssTextInputPrivate *priv = RSSTEXTINPUT_GET_PRIVATE (rss_text_input); + + xmlNode *xnode = xmlNewNode (NULL, (const xmlChar *)"textInput"); + + xmlNewTextChild (xnode, NULL, (const xmlChar *)"title", (const xmlChar *)priv->title); + xmlNewTextChild (xnode, NULL, (const xmlChar *)"description", (const xmlChar *)priv->description); + xmlNewTextChild (xnode, NULL, (const xmlChar *)"name", (const xmlChar *)priv->name); + xmlNewTextChild (xnode, NULL, (const xmlChar *)"link", (const xmlChar *)priv->link); + + return xnode; +} + +static void +rss_text_input_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + RssTextInput *rssti = RSSTEXTINPUT (object); + + RssTextInputPrivate *priv = RSSTEXTINPUT_GET_PRIVATE (rssti); + + switch (property_id) + { + case PROP_TITLE: + priv->title = g_strdup (g_value_get_string (value)); + break; + + case PROP_DESCRIPTION: + priv->description = g_strdup (g_value_get_string (value)); + break; + + case PROP_NAME: + priv->name = g_strdup (g_value_get_string (value)); + break; + + case PROP_LINK: + priv->link = g_strdup (g_value_get_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +rss_text_input_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + RssTextInput *rssti = RSSTEXTINPUT (object); + + RssTextInputPrivate *priv = RSSTEXTINPUT_GET_PRIVATE (rssti); + + switch (property_id) + { + case PROP_TITLE: + g_value_set_string (value, priv->title); + break; + + case PROP_DESCRIPTION: + g_value_set_string (value, priv->description); + break; + + case PROP_NAME: + g_value_set_string (value, priv->name); + break; + + case PROP_LINK: + g_value_set_string (value, priv->link); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} diff --git a/src/rsstextinput.h b/src/rsstextinput.h new file mode 100644 index 0000000..b5b352b --- /dev/null +++ b/src/rsstextinput.h @@ -0,0 +1,66 @@ +/* libgfeed + * + * Copyright (C) 2005-2006 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Andrea Zagli + */ + +#ifndef __RSSTEXTINPUT_H__ +#define __RSSTEXTINPUT_H__ + +#include +#include +#include + +G_BEGIN_DECLS + + +#define TYPE_RSSTEXTINPUT (rss_text_input_get_type ()) +#define RSSTEXTINPUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_RSSTEXTINPUT, RssTextInput)) +#define RSSTEXTINPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_RSSTEXTINPUT, RssTextInputClass)) +#define IS_RSSTEXTINPUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_RSSTEXTINPUT)) +#define IS_RSSTEXTINPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_RSSTEXTINPUT)) +#define RSSTEXTINPUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_RSSTEXTINPUT, RssTextInputClass)) + + +typedef struct _RssTextInput RssTextInput; +typedef struct _RssTextInputClass RssTextInputClass; + +struct _RssTextInput + { + GObject parent; + }; + +struct _RssTextInputClass + { + GObjectClass parent_class; + }; + +GType rss_text_input_get_type (void) G_GNUC_CONST; + +RssTextInput *rss_text_input_new (const gchar *title, + const gchar *description, + const gchar *name, + const gchar *link); +RssTextInput *rss_text_input_new_from_xml (xmlNode *xnode); + +xmlNode *rss_text_input_get_xml (RssTextInput *rss_text_input); + + +G_END_DECLS + +#endif /* __RSSTEXTINPUT_H__ */ diff --git a/test/Makefile.am b/test/Makefile.am new file mode 100644 index 0000000..e6c06ac --- /dev/null +++ b/test/Makefile.am @@ -0,0 +1,13 @@ +LIBS = $(GFEED_LIBS) + +AM_CPPFLAGS = $(GFEED_CFLAGS) \ + -I$(top_srcdir)/src + +noinst_PROGRAMS = test_rss \ + test_rss_load \ + test_rss_load_buffer \ + test_atom \ + test_atom_load \ + test_atom_load_buffer + +LDADD = $(top_srcdir)/src/libgfeed.la diff --git a/test/test_atom.c b/test/test_atom.c new file mode 100644 index 0000000..d4d1070 --- /dev/null +++ b/test/test_atom.c @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2005-2006 Andrea Zagli + * + * 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 2 of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include + +#include + +int +main (int argc, char **argv) +{ + Atom *atom; + AtomID *id; + AtomText *title; + AtomDate *updated; + GList *authors = NULL, + *entries = NULL; + AtomEntry *entry; + AtomContent *content; + time_t timet; + struct tm tm; + xmlDoc *xdoc; + + g_type_init (); + + id = atom_id_new ("http://foo.mydomain.com/"); + title = atom_text_new (ATOM_TEXT_XHTML, "dive into mark"); + g_object_set (G_OBJECT (title), + "lang", "it", + NULL); + + timet = time (NULL); + + gmtime_r ((const time_t *)&timet, (struct tm *)&tm); + tm.tm_sec = 0; + tm.tm_min = 0; + tm.tm_hour = 0; + + updated = atom_date_new (tm); + + atom = atom_new (id, title, updated); + + authors = g_list_append (authors, (gpointer)atom_person_new ("Andrea Zagli")); + g_object_set (G_OBJECT (authors->data), + "uri", "http://saettaz.altervista.org ", + "email", " azagli@inwind.it", + NULL); + + g_object_set (G_OBJECT (atom), + "author", authors, + NULL); + + content = atom_content_new (ATOM_CONTENT_XHTML); + g_object_set (G_OBJECT (content), + "text", "content's text", + NULL); + + entries = g_list_append (entries, (gpointer)atom_entry_new ( + atom_id_new ("http://foo.mydomain.com/e1.html"), + atom_text_new (ATOM_TEXT_TEXT, "the title"), + updated)); + g_object_set (G_OBJECT (entries->data), + "content", content, + NULL); + + entry = atom_entry_new (atom_id_new ("http://foo.mydomain.com/e2.html"), + atom_text_new (ATOM_TEXT_TEXT, "the second entry"), + updated); + + g_object_set (G_OBJECT (entry), + "content", content, + NULL); + + entries = g_list_append (entries, (gpointer)entry); + + g_object_set (G_OBJECT (atom), + "entry", entries, + NULL); + + xdoc = atom_get_xml_doc (atom); + xmlSaveFormatFileEnc ("./test_atom.xml", xdoc, "iso-8859-1", 2); + + atom_save_file (atom, "./test_atom_gfeed.xml"); + + return 0; +} diff --git a/test/test_atom_load.c b/test/test_atom_load.c new file mode 100644 index 0000000..2daeddf --- /dev/null +++ b/test/test_atom_load.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2005-2006 Andrea Zagli + * + * 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 2 of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include + +#include + +int +main (int argc, char **argv) +{ + Atom *atom; + xmlDoc *xdoc; + + g_type_init (); + + atom = atom_new_from_file (argv[1]); + + if (atom != NULL) + { + xdoc = atom_get_xml_doc (atom); + if (xdoc != NULL) + { + xmlSaveFormatFileEnc ("./test_atom_load.xml", xdoc, "iso-8859-1", 2); + } + else + { + g_fprintf (stderr, "xdoc is null\n"); + } + + atom_save_file (atom, "./test_atom_load_gfeed.xml"); + } + else + { + g_fprintf (stderr, "atom is null\n"); + } + + return 0; +} diff --git a/test/test_atom_load_buffer.c b/test/test_atom_load_buffer.c new file mode 100644 index 0000000..78e6466 --- /dev/null +++ b/test/test_atom_load_buffer.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2005-2006 Andrea Zagli + * + * 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 2 of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include + +#include + +gchar * +read_file (const gchar *filename) +{ + gchar *ret = ""; + FILE *fin; + + fin = fopen (filename, "r"); + + if (fin != NULL) + { + gchar ch; + + while ((ch = getc (fin)) != EOF) + { + ret = g_strconcat (ret, g_strdup_printf ("%c", ch), NULL); + } + } + + fclose (fin); + + return ret; +} + +int +main (int argc, char **argv) +{ + gchar *buffer; + Atom *atom; + xmlDoc *xdoc; + + g_type_init (); + + /* reading the file */ + buffer = read_file (argv[1]); + + atom = atom_new_from_buffer (buffer); + + if (atom != NULL) + { + xdoc = atom_get_xml_doc (atom); + if (xdoc != NULL) + { + xmlSaveFormatFileEnc ("./test_atom_load_buffer.xml", xdoc, "iso-8859-1", 2); + } + else + { + g_fprintf (stderr, "xdoc is null\n"); + } + + atom_save_file (atom, "./test_atom_load_buffer_gfeed.xml"); + } + else + { + g_fprintf (stderr, "atom is null\n"); + } + + return 0; +} diff --git a/test/test_rss.c b/test/test_rss.c new file mode 100644 index 0000000..ee20909 --- /dev/null +++ b/test/test_rss.c @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2005-2006 Andrea Zagli + * + * 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 2 of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include + +#include + +int +main (int argc, char **argv) +{ + Rss *rss; + RssChannel *rssc; + RssCategory *rssca; + RssCloud *rsscl; + RssImage *rssi; + RssTextInput *rssti; + RssChannelItem *rssci; + time_t timet; + struct tm pubDate, lastBuildDate; + xmlDoc *xdoc; + guint skipDays, skipHours; + + g_type_init (); + + rss = rss_new (); + + rssc = rss_channel_new ("Channel", + "http://www.channels.org/link1.html", + "First channel - Description"); + + if (rssc == NULL) return 0; + + g_object_set (G_OBJECT (rss), + "channel", rssc, + NULL); + + rssca = rss_category_new ("Comics"); + rss_channel_add_category (rssc, rssca); + + rssca = rss_category_new ("Horror"); + g_object_set (G_OBJECT (rssca), + "domain", "the domain", + NULL); + rss_channel_add_category (rssc, rssca); + + timet = time (NULL); + + gmtime_r ((const time_t *)&timet, (struct tm *)&pubDate); + pubDate.tm_sec = 0; + pubDate.tm_min = 0; + pubDate.tm_hour = 0; + + gmtime_r ((const time_t *)&timet, (struct tm *)&lastBuildDate); + + rsscl = rss_cloud_new ("radio.xmlstoragesystem.com", 80, "/RPC2", "xmlStorageSystem.rssPleaseNotify", "xml-rpc"); + + rssi = rss_image_new ("http://www.image.com/01.png", "the title", "http://www.channels.org/link1.html"); + + rssti = rss_text_input_new ("The text input's title", "a short description", "ti1", "http://www.google.com"); + + skipDays = RSSCHANNEL_DAY_MONDAY | RSSCHANNEL_DAY_TUESDAY | RSSCHANNEL_DAY_WEDNESDAY | + RSSCHANNEL_DAY_THURSDAY | RSSCHANNEL_DAY_FRIDAY | RSSCHANNEL_DAY_SATURDAY | RSSCHANNEL_DAY_SUNDAY; + + skipHours = RSSCHANNEL_HOUR_23; + + g_object_set (G_OBJECT (rssc), + "language", "en", + "copyright", "mine", + "pub-date", &pubDate, + "last-build-date", &lastBuildDate, + "cloud", rsscl, + "image", rssi, + "text-input", rssti, + "skip-days", skipDays, + "skip-hours", skipHours, + NULL); + + rssci = rss_channel_item_new ("Title item 1", "with this description"); + + rssca = rss_category_new ("Sci-Fi"); + g_object_set (G_OBJECT (rssca), + "domain", "my domain", + NULL); + rss_channel_item_add_category (rssci, rssca); + + g_object_set (G_OBJECT (rssci), + "author", "author@myhouse.it", + "comments", "http://www.google.com", + NULL); + + rss_channel_add_item (rssc, rssci); + + xdoc = rss_get_xml_doc (rss); + xmlSaveFormatFileEnc ("./test.xml", xdoc, "iso-8859-1",2); + + rss_save_file (rss, "./test_gfeed.xml"); + + return 0; +} diff --git a/test/test_rss_load.c b/test/test_rss_load.c new file mode 100644 index 0000000..f76ea35 --- /dev/null +++ b/test/test_rss_load.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2005-2006 Andrea Zagli + * + * 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 2 of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include + +#include + +int +main (int argc, char **argv) +{ + Rss *rss; + xmlDoc *xdoc; + + g_type_init (); + + rss = rss_new_from_file (argv[1]); + + if (rss != NULL) + { + xdoc = rss_get_xml_doc (rss); + if (xdoc != NULL) + { + xmlSaveFormatFileEnc ("./test_load.xml", xdoc, "iso-8859-1", 2); + } + else + { + g_fprintf (stderr, "xdoc is null\n"); + } + + rss_save_file (rss, "./test_load_gfeed.xml"); + } + else + { + g_fprintf (stderr, "rss is null\n"); + } + + return 0; +} diff --git a/test/test_rss_load_buffer.c b/test/test_rss_load_buffer.c new file mode 100644 index 0000000..9a8f57b --- /dev/null +++ b/test/test_rss_load_buffer.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2005-2006 Andrea Zagli + * + * 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 2 of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include + +#include + +gchar * +read_file (const gchar *filename) +{ + gchar *ret = ""; + FILE *fin; + + fin = fopen (filename, "r"); + + if (fin != NULL) + { + gchar ch; + + while ((ch = getc (fin)) != EOF) + { + ret = g_strconcat (ret, g_strdup_printf ("%c", ch), NULL); + } + } + + fclose (fin); + + return ret; +} + +int +main (int argc, char **argv) +{ + Rss *rss; + xmlDoc *xdoc; + gchar *buffer; + + g_type_init (); + + /* reading the file */ + buffer = read_file (argv[1]); + + rss = rss_new_from_buffer (buffer); + + if (rss != NULL) + { + xdoc = rss_get_xml_doc (rss); + if (xdoc != NULL) + { + xmlSaveFormatFileEnc ("./test_load_buffer.xml", xdoc, "iso-8859-1", 2); + } + else + { + g_fprintf (stderr, "xdoc is null\n"); + } + + rss_save_file (rss, "./test_load_gfeed_buffer.xml"); + } + else + { + g_fprintf (stderr, "rss is null\n"); + } + + return 0; +}