X-Git-Url: http://sjero.net/git/?a=blobdiff_plain;f=src%2Fftp.c;h=3159171f7c4caa3c26bc92d59aadf83ea0254ca0;hb=30ac043b0a4a9a983dd1b50ce1c89ed953019292;hp=6d406222a1caf901ecc4abd026b58b79c4e9eb2b;hpb=5390ada318a462655c79ef8cfc02d675bab78f7e;p=wget diff --git a/src/ftp.c b/src/ftp.c index 6d406222..3159171f 100644 --- a/src/ftp.c +++ b/src/ftp.c @@ -16,7 +16,17 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Wget; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +In addition, as a special exception, the Free Software Foundation +gives permission to link the code of its release of Wget with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. */ #include @@ -175,7 +185,7 @@ getftp (struct url *u, long *len, long restval, ccon *con) address_list_release (al); if (csock < 0) - return errno == ECONNREFUSED ? CONREFUSED : CONERROR; + return CONNECT_ERROR (errno); if (cmd & LEAVE_PENDING) rbuf_initialize (&con->rbuf, csock); @@ -383,17 +393,31 @@ Error in server response, closing control connection.\n")); /* Change working directory. To change to a non-absolute Unix directory, we need to prepend initial directory - (con->id) to it. Absolute directories "just work". */ + (con->id) to it. Absolute directories "just work". - if (*target != '/') + A relative directory is one that does not begin with '/' + and, on non-Unix OS'es, one that doesn't begin with + ":". */ + + if (target[0] != '/' + && !(con->rs != ST_UNIX + && ISALPHA (target[0]) && target[1] == ':')) { int idlen = strlen (con->id); - char *ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1); - /* idlen == 1 means con->id = "/" */ - sprintf (ntarget, "%s%s%s", con->id, idlen == 1 ? "" : "/", - target); + char *ntarget, *p; + + /* Strip trailing slash(es) from con->id. */ + while (idlen > 0 && con->id[idlen - 1] == '/') + --idlen; + p = ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1); + memcpy (p, con->id, idlen); + p += idlen; + *p++ = '/'; + strcpy (p, target); + DEBUGP (("Prepended initial PWD to relative path:\n")); - DEBUGP ((" old: '%s'\n new: '%s'\n", target, ntarget)); + DEBUGP ((" pwd: '%s'\n old: '%s'\n new: '%s'\n", + con->id, target, ntarget)); target = ntarget; } @@ -554,7 +578,7 @@ Error in server response, closing control connection.\n")); logprintf (LOG_VERBOSE, _("couldn't connect to %s:%hu: %s\n"), pretty_print_address (&passive_addr), passive_port, strerror (save_errno)); - return save_errno == ECONNREFUSED ? CONREFUSED : CONERROR; + return CONNECT_ERROR (save_errno); } pasv_mode_open = 1; /* Flag to avoid accept port */ @@ -684,6 +708,18 @@ Error in server response, closing control connection.\n")); if (cmd & DO_RETR) { + /* If we're in spider mode, don't really retrieve anything. The + fact that we got to this point should be proof enough that + the file exists, vaguely akin to HTTP's concept of a "HEAD" + request. */ + if (opt.spider) + { + CLOSE (csock); + closeport (dtsock); + rbuf_uninitialize (&con->rbuf); + return RETRFINISHED; + } + if (opt.verbose) { if (!opt.server_response) @@ -835,7 +871,7 @@ Error in server response, closing control connection.\n")); /* Rewind the output document if the download starts over and if this is the first download. See gethttp() for a longer explanation. */ - if (!restval && global_download_count == 0) + if (!restval && global_download_count == 0 && opt.dfp != stdout) { /* This will silently fail for streams that don't correspond to regular files, but that's OK. */ @@ -1557,7 +1593,7 @@ Not descending to `%s' as it is excluded/not-included.\n"), newdir); static uerr_t ftp_retrieve_glob (struct url *u, ccon *con, int action) { - struct fileinfo *orig, *start; + struct fileinfo *f, *orig, *start; uerr_t res; con->cmd |= LEAVE_PENDING; @@ -1570,8 +1606,7 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action) opt.accepts and opt.rejects. */ if (opt.accepts || opt.rejects) { - struct fileinfo *f = orig; - + f = orig; while (f) { if (f->type != FT_DIRECTORY && !acceptable (f->name)) @@ -1583,13 +1618,25 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action) f = f->next; } } + /* Remove all files with possible harmful names */ + f = orig; + while (f) + { + if (has_insecure_name_p(f->name)) + { + logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name); + f = delelement (f, &start); + } + else + f = f->next; + } /* Now weed out the files that do not match our globbing pattern. If we are dealing with a globbing pattern, that is. */ if (*u->file && (action == GLOBALL || action == GETONE)) { int matchres = 0; - struct fileinfo *f = start; + f = start; while (f) { matchres = fnmatch (u->file, f->name, 0);