diff options
author | Nick White <arch@njw.me.uk> | 2007-02-28 17:51:46 +0000 |
---|---|---|
committer | Nick White <arch@njw.me.uk> | 2007-02-28 17:51:46 +0000 |
commit | 877096c9f399e6a12c48f792f5896c04cf338acb (patch) | |
tree | a13331383a0a269cfe26a2783ec551f1b3ef1166 |
Initial importmaster--base-0
git-archimport-id: getht@sv.gnu.org/getht--mainline--0.1--base-0
-rw-r--r-- | AUTHOR | 3 | ||||
-rw-r--r-- | BUGS | 2 | ||||
-rw-r--r-- | COPYING | 339 | ||||
-rw-r--r-- | CREDITS | 5 | ||||
-rw-r--r-- | ChangeLog | 1 | ||||
-rw-r--r-- | INSTALL | 21 | ||||
-rw-r--r-- | Makefile | 37 | ||||
-rw-r--r-- | README | 48 | ||||
-rw-r--r-- | TODO | 58 | ||||
-rw-r--r-- | config.c | 168 | ||||
-rw-r--r-- | download.c | 231 | ||||
-rw-r--r-- | getht.c | 391 | ||||
-rw-r--r-- | getht.h | 47 | ||||
-rw-r--r-- | issue.h | 72 | ||||
-rw-r--r-- | mediarev.c | 113 | ||||
-rw-r--r-- | mediaxml.c | 233 | ||||
-rw-r--r-- | tocxml.c | 276 | ||||
-rw-r--r-- | version.h | 22 | ||||
-rw-r--r-- | xml.c | 62 |
19 files changed, 2129 insertions, 0 deletions
@@ -0,0 +1,3 @@ +Main program code and maintainer: +Nick White <nick@njw.me.uk> + http://www.njw.me.uk @@ -0,0 +1,2 @@ +getht.c + running clearmed clears unrelated title in update media section @@ -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. @@ -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 @@ -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 @@ -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. @@ -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); +} @@ -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; +} @@ -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; @@ -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" @@ -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; +} |