summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHOR3
-rw-r--r--BUGS2
-rw-r--r--COPYING339
-rw-r--r--CREDITS5
-rw-r--r--ChangeLog1
-rw-r--r--INSTALL21
-rw-r--r--Makefile37
-rw-r--r--README48
-rw-r--r--TODO58
-rw-r--r--config.c168
-rw-r--r--download.c231
-rw-r--r--getht.c391
-rw-r--r--getht.h47
-rw-r--r--issue.h72
-rw-r--r--mediarev.c113
-rw-r--r--mediaxml.c233
-rw-r--r--tocxml.c276
-rw-r--r--version.h22
-rw-r--r--xml.c62
19 files changed, 2129 insertions, 0 deletions
diff --git a/AUTHOR b/AUTHOR
new file mode 100644
index 0000000..a476016
--- /dev/null
+++ b/AUTHOR
@@ -0,0 +1,3 @@
+Main program code and maintainer:
+Nick White <nick@njw.me.uk>
+ http://www.njw.me.uk
diff --git a/BUGS b/BUGS
new file mode 100644
index 0000000..fb483d5
--- /dev/null
+++ b/BUGS
@@ -0,0 +1,2 @@
+getht.c
+ running clearmed clears unrelated title in update media section
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..a43ea21
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/CREDITS b/CREDITS
new file mode 100644
index 0000000..e333553
--- /dev/null
+++ b/CREDITS
@@ -0,0 +1,5 @@
+So far this program has been written entirely by me, Nick.
+
+If you'd like to contribute suggestions, bug reports, or anything
+else you believe would be useful, I would be delighted, and your
+name would be mentioned here.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..fd935f6
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1 @@
+2006-08: pre-release
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..e6a3f1c
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,21 @@
+The project is too small to warrent autoconf or anything else complex,
+so simply use the makefile provided to compile and install the software
+from source.
+
+For a default install all that is needed is the following:
+
+1. Decompress/archive the project file:
+ tar -xzf getht-<version>.tar.gz
+or
+ tar -xyf getht-<version>.tar.bz2
+
+2. Change to hdte directory:
+ cd getht-<version>
+
+3. Run make to compile the source:
+ make
+
+4. Use make again to install it (you'll need to have root privilages):
+ make install
+
+For further build options, see the output of "make help"
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..b9925cc
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,37 @@
+PREFIX=/usr
+DOCS=AUTHOR COPYING CREDITS ChangeLog INSTALL README TODO
+CFLAGS+=-g `curl-config --cflags` `xml2-config --cflags`
+LDFLAGS+=`curl-config --libs` `xml2-config --libs`
+
+all: getht
+
+getht: download.o config.o tocxml.o mediarev.o mediaxml.o xml.o
+
+tocxml.o mediaxml.o: xml.o
+
+static:
+ CFLAGS="$(CFLAGS) -s -static"
+ @echo "Not implemented yet, sorry."
+
+clean:
+ rm -rf *.o
+
+install:
+ cp getht $(PREFIX)/bin
+ mkdir -p $(PREFIX)/doc/getht
+ cp $(DOCS) $(PREFIX)/doc/getht
+
+uninstall:
+ rm $(PREFIX)/bin/getht
+ rm -r $(PREFIX)/doc/getht
+
+help:
+ @echo -e "Make targets:"
+ @echo -e "make (all)\tBuilds GetHT with default settings"
+ @echo -e "make install\tInstalls GetHT"
+ @echo -e "make uninstall\tRemoves GetHT"
+ @echo -e "make clean\tRemoves all object files"
+ @echo -e "make static\tBuilds a statically linked GetHT binary"
+ @echo -e "make help\tPrint this help message"
+
+.PHONY: all clean install uninstall help
diff --git a/README b/README
new file mode 100644
index 0000000..0097953
--- /dev/null
+++ b/README
@@ -0,0 +1,48 @@
+GetHT - The Free Hinduism Today Digital Edition Fetcher
+
+Summary:
+The nice people at Hinduism Today have recently begun freely distributing
+their magazine in pdf format, so that anybody may read a copy for free.
+
+However, rather than provide links to the PDF files on their website,
+they ask users to download their software which then downloads and opens
+the PDFs itself.
+
+This unfortunately means those who are not using a Mac or Windows PC are
+unable to download the new issues.
+
+This program is written to change all that.
+
+License:
+htde is released under the GPL, see the file COPYING for details.
+Basically this means that you are free to study the program, modify it,
+and redistribute it however you see fit, provided you extend the same
+freedom to others by releasing derivatives with the same license.
+
+Proxy Support:
+GetHT supports HTTP, SOCKS4 & SOCKS5 proxys (though they haven't been
+thoroughly tested - let me know if there are any problems).
+Environmental variables (e.g. http_proxy) are used, but may be overridden
+with the following lines in the config.ini file. Any lines which are not
+needed (for example the authentication lines) should just be omitted.
+The format of the options is:
+proxy_type <type_of_proxy> (http, socks4 or socks5)
+proxy_address <address>
+proxy_port <port>
+proxy_auth <proxy_auth_method> (none, basic, digest or ntlm)
+proxy_user <proxy_username>
+proxy_pass <proxy_password>
+
+Dependancies:
+libxml2 To parse the contents and media files; ensure to compile
+ with zlib support
+libcurl 7.7.2+ To download the necessary issues and periphery
+Unless compiled with "make nogui":
+fltk 2.0+ To draw and control the windows
+
+Install:
+The project is too small to warrent autoconf or anything else complex,
+so simply use the makefile provided to compile and install the software
+from source.
+
+For more details see the included INSTALL file.
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..1b7ce6a
--- /dev/null
+++ b/TODO
@@ -0,0 +1,58 @@
+-savannah-
+
+add news, with current status, likely time to usability, & hello
+
+checkin to arch
+
+add tasks to tracker
+
+look into getting a commit mailing list (writable) to work
+
+post a screenshot?
+
+-immediate term-
+
+save entered directories to config file
+
+utilise and expand initial clean procedures
+
+add sorting algo for issues, only needs a few pointers passing around, use temp iss*
+ look online for v. basic sorting algos or write own
+ then no more latest_iss pointer needed
+
+add if file is readable checks to appropriate functions e.g. reading xml / rev and handle appropriately
+
+add new source file for freeing memory plus mem error functions
+
+handle file errors better
+
+-malloc-
+
+redo passing memory pointers rather than whole arrays etc.
+
+malloc sections, items, and media
+ will ensure ease of finding existance, as no_of_sections no_of_media no_of_items can be used (embedded in struct)
+
+reduce code duplication
+
+handle smil files successfully
+
+if no required contents file exists, attempt to retrieve it, even if update is not passed
+comment source - at least all functions
+add long options
+
+use autotools
+integrate gettext
+
+add options to allow decent listing of issues
+add options to allow downloading of any issue
+
+add manpage & ensure it's compiled if nec
+add texinfo & ensure it's compiled if nec
+
+add resume functions (if ht server supports it)
+ensure better integration with official htde - look for existing installation & use its ebook dirs etc.
+
+doxygen?
+
+submit software to the gnu directory
diff --git a/config.c b/config.c
new file mode 100644
index 0000000..57807b1
--- /dev/null
+++ b/config.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2006 Nick White
+ *
+ * This file is part of GetHT
+ *
+ * GetHT 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.
+ *
+ * GetHT 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 GetHT; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "getht.h"
+
+extern proxytype proxy_type;
+extern char proxy_addr[STR_MAX];
+extern long proxy_port;
+extern proxyauth proxy_auth;
+extern char proxy_user[STR_MAX];
+extern char proxy_pass[STR_MAX];
+
+int loadconfig(char * htde_path, char * issue_path, int * update)
+/* Loads variables from config file to extern and passed
+ * variables. */
+{
+ FILE * config_file;
+ char filepath[STR_MAX];
+
+ snprintf(filepath, STR_MAX, "%s/config.ini", htde_path);
+
+ if((config_file = fopen(filepath,"r")) == NULL)
+ {
+ fprintf(stderr,"Cannot open file %s for reading.\n",filepath);
+ return 1;
+ }
+
+ char parameter[80], option[80];
+ while(!feof(config_file))
+ {
+ fscanf(config_file, "%s = %s", option, parameter);
+
+ if(option[0] == '#'); /* ignore lines beginning with a hash */
+ else if(!strcmp(option, "issuepath"))
+ strncpy(issue_path, parameter, STR_MAX);
+ else if(!strcmp(option, "startup_check"))
+ *update = atoi(parameter);
+ else if(!strcmp(option, "proxy_type"))
+ {
+ if(!strcmp(parameter, "http"))
+ proxy_type = HTTP;
+ else if(!strcmp(parameter, "socks4"))
+ proxy_type = SOCKS4;
+ else if(!strcmp(parameter, "socks5"))
+ proxy_type = SOCKS5;
+ else
+ fprintf(stderr,
+ "Proxy type %s not known, please use either http, socks4 or socks5",
+ parameter);
+ }
+ else if(!strcmp(option, "proxy_address"))
+ strncpy(proxy_addr, parameter, STR_MAX);
+ else if(!strcmp(option, "proxy_port"))
+ proxy_port = (long) atoi(parameter);
+ else if(!strcmp(option, "proxy_auth"))
+ {
+ if(!strcmp(parameter, "basic"))
+ proxy_auth = BASIC;
+ else if(!strcmp(parameter, "digest"))
+ proxy_auth = DIGEST;
+ else if(!strcmp(parameter, "ntlm"))
+ proxy_auth = NTLM;
+ else
+ fprintf(stderr,
+ "Proxy authentication method %s not known, please use basic, digest or ntlm",
+ parameter);
+ }
+ else if(!strcmp(option, "proxy_user"))
+ strncpy(proxy_user, parameter, STR_MAX);
+ else if(!strcmp(option, "proxy_pass"))
+ strncpy(proxy_pass, parameter, STR_MAX);
+ else
+ fprintf(stderr, "Option '%s' not recognised, ignoring\n", option);
+ }
+
+ return 0;
+}
+
+int writefreshconfig(char * htde_path, char * issue_path, int * update)
+/* Write a new config file according to extern and passed variables. */
+{
+ FILE * config_file;
+ char filepath[STR_MAX];
+
+ snprintf(filepath, STR_MAX, "%s/config.ini", htde_path);
+
+ if((config_file = fopen(filepath,"w")) == NULL)
+ {
+ fprintf(stderr,"Cannot open file %s for writing.\n",filepath);
+ return 1;
+ }
+ else
+ fprintf(stdout,"Writing a fresh config file to %s.\n",filepath);
+
+ if(issue_path[0])
+ fprintf(config_file, "%s = %s\n", "issuepath", issue_path);
+ if(update)
+ fprintf(config_file, "%s = %i\n", "startup_check", *update);
+ if(proxy_type != NONE)
+ {
+ if(proxy_type = HTTP)
+ fprintf(config_file, "%s = %s\n", "proxy_type", "http");
+ else if(proxy_type = SOCKS4)
+ fprintf(config_file, "%s = %s\n", "proxy_type", "socks4");
+ else if(proxy_type = SOCKS5)
+ fprintf(config_file, "%s = %s\n", "proxy_type", "socks5");
+ }
+ if(proxy_addr[0])
+ fprintf(config_file, "%s = %s\n", "proxy_address", proxy_addr);
+ if(proxy_port)
+ fprintf(config_file, "%s = %i\n", "proxy_port", proxy_port);
+ if(proxy_auth != NOAUTH)
+ {
+ if(proxy_auth = BASIC)
+ fprintf(config_file, "%s = %s\n", "proxy_auth", "basic");
+ else if(proxy_auth = DIGEST)
+ fprintf(config_file, "%s = %s\n", "proxy_auth", "digest");
+ else if(proxy_auth = NTLM)
+ fprintf(config_file, "%s = %s\n", "proxy_auth", "ntlm");
+ }
+ if(proxy_user[0])
+ fprintf(config_file, "%s = %s\n", "proxy_user", proxy_user);
+ if(proxy_pass[0])
+ fprintf(config_file, "%s = %s\n", "proxy_pass", proxy_pass);
+
+ return 0;
+}
+
+int updateconfig(char * htde_path, char * issue_path, int * update)
+/* Read existing config file, and rewrite any variables which differ
+ * in memory. */
+{
+ FILE * config_file;
+ char filepath[STR_MAX];
+
+ snprintf(filepath, STR_MAX, "%s/config.ini", htde_path);
+
+ if((config_file = fopen(filepath,"rw")) == NULL)
+ {
+ fprintf(stderr,"Cannot open file %s for reading/writing.\n",filepath);
+ return 1;
+ }
+
+ fprintf(stderr,"Not yet implemented.\n");
+
+ return 1;
+}
diff --git a/download.c b/download.c
new file mode 100644
index 0000000..240393a
--- /dev/null
+++ b/download.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2006 Nick White
+ *
+ * This file is part of GetHT
+ *
+ * GetHT 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.
+ *
+ * GetHT 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 GetHT; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <curl/curl.h>
+#include <curl/types.h>
+#include <curl/easy.h>
+
+#include "getht.h"
+#include "issue.h"
+
+int read_func(void *ptr, size_t size, size_t nmemb, FILE *stream)
+ { return fread(ptr, size, nmemb, stream); }
+int write_func(void *ptr, size_t size, size_t nmemb, FILE *stream)
+ { return fwrite(ptr, size, nmemb, stream); }
+int update_progress(void *data, double dltotal, double dlnow,
+ double ultotal, double ulnow);
+
+extern proxytype proxy_type;
+extern char proxy_addr[STR_MAX];
+extern long proxy_port;
+extern proxyauth proxy_auth;
+extern char proxy_user[STR_MAX];
+extern char proxy_pass[STR_MAX];
+extern CURL *main_curl_handle;
+
+void save_file(CURL *curl_handle, char *url, char *filepath)
+/* Save the file *url to *filepath */
+{
+ printf("Downloading %s\n",url);
+
+ if(curl_handle == NULL)
+ curl_handle = main_curl_handle;
+
+ if(curl_handle) {
+ FILE *file;
+ if((file = fopen(filepath,"w")) == NULL)
+ fprintf(stderr,"Error: cannot open file %s for writing.\n",filepath);
+
+ curl_easy_setopt(curl_handle, CURLOPT_URL, url);
+ curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_func);
+ curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, file);
+ curl_easy_setopt(curl_handle, CURLOPT_READFUNCTION, read_func);
+
+ if(proxy_type != NONE)
+ {
+ if(proxy_type == HTTP)
+ curl_easy_setopt(curl_handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
+ else if(proxy_type == SOCKS4)
+ curl_easy_setopt(curl_handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
+ else if(proxy_type == SOCKS5)
+ curl_easy_setopt(curl_handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
+
+ curl_easy_setopt(curl_handle, CURLOPT_PROXY, proxy_addr);
+
+ if(proxy_port)
+ curl_easy_setopt(curl_handle, CURLOPT_PROXYPORT, proxy_port);
+
+ if(proxy_auth != NOAUTH)
+ {
+ if(proxy_auth == BASIC)
+ curl_easy_setopt(curl_handle, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
+ else if(proxy_auth == DIGEST)
+ curl_easy_setopt(curl_handle, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST);
+ else if(proxy_auth == NTLM)
+ curl_easy_setopt(curl_handle, CURLOPT_PROXYAUTH, CURLAUTH_NTLM);
+
+ if(proxy_user[0] && proxy_pass[0])
+ {
+ char userpass[STR_MAX];
+ snprintf(userpass, STR_MAX, "%s:%s", proxy_user, proxy_pass);
+ curl_easy_setopt(curl_handle, CURLOPT_PROXYUSERPWD, userpass);
+ }
+ }
+ }
+
+ curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 0);
+ curl_easy_setopt(curl_handle, CURLOPT_PROGRESSFUNCTION, update_progress);
+
+ if(curl_easy_perform(curl_handle))
+ fprintf(stderr,"Error, could not download %s\n",url);
+
+/* double d;
+ curl_easy_getinfo(curl_handle, CURLINFO_SIZE_DOWNLOAD, &d);
+ printf("Total downloaded: %lf\n",d);
+
+ curl_easy_getinfo(curl_handle, CURLINFO_SPEED_DOWNLOAD, &d);
+ printf("Average speed downloaded: %lf\n",d);
+
+ curl_easy_getinfo(curl_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d);
+ printf("Content Length: %lf\n",d);
+*/
+ fclose(file);
+ }
+ else {
+ fprintf(stderr,"Error: curl failed to initialise.\n");
+ printf("Could not download %s\n",url);
+ }
+}
+
+int update_progress(void *data, double dltotal, double dlnow,
+ double ultotal, double ulnow)
+/* Print status information */
+{
+ double frac;
+ frac = 100 * dlnow / dltotal;
+ printf("\rDownloading... %3.0lf%% ", frac);
+ fflush(stdout);
+
+ return 0;
+}
+
+void downloadissue(CURL *curl_handle, char * directory, iss * issue, int force)
+/* Download issue pointed to */
+{
+ sec * cur_section;
+ char newdir[STR_MAX];
+ char filename[STR_MAX];
+ FILE * testfile;
+
+ snprintf(newdir,STR_MAX,"%s/%i_%i-%i",directory,
+ issue->date.year,issue->date.firstmonth,issue->date.lastmonth);
+
+ printf("Downloading issue entitled '%s' to '%s'\n",issue->title,newdir);
+
+ if(!opendir(newdir))
+ if(mkdir(newdir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH))
+ {
+ printf("Please enter the path of a directory to save issues in: ");
+ scanf("%s", newdir); /* TODO: incorporate tab-completion */
+ }
+
+ if(issue->cover.title[0])
+ {
+ snprintf(filename,STR_MAX,"%s/cover.pdf", newdir);
+ if(!force){
+ testfile = fopen(filename, "r");
+ if(!testfile)
+ save_file(curl_handle, issue->cover.uri, filename);
+ else
+ {
+ fclose(testfile);
+ printf("Skipping download of cover\n");
+ }
+ }
+ else
+ save_file(curl_handle, issue->cover.uri, filename);
+ }
+
+ for(cur_section = issue->section; cur_section->number>0 && cur_section->number<=SEC_NO; cur_section++)
+ {
+ snprintf(filename,STR_MAX,"%s/section_%i.pdf", newdir, cur_section->number);
+ if(!force){
+ testfile = fopen(filename, "r");
+ if(!testfile)
+ save_file(curl_handle, cur_section->uri, filename);
+ else
+ {
+ fclose(testfile);
+ printf("Skipping download of section %i\n", cur_section->number);
+ }
+ }
+ else
+ save_file(curl_handle, cur_section->uri, filename);
+ }
+}
+
+void downloadmedia(CURL * curl_handle, char * directory, med * media, int force)
+/* Download media pointed to. */
+{
+ char newdir[STR_MAX], filename[STR_MAX], fn[STR_MAX];
+ FILE * testfile;
+
+ /* for the moment just save to down/media, in future save to issue directories
+ * (regardless of if they're occupied) */
+ snprintf(newdir,STR_MAX,"%s/%s",directory,"media");
+
+ if(!opendir(newdir))
+ if(mkdir(newdir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH))
+ {
+ printf("Please enter the path of a directory to save media in: ");
+ scanf("%s", newdir); /* TODO: incorporate GETTEXT */
+ }
+
+ /* get the position of the final forwardslash of the uri */
+ int slashpos;
+ for(slashpos=strlen(media->uri);
+ slashpos>=0 && media->uri[slashpos] != '/';
+ slashpos--);
+
+ /* copy from there to fn */
+ int tmp;
+ for(tmp=0, slashpos++; media->uri[slashpos]; tmp++, slashpos++)
+ fn[tmp] = media->uri[slashpos];
+ fn[tmp] = '\0';
+
+ snprintf(filename,STR_MAX,"%s/%s", newdir, fn);
+
+ if(!force){
+ testfile = fopen(filename, "r");
+ if(!testfile)
+ save_file(curl_handle, media->uri, filename);
+ else
+ {
+ fclose(testfile);
+ printf("Skipping download of media item %s\n", media->title);
+ }
+ }
+ else
+ save_file(curl_handle, media->uri, filename);
+}
diff --git a/getht.c b/getht.c
new file mode 100644
index 0000000..a27104c
--- /dev/null
+++ b/getht.c
@@ -0,0 +1,391 @@
+/*
+ * Copyright 2006 Nick White
+ *
+ * This file is part of GetHT
+ *
+ * GetHT 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.
+ *
+ * GetHT 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 GetHT; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <curl/curl.h>
+
+#include "version.h"
+#include "issue.h"
+#include "getht.h"
+
+void show_iss_struct(iss ** issue, int no_of_issues);
+void show_med_struct(med * issue);
+
+void clearmed(med * cur_media);
+void cleariss(iss * cur_issue);
+
+med * findnewestmed(iss ** issue, int no_of_issues);
+
+proxytype proxy_type; char proxy_addr[STR_MAX]; long proxy_port;
+proxyauth proxy_auth;
+char proxy_user[STR_MAX]; char proxy_pass[STR_MAX];
+char issue_xml[STR_MAX]; char media_xml[STR_MAX]; char media_rev[STR_MAX];
+CURL *main_curl_handle;
+
+int main(int argc, char *argv[])
+{
+ char getht_path[STR_MAX];
+ char save_path[STR_MAX];
+
+ /* Define & set up paths */
+ snprintf(getht_path,STR_MAX,"%s/.getht",getenv("HOME"));
+
+ if(!opendir(getht_path))
+ if(mkdir(getht_path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH))
+ {
+ fprintf(stderr,"Cannot open/create directory %s",getht_path);
+ printf("Please enter the path of a directory to save settings in: ");
+ scanf("%s", getht_path);
+ }
+
+ snprintf(issue_xml,STR_MAX,"%s/%s",getht_path,ISS_XML_FILE);
+ snprintf(media_xml,STR_MAX, "%s/%s", getht_path, MED_XML_FILE);
+ snprintf(media_rev,STR_MAX,"%s/%s",getht_path,MED_REVGZ_FILE);
+
+ snprintf(save_path,STR_MAX,"%s/hinduism_today",getenv("HOME"));
+
+ int downall = 0, downlatest = 0;
+ int downallmedia = 0, downlatestmedia = 0;
+ int downissue = 0, downmedia = 0;
+ int force = 0, update = 0, showstr = 0;
+
+ proxy_type = NONE;
+ proxy_port = 0;
+ proxy_addr[0] = '\0';
+ proxy_auth = NOAUTH;
+ proxy_user[0] = '\0';
+ proxy_pass[0] = '\0';
+
+ if(loadconfig(getht_path, &save_path, &update) != 0)
+ writefreshconfig(getht_path, &save_path, &update);
+
+ if(!opendir(save_path))
+ if(mkdir(save_path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH))
+ {
+ fprintf(stderr,"Cannot open/create directory %s",save_path);
+ printf("Please enter the path of a directory to save issues in: ");
+ scanf("%s", save_path);
+
+ updateconfig(getht_path, &save_path, NULL);
+ }
+
+ /* Parse command line options */
+ char c;
+ while((c = getopt(argc, argv, "adfhmnsuvxt:")) != -1) {
+ switch(c) {
+ case 'a':
+ downall = 1;
+ downissue = 1;
+ break;
+ case 'd':
+ downlatest = 1;
+ downissue = 1;
+ break;
+ case 'm':
+ downallmedia = 1;
+ downmedia = 1;
+ break;
+ case 'n':
+ downlatestmedia = 1;
+ downmedia = 1;
+ break;
+ case 'f':
+ force = 1;
+ break;
+ case 'u':
+ update = 1;
+ break;
+ case 's':
+ showstr = 1;
+ break;
+ case 't':
+ strcpy(issue_xml, strdup(optarg));
+ break;
+ case 'h':
+ printf("Usage: getht -am dn -f [-t tocfile] -u -hv\n");
+ printf("-a Download all issues\n");
+ printf("-d Download latest issue\n");
+ printf("-m Download all media\n");
+ printf("-n Download latest issue's media\n");
+ printf("-f Force redownloading of existent issues\n");
+ printf("-u Download new contents files\n");
+ printf("-t file Use alternative contents xml file\n");
+ printf("-h Print this help message\n");
+ printf("-v Print version information\n");
+ printf(" ---DEBUGGING--\n");
+ printf("-s Print structure information\n");
+ return 0;
+ break;
+ case 'v':
+ printf("GetHT version: %s\n",VERSION);
+ return 0;
+ break;
+ default:
+ fprintf(stderr,"Unknown option: %c\n",c);
+ }
+ }
+
+ main_curl_handle = curl_easy_init();
+
+ if(update)
+ {
+ if(update_contents_files(NULL, NULL))
+ fprintf(stderr,"Could not update contents files");
+ }
+
+ /* Parse TOC, filling issue structure */
+
+ iss **issue;
+ int no_of_issues = -1;
+ int latest_index = -1;
+ int i;
+
+ if(downissue || showstr)
+ {
+ issue = parsetoc(issue_xml, &no_of_issues, &latest_index);
+
+ if(showstr)
+ show_iss_struct(issue, no_of_issues);
+
+ if(latest_index == -1)
+ {
+ fprintf(stderr, "Error: Cannot ascertain latest issue. ");
+ fprintf(stderr, "Defaulting to first issue in contents file\n");
+ latest_index = 0;
+ }
+
+ if(downall)
+ {
+ for(i = 0; i < no_of_issues; i++)
+ downloadissue(NULL, save_path, issue[i], force);
+ }
+
+ if(downlatest)
+ downloadissue(NULL, save_path, issue[latest_index], force);
+ }
+
+ if(downmedia)
+ {
+ med * cur_media;
+ int newest;
+
+ issue = parsemedia(media_xml, &issue, &no_of_issues);
+
+ if(downlatestmedia)
+ {
+ newest = findnewestiss(issue, no_of_issues);
+ for(i = 0; i <= issue[newest]->no_of_media; i++)
+ downloadmedia(NULL, save_path, &(issue[newest]->media[i]), force);
+ }
+
+ if(downallmedia)
+ {
+ for(i = 0; i <= no_of_issues; i++)
+ {
+ for(newest = 0; newest <= issue[i]->no_of_media; newest++)
+ downloadmedia(NULL, save_path, &(issue[i]->media[newest]), force);
+ }
+ }
+ }
+
+ if(no_of_issues > -1)
+ {
+ for(i = 0; i < no_of_issues; i++)
+ free(issue[i]);
+ free(issue);
+ }
+
+ /* Ensure curl cleans itself up */
+ curl_easy_cleanup(main_curl_handle);
+
+ return 0;
+}
+
+int update_contents_files(CURL *curl_handle, int temp)
+/* Returns 0 on success, 1 on failure */
+{
+ save_file(NULL, XML_TOC_URL, issue_xml);
+
+ /* see if current issue's media toc has already
+ been written to the xml, if not do so */
+
+ char isstitle[STR_MAX];
+ issdates date;
+
+ if(access(issue_xml, R_OK) == 0)
+ cur_identifiers(issue_xml, isstitle, &date);
+ else
+ return 1;
+
+ if(media_accounted_for(media_xml, &date))
+ {
+ save_file(curl_handle, MEDIA_TOC_URL, media_rev);
+
+ med temp_med[MED_NO];
+
+ clearmed(temp_med);
+ /* BUG: for no good reason, this resets title[] too...
+ * Until we can find why, just get the title again */
+
+ cur_identifiers(issue_xml, isstitle, &date);
+
+ int med_no = -1;
+ parsemediagz(media_rev, temp_med, &med_no);
+ /* BUG: this blanks title too... strange
+ * Until we can find why, just get the title again */
+ cur_identifiers(issue_xml, isstitle, &date);
+
+ unlink(media_rev);
+
+ addmediaissue(media_xml, isstitle, &date, temp_med, med_no);
+ }
+
+ return 0;
+}
+
+void show_iss_struct(iss ** issue, int no_of_issues)
+/* Prints issue information */
+{
+ int iss_no, sec_no, it_no;
+ printf("%i Issues\n",no_of_issues);
+ for(iss_no=0;iss_no<no_of_issues;iss_no++)
+ {
+ printf("-Issue %i-\n", (iss_no+1));
+ printf("Title:\t'%s'\n", issue[iss_no]->title);
+ printf("Preview URI:\t'%s'\n", issue[iss_no]->preview_uri);
+ printf("Months:\t'%i' - '%i'\n",issue[iss_no]->date.firstmonth,issue[iss_no]->date.lastmonth);
+ printf("Year:\t'%i'\n",issue[iss_no]->date.year);
+ printf("Number of Sections:\t'%i'\n",issue[iss_no]->no_of_sections);
+
+ printf("\t-Cover-\n");
+ printf("\tTitle:\t'%s'\n", issue[iss_no]->cover.title);
+ printf("\tURI:\t'%s'\n", issue[iss_no]->cover.uri);
+
+ for(sec_no=0; sec_no < (issue[iss_no]->no_of_sections); sec_no++)
+ {
+ printf("\t-Section %i-\n", (sec_no+1));
+ printf("\tTitle:\t'%s'\n", issue[iss_no]->section[sec_no].title);
+ printf("\tURI:\t'%s'\n", issue[iss_no]->section[sec_no].uri);
+ printf("\tNo. of Items:\t'%i'\n", issue[iss_no]->section[sec_no].no_of_items);
+
+ for(it_no=0; it_no < issue[iss_no]->section[sec_no].no_of_items; it_no++)
+ {
+ printf("\t\t-Item-\n");
+ printf("\t\tTitle:\t'%s'\n",issue[iss_no]->section[sec_no].item[it_no].title);
+ printf("\t\tFirst page:\t'%i'",issue[iss_no]->section[sec_no].item[it_no].firstpage);
+ printf("\tLast page:\t'%i'\n",issue[iss_no]->section[sec_no].item[it_no].lastpage);
+ }
+ it_no = 0;
+ }
+ sec_no = 0;
+ }
+}
+
+void show_med_struct(med * cur_media)
+/* Prints media information */
+{
+ int tmp;
+ for(tmp=0;tmp<MED_NO;cur_media++,tmp++)
+ {
+ printf("--Media item--\n");
+
+ printf("uri: '%s'\n", cur_media->uri);
+ printf("title: '%s'\n", cur_media->title);
+ printf("comment: '%s'\n", cur_media->comment);
+ printf("preview_uri: '%s'\n", cur_media->preview_uri);
+ printf("size: '%i'\n", cur_media->size);
+
+ printf("\n");
+ }
+}
+
+void cleariss(iss * cur_issue)
+/* turns off exist flags for all issue structures */
+{
+ int tmp;
+ for(tmp=0; tmp<MAX_ISS; cur_issue++,tmp++)
+ {
+ cur_issue->preview_uri[0] = '\0';
+ cur_issue->title[0] = '\0';
+ cur_issue->size = 0;
+ cur_issue->no_of_sections = 0;
+ cur_issue->no_of_media = 0;
+ clearmed(cur_issue->media);
+ }
+}
+
+void clearmed(med * cur_media)
+/* clears all members of media arrays */
+{
+ int tmp;
+ for(tmp=0; tmp<=MED_NO; cur_media++,tmp++)
+ {
+ cur_media->uri[0] = '\0';
+ cur_media->title[0] = '\0';
+ cur_media->comment[0] = '\0';
+ cur_media->preview_uri[0] = '\0';
+ cur_media->size = 0;
+ }
+}
+
+void clearsec(sec * cur_section)
+/* clears all members of section arrays */
+{
+ int tmp;
+ for(tmp=0; tmp<=SEC_NO; cur_section++,tmp++)
+ {
+ cur_section->uri[0] = '\0';
+ cur_section->title[0] = '\0';
+ cur_section->size = 0;
+ cur_section->number = 0;
+ cur_section->no_of_items = 0;
+ }
+}
+
+int findnewestiss(iss ** issue, int no_of_issues)
+/* returns newest issue indice */
+{
+ iss * tmp_issue; issdates newest;
+ int new_iss;
+
+ new_iss = -1;
+ newest.year = 0; newest.firstmonth = 0; newest.lastmonth = 0;
+
+ int i;
+
+ for(i = 0; i <= no_of_issues; i++)
+ {
+ if(issue[i]->date.year > newest.year ||
+ (issue[i]->date.year == newest.year && issue[i]->date.firstmonth > newest.firstmonth))
+ {
+ newest.year = issue[i]->date.year;
+ newest.firstmonth = issue[i]->date.firstmonth;
+ newest.lastmonth = issue[i]->date.lastmonth;
+ new_iss = i;
+ }
+ }
+
+ return new_iss;
+}
diff --git a/getht.h b/getht.h
new file mode 100644
index 0000000..df2b1b2
--- /dev/null
+++ b/getht.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2006 Nick White
+ *
+ * This file is part of GetHT
+ *
+ * GetHT 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.
+ *
+ * GetHT 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 GetHT; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#define XML_TOC_URL "http://www.hinduismtoday.com/digital/htde_toc.xml"
+#define MEDIA_TOC_URL "http://www.hinduismtoday.com/digital/htde_media-player.rev.gz"
+
+#define MED_XML_FILE "media_toc.xml"
+#define ISS_XML_FILE "htde_toc.xml"
+#define MED_REVGZ_FILE "htde_media-player.rev.gz"
+
+#define STR_MAX 512
+
+#define MAX_ISS 10
+
+typedef enum
+{
+ NONE,
+ HTTP,
+ SOCKS4,
+ SOCKS5
+} proxytype;
+
+typedef enum
+{
+ NOAUTH,
+ BASIC,
+ DIGEST,
+ NTLM,
+} proxyauth;
diff --git a/issue.h b/issue.h
new file mode 100644
index 0000000..a0eda1f
--- /dev/null
+++ b/issue.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2006 Nick White
+ *
+ * This file is part of GetHT
+ *
+ * GetHT 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.
+ *
+ * GetHT 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 GetHT; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#define SEC_NO 4
+#define ITEM_NO 30
+#define MED_NO 2
+
+/* all sizes are in bytes and are child-inclusive */
+
+typedef struct
+{
+ int year;
+ int firstmonth;
+ int lastmonth;
+} issdates;
+
+typedef struct
+{
+ int firstpage;
+ int lastpage;
+ char * title;
+} it;
+
+typedef struct
+{
+ char uri[512];
+ char title[512];
+ int number;
+ int size;
+ it item[ITEM_NO];
+ int no_of_items;
+} sec;
+
+typedef struct
+{
+ char uri[512];
+ char title[512];
+ char comment[512];
+ char preview_uri[512];
+ int size;
+} med;
+
+typedef struct
+{
+ char preview_uri[512];
+ char title[512];
+ int size;
+ issdates date;
+ sec cover;
+ sec section[SEC_NO];
+ int no_of_sections;
+ med media[MED_NO];
+ int no_of_media;
+} iss;
diff --git a/mediarev.c b/mediarev.c
new file mode 100644
index 0000000..8181c19
--- /dev/null
+++ b/mediarev.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2006 Nick White
+ *
+ * This mediagz is part of GetHT
+ *
+ * GetHT 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.
+ *
+ * GetHT 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 GetHT; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <zlib.h>
+
+#include "getht.h"
+#include "issue.h"
+
+void getquote(char * input, char * label);
+
+int parsemediagz(char * media_path, med * cur_media, int * no_of_media)
+/* Parses gzipped adobe pagemaker files for media urls and metadata,
+ * filling cur_media with the information. */
+{
+ char cur_line[STR_MAX];
+ gzFile mediagz;
+
+ strcpy(cur_line,""); /* reset cur_line */
+
+ mediagz = gzopen(media_path, "r");
+
+ while(gzeof(mediagz)==0)
+ {
+ gzgets(mediagz, cur_line, STR_MAX);
+ cur_line[strlen(cur_line)-1] = '\0'; /* get rid of trailing newline */
+
+ if(!strcmp(cur_line,"on mouseUp"))
+ {
+ strcpy(cur_line,""); /* reset cur_line */
+ while(strcmp(cur_line,"end mouseUp") && gzeof(mediagz)==0)
+ {
+ strcpy(cur_line,""); /* reset cur_line */
+ gzgets(mediagz, cur_line, STR_MAX);
+ cur_line[strlen(cur_line)-1] = '\0'; /* get rid of trailing newline */
+
+ if(!strncmp(cur_line," set the filename of player \"player1\" to \"",45))
+ {
+ /* todo: if smil follow, otherwise load into media->url */
+ sscanf(cur_line," set the filename of player \"player1\" to \"%s\"",cur_media->uri);
+ cur_media->uri[strlen(cur_media->uri)-1] = '\0'; /* workaround extra final character */
+ }
+ else if(!strncmp(cur_line," set the label of this stack to \"",36))
+ {
+ getquote(cur_line,cur_media->title);
+ }
+ else if(!strncmp(cur_line," statusMsg \(\"",16))
+ {
+ getquote(cur_line,cur_media->comment);
+ }
+ /* else
+ * fprintf(stderr,"Interesting line to put in struct: '%s'\n",cur_line);
+ */
+
+ }
+ *cur_media++;
+ (*no_of_media)++;
+ cur_media->uri[0] = '\0';
+ }
+ strcpy(cur_line,""); /* reset cur_line */
+ }
+ return 0;
+}
+
+int smilurl(char * smilurl, med * cur_media)
+/* Extracts url and other data from remote smil file, storing
+ * the info in the cur_media structure. */
+{
+ return 0;
+}
+
+void getquote(char * input, char * quote)
+/* sets quote from a line of the format:
+ * `something "quote" something' */
+{
+ char * cur_pos;
+ cur_pos = quote;
+
+ /* advance until " character is reached */
+ while(*input != '"' && *input)
+ input++;
+
+ input++;
+
+ /* copy characters in until next '"' */
+ while(*input != '"' && *input)
+ {
+ *cur_pos = *input;
+ cur_pos++;
+ input++;
+ }
+
+ *cur_pos = '\0';
+}
diff --git a/mediaxml.c b/mediaxml.c
new file mode 100644
index 0000000..60d4576
--- /dev/null
+++ b/mediaxml.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2006 Nick White
+ *
+ * This file is part of GetHT
+ *
+ * GetHT 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.
+ *
+ * GetHT 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 GetHT; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+#include "getht.h"
+#include "issue.h"
+
+int media_accounted_for(char * filepath, issdates * date)
+/* checks if media for issue is found */
+{
+ xmlDocPtr media_file;
+ xmlNodePtr node;
+
+ if(ready_xml(filepath, "media", &media_file, &node))
+ return 1;
+
+ *node = *node->xmlChildrenNode;
+
+ issdates curdate;
+ int found = 1;
+
+ while (node != NULL)
+ {
+ if(!xmlStrcmp(node->name,(char *) "issue"))
+ {
+ curdate.year = atoi( (char *) xmlGetProp(node, "year"));
+ curdate.firstmonth = atoi( (char *) xmlGetProp(node, "firstmonth"));
+ curdate.lastmonth = atoi( (char *) xmlGetProp(node, "lastmonth"));
+ }
+
+ if( curdate.year == date->year &&
+ curdate.firstmonth == date->firstmonth &&
+ curdate.lastmonth == date->lastmonth )
+ {
+ found = 0;
+ break;
+ }
+
+ node = node->next;
+ }
+
+ xmlFreeDoc(media_file);
+
+ return found;
+}
+
+int addmediaissue(char * filepath, char * title, issdates * date, med * media, int med_no)
+/* Appends data from media structures to xml file. */
+{
+ xmlDocPtr media_file;
+ xmlNodePtr node;
+
+ /* if xml file doesn't exist */
+ if(ready_xml(filepath, "media", &media_file, &node))
+ {
+ /* set up fresh xml file */
+ media_file = xmlNewDoc(NULL);
+ node = xmlNewNode(NULL, "media");
+ xmlDocSetRootElement(media_file, node);
+ }
+
+ xmlNodePtr curissue;
+ char tmp[5];
+
+ /* set up issue node */
+ curissue = xmlNewTextChild(node, NULL, "issue", NULL);
+
+ xmlNewProp(curissue, "title", title);
+
+ snprintf(tmp,5,"%i", date->year);
+ xmlNewProp(curissue, "year", tmp);
+
+ snprintf(tmp,5,"%i",date->firstmonth);
+ xmlNewProp(curissue, "firstmonth", tmp);
+
+ snprintf(tmp,5,"%i",date->lastmonth);
+ xmlNewProp(curissue, "lastmonth", tmp);
+
+ xmlNodePtr curitem;
+ int i;
+ for(i = 0; i <= med_no; i++)
+ {
+ curitem = xmlNewTextChild(curissue, NULL, "item", media[i].title);
+
+ xmlNewProp(curitem, "uri", media[i].uri);
+
+ if(media[i].comment)
+ xmlNewProp(curitem, "comment", media[i].comment);
+ if(media[i].preview_uri)
+ xmlNewProp(curitem, "preview_uri", media[i].preview_uri);
+ }
+
+ xmlKeepBlanksDefault(0);
+
+ xmlSaveFormatFile(filepath, media_file, 1);
+
+ xmlFreeDoc(media_file);
+
+ return 0;
+}
+
+iss ** parsemedia(char * filepath, iss ** issue, int * no_of_issues)
+/* Fills issues with relevant info from media xml, creating new
+ ones where necessary. */
+{
+ issdates tmpdate;
+
+ iss * cur_issue; med * cur_media;
+
+ xmlDocPtr media_file;
+ xmlNodePtr node, itnode;
+
+ ready_xml(filepath, "media", &media_file, &node);
+
+ *node = *node->xmlChildrenNode;
+
+ int issue_there = 0;
+
+ char title[STR_MAX];
+ issdates curdate;
+ int tmp;
+
+ while (node != NULL)
+ {
+ if(!xmlStrcmp(node->name,(char *) "issue"))
+ {
+ /* check if issue with title already exists */
+ for(tmp = 0; tmp < *no_of_issues; tmp++)
+ {
+ curdate.year = atoi( (char *) xmlGetProp(node, "year"));
+ curdate.firstmonth = atoi( (char *) xmlGetProp(node, "firstmonth"));
+ curdate.lastmonth = atoi( (char *) xmlGetProp(node, "lastmonth"));
+
+ if( curdate.year == issue[tmp]->date.year &&
+ curdate.firstmonth == issue[tmp]->date.firstmonth &&
+ curdate.lastmonth == issue[tmp]->date.lastmonth )
+ {
+ issue_there = 1;
+ break;
+ }
+ }
+
+ if(!issue_there)
+ { /* advance to the next free issue */
+ iss ** tmpiss;
+ if(*no_of_issues == -1)
+ { /* make issue** a new array of issue pointers */
+ if( (tmpiss = malloc(sizeof(iss *))) == NULL )
+ nogo_mem();
+ }
+ else
+ { /* add a new pointer to issue pointer list */
+ if( (tmpiss = realloc(issue, sizeof(iss *) + (*no_of_issues * sizeof(iss *)))) == NULL )
+ nogo_mem();
+ }
+
+ (*no_of_issues)++;
+
+ /* make new array item a pointer to issue */
+ if( (tmpiss[*no_of_issues] = malloc(sizeof(iss))) == NULL )
+ nogo_mem();
+
+ issue = tmpiss;
+
+ issue[*no_of_issues]->date.year = atoi( (char *) xmlGetProp(node, "year"));
+ issue[*no_of_issues]->date.firstmonth = atoi( (char *) xmlGetProp(node, "firstmonth"));
+ issue[*no_of_issues]->date.lastmonth = atoi( (char *) xmlGetProp(node, "lastmonth"));
+
+ strncpy(issue[*no_of_issues]->title, (char *) xmlGetProp(node, "title"), STR_MAX);
+
+ issue[*no_of_issues]->no_of_media = -1;
+ }
+
+ cur_media = issue[(*no_of_issues)]->media;
+
+
+ itnode = node->xmlChildrenNode;
+
+ while (itnode != NULL)
+ {
+
+ if(!xmlStrcmp(itnode->name,(char *) "item"))
+ {
+ /* add media info to cur_media */
+ if(xmlGetProp(itnode, "uri"))
+ strncpy(cur_media->uri, (char *) xmlGetProp(itnode, "uri"), STR_MAX);
+
+ if(xmlGetProp(itnode, "comment"))
+ strncpy(cur_media->comment, (char *) xmlGetProp(itnode, "comment"), STR_MAX);
+
+ if(xmlGetProp(itnode, "preview"))
+ strncpy(cur_media->preview_uri, (char *) xmlGetProp(itnode, "preview_uri"), STR_MAX);
+
+ strncpy(cur_media->title, (char *) xmlNodeListGetString(media_file, itnode->xmlChildrenNode, 1), STR_MAX);
+
+ issue[*no_of_issues]->no_of_media++;
+
+ cur_media++;
+ }
+
+ itnode = itnode->next;
+ }
+ }
+
+ node = node->next;
+ }
+
+ xmlFreeDoc(media_file);
+
+ return issue;
+}
diff --git a/tocxml.c b/tocxml.c
new file mode 100644
index 0000000..da0771b
--- /dev/null
+++ b/tocxml.c
@@ -0,0 +1,276 @@
+/*
+ * Copyright 2006 Nick White
+ *
+ * This file is part of GetHT
+ *
+ * GetHT 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.
+ *
+ * GetHT 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 GetHT; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+#include "issue.h"
+#include "getht.h"
+
+iss ** parsetoc(char *filepath, int * iss_no, int * latest);
+iss ** parseyear(xmlDocPtr file, xmlNodePtr node, iss ** issue, int * latest);
+int parseissue(xmlDocPtr file, xmlNodePtr node, iss * cur_issue, int * latest);
+void parsesection(xmlDocPtr file, xmlNodePtr node, sec * cur_section);
+
+void tokenise_hyphons(char to_token[10], int * first, int * last);
+
+int no_of_issues;
+
+void nogo_mem()
+/* called if memory assignation fails
+ TODO: handle freeing of memory to avoid leaks */
+{
+ fprintf(stderr, "Could not assign memory, exitting\n");
+ exit(1);
+}
+
+iss ** parsetoc(char *filepath, int * iss_no, int * latest)
+/* starts parsing of xml to issue structure
+ TODO: combine with parseyear */
+{
+ xmlDocPtr file;
+ xmlNodePtr node;
+
+ if(ready_xml(filepath, "issues", &file, &node))
+ return NULL;
+
+ *node = *node->xmlChildrenNode;
+
+ no_of_issues = -1;
+
+ iss ** issue;
+
+ int year;
+ iss ** tmp;
+
+ xmlNodePtr cnode;
+
+ while(node != NULL)
+ {
+ if(!xmlStrncmp(node->name,(char *) "year",4))
+ {
+ cnode = node->children;
+ while(cnode != NULL)
+ {
+ if(!xmlStrncmp(cnode->name,(char *) "issue",5))
+ {
+ if(no_of_issues < 0)
+ { /* make issue** a new array of issue pointers */
+ if( (tmp = malloc(sizeof(iss *))) == NULL )
+ nogo_mem();
+ }
+ else
+ { /* add a new pointer to issue pointer list */
+ if( (tmp = realloc(issue, sizeof(iss *) + ((no_of_issues+1) * sizeof(iss *)))) == NULL )
+ nogo_mem();
+ }
+
+ no_of_issues++;
+
+ /* make new array item a pointer to issue */
+ if( (tmp[no_of_issues] = malloc(sizeof(iss))) == NULL )
+ nogo_mem();
+
+ issue = tmp;
+
+ issue[no_of_issues]->date.year = atoi( (const char *)(xmlStrsub(node->name,5,4)) );
+ tokenise_hyphons(xmlStrsub(cnode->name,6,5), &(issue[no_of_issues]->date.firstmonth), &(issue[no_of_issues]->date.lastmonth));
+ issue[no_of_issues]->no_of_sections = parseissue(file, cnode, issue[no_of_issues], latest);
+ }
+ cnode = cnode->next;
+ }
+ }
+ node = node->next;
+ }
+
+ xmlFreeDoc(file);
+
+ *iss_no = no_of_issues;
+
+ return issue;
+}
+
+int parseissue(xmlDocPtr file, xmlNodePtr node, iss * cur_issue, int * latest)
+/* parses issue from xml, saving in cur_issue structure */
+{
+ int no_of_sections = -1;
+
+ strncpy(cur_issue->title, (char *) xmlGetProp(node, "title"), STR_MAX);
+ strncpy(cur_issue->preview_uri, (char *) xmlGetProp(node, "coverlink"), STR_MAX);
+
+ if(xmlGetProp(node, "current") && *latest==-1)
+ *latest = no_of_issues;
+
+ sec * cur_section = NULL;
+
+ node = node->xmlChildrenNode;
+
+ while(node != NULL){
+ if(!xmlStrcmp(node->name, (const xmlChar *) "cover"))
+ {
+ cur_section = &(cur_issue->cover);
+ parsesection(file, node, cur_section);
+ }
+ else if(!xmlStrncmp(node->name, (char *) "section",7))
+ {
+ no_of_sections++;
+ cur_section = &(cur_issue->section[no_of_sections]);
+
+ parsesection(file, node, cur_section);
+ }
+ node = node->next;
+ }
+
+ return no_of_sections;
+}
+
+void parsesection(xmlDocPtr file, xmlNodePtr node, sec * cur_section)
+/* parses section xml, filling cur_section structure */
+{
+ it * cur_item;
+
+ strncpy(cur_section->uri, (char *) xmlGetProp(node, "pdflink"), STR_MAX);
+ strncpy(cur_section->title, (char *) xmlGetProp(node, "title"), STR_MAX);
+
+ if(!xmlStrcmp(node->name, (const xmlChar *) "cover"))
+ cur_section->number = 0;
+ else
+ cur_section->number = atoi( (const char *)(xmlStrsub(node->name,8,1)) );
+
+ cur_item = cur_section->item;
+ cur_section->no_of_items = 0;
+
+ node = node->xmlChildrenNode;
+
+ char * pagenums;
+
+ while(node != NULL)
+ {
+ if(!xmlStrcmp(node->name, (const xmlChar *) "item"))
+ {
+ cur_section->no_of_items++;
+ cur_item->title = xmlNodeListGetString(file, node->xmlChildrenNode, 1);
+ if(pagenums = (char *) xmlGetProp(node, "pages"))
+ tokenise_hyphons(pagenums, &(cur_item->firstpage), &(cur_item->lastpage));
+ else
+ {
+ cur_item->firstpage = 0;
+ cur_item->lastpage = 0;
+ }
+ cur_item++;
+ }
+ node = node->next;
+ }
+ cur_item = 0;
+}
+
+void tokenise_hyphons(char to_token[10], int * first, int * last)
+/* splits string to_token, filling positions passed */
+{
+ char token[10];
+ char * tmp;
+
+ tmp = token;
+
+ while(*to_token != '-' && *to_token)
+ {
+ *tmp = *to_token;
+ to_token++; tmp++;
+ }
+
+ *first = atoi(token);
+
+ if(!*to_token)
+ *last = *first;
+ else
+ {
+ to_token++; /* advance past '-' */
+ tmp = token; /* reset tmp */
+ while(*to_token)
+ {
+ *tmp = *to_token;
+ tmp++; to_token++;
+ }
+ *last = atoi(token);
+ }
+}
+
+int cur_identifiers(char * filepath, char * title, issdates * date)
+/* parses xml file to ascertain current issue title and date */
+{
+ xmlDocPtr file;
+
+ if((file = xmlParseFile(filepath)) == NULL)
+ {
+ return 1;
+ }
+
+ xmlNodePtr node,cnode;
+
+ node = xmlDocGetRootElement(file);
+
+ if(node == NULL)
+ {
+ fprintf(stderr,"Error: xml file %s has no root element",filepath);
+ xmlFreeDoc(file);
+ return 1;
+ }
+
+ if(xmlStrcmp(node->name, (const xmlChar *) "issues"))
+ {
+ fprintf(stderr,"Document of the wrong type, root node is '%s' (expected 'issues').\n",(char *) node->name);
+ fprintf(stderr,"Continuing regardless...\n");
+ }
+
+ /* Now that's all sorted, let's do some work */
+
+ node = node->xmlChildrenNode;
+
+ xmlChar *temp;
+ while(node != NULL)
+ {
+ if(!xmlStrncmp(node->name,(char *) "year",4))
+ {
+ cnode = node->children;
+ while(cnode != NULL)
+ {
+ if(!xmlStrncmp(cnode->name,(char *) "issue",5))
+ {
+ temp = xmlGetProp(cnode, "current");
+ if(temp)
+ {
+ strncpy(title, (char *) xmlGetProp(cnode, "title"), STR_MAX);
+ date->year = atoi( (const char *)(xmlStrsub(node->name,5,4)) );
+ tokenise_hyphons(xmlStrsub(cnode->name,6,5), &(date->firstmonth), &(date->lastmonth));
+ return 0;
+ }
+ }
+ cnode = cnode->next;
+ }
+ }
+ node = node->next;
+ }
+
+ return 0;
+}
diff --git a/version.h b/version.h
new file mode 100644
index 0000000..20383e4
--- /dev/null
+++ b/version.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2006 Nick White
+ *
+ * This file is part of GetHT
+ *
+ * GetHT 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.
+ *
+ * GetHT 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 GetHT; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#define VERSION "pre-release"
diff --git a/xml.c b/xml.c
new file mode 100644
index 0000000..1a3ea3c
--- /dev/null
+++ b/xml.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2006 Nick White
+ *
+ * This file is part of GetHT
+ *
+ * GetHT 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.
+ *
+ * GetHT 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 GetHT; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+#include "getht.h"
+#include "issue.h"
+
+int ready_xml(char * filepath, char * rootnode, xmlDocPtr * file, xmlNodePtr * node)
+/* Opens filepath, filling nec pointers with essential information. */
+{
+ if(access(filepath, R_OK) != 0)
+ return 1;
+
+ if((*file = xmlParseFile(filepath)) == NULL)
+ {
+ fprintf(stderr, "Error: cannot open xml file %s\n", filepath);
+ return 1;
+ }
+
+ *node = xmlDocGetRootElement(*file);
+
+ if(*node == NULL)
+ {
+ fprintf(stderr,"Error: xml file %s has no root element",filepath);
+ xmlFreeDoc(*file);
+ return 1;
+ }
+
+ char * test;
+ test = (char *) (*node)->name;
+
+ if(xmlStrcmp((*node)->name, (const xmlChar *) rootnode))
+ {
+ fprintf(stderr,"Document of the wrong type, root node is '%s' (expected '%s').\n",(char *) (*node)->name, rootnode);
+ fprintf(stderr,"Continuing regardless...\n");
+ }
+
+ return 0;
+}