From b0b1c815c15e49c9172f59428810713097a65e37 Mon Sep 17 00:00:00 2001 From: hniksic Date: Sun, 19 Nov 2000 12:50:10 -0800 Subject: [PATCH] [svn] A bunch of new features: - use mmap() to read whole files in core instead of allocating memory and read'ing it. - use a new, more general, HTML parser (html-parse.c) and interface to it from Wget (html-url.c). - respect (easy with the new HTML parser). - use hash tables instead of linked lists in places where the lists were used to facilitate mappings. - rewrite the code in host.c to be more readable and faster (hash tables instead of home-grown lists.) - make convert_links properly convert partial URLs to complete ones for those URLs that have *not* been downloaded. - use HTTP persistent connections where available. very simple-minded, caches the last connection to the server. Published in . --- ChangeLog | 4 + TODO | 12 - configure | 348 ++++++++++++++++--- configure.in | 1 + doc/ChangeLog | 5 + doc/wget.texi | 4 +- po/cs.gmo | Bin 15443 -> 14838 bytes po/de.gmo | Bin 15624 -> 14975 bytes po/hr.gmo | Bin 21184 -> 24828 bytes po/it.gmo | Bin 15483 -> 14838 bytes po/no.gmo | Bin 14809 -> 14214 bytes po/pl.gmo | Bin 15598 -> 14974 bytes po/pt_BR.gmo | Bin 14564 -> 13920 bytes po/ru.gmo | Bin 19691 -> 19040 bytes src/ChangeLog | 114 +++++++ src/Makefile.in | 58 ++-- src/config.h.in | 3 + src/connect.c | 31 ++ src/ftp-ls.c | 173 ++++++++++ src/ftp.c | 3 +- src/ftp.h | 2 + src/hash.c | 403 ++++++++++++++++++++++ src/hash.h | 50 +++ src/headers.c | 8 + src/headers.h | 1 + src/host.c | 340 ++++++++----------- src/html-parse.c | 856 +++++++++++++++++++++++++++++++++++++++++++++++ src/html-parse.h | 44 +++ src/html-url.c | 569 +++++++++++++++++++++++++++++++ src/http.c | 203 ++++++++--- src/main.c | 15 + src/recur.c | 148 +++++--- src/retr.c | 70 ++-- src/retr.h | 2 +- src/url.c | 617 ++++++++++++---------------------- src/url.h | 3 +- src/utils.c | 303 ++++++++++++----- src/utils.h | 27 +- src/wget.h | 2 +- 39 files changed, 3518 insertions(+), 901 deletions(-) create mode 100644 src/hash.c create mode 100644 src/hash.h create mode 100644 src/html-parse.c create mode 100644 src/html-parse.h create mode 100644 src/html-url.c diff --git a/ChangeLog b/ChangeLog index 46905616..e873628f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2000-11-10 Hrvoje Niksic + + * configure.in: Test for MMAP. + 2000-11-16 Hrvoje Niksic * windows/config.h.ms: snprintf and vsnprintf exist under Windows. diff --git a/TODO b/TODO index d8319039..c0fecefc 100644 --- a/TODO +++ b/TODO @@ -49,15 +49,6 @@ changes. * Make `-k' check for files that were downloaded in the past and convert links to them in newly-downloaded documents. -* -k should convert relative references to absolute if not downloaded. - -* -k should convert "hostless absolute" URLs, like . - However, Brian McMahon wants the old incorrect behavior to still - be available as an option, as he depends on it to allow mirrors of his site to - send CGI queries to his original site, but still get graphics off of the - mirror site. Perhaps this would be better dealt with by adding an option to - tell -k not to convert certain URL patterns? - * Add option to clobber existing file names (no `.N' suffixes). * Introduce a concept of "boolean" options. For instance, every @@ -85,9 +76,6 @@ changes. * Allow size limit to files (perhaps with an option to download oversize files up through the limit or not at all, to get more functionality than [u]limit. -* Recognize HTML comments correctly. Add more options for handling - bogus HTML found all over the 'net. - * Implement breadth-first retrieval. * Download to .in* when mirroring. diff --git a/configure b/configure index f7e130a2..de78c984 100755 --- a/configure +++ b/configure @@ -2040,15 +2040,281 @@ EOF fi +for ac_hdr in unistd.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2048: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2058: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_func in getpagesize +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2087: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2115: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +echo $ac_n "checking for working mmap""... $ac_c" 1>&6 +echo "configure:2140: checking for working mmap" >&5 +if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_mmap_fixed_mapped=no +else + cat > conftest.$ac_ext < +#include +#include + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +# ifdef HAVE_UNISTD_H +# include +# endif + +/* Assume that all systems that can run configure have sys/param.h. */ +# ifndef HAVE_SYS_PARAM_H +# define HAVE_SYS_PARAM_H 1 +# endif + +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# ifdef HAVE_SYS_PARAM_H +# include +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +#ifdef __cplusplus +extern "C" { void *malloc(unsigned); } +#else +char *malloc(); +#endif + +int +main() +{ + char *data, *data2, *data3; + int i, pagesize; + int fd; + + pagesize = getpagesize(); + + /* + * First, make a file with some known garbage in it. + */ + data = malloc(pagesize); + if (!data) + exit(1); + for (i = 0; i < pagesize; ++i) + *(data + i) = rand(); + umask(0); + fd = creat("conftestmmap", 0600); + if (fd < 0) + exit(1); + if (write(fd, data, pagesize) != pagesize) + exit(1); + close(fd); + + /* + * Next, try to mmap the file at a fixed address which + * already has something else allocated at it. If we can, + * also make sure that we see the same garbage. + */ + fd = open("conftestmmap", O_RDWR); + if (fd < 0) + exit(1); + data2 = malloc(2 * pagesize); + if (!data2) + exit(1); + data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1); + if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0L)) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + exit(1); + + /* + * Finally, make sure that changes to the mapped area + * do not percolate back to the file as seen by read(). + * (This is a bug on some variants of i386 svr4.0.) + */ + for (i = 0; i < pagesize; ++i) + *(data2 + i) = *(data2 + i) + 1; + data3 = malloc(pagesize); + if (!data3) + exit(1); + if (read(fd, data3, pagesize) != pagesize) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + exit(1); + close(fd); + unlink("conftestmmap"); + exit(0); +} + +EOF +if { (eval echo configure:2288: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_func_mmap_fixed_mapped=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_func_mmap_fixed_mapped=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6 +if test $ac_cv_func_mmap_fixed_mapped = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_MMAP 1 +EOF + +fi + for ac_func in strdup strstr strcasecmp strncasecmp do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2047: checking for $ac_func" >&5 +echo "configure:2313: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2341: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2098,12 +2364,12 @@ done for ac_func in gettimeofday mktime strptime do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2102: checking for $ac_func" >&5 +echo "configure:2368: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2396: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2153,12 +2419,12 @@ done for ac_func in strerror snprintf vsnprintf select signal symlink access isatty do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2157: checking for $ac_func" >&5 +echo "configure:2423: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2451: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2208,12 +2474,12 @@ done for ac_func in uname gethostname do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2212: checking for $ac_func" >&5 +echo "configure:2478: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2506: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2264,12 +2530,12 @@ done for ac_func in gethostbyname do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2268: checking for $ac_func" >&5 +echo "configure:2534: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2562: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2314,7 +2580,7 @@ EOF else echo "$ac_t""no" 1>&6 echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6 -echo "configure:2318: checking for gethostbyname in -lnsl" >&5 +echo "configure:2584: checking for gethostbyname in -lnsl" >&5 ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2322,7 +2588,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2603: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2367,7 +2633,7 @@ done echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6 -echo "configure:2371: checking for socket in -lsocket" >&5 +echo "configure:2637: checking for socket in -lsocket" >&5 ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2375,7 +2641,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lsocket $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2656: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2417,7 +2683,7 @@ fi if test "x${with_socks}" = xyes then echo $ac_n "checking for main in -lresolv""... $ac_c" 1>&6 -echo "configure:2421: checking for main in -lresolv" >&5 +echo "configure:2687: checking for main in -lresolv" >&5 ac_lib_var=`echo resolv'_'main | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2425,14 +2691,14 @@ else ac_save_LIBS="$LIBS" LIBS="-lresolv $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2702: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2460,7 +2726,7 @@ else fi echo $ac_n "checking for Rconnect in -lsocks""... $ac_c" 1>&6 -echo "configure:2464: checking for Rconnect in -lsocks" >&5 +echo "configure:2730: checking for Rconnect in -lsocks" >&5 ac_lib_var=`echo socks'_'Rconnect | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2468,7 +2734,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lsocks $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2749: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2511,7 +2777,7 @@ fi ALL_LINGUAS="cs de hr it no pl pt_BR ru" echo $ac_n "checking whether NLS is requested""... $ac_c" 1>&6 -echo "configure:2515: checking whether NLS is requested" >&5 +echo "configure:2781: checking whether NLS is requested" >&5 # Check whether --enable-nls or --disable-nls was given. if test "${enable_nls+set}" = set; then enableval="$enable_nls" @@ -2528,7 +2794,7 @@ fi # Extract the first word of "msgfmt", so it can be a program name with args. set dummy msgfmt; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2532: checking for $ac_word" >&5 +echo "configure:2798: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2562,7 +2828,7 @@ fi # Extract the first word of "xgettext", so it can be a program name with args. set dummy xgettext; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2566: checking for $ac_word" >&5 +echo "configure:2832: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2597,7 +2863,7 @@ fi # Extract the first word of "gmsgfmt", so it can be a program name with args. set dummy gmsgfmt; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2601: checking for $ac_word" >&5 +echo "configure:2867: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2647,17 +2913,17 @@ fi do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:2651: checking for $ac_hdr" >&5 +echo "configure:2917: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2661: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2927: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2687,12 +2953,12 @@ done for ac_func in gettext do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2691: checking for $ac_func" >&5 +echo "configure:2957: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2985: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2737,7 +3003,7 @@ EOF else echo "$ac_t""no" 1>&6 echo $ac_n "checking for gettext in -lintl""... $ac_c" 1>&6 -echo "configure:2741: checking for gettext in -lintl" >&5 +echo "configure:3007: checking for gettext in -lintl" >&5 ac_lib_var=`echo intl'_'gettext | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2745,7 +3011,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lintl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3026: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2824,7 +3090,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2828: checking for $ac_word" >&5 +echo "configure:3094: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_MAKEINFO'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else diff --git a/configure.in b/configure.in index 474e5d57..4f4440b0 100644 --- a/configure.in +++ b/configure.in @@ -160,6 +160,7 @@ dnl dnl Checks for library functions. dnl AC_FUNC_ALLOCA +AC_FUNC_MMAP AC_CHECK_FUNCS(strdup strstr strcasecmp strncasecmp) AC_CHECK_FUNCS(gettimeofday mktime strptime) AC_CHECK_FUNCS(strerror snprintf vsnprintf select signal symlink access isatty) diff --git a/doc/ChangeLog b/doc/ChangeLog index bddc4b5d..110102a6 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,8 @@ +2000-11-15 Hrvoje Niksic + + * wget.texi (Robots): Document that we now support the meta tag + exclusion. + 2000-11-16 Hrvoje Niksic * wget.texi: Use --- consistently. diff --git a/doc/wget.texi b/doc/wget.texi index eb4d00c9..1accbb94 100644 --- a/doc/wget.texi +++ b/doc/wget.texi @@ -2548,8 +2548,8 @@ this: This is explained in some detail at @url{http://info.webcrawler.com/mak/projects/robots/meta-user.html}. -Unfortunately, Wget does not support this method of robot exclusion yet, -but it will be implemented in the next release. +Wget supports this method of robot exclusion in addition to the usual +@file{/robots.txt} exclusion. @node Security Considerations, Contributors, Robots, Appendices @section Security Considerations diff --git a/po/cs.gmo b/po/cs.gmo index 5511ce5c7c3f5e1de27487239e7c88a41b6fdce8..c276436c9b14f2f5190c5e08a9c1d84ea271c535 100644 GIT binary patch delta 3351 zcmZA12~bs49LMp$8_MGeilQVM$itK^!4+8wRFc9%6ESl`w9G_t!6eO|nj0!gp=D}L zqcu2MQwlW=mQFg=Oj%4(&9s;;PU2*iP2-Z)^!@P;GfZdR|9;NB_uaGn&$+j$;_5R0 zci|m(8D$UAm$=l?tO?%^=0NGLo!h(j?3XJLO_gBsug?2acf0Y61O_cz9&uUo)8)W8>F zELLJ9zJj;ndw3`P+j%PLFpgGrV*=iSWjF{cQ5_#c4YU!}@NbxgA>n2zI2MQFa*V+v zn1g3f?S_($-k6LUNG|&5-)2%#hwHE(?nB084VZ)^ZDq*YSaMh zou8xH`4hF8og&PrS{U}iIP?#slHo4QK_+D@k+rdHn28OjhOaq$^RzND5|xQU)QlFR zW?G4T@Q}NI8rAMOcYej)_w*+JO35G&Q`?zkqc+JNTGLwAqSp8fYKGTvC`OSk4X^;! z(P|ulyHRW1h|1(2sP?+?CvCcZsEm%oAz0pr{Ob?3TwwoMJu*orhq%-MLKRx_Z)ImI|p$vDU+_?p{hA$#N zJIaAc*(a#AY(~8u|KLcBX4>j_3dZ1EBx$w*`HSsGZT91+cKsKqC}r1C8Hi#5m8t~P zObSsWElZGV(F1oo3Wt3E`mU6H)&gg&M$oBnh?=`T6Yt#~3c0LZ#{_ z)Eb9!k*bYGT`xiH{wmb&T1Kk|zDXC+Ui9N1xbF@BbKv zy^b5RaX6mGBJ9JCOT{Iq2M;=5Lp6BZoj0OV{tYT~&8W>8&JHFSmW?Sm3)Ox#(zm^j zKKi$2DrDchOiz0u0ku0bF%ip959~$8X78X<{ypjgbrZG5aeNHaVHQrt>3BOHL%OgZ zP)iWRPSyZ@sQqUXsp!E)sMJS@)v`Qin8QO_+oKCX#=pHajVh>Jrp|wxc>chFY3NcmAu>L;mzO3`8wi4r*6V zLOoxGnn(@iw=;Vay_~n_RnVRaLuD?rB-obeTs(~A*ne^q~dawYMnYE|} zYmv6C9?7cxh#BbR&&p69s{JBV>Ps;U{qDMd2Nj;Nmr8yogG@kBt$6>8N(@LS3JYhp+;b`u==2<#_C&_kRTyrFtvs!9%Fjo<{A7vsjGn z*-`3v4(k7lQU9w#t!*tTb045SWI-bWnTbF;vN5R5JOwq8jV;$%|7t2~=q2olC$I>c zPyF~n$M3-KrsNpvS#%N{EFYG}x9 z%X&^$6C2#cB-9pFc`|@4MABCXwTo2Pu{MR+rj!2_Eu_lx#1bN#c#3$4 zXj{5*GS^+mLM?0oQB0^TCbT(J@&jQBB;f21|$zL=d5}Eo)S?TMl8d?ViH>K(Bcp>3@)hFD7E=5m-ploC%6DpiDD;MStglFAxl7BPp& zBvf`0<7@VLql>3g8>UN?5aKZ+fv6x(h^fr>yE@;2&sF0@Imi?*C0Gy delta 3924 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 diff --git a/po/de.gmo b/po/de.gmo index 6dc32778c758b6edffd41764374db7d34a8e231c..63f01f82da200b1cc5f948b444ebdab9959dc249 100644 GIT binary patch delta 3351 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 Y|E&)XVNLSF=qZx7a@N?>J71ji{}i66mH+?% delta 3686 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 delta 3964 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 MlNR}X!@aTWKft~T)Bpeg diff --git a/po/no.gmo b/po/no.gmo index a150d4e0a471c15387b7223f2ee97e9c5ed0e9d5..c54d1a07428ccc875caa45f6e66ec91274630608 100644 GIT binary patch delta 3351 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 diff --git a/po/pl.gmo b/po/pl.gmo index 6308a0e4e7a85c8b8924b537edfd8514accaae91..96e50064dfffcf667e874c24a3eaf1f07d41f801 100644 GIT binary patch delta 3351 zcmY+`drZ}39LMo5g&-F}K>hbR5XpK zIcw9UZq(r~vvfLFE6O$P4_9WJuC$!yWofQl@6S08oBhW3yq@24&Ur51=leT)bM>Pt z|IZ2GdyT7s=tA5GH#?6fqIltI8*P?`QMd)WV;}q&i}4b6$ILjh7%Xv4!9?!ox%;&k z%l&rD#66g6=C?0sq|YMg7RT8ZIB-_J&UZUAZl^N}RjHssH52YL0-aT=AX zE2uM$qm!l$NA*{rs=pT1A3!baJVxMUjKp72)qd06KR_OwV4C##j-)Fqj5)E3p8sN& z{T^>rq9zWf(k5a)>PYHPDg6@T@d7FXSKa;JsLVxCvHE-p4#HAo4y(f)Y{K4n3ALek zc9YHgRzO2Lnu|JZjh&h82g7G;l61A6({n}lOfJ38RJ=uBW0Mf4Y=2HJ&M@K>k_{z4UF65G^S zk4N<{KxME7naUcn$Uk*wr|IzEFYb*nN>r)KM18OrHNXmIJ?cmT7=x!!#npnE@H*=8 zY(w6anF7>PP>zMT9Oq&n#~=EQPi6Vq`3NLyHXk+NPE^%5p%(Hrs+jH|$*_oLLPwT| zT5uuiDX4I6#nLc-2{D%bhk49_k-pGT7W-)^RVz_Na}0G>zoU+(D;1+N%*O$^3fY`B zp$7a38QZR-iZ_KX)3mV|hZ|5Cu0<8?5$7pXru;w9P?6n659Tn6s(&1g#SbwG|HK%4 zh?+Qp{IVHK#P&D>)nA5M_)OF<+&V18-LC&U^1#^5(7oRh`h`-R>l}wV%SA{XSq%=w zX4C}tP$>?h@^myA=)obV3{FQCStI7)QFnh4gPFo;`cp`I2R;8iXe7~*k1CQ9)P$9o zjE9lr*eTQ*-$f13iARIAm=`@*j(UF$s&*Pt-#dZ)*)3jl_Psbq4=%(!=C@iJ8t8L% z;9XRzy_}0C%5xT=`iq>Un8^K9RA!c87D(t0s4-E zavduBDMUI^Ppl?1o_=vQ5md0PAlec;i7^_mf_RdMAardG5iGrFuDuUC5qk(#oPP42 zCv>e0VWaQ~qOZH(hT~m39QCMVyL*-Ma-yh+m#M@;VjZEYme9W{t=B-;*of1KS%e-~ zU3-bK^^LLVGhU&^Pebrhv9BVsh}VNX{J#TBi7tfK^}UAMi5H1ou1_o>MiP1o6Nu47 nAf??OQGq@wbE4bz&h_>4`0@*U`PshSfseZV7#nEv4T=2^v|Bl% delta 3943 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 diff --git a/po/pt_BR.gmo b/po/pt_BR.gmo index 917f90f80ab6065d6f55e85c64521cbc2ac19391..447bdf177aeae02ede9899fc377f3f9dd017e340 100644 GIT binary patch delta 3248 zcmX}tdrVe!9LMo5i5DJ-n}{Nbhg1k3qz9D(K}?d+6mOY@kyK)lnkk}b8cz}ll9#+- zMz^h^=GM}rWh=|98B^EjkCtnNX_?s{P1k0#Wv%z;JU{!*?|J>sc@DqJ_k7Rs+{!b{ z!l#p?+l{uHxPdqvZFUT+V>r-O#F?ezN^HihI2MxwX4A18N8t{P#Y4_7a3JSB?)+!u zPwgV+;8h%B7PhQ-v*BErhgsNwL3{~4?8Z#IfLdT6!7K^0aWod;NUU{kMlJYVyb({} z5d0l8uwSCtBpihq%x{b7q;a7cZ^Bnm6Lq5&b`CXQG_w|>has%O0&GJMKf}p*7B$g` zWV69ohFZV^9D%D)^Syw>nBU%`!yMLwxp+oDV1WE7wL#SNIj9UZq6X?jE%3PWH`F*W zDFhBh{@F+lsaS;BI2&1`t;I0Uz}o1P;D@LIFFOYfie#bym4Ugaoh(P~umy+WTkiLx zsDXRk`9=48EVC;USy&ZiR*I^Hy@ScWo?R!u>RFyZ?d&p+!!%~o0xMAyt;bt%59--| zh04?=)PV8iRmGK#%2+v$#d_55ok$tkL1b-qG>!c0!YM9j<>yf;x`LX}<1ikJu@G0_ z0NjTZupLAV{0aISK{Q>Hf`0YzhBKkZ_Q3r4Sb5qP!DQ@f1olGMY^=`AZmf(B08G595rzb-i!^% zChSerKu1u2_>=qn5;CTF6as6riKyDCLJ!xWGSY#1l*ioff4S>v+)QzYZ3-Rz;Svs7 zQ5*KdJ=h;#K~;07JKv8Kx*bB@e-cY6s#B;1rINO7I1UT&bF9KEsM?y#ZuEC+Fj4P+ z6CDk>%lWpu;bT-SbYl=NqKD~>qVp0|rs_}w@8zIkK8&oz&Y~Vg6c_U_8TI;3M%`D( zA%ppCD;+(XcTkVwThxG;umV%alYXy8)?k~k1oxqKd>%dQ!{|H}8;R4f3@6|gRMB;# zhuYOd$iy&@!)oX-mo=g$cmuVNFOfIV&Y+(06;u_c@R_7*S*ZJFq841|u5Uq&_dbU3 zJ0$xSU>7nM^_I-cA^++u7 zQdE(3Ah+7rs0puPDW-E%E-pYVs0B6N>&Pv(KkRPk#XGnVprQge2etDWsr)?+MgKuz3=T5vlm1L2c&2GBW;djEe#J>#pWf#UNc zJDP#o`BL<7ySsh>weub{8`Dg7MG|_R?qdbocY_SxCs(u*i`h3*0Uyr)~Ma>*o)bn3MEFzf0PuElUD50kGM-$45cA&P4P{q$7W)Rof?R5GOJBXdcGGYtyIH5L| zSWATOmT4n_QKeA%_ z&$x548un8>n+vLX6^2@C1Z#7OZN$CAG@^!3=B^{uvWaHmPMy$Z5le}B;sHV}pU~Iv zL7mVV{G&#psX|qRYIhM26YB{Tj#@d9NAx9f2{k?I9AdgoXj=&toJTxKJV&T$V`>{C z_-~oI1Bu<5e>Cw3kxX1`{phHO77}``77)~@-)qMBH)6Pk)m?SA5UVx3NC zNyOd63Z2ka6aM~H%_W4Ybv_X!HWO-%#6txC$M~Pn4LFf#BBl_x5l<5p#685dHkr<1 z;xS@~yBO!(?&Nijv8kNY5?!rv8)Lc(2M-TipFbv4;Drh&gbIV9{I1%}wXt1kc_#z^ E0TWv$-T(jq delta 3894 zcmbuBdu*Fm8HZ1|?ou~2T@sVViQ|)76DO_{$FbwCYdbGZQjc7HS(lBneo4M0PJKyj zr(MT})9%*NvX0SifIy?0h6MaEp>ms`2u(0laobdo7?*W}iHgex65_Ir+wcmlFt)${DH zoOCWQu@Q<@9{5kld^NU;wbcXV`RXLZq3S0g3ss+o1X%q>nKf%5>(n&Cb&z9H*j#f9 zd_NSY+TjAk!J5a}UvUIAk^wK(ybM{;ZnMZUal$?dalpO^$;AE$Bt!et&;h?~J%1Il zu>EgJt?{y_oHgIo2Fvf&Mj?*Wrg=UEiw`qFQEa*dIm1nVf}Cj`i%5ob61gAlg9KA| z8nR*Ci;zX@ehr(Ml48O!M?YjeM*>o0j%kRaj*}2K94}bUWuFb4zvCS`c7nXIJW(&j z!RGanIaby0glt$p5BuOz7=mAid{h4yh+Flt4jVVDg(T1*2~e>Ok^r}&VFa>I!<~?4 z4H+2X{2NxR2ND@pH^}v=gAyTGIj@JDrxP0$**UjEHgYaQ4J9Cs#Q7}bd*`b>T#%%^OuYpw?dq0+zo9-I#QKH*ti1OxbY-pWGA_!zto1}G=KRa0;$q_$cbwJi{ z6U)7jAmkdi9h3VnFUp5R-S$(6t!;mWb-d$*EVx-L9)@?9pKpE^aul0?1aE;-gk;<< zMXTZMkZ;@f!w5VMZ-y5k#oHl?XgJLNYCD|;NB|vj<^ZVh|NHmagXhs`BozhsOP{&9FCoQ5@UKO}Si z3S=Sw6OhgPFGDi-OU4@42~OtwBmgq+i@~jsJtV=t7a&F2_Y!2UK1rmAwSE7lL*@Yu z*(fjuaU-w~l40Oc*a@G4WE*%9l5yY_$k_%iLmUZS14%0=iLg;{6mpcoMaa6rQ;_Np zp0(z==0z!j;D4FmgMRwT2e~SeL4OJk!%spi?SCEime$~)p?FAOp&5v!AvvlW;HND< z1F<~xMTn!JuRsD1ore^1=%U>JH4HwCq{%hZh()EkOKpx{qQBCb=-qi`RI*rooG}5F z+9bapL{blOO9)8pmjKmCB#pneYFRpRHg`yewhujss0FnLNnuGlT1M&jpw-8fQlmhX z*uL5xr^8XoAEi=-k+n)9u3V`-#P1GdmWQe+XT92{tj=NRMQ5zBoTCk`MdQ|-U=#A7 zC1jx07PUImko<#MYH^E#d2}4LNdEg}#%c+R)PTyOW7ha~Xh)wwk07a!JZeW$GeL9@ zl6D)~j;3WmOQUT_oGzf%R!!$)GD{(-0VKt9KdMD{p-Oah`v`-*D0kJQgZ>Djs!Q!Y zes`e<%0s!%>Q<|tfo}96)Njq5mZ-$qLue57pcCjiG=ro~pd+PTshZU+{V+1jCdICL)VyGEikFG^E=awpttSc@Z z&L!s;3c6#!t$ka!20Zc`EdBPEenWaFXPP>eohuwNa;6^2E@x(qLNc52=tyS9Yl|-= z^LizrBsr2i6m!a3Ws%e&Nez29oWtL z;oBl3k@%F(=JZe`J~kMO>7ntc4(o|K=%JPaxh;oSB*6E@2?p7)@)YKWYapUv(t-aA$c%MK>EP4sq^Ndq2DbeQ$>$0 zZRB-qa8yqw!XuN3!KfY%i;I!)Hk~okI&J3DS#9WfLySur`Yo|?CRs38%r-DCE=Ecg z?h5Z3)Y)a(BN4~a(ijiJIx(szqT>@6W0CmyRjzt%ckGZrjIwc;4L$L$_-Np(xGD~J clx&_DaqA@l&}l;o1y@rGrr3JA>xZ`g0hdnmumAu6 diff --git a/po/ru.gmo b/po/ru.gmo index 6019b4af6213f8139ff01898cc4429452f4c45d0..df7cd87d720b7afaecef05978aa369e788f25e61 100644 GIT binary patch delta 3472 zcmZwJdra0<9LMo5-cT-zAXhIuB#MX%h#298FwDd&3gP{JtJKI#W}=TJsTG=vB&aD{ z%xuj+8oEqpb4yFHnX}wXUD#!=X{Fugl1@UoVPH7_Ft|Y+`%k_ zb~GkqBK9@&+gK{`Tqwn!xEE9KWAx!|Ou(=(Z-D)=Bkgh68)u{LE5}5vb6!Rbyb&M5 zSZ<2J!PpIpFo);c3MzWwVfV##jHUe#_QKe3@4>@R1D%QL*pFGb2h;FN%*57A+lPZN z7pI{fxDTW81Zp6cushGUpQ-49;hoI7VjpDCmXCdKs=K}!mFffT`e&$_-^K3ei}VJV z=bVS?rwrR+CGu0-k5PCS{Yg~LxeLD`leQqfWo@hr4#s@c-q?i7K&|tXyZ${YBLPfL zGwX_)@j#5jBGmUKsQ$}cdtWs9*AI?yfq!<1kI4aMKcP0u2-2c8Ekv#LYSc_?F$2$_ z26`XWPj5a3;&9ZOm!dMdAJyLp)aI*4W%lje}3Xu(Kvyo(2iED2}jl2?- zv3HO@>~kD|H&J^bo;0<^NytI5*{FUOW77nX{cN?U({k8PCAEdwNz?=HkT*T34S80F zF{tYW&V{HoU5ngeTan4zd#JTNjXEt?@L{}<8o&Ubw<&W`OEd>{zkdxC?fxpf*wXA2 z>H)jRyHa=%m63C()LlW%tQ9*^GYH3_*bOz1>8OFM!aG=wskoM%s*D{%W&8}%zu)dr zVUX61ysG1&s2fJ3Mp%ku*Q!y!JAyvEgi7h3sJ)QDS=IMNsOu|{XIqWC{t0TpH?R%< zih(-+cd6)j1Teio3`S0*MWAj-!d`634Acy!(fa{hg&Jr#(wC28QJb$CgYW_>b5~JI zdegPB^{-`a)##R)V^5H);S!QTJcQQP_w> za3rHqMmC`ac9Dei+2KndZWw*GXj$3e;HN#ZY55}N6oQ0av zcGQEep#~6`=^eLp)cq4t8C&nJ??o-$N2sOw7Jb;3^hRQ`pNfu64k{CqQF~w=&Sle8 zV+id=(!)NrAYKYg)-q57Sb$3THq-#lqh7uDa4^O_;vMf|)M?s)>aPY#w)qcHVNlk9 zTKmXsFGaEC~gq<0-W^j_XiXPm6Be4J4BDYDpJjqRxL6l>{!FKyAVXJjQPJBh&pCDq)ltQ6!m=#YL9$@8n||}za6%xq6;yoHR|q6L#_D`R3-{A0GWtY z5^oUdP(>4nCtg&8GMm`lRO7#NxZc&ZWX#9L5gmAb(@ZqV?Zg^FWr~LtJ9C`PY@*WJ zHD1S9LTkUoT~k(7ltmS7*fL@mv4L1gloQWs{e!5eXwyw65{an<2g2SWl+tWsCZXR3 z6YB_-rNknlml~93#$V2}S-7B`QSC29II+6kW`iU_5AA<@9P~i_ zC0F0$WPjN+#AB{K4|i4Mg{1i3bXO)jwR;{c)ies+g|!cSG0WAHFwfPe;VZ5lh))vQ z?j=M%v7FdXEFiWJky>ZYmaQOOCH}9ht_TZ_9$D(XT7~n8OkyL!TfM2I^7*o>kH!f^ z6|sXzCRD}}V=78QqZ9X0YfJPbb`s5H4i)`18&A|73~d`!*AR2AV`zHcv`k-GR(4ue SN?Ll|2faTHsjJUQ==3iib5>~p delta 4110 zcmbuBdvMgn9l$q&3I~`F@`5CEqb1~VIr0vWhrOgEx#W15M`=`$5H932Ip9*01ZQa64Rex#Ji9Nsql3MR7tHGB;EVXjiQ)WBM} z6)u1QI0KFw{2b0vD)Q#=IuadfChLVT9p*!C7L&D1z5#c_RQL+ago9ASYcNHrDCXi| zR5_dt?|~Wce#pJ30}$t<-Z6L{Vsy3%-U>0Q5}+NXc41WW&;V>*9=vb&>EwsXRh`~9p!g$yZab(U2_SJ1nzGMS~ zF?gwxVF`?acS19~&)DAwNp;Ncjr|WHk;hJl=!wM%aWJ;Qpa-HSb`RuC>`O2Pz6Rr9 zFZLDni2WeE5jO>r+PHa;(!^n0;Y^%3LI&cVff$H;-QbY1e+80}cyN_w88<>4&S1~0Zeo(d22Nyx} z^b%n~hw*(UL}9@Tum&E3oGm0P;y_^~Oo5${`-M+Kz7_t-*#7`hy239YWhmk-fq7L? z6%*cjQ5(%g>WUs=>7&6q1p}!;ms8!O@5o$ez68rIOk-xEJO^$smp_{REQwVsQ*d zikskkxE)fK;+G)3R(uvFdD$Z!qOgQbl>_A!@RUmKg=C@RAT&X_z}b=sNM=f|L0(5G zb9ug{+?CRlHb90^-KN)JH{myW`l`H4t{1XE^#UJRFsL7J>gYAx%BAqvWN@Qe5h z_%drEu#z1yY!%0BP%=Q-tOJm&ST8^_RUQd7%z$K}T<#^njgWKY+u-exOnAj$`3M`- zw)}GVKm~P@T2@p;ny~_dQv&ektjR!CJ0#+&hoA{Q56M{7E5=$fMK4uJrizuSCTelC zx&lVSyWr=rL*9QL!C*ilvxy>7ZhH%s!Y|=M`i=C-#hML}Y}IUr>F~D@XKSRZ7eF~r zAhkp(JyF{T(N`;(BHgt|A!VxlEd1S`iG67j`&vjO_9x+VxZha62+5HBRfBIrYHt5C zBop=zVFV(j`zf*;LEq#c0C{@qq3}|zhtC@G=isA=Q`Xc>8bz%_q;^CiUaF^&hY=Zf zg`vJ{kow7gM*lM;!VF`z6V62vkq%>TTaV8)$NNK8<%k1$0FfVRH$v!>V?KW+6_UTZ zktN9U2su~QxK_{3=5(W8cKB{GVVj9Y3N2ZRc=vCd24D1(uK%4 zghWlwlxi|4DE`X)`^Nl$!D`r!R2XYJ+}D#cGt>Kwv2&+E+U38-&sfzNJCA(jOS3Vj z-_^H``5L(0n9CztjbtPDBQ=NzIf!gTeuBixyR2l=jr<7tU*mf{U(AfRZ8bhU2wRZ? zVrUik>yI;!|E=HVsKd_9E9u3lshsQ+FKRH*1>7 z+quQ<+}P&PX%*=@XUUQRv-~Zb{982ncd@Q?I~=;+)#};Y>~`o%S9iyTW{=a=Vb->e z7K^E&&Do_p-L8%9=1rRE24|PY?OfmOact1e4((}k=r&iUgGsYTJ3V@{v%Oufcj)de zM{BpY-E88hUTtfrUfI~7tt*=JYHMAcbwxu{F-JXZF1|V*aD){(H+8l<(TgYU<_^ym z?P@hGUshL9&3S9N&2DRG(k{2Iv^A_)R$s3xSJr8(US+LouvIkLt#x`;W8JEi^~)?; z*Ao-2Sxi+c8g-SU!{Kgj*Q>hMw>w+3-Pz*k=yK>*RBdt*^9F~f+1cJ@F&%y`J~(?; zc2;hl&dpnzlb@AcbojyaBQw1fuKz!g!@gk9cU&JE2pt*l_4oVqfNzk+;Lw0Cc-%iU zcwC>k+2$&|u$40JR8vpdl zs1Ec6^u*=SbK}F|_3+pydVJ#Y$neP6$fZl;7xc#?W1|*5yu1&;LwzSs`-6ew`t4Ak p-)|EAp|^u*4g}u~4fOlo2?X?De`shRFyz-?pLVibR(Na7zX8!Wh0_24 diff --git a/src/ChangeLog b/src/ChangeLog index 29f99623..acbc0331 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,117 @@ +2000-11-19 Hrvoje Niksic + + * retr.c (get_contents): If use_expected, make sure that the + appropriate amount of data is being read. + + * http.c (gethttp): Check for both `Keep-Alive: ...' and + `Connection: Keep-Alive'. + + * wget.h (DEBUGP): Call debug_logprintf only if opt.debug is + turned on. + +2000-11-19 Hrvoje Niksic + + * http.c (connection_available_p): Use it. + + * connect.c (test_socket_open): New function. + + * http.c (gethttp): Support persistent connections. Based on the + ideas, and partly on code, by Sam Horrocks . + (register_persistent): New function. + (connection_available_p): Ditto. + (invalidate_connection): Ditto. + +2000-11-19 Hrvoje Niksic + + * url.c (convert_links): Handle UREL2ABS case. + + * recur.c (recursive_retrieve): Instead of the list + urls_downloaded, use hash tables dl_file_url_map and + dl_url_file_map. + (convert_all_links): Use them to retrieve data. + + * host.c (clean_hosts): Free the hash tables. + + * main.c (private_initialize): Call host_init(). + + * host.c (store_hostaddress): Use a saner, hash table-based data + model. + (realhost): Ditto. + (host_init): Initialize the hash tables. + +2000-11-18 Hrvoje Niksic + + * utils.c (slist_append): Eviscerate NOSORT. Hash tables are now + used for what the sorted slists used to be used for. + (slist_contains): Don't rely on the list being sorted. + (slist_append): Simplify the code. + + * recur.c (recursive_cleanup): Use free_string_set. + + * utils.c (string_set_add, string_set_exists, string_set_free): + New functions for easier freeing of hash tables whose keys are + strdup'ed strings. + + * recur.c (recursive_retrieve): Use the hash table functions for + storing undesirable URLs. + + * hash.c: New file. + +2000-11-17 Hrvoje Niksic + + * main.c (private_initialize): Call url_init. + (main): Call private_initialize. + + * url.c (unsafe_char_table): New table. + (UNSAFE_CHAR): Use it. + (init_unsafe_char_table): New function. + (url_init): New function; call init_unsafe_char_table. + +2000-11-15 Hrvoje Niksic + + * html-url.c (handle_link): Handle HTML fragment identifiers. + + * recur.c (recursive_retrieve): If norobot info is respected and + the file is specified not to be followed by robots, respect that. + + * html-url.c (collect_tags_mapper): Handle . For us the important cases are where X is NONE or + where X contains NOFOLLOW. + (get_urls_html): Propagate that information to the caller. + +2000-11-13 Hrvoje Niksic + + * url.c (convert_links): Unlink the file we might be reading from + before writing to it. + (convert_links): Use alloca instead of malloc for + filename_plus_orig_suffix. + +2000-11-10 Hrvoje Niksic + + * url.c (get_urls_file): Ditto. + (convert_links): Ditto. + + * html-url.c (get_urls_html): Use read_file() instead of + load_file(). + + * utils.c (read_file): New function, instead of the old + load_file(). + (read_file_free): Ditto. + + * url.c (findurl): Search only for the supported protocols. + (convert_links): Use fwrite() when writing out a region of + characters. + +2000-11-10 Hrvoje Niksic + + * ftp-ls.c: Move html_quote_string and ftp_index here. + + * url.c: Remove get_urls_html, since that's now in html-url.c. + + * html-url.c: New file. + + * html-parse.c: New file. + 2000-11-16 Hrvoje Niksic * mswindows.h: Define snprintf and vsnprintf to _snprintf and diff --git a/src/Makefile.in b/src/Makefile.in index e3b433b0..bfe9868d 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -57,9 +57,10 @@ MD5_OBJ = @MD5_OBJ@ OPIE_OBJ = @OPIE_OBJ@ OBJ = $(ALLOCA) cmpt$o connect$o fnmatch$o ftp$o ftp-basic$o \ - ftp-ls$o $(OPIE_OBJ) getopt$o headers$o host$o html$o \ - http$o init$o log$o main$o $(MD5_OBJ) netrc$o rbuf$o \ - recur$o retr$o snprintf$o url$o utils$o version$o + ftp-ls$o $(OPIE_OBJ) getopt$o hash$o headers$o host$o \ + html-parse$o html-url$o http$o init$o log$o main$o \ + $(MD5_OBJ) netrc$o rbuf$o recur$o retr$o snprintf$o \ + url$o utils$o version$o .SUFFIXES: .SUFFIXES: .c .o ._c ._o @@ -133,26 +134,31 @@ TAGS: *.c *.h # DO NOT DELETE THIS LINE -- make depend depends on it. -cmpt$o: config.h wget.h sysdep.h options.h -connect$o: config.h wget.h sysdep.h options.h connect.h host.h -fnmatch$o: config.h wget.h sysdep.h options.h fnmatch.h -ftp-basic$o: config.h wget.h sysdep.h options.h utils.h rbuf.h connect.h host.h -ftp-ls$o: config.h wget.h sysdep.h options.h utils.h ftp.h rbuf.h -ftp-opie$o: config.h wget.h sysdep.h options.h md5.h -ftp$o: config.h wget.h sysdep.h options.h utils.h url.h rbuf.h retr.h ftp.h html.h connect.h host.h fnmatch.h netrc.h -getopt$o: wget.h sysdep.h options.h -headers$o: config.h wget.h sysdep.h options.h connect.h rbuf.h headers.h -host$o: config.h wget.h sysdep.h options.h utils.h host.h url.h -html$o: config.h wget.h sysdep.h options.h url.h utils.h ftp.h rbuf.h html.h -http$o: config.h wget.h sysdep.h options.h utils.h url.h host.h rbuf.h retr.h headers.h connect.h fnmatch.h netrc.h -init$o: config.h wget.h sysdep.h options.h utils.h init.h host.h recur.h netrc.h -log$o: config.h wget.h sysdep.h options.h utils.h -main$o: config.h wget.h sysdep.h options.h utils.h getopt.h init.h retr.h rbuf.h recur.h host.h -md5$o: wget.h sysdep.h options.h md5.h -mswindows$o: config.h winsock.h wget.h sysdep.h options.h url.h -netrc$o: wget.h sysdep.h options.h utils.h netrc.h init.h -rbuf$o: config.h wget.h sysdep.h options.h rbuf.h connect.h -recur$o: config.h wget.h sysdep.h options.h url.h recur.h utils.h retr.h rbuf.h ftp.h fnmatch.h host.h -retr$o: config.h wget.h sysdep.h options.h utils.h retr.h rbuf.h url.h recur.h ftp.h host.h connect.h -url$o: config.h wget.h sysdep.h options.h utils.h url.h host.h html.h -utils$o: config.h wget.h sysdep.h options.h utils.h fnmatch.h +cmpt$o: wget.h +connect$o: wget.h connect.h host.h +fnmatch$o: wget.h fnmatch.h +ftp-basic$o: wget.h utils.h rbuf.h connect.h host.h +ftp-ls$o: wget.h utils.h ftp.h url.h +ftp-opie$o: wget.h md5.h +ftp$o: wget.h utils.h url.h rbuf.h retr.h ftp.h connect.h host.h fnmatch.h netrc.h +getopt$o: wget.h getopt.h +hash$o: wget.h utils.h hash.h +headers$o: wget.h connect.h rbuf.h headers.h +host$o: wget.h utils.h host.h url.h hash.h +html-parse$o: wget.h html-parse.h +html-url$o: wget.h html-parse.h url.h utils.h +html$o: wget.h url.h utils.h ftp.h +http$o: wget.h utils.h url.h host.h rbuf.h retr.h headers.h connect.h fnmatch.h netrc.h md5.h +init$o: wget.h utils.h init.h host.h recur.h netrc.h +log$o: wget.h utils.h +main$o: wget.h utils.h getopt.h init.h retr.h recur.h host.h +md5$o: wget.h md5.h +mswindows$o: wget.h url.h +netrc$o: wget.h utils.h netrc.h init.h +rbuf$o: wget.h rbuf.h connect.h +recur$o: wget.h url.h recur.h utils.h retr.h ftp.h fnmatch.h host.h hash.h +retr$o: wget.h utils.h retr.h url.h recur.h ftp.h host.h connect.h hash.h +snprintf$o: +url$o: wget.h utils.h url.h host.h +utils$o: wget.h utils.h fnmatch.h hash.h +version$o: diff --git a/src/config.h.in b/src/config.h.in index 2038acde..ed200e32 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -101,6 +101,9 @@ char *alloca (); /* Define if you have the uname function. */ #undef HAVE_UNAME +/* Define if you have a working version of mmap. */ +#undef HAVE_MMAP + /* Define if you have the gethostname function. */ #undef HAVE_GETHOSTNAME diff --git a/src/connect.c b/src/connect.c index 28ce2043..feb2bb52 100644 --- a/src/connect.c +++ b/src/connect.c @@ -107,6 +107,37 @@ make_connection (int *sock, char *hostname, unsigned short port) return NOCONERROR; } +int +test_socket_open (int sock) +{ +#ifdef HAVE_SELECT + fd_set check_set; + struct timeval to; + + /* Check if we still have a valid (non-EOF) connection. From Andrew + * Maholski's code in the Unix Socket FAQ. */ + + FD_ZERO (&check_set); + FD_SET (sock, &check_set); + + /* Wait one microsecond */ + to.tv_sec = 0; + to.tv_usec = 1; + + /* If we get a timeout, then that means still connected */ + if (select (sock + 1, &check_set, NULL, NULL, &to) == 0) + { + /* Connection is valid (not EOF), so continue */ + return 1; + } + else + return 0; +#else + /* Without select, it's hard to know for sure. */ + return 1; +#endif +} + /* Bind the local port PORT. This does all the necessary work, which is creating a socket, setting SO_REUSEADDR option on it, then calling bind() and listen(). If *PORT is 0, a random port is diff --git a/src/ftp-ls.c b/src/ftp-ls.c index 16a7f7d6..884cf3d8 100644 --- a/src/ftp-ls.c +++ b/src/ftp-ls.c @@ -36,6 +36,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "wget.h" #include "utils.h" #include "ftp.h" +#include "url.h" /* Converts symbolic permissions to number-style ones, e.g. string rwxr-xr-x to 755. For now, it knows nothing of @@ -388,3 +389,175 @@ ftp_parse_ls (const char *file) { return ftp_parse_unix_ls (file); } + +/* Stuff for creating FTP index. */ + +/* The function returns the pointer to the malloc-ed quoted version of + string s. It will recognize and quote numeric and special graphic + entities, as per RFC1866: + + `&' -> `&' + `<' -> `<' + `>' -> `>' + `"' -> `"' + + No other entities are recognized or replaced. */ +static char * +html_quote_string (const char *s) +{ + const char *b = s; + char *p, *res; + int i; + + /* Pass through the string, and count the new size. */ + for (i = 0; *s; s++, i++) + { + if (*s == '&') + i += 4; /* `amp;' */ + else if (*s == '<' || *s == '>') + i += 3; /* `lt;' and `gt;' */ + else if (*s == '\"') + i += 5; /* `quot;' */ + } + res = (char *)xmalloc (i + 1); + s = b; + for (p = res; *s; s++) + { + switch (*s) + { + case '&': + *p++ = '&'; + *p++ = 'a'; + *p++ = 'm'; + *p++ = 'p'; + *p++ = ';'; + break; + case '<': case '>': + *p++ = '&'; + *p++ = (*s == '<' ? 'l' : 'g'); + *p++ = 't'; + *p++ = ';'; + break; + case '\"': + *p++ = '&'; + *p++ = 'q'; + *p++ = 'u'; + *p++ = 'o'; + *p++ = 't'; + *p++ = ';'; + break; + default: + *p++ = *s; + } + } + *p = '\0'; + return res; +} + +/* The function creates an HTML index containing references to given + directories and files on the appropriate host. The references are + FTP. */ +uerr_t +ftp_index (const char *file, struct urlinfo *u, struct fileinfo *f) +{ + FILE *fp; + char *upwd; + char *htclfile; /* HTML-clean file name */ + + if (!opt.dfp) + { + fp = fopen (file, "wb"); + if (!fp) + { + logprintf (LOG_NOTQUIET, "%s: %s\n", file, strerror (errno)); + return FOPENERR; + } + } + else + fp = opt.dfp; + if (u->user) + { + char *tmpu, *tmpp; /* temporary, clean user and passwd */ + + tmpu = CLEANDUP (u->user); + tmpp = u->passwd ? CLEANDUP (u->passwd) : NULL; + upwd = (char *)xmalloc (strlen (tmpu) + + (tmpp ? (1 + strlen (tmpp)) : 0) + 2); + sprintf (upwd, "%s%s%s@", tmpu, tmpp ? ":" : "", tmpp ? tmpp : ""); + free (tmpu); + FREE_MAYBE (tmpp); + } + else + upwd = xstrdup (""); + fprintf (fp, "\n"); + fprintf (fp, "\n\n"); + fprintf (fp, _("Index of /%s on %s:%d"), u->dir, u->host, u->port); + fprintf (fp, "\n\n\n

"); + fprintf (fp, _("Index of /%s on %s:%d"), u->dir, u->host, u->port); + fprintf (fp, "

\n
\n
\n");
+  while (f)
+    {
+      fprintf (fp, "  ");
+      if (f->tstamp != -1)
+	{
+	  /* #### Should we translate the months? */
+	  static char *months[] = {
+	    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+	    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+	  };
+	  struct tm *ptm = localtime ((time_t *)&f->tstamp);
+
+	  fprintf (fp, "%d %s %02d ", ptm->tm_year + 1900, months[ptm->tm_mon],
+		  ptm->tm_mday);
+	  if (ptm->tm_hour)
+	    fprintf (fp, "%02d:%02d  ", ptm->tm_hour, ptm->tm_min);
+	  else
+	    fprintf (fp, "       ");
+	}
+      else
+	fprintf (fp, _("time unknown       "));
+      switch (f->type)
+	{
+	case FT_PLAINFILE:
+	  fprintf (fp, _("File        "));
+	  break;
+	case FT_DIRECTORY:
+	  fprintf (fp, _("Directory   "));
+	  break;
+	case FT_SYMLINK:
+	  fprintf (fp, _("Link        "));
+	  break;
+	default:
+	  fprintf (fp, _("Not sure    "));
+	  break;
+	}
+      htclfile = html_quote_string (f->name);
+      fprintf (fp, "host, u->port);
+      if (*u->dir != '/')
+	putc ('/', fp);
+      fprintf (fp, "%s", u->dir);
+      if (*u->dir)
+	putc ('/', fp);
+      fprintf (fp, "%s", htclfile);
+      if (f->type == FT_DIRECTORY)
+	putc ('/', fp);
+      fprintf (fp, "\">%s", htclfile);
+      if (f->type == FT_DIRECTORY)
+	putc ('/', fp);
+      fprintf (fp, " ");
+      if (f->type == FT_PLAINFILE)
+	fprintf (fp, _(" (%s bytes)"), legible (f->size));
+      else if (f->type == FT_SYMLINK)
+	fprintf (fp, "-> %s", f->linkto ? f->linkto : "(nil)");
+      putc ('\n', fp);
+      free (htclfile);
+      f = f->next;
+    }
+  fprintf (fp, "
\n\n\n"); + free (upwd); + if (!opt.dfp) + fclose (fp); + else + fflush (fp); + return FTPOK; +} diff --git a/src/ftp.c b/src/ftp.c index 4c26cf7d..aa283cf8 100644 --- a/src/ftp.c +++ b/src/ftp.c @@ -40,7 +40,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "rbuf.h" #include "retr.h" #include "ftp.h" -#include "html.h" #include "connect.h" #include "host.h" #include "fnmatch.h" @@ -722,7 +721,7 @@ Error in server response, closing control connection.\n")); } reset_timer (); /* Get the contents of the document. */ - res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf); + res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf, 0); con->dltime = elapsed_time (); tms = time_str (NULL); tmrate = rate (*len - restval, con->dltime); diff --git a/src/ftp.h b/src/ftp.h index c2e6d44c..064e6354 100644 --- a/src/ftp.h +++ b/src/ftp.h @@ -92,4 +92,6 @@ typedef struct struct fileinfo *ftp_parse_ls PARAMS ((const char *)); uerr_t ftp_loop PARAMS ((struct urlinfo *, int *)); +uerr_t ftp_index (const char *, struct urlinfo *, struct fileinfo *); + #endif /* FTP_H */ diff --git a/src/hash.c b/src/hash.c new file mode 100644 index 00000000..e54fb33a --- /dev/null +++ b/src/hash.c @@ -0,0 +1,403 @@ +/* Hash tables. + Copyright (C) 2000 Free Software Foundation, Inc. + +This file is part of Wget. + +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. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include "wget.h" +#include "utils.h" + +#include "hash.h" + +#ifdef STANDALONE +# define xmalloc malloc +# define xrealloc realloc +#endif + +/* This file implements simple hash tables based on linear probing. + The hash table stores key-value pairs in a contiguous array. Both + key and value are void pointers that the hash and test functions + know how to handle. + + Although Knuth & co. recommend double hashing over linear probing, + we use the latter because it accesses array elements sequentially + in case of a collision, yielding in better cache behaviour and + ultimately in better speed. To avoid collision problems with + linear probing, we make sure that the table grows as soon as the + fullness/size ratio exceeds 75%. */ + +struct ht_pair { + void *key; + void *value; +}; + +struct hash_table { + unsigned long (*hash_function) (const void *); + int (*test_function) (const void *, const void *); + + int size; /* size of the array */ + int fullness; /* number of non-empty fields */ + int count; /* number of non-empty, non-deleted + fields. */ + + struct ht_pair *pairs; +}; + +#define ENTRY_DELETED ((void *)0xdeadbeef) + +#define DELETED_ENTRY_P(ptr) ((ptr) == ENTRY_DELETED) +#define EMPTY_ENTRY_P(ptr) ((ptr) == NULL) + +/* Find a prime near, but greather than or equal to SIZE. */ + +int +prime_size (int size) +{ + static const unsigned long primes [] = { + 19, 29, 41, 59, 79, 107, 149, 197, 263, 347, 457, 599, 787, 1031, + 1361, 1777, 2333, 3037, 3967, 5167, 6719, 8737, 11369, 14783, + 19219, 24989, 32491, 42257, 54941, 71429, 92861, 120721, 156941, + 204047, 265271, 344857, 448321, 582821, 757693, 985003, 1280519, + 1664681, 2164111, 2813353, 3657361, 4754591, 6180989, 8035301, + 10445899, 13579681, 17653589, 22949669, 29834603, 38784989, + 50420551, 65546729, 85210757, 110774011, 144006217, 187208107, + 243370577, 316381771, 411296309, 534685237, 695090819, 903618083, + 1174703521, 1527114613, 1985248999, 2580823717UL, 3355070839UL + }; + int i; + for (i = 0; i < ARRAY_SIZE (primes); i++) + if (primes[i] >= size) + return primes[i]; + /* huh? */ + return size; +} + +/* Create a hash table of INITIAL_SIZE with hash function + HASH_FUNCTION and test function TEST_FUNCTION. If you wish to + start out with a "small" table which will be regrown as needed, + specify 0 as INITIAL_SIZE. */ + +struct hash_table * +hash_table_new (int initial_size, + unsigned long (*hash_function) (const void *), + int (*test_function) (const void *, const void *)) +{ + struct hash_table *ht + = (struct hash_table *)xmalloc (sizeof (struct hash_table)); + ht->hash_function = hash_function; + ht->test_function = test_function; + ht->size = prime_size (initial_size); + ht->fullness = 0; + ht->count = 0; + ht->pairs = xmalloc (ht->size * sizeof (struct ht_pair)); + memset (ht->pairs, '\0', ht->size * sizeof (struct ht_pair)); + return ht; +} + +/* Free the data associated with hash table HT. */ + +void +hash_table_destroy (struct hash_table *ht) +{ + free (ht->pairs); + free (ht); +} + +/* Get the value that corresponds to the key KEY in the hash table HT. + If no value is found, return NULL. Note that NULL is a legal value + for value; if you are storing NULLs in your hash table, you can use + hash_table_exists to be sure that a (possibly NULL) value exists in + the table. */ + +void * +hash_table_get (struct hash_table *ht, const void *key) +{ + int location = ht->hash_function (key) % ht->size; + while (1) + { + struct ht_pair *the_pair = ht->pairs + location; + if (EMPTY_ENTRY_P (the_pair->key)) + return NULL; + else if (DELETED_ENTRY_P (the_pair->key) + || !ht->test_function (key, the_pair->key)) + { + ++location; + if (location == ht->size) + location = 0; + } + else + return the_pair->value; + } +} + +/* Return 1 if KEY exists in HT, 0 otherwise. */ + +int +hash_table_exists (struct hash_table *ht, const void *key) +{ + int location = ht->hash_function (key) % ht->size; + while (1) + { + struct ht_pair *the_pair = ht->pairs + location; + if (EMPTY_ENTRY_P (the_pair->key)) + return 0; + else if (DELETED_ENTRY_P (the_pair->key) + || !ht->test_function (key, the_pair->key)) + { + ++location; + if (location == ht->size) + location = 0; + } + else + return 1; + } +} + +#define MAX(i, j) (((i) >= (j)) ? (i) : (j)) + +/* Grow hash table HT as necessary, and rehash all the key-value + pairs. */ + +static void +grow_hash_table (struct hash_table *ht) +{ + int i; + struct ht_pair *old_pairs = ht->pairs; + int old_count = ht->count; /* for assert() below */ + int old_size = ht->size; + + /* Normally, the idea is to double ht->size (and round it to next + prime) on each regrow: + + ht->size = prime_size (ht->size * 2); + + But it is possible that the table has large fullness because of + the many deleted entries. If that is the case, we don't want to + blindly grow the table; we just want to rehash it. For that + reason, we use ht->count as the relevant parameter. MAX is used + only because we don't want to actually shrink the table. (But + maybe that's wrong.) */ + + int needed_size = prime_size (ht->count * 2); + ht->size = MAX (old_size, needed_size); + + ht->pairs = xmalloc (ht->size * sizeof (struct ht_pair)); + memset (ht->pairs, '\0', ht->size * sizeof (struct ht_pair)); + + /* Need to reset these two; hash_table_put will reinitialize them. */ + ht->fullness = 0; + ht->count = 0; + for (i = 0; i < old_size; i++) + { + struct ht_pair *the_pair = old_pairs + i; + if (!EMPTY_ENTRY_P (the_pair->key) + && !DELETED_ENTRY_P (the_pair->key)) + hash_table_put (ht, the_pair->key, the_pair->value); + } + assert (ht->count == old_count); + free (old_pairs); +} + +/* Put VALUE in the hash table HT under the key KEY. This regrows the + table if necessary. */ + +void +hash_table_put (struct hash_table *ht, const void *key, void *value) +{ + int location = ht->hash_function (key) % ht->size; + while (1) + { + struct ht_pair *the_pair = ht->pairs + location; + if (EMPTY_ENTRY_P (the_pair->key)) + { + ++ht->fullness; + ++ht->count; + just_insert: + the_pair->key = (void *)key; /* const? */ + the_pair->value = value; + break; + } + else if (DELETED_ENTRY_P (the_pair->key)) + { + /* We're replacing a deleteed entry, so ht->count gets + increased, but ht->fullness remains unchanged. */ + ++ht->count; + goto just_insert; + } + else if (ht->test_function (key, the_pair->key)) + { + /* We're replacing an existing entry, so ht->count and + ht->fullness remain unchanged. */ + goto just_insert; + } + else + { + ++location; + if (location == ht->size) + location = 0; + } + } + if (ht->fullness * 4 > ht->size * 3) + /* When fullness exceeds 75% of size, regrow the table. */ + grow_hash_table (ht); +} + +/* Remove KEY from HT. */ + +int +hash_table_remove (struct hash_table *ht, const void *key) +{ + int location = ht->hash_function (key) % ht->size; + while (1) + { + struct ht_pair *the_pair = ht->pairs + location; + if (EMPTY_ENTRY_P (the_pair->key)) + return 0; + else if (DELETED_ENTRY_P (the_pair->key) + || !ht->test_function (key, the_pair->key)) + { + ++location; + if (location == ht->size) + location = 0; + } + else + { + /* We don't really remove an entry from the hash table: we + just mark it as deleted. This is because there may be + other entries located after this entry whose hash number + points to a location before this entry. (Example: keys + A, B and C have the same hash. If you were to really + *delete* B from the table, C could no longer be found.) + + As an optimization, it might be worthwhile to check + whether the immediately preceding entry is empty and, if + so, really delete the pair (set it to empty and decrease + the fullness along with the count). I *think* it should + be safe. */ + the_pair->key = ENTRY_DELETED; + --ht->count; + return 1; + } + } +} + +void +hash_table_clear (struct hash_table *ht) +{ + memset (ht->pairs, '\0', ht->size * sizeof (struct ht_pair)); + ht->fullness = 0; + ht->count = 0; +} + +void +hash_table_map (struct hash_table *ht, + int (*mapfun) (void *, void *, void *), + void *closure) +{ + int i; + for (i = 0; i < ht->size; i++) + { + struct ht_pair *the_pair = ht->pairs + i; + if (!EMPTY_ENTRY_P (the_pair->key) + && !DELETED_ENTRY_P (the_pair->key)) + if (mapfun (the_pair->key, the_pair->value, closure)) + return; + } +} + +/* Support for hash tables whose keys are strings. */ + +/* supposedly from the Dragon Book P436. */ +unsigned long +string_hash (const void *sv) +{ + unsigned int h = 0; + unsigned const char *x = (unsigned const char *) sv; + + while (*x) + { + unsigned int g; + h = (h << 4) + *x++; + if ((g = h & 0xf0000000) != 0) + h = (h ^ (g >> 24)) ^ g; + } + + return h; +} + +int +string_cmp (const void *s1, const void *s2) +{ + return !strcmp ((const char *)s1, (const char *)s2); +} + +struct hash_table * +make_string_hash_table (int initial_size) +{ + return hash_table_new (initial_size, string_hash, string_cmp); +} + + +#ifdef STANDALONE + +#include +#include + +int +print_hash_table_mapper (const void *key, void *value, void *count) +{ + ++*(int *)count; + printf ("%s: %s\n", (const char *)key, (char *)value); + return 0; +} + +void +print_hash (struct hash_table *sht) +{ + int debug_count = 0; + hash_table_map (sht, print_hash_table_mapper, &debug_count); + assert (debug_count == sht->count); +} + +int +main (void) +{ + struct hash_table *ht = make_string_hash_table (0); + char line[80]; + while ((fgets (line, sizeof (line), stdin))) + { + int len = strlen (line); + if (len <= 1) + continue; + line[--len] = '\0'; + hash_table_put (ht, strdup (line), "here I am!"); + if (len % 2) + hash_table_remove (ht, line); + } + print_hash (ht); +#if 0 + printf ("%d %d %d\n", ht->count, ht->fullness, ht->size); +#endif + return 0; +} +#endif diff --git a/src/hash.h b/src/hash.h new file mode 100644 index 00000000..ab3136aa --- /dev/null +++ b/src/hash.h @@ -0,0 +1,50 @@ +/* Hash table declarations. + Copyright (C) 2000 Free Software Foundation, Inc. + +This file is part of Wget. + +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. */ + +/* From XEmacs, and hence from Dragon book. */ + +#define GOOD_HASH 65599 /* prime number just over 2^16; Dragon book, p. 435 */ +#define HASH2(a,b) (GOOD_HASH * (a) + (b)) +#define HASH3(a,b,c) (GOOD_HASH * HASH2 (a,b) + (c)) +#define HASH4(a,b,c,d) (GOOD_HASH * HASH3 (a,b,c) + (d)) +#define HASH5(a,b,c,d,e) (GOOD_HASH * HASH4 (a,b,c,d) + (e)) +#define HASH6(a,b,c,d,e,f) (GOOD_HASH * HASH5 (a,b,c,d,e) + (f)) +#define HASH7(a,b,c,d,e,f,g) (GOOD_HASH * HASH6 (a,b,c,d,e,f) + (g)) +#define HASH8(a,b,c,d,e,f,g,h) (GOOD_HASH * HASH7 (a,b,c,d,e,f,g) + (h)) +#define HASH9(a,b,c,d,e,f,g,h,i) (GOOD_HASH * HASH8 (a,b,c,d,e,f,g,h) + (i)) + +struct hash_table; + +struct hash_table *hash_table_new PARAMS ((int, + unsigned long (*) (const void *), + int (*) (const void *, + const void *))); +void hash_table_destroy PARAMS ((struct hash_table *)); +void *hash_table_get PARAMS ((struct hash_table *, const void *)); +int hash_table_exists PARAMS ((struct hash_table *, const void *)); +void hash_table_put PARAMS ((struct hash_table *, const void *, void *)); +int hash_table_remove PARAMS ((struct hash_table *, const void *)); +void hash_table_clear PARAMS ((struct hash_table *)); +void hash_table_map PARAMS ((struct hash_table *, + int (*) (void *, void *, void *), + void *)); + +unsigned long string_hash PARAMS ((const void *)); +int string_cmp PARAMS ((const void *, const void *)); +struct hash_table *make_string_hash_table PARAMS ((int)); diff --git a/src/headers.c b/src/headers.c index 6b1a670f..521073df 100644 --- a/src/headers.c +++ b/src/headers.c @@ -165,6 +165,14 @@ header_strdup (const char *header, void *closure) return 1; } +/* Write the value 1 into the integer pointed to by CLOSURE. */ +int +header_exists (const char *header, void *closure) +{ + *(int *)closure = 1; + return 1; +} + /* Skip LWS (linear white space), if present. Returns number of characters to skip. */ int diff --git a/src/headers.h b/src/headers.h index cc66e49b..5f85c6eb 100644 --- a/src/headers.h +++ b/src/headers.h @@ -31,5 +31,6 @@ int header_process PARAMS ((const char *, const char *, int header_extract_number PARAMS ((const char *, void *)); int header_strdup PARAMS ((const char *, void *)); +int header_exists PARAMS ((const char *, void *)); int skip_lws PARAMS ((const char *)); diff --git a/src/host.c b/src/host.c index 3fa1bb84..eeb4940d 100644 --- a/src/host.c +++ b/src/host.c @@ -1,5 +1,5 @@ /* Dealing with host names. - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 1995, 1996, 1997, 2000 Free Software Foundation, Inc. This file is part of Wget. @@ -48,35 +48,38 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "utils.h" #include "host.h" #include "url.h" +#include "hash.h" #ifndef errno extern int errno; #endif -/* Host list entry */ -struct host +/* Mapping between all known hosts to their addresses (n.n.n.n). */ +struct hash_table *host_name_address_map; + +/* Mapping between all known addresses (n.n.n.n) to their hosts. This + is the inverse of host_name_address_map. These two tables share + the strdup'ed strings. */ +struct hash_table *host_address_name_map; + +/* Mapping between auxilliary (slave) and master host names. */ +struct hash_table *host_slave_master_map; + +/* Utility function: like xstrdup(), but also lowercases S. */ + +static char * +xstrdup_lower (const char *s) { - /* Host's symbolical name, as encountered at the time of first - inclusion, e.g. "fly.cc.fer.hr". */ - char *hostname; - /* Host's "real" name, i.e. its IP address, written out in ASCII - form of N.N.N.N, e.g. "161.53.70.130". */ - char *realname; - /* More than one HOSTNAME can correspond to the same REALNAME. For - our purposes, the canonical name of the host is its HOSTNAME when - it was first encountered. This entry is said to have QUALITY. */ - int quality; - /* Next entry in the list. */ - struct host *next; -}; - -static struct host *hlist; - -static struct host *add_hlist PARAMS ((struct host *, const char *, - const char *, int)); + char *copy = xstrdup (s); + char *p = copy; + for (; *p; p++) + *p = TOLOWER (*p); + return copy; +} /* The same as gethostbyname, but supports internet addresses of the - form `N.N.N.N'. */ + form `N.N.N.N'. On some systems gethostbyname() knows how to do + this automatically. */ struct hostent * ngethostbyname (const char *name) { @@ -91,42 +94,51 @@ ngethostbyname (const char *name) return hp; } -/* Search for HOST in the linked list L, by hostname. Return the - entry, if found, or NULL. The search is case-insensitive. */ -static struct host * -search_host (struct host *l, const char *host) -{ - for (; l; l = l->next) - if (strcasecmp (l->hostname, host) == 0) - return l; - return NULL; -} +/* Add host name HOST with the address ADDR_TEXT to the cache. + Normally this means that the (HOST, ADDR_TEXT) pair will be to + host_name_address_map and to host_address_name_map. (It is the + caller's responsibility to make sure that HOST is not already in + host_name_address_map.) -/* Like search_host, but searches by address. */ -static struct host * -search_address (struct host *l, const char *address) + If the ADDR_TEXT has already been seen and belongs to another host, + HOST will be added to host_slave_master_map instead. */ + +static void +add_host_to_cache (const char *host, const char *addr_text) { - for (; l; l = l->next) + char *canonical_name = hash_table_get (host_address_name_map, addr_text); + if (canonical_name) + { + DEBUGP (("Mapping %s to %s in host_slave_master_map.\n", + host, canonical_name)); + /* We've already dealt with that host under another name. */ + hash_table_put (host_slave_master_map, + xstrdup_lower (host), + xstrdup_lower (canonical_name)); + } + else { - int cmp = strcmp (l->realname, address); - if (cmp == 0) - return l; - else if (cmp > 0) - return NULL; + /* This is really the first time we're dealing with that host. */ + char *h_copy = xstrdup_lower (host); + char *a_copy = xstrdup (addr_text); + DEBUGP (("Caching %s <-> %s\n", h_copy, a_copy)); + hash_table_put (host_name_address_map, h_copy, a_copy); + hash_table_put (host_address_name_map, a_copy, h_copy); } - return NULL; } -/* Store the address of HOSTNAME, internet-style, to WHERE. First - check for it in the host list, and (if not found), use - ngethostbyname to get it. +/* Store the address of HOSTNAME, internet-style (four octets in + network order), to WHERE. First try to get the address from the + cache; if it is not available, call the DNS functions and update + the cache. Return 1 on successful finding of the hostname, 0 otherwise. */ int store_hostaddress (unsigned char *where, const char *hostname) { - struct host *t; unsigned long addr; + char *addr_text; + char *canonical_name; struct hostent *hptr; struct in_addr in; char *inet_s; @@ -134,178 +146,119 @@ store_hostaddress (unsigned char *where, const char *hostname) /* If the address is of the form d.d.d.d, there will be no trouble with it. */ addr = (unsigned long)inet_addr (hostname); - if ((int)addr == -1) - { - /* If it is not of that form, try to find it in the cache. */ - t = search_host (hlist, hostname); - if (t) - addr = (unsigned long)inet_addr (t->realname); - } /* If we have the numeric address, just store it. */ if ((int)addr != -1) { - /* ADDR is in network byte order, meaning the code works on - little and big endian 32-bit architectures without change. - On big endian 64-bit architectures we need to be careful to - copy the correct four bytes. */ - int offset = 0; + /* ADDR is defined to be in network byte order, meaning the code + works on little and big endian 32-bit architectures without + change. On big endian 64-bit architectures we need to be + careful to copy the correct four bytes. */ + int offset; + have_addr: #ifdef WORDS_BIGENDIAN offset = sizeof (unsigned long) - 4; +#else + offset = 0; #endif memcpy (where, (char *)&addr + offset, 4); return 1; } + + /* By now we know that the address is not of the form d.d.d.d. Try + to find it in our cache of host addresses. */ + addr_text = hash_table_get (host_name_address_map, hostname); + if (addr_text) + { + DEBUGP (("Found %s in host_name_address_map: %s\n", + hostname, addr_text)); + addr = (unsigned long)inet_addr (addr_text); + goto have_addr; + } + + /* Maybe this host is known to us under another name. If so, we'll + find it in host_slave_master_map, and use the master name to find + its address in host_name_address_map. */ + canonical_name = hash_table_get (host_slave_master_map, hostname); + if (canonical_name) + { + addr_text = hash_table_get (host_name_address_map, canonical_name); + assert (addr_text != NULL); + DEBUGP (("Found %s as slave of %s -> %s\n", + hostname, canonical_name, addr_text)); + addr = (unsigned long)inet_addr (addr_text); + goto have_addr; + } + /* Since all else has failed, let's try gethostbyname(). Note that we use gethostbyname() rather than ngethostbyname(), because we - *know* the address is not numerical. */ + already know that the address is not numerical. */ hptr = gethostbyname (hostname); if (!hptr) return 0; /* Copy the address of the host to socket description. */ memcpy (where, hptr->h_addr_list[0], hptr->h_length); - /* Now that we're here, we could as well cache the hostname for - future use, as in realhost(). First, we have to look for it by - address to know if it's already in the cache by another name. */ + assert (hptr->h_length == 4); + /* Now that we've gone through the truoble of calling + gethostbyname(), we can store this valuable information to the + cache. First, we have to look for it by address to know if it's + already in the cache by another name. */ /* Originally, we copied to in.s_addr, but it appears to be missing on some systems. */ memcpy (&in, *hptr->h_addr_list, sizeof (in)); - STRDUP_ALLOCA (inet_s, inet_ntoa (in)); - t = search_address (hlist, inet_s); - if (t) /* Found in the list, as realname. */ - { - /* Set the default, 0 quality. */ - hlist = add_hlist (hlist, hostname, inet_s, 0); - return 1; - } - /* Since this is really the first time this host is encountered, - set quality to 1. */ - hlist = add_hlist (hlist, hostname, inet_s, 1); + inet_s = inet_ntoa (in); + add_host_to_cache (hostname, inet_s); return 1; } -/* Add a host to the host list. The list is sorted by addresses. For - equal addresses, the entries with quality should bubble towards the - beginning of the list. */ -static struct host * -add_hlist (struct host *l, const char *nhost, const char *nreal, int quality) -{ - struct host *t, *old, *beg; - - /* The entry goes to the beginning of the list if the list is empty - or the order requires it. */ - if (!l || (strcmp (nreal, l->realname) < 0)) - { - t = (struct host *)xmalloc (sizeof (struct host)); - t->hostname = xstrdup (nhost); - t->realname = xstrdup (nreal); - t->quality = quality; - t->next = l; - return t; - } - - beg = l; - /* Second two one-before-the-last element. */ - while (l->next) - { - int cmp; - old = l; - l = l->next; - cmp = strcmp (nreal, l->realname); - if (cmp >= 0) - continue; - /* If the next list element is greater than s, put s between the - current and the next list element. */ - t = (struct host *)xmalloc (sizeof (struct host)); - old->next = t; - t->next = l; - t->hostname = xstrdup (nhost); - t->realname = xstrdup (nreal); - t->quality = quality; - return beg; - } - t = (struct host *)xmalloc (sizeof (struct host)); - t->hostname = xstrdup (nhost); - t->realname = xstrdup (nreal); - t->quality = quality; - /* Insert the new element after the last element. */ - l->next = t; - t->next = NULL; - return beg; -} - /* Determine the "real" name of HOST, as perceived by Wget. If HOST is referenced by more than one name, "real" name is considered to - be the first one encountered in the past. - - If the host cannot be found in the list of already dealt-with - hosts, try with its INET address. If this fails too, add it to the - list. The routine does not call gethostbyname twice for the same - host if it can possibly avoid it. */ + be the first one encountered in the past. */ char * realhost (const char *host) { - struct host *l, *l_real; struct in_addr in; struct hostent *hptr; - char *inet_s; + char *master_name; - DEBUGP (("Checking for %s.\n", host)); - /* Look for the host, looking by the host name. */ - l = search_host (hlist, host); - if (l && l->quality) /* Found it with quality */ + DEBUGP (("Checking for %s in host_name_address_map.\n", host)); + if (hash_table_exists (host_name_address_map, host)) { - DEBUGP (("%s was already used, by that name.\n", host)); - /* Here we return l->hostname, not host, because of the possible - case differences (e.g. jaGOR.srce.hr and jagor.srce.hr are - the same, but we want the one that was first. */ - return xstrdup (l->hostname); + DEBUGP (("Found; %s was already used, by that name.\n", host)); + return xstrdup_lower (host); } - else if (!l) /* Not found, with or without quality */ - { - /* The fact that gethostbyname will get called makes it - necessary to store it to the list, to ensure that - gethostbyname will not be called twice for the same string. - However, the quality argument must be set appropriately. - - Note that add_hlist must be called *after* the realname - search, or the quality would be always set to 0 */ - DEBUGP (("This is the first time I hear about host %s by that name.\n", - host)); - hptr = ngethostbyname (host); - if (!hptr) - return xstrdup (host); - /* Originally, we copied to in.s_addr, but it appears to be - missing on some systems. */ - memcpy (&in, *hptr->h_addr_list, sizeof (in)); - STRDUP_ALLOCA (inet_s, inet_ntoa (in)); - } - else /* Found, without quality */ + + DEBUGP (("Checking for %s in host_slave_master_map.\n", host)); + master_name = hash_table_get (host_slave_master_map, host); + if (master_name) { - /* This case happens when host is on the list, - but not as first entry (the one with quality). - Then we just get its INET address and pick - up the first entry with quality. */ - DEBUGP (("We've dealt with host %s, but under the name %s.\n", - host, l->realname)); - STRDUP_ALLOCA (inet_s, l->realname); + has_master: + DEBUGP (("Found; %s was already used, by the name %s.\n", + host, master_name)); + return xstrdup (master_name); } - /* Now we certainly have the INET address. The following loop is - guaranteed to pick either an entry with quality (because it is - the first one), or none at all. */ - l_real = search_address (hlist, inet_s); - if (l_real) /* Found in the list, as realname. */ + DEBUGP (("First time I hear about %s by that name; looking it up.\n", + host)); + hptr = ngethostbyname (host); + if (hptr) { - if (!l) - /* Set the default, 0 quality. */ - hlist = add_hlist (hlist, host, inet_s, 0); - return xstrdup (l_real->hostname); + char *inet_s; + /* Originally, we copied to in.s_addr, but it appears to be + missing on some systems. */ + memcpy (&in, *hptr->h_addr_list, sizeof (in)); + inet_s = inet_ntoa (in); + + add_host_to_cache (host, inet_s); + + /* add_host_to_cache() can establish a slave-master mapping. */ + DEBUGP (("Checking again for %s in host_slave_master_map.\n", host)); + master_name = hash_table_get (host_slave_master_map, host); + if (master_name) + goto has_master; } - /* Since this is really the first time this host is encountered, - set quality to 1. */ - hlist = add_hlist (hlist, host, inet_s, 1); - return xstrdup (host); + + return xstrdup_lower (host); } /* Compare two hostnames (out of URL-s if the arguments are URL-s), @@ -547,20 +500,23 @@ herrmsg (int error) return _("Unknown error"); } -/* Clean the host list. This is a separate function, so we needn't - export HLIST and its implementation. Ha! */ void clean_hosts (void) { - struct host *l = hlist; + /* host_name_address_map and host_address_name_map share the + strings. Because of that, calling free_keys_and_values once + suffices for both. */ + free_keys_and_values (host_name_address_map); + hash_table_destroy (host_name_address_map); + hash_table_destroy (host_address_name_map); + free_keys_and_values (host_slave_master_map); + hash_table_destroy (host_slave_master_map); +} - while (l) - { - struct host *p = l->next; - free (l->hostname); - free (l->realname); - free (l); - l = p; - } - hlist = NULL; +void +host_init (void) +{ + host_name_address_map = make_string_hash_table (0); + host_address_name_map = make_string_hash_table (0); + host_slave_master_map = make_string_hash_table (0); } diff --git a/src/html-parse.c b/src/html-parse.c new file mode 100644 index 00000000..b5efa7f2 --- /dev/null +++ b/src/html-parse.c @@ -0,0 +1,856 @@ +/* HTML parser for Wget. + Copyright (C) 1998, 2000 Free Software Foundation, Inc. + +This file is part of Wget. + +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. */ + +/* The only entry point to this module is map_html_tags(), which see. */ + +/* TODO: + + - Allow hooks for callers to process contents outside tags. This + is needed to implement handling