On Thu, Jun 12, 2014 at 06:32:00PM +0200, Alexander Hall wrote:
> On June 11, 2014 6:18:19 AM CEST, Lawrence Teo <l...@openbsd.org> wrote:
> >This diff allows ftp(1) to change the User-Agent for HTTP(S) URL
> >requests via the FTPUSERAGENT environment variable (personally I prefer
> >HTTPUSERAGENT but FTPUSERAGENT is what's used by ftp(1) on other BSDs).
> >
> >This is useful when fetching URLs that are sensitive to the User-Agent,
> >such as sites that send different content if you're using a mobile
> >browser/device.
> 
> I generally dislike passing options as environment variables. The use
> case you describe does not really strike me as something I'd have in
> my $ENV.
> 
> Does any of the other ftp's have a corresponding switch for it?

Thanks for your feedback.  As Adam Thompson also mentioned in his reply,
the other ftp's don't have a corresponding switch for the User-Agent.
The closest switch is FreeBSD's fetch(1) which uses --user-agent, but I
don't think we want that. :)

I only chose the environment variable approach because it's what's used
by the other BSDs.  But if a command-line option is preferred, I don't
mind it at all.

So here's an alternate implementation that uses -U to specify the
User-Agent.  After testing it, I find that I prefer it over using the
environment variable... for starters, there's way less typing! :)


Index: fetch.c
===================================================================
RCS file: /cvs/src/usr.bin/ftp/fetch.c,v
retrieving revision 1.122
diff -u -p -r1.122 fetch.c
--- fetch.c     20 May 2014 01:25:23 -0000      1.122
+++ fetch.c     14 Jun 2014 02:45:41 -0000
@@ -893,10 +893,10 @@ again:
                if (cookie)
                        ftp_printf(fin, ssl, "GET %s HTTP/1.0\r\n"
                            "Proxy-Authorization: Basic %s%s\r\n%s\r\n\r\n",
-                           epath, cookie, buf ? buf : "", HTTP_USER_AGENT);
+                           epath, cookie, buf ? buf : "", httpuseragent);
                else
                        ftp_printf(fin, ssl, "GET %s HTTP/1.0\r\n%s%s\r\n\r\n",
-                           epath, buf ? buf : "", HTTP_USER_AGENT);
+                           epath, buf ? buf : "", httpuseragent);
 
        } else {
 #ifndef SMALL
@@ -954,7 +954,7 @@ again:
                        ftp_printf(fin, ssl, ":%s", port);
 #endif /* !SMALL */
                ftp_printf(fin, ssl, "\r\n%s%s\r\n\r\n",
-                   buf ? buf : "", HTTP_USER_AGENT);
+                   buf ? buf : "", httpuseragent);
                if (verbose)
                        fprintf(ttyout, "\n");
        }
@@ -1293,6 +1293,9 @@ auto_fetch(int argc, char *argv[], char 
        char *cp, *url, *host, *dir, *file, *portnum;
        char *username, *pass, *pathstart;
        char *ftpproxy, *httpproxy;
+#ifndef SMALL
+       char *uagent = NULL;
+#endif /* !SMALL */
        int rval, xargc;
        volatile int argpos;
        int dirhasglob, filehasglob, oautologin;
@@ -1313,6 +1316,13 @@ auto_fetch(int argc, char *argv[], char 
        if ((httpproxy = getenv(HTTP_PROXY)) != NULL && *httpproxy == '\0')
                httpproxy = NULL;
 
+       if (httpuseragent == NULL)
+               httpuseragent = HTTP_USER_AGENT;
+#ifndef SMALL
+       else
+               uagent = httpuseragent;
+#endif /* !SMALL */
+
        /*
         * Loop through as long as there's files to fetch.
         */
@@ -1583,6 +1593,9 @@ bad_ftp_url:
        }
        if (connected && rval != -1)
                disconnect(0, NULL);
+#ifndef SMALL
+       free(uagent);
+#endif /* !SMALL */
        return (rval);
 }
 
Index: ftp.1
===================================================================
RCS file: /cvs/src/usr.bin/ftp/ftp.1,v
retrieving revision 1.91
diff -u -p -r1.91 ftp.1
--- ftp.1       23 Jan 2014 08:09:08 -0000      1.91
+++ ftp.1       14 Jun 2014 02:45:41 -0000
@@ -62,6 +62,7 @@
 .Op Fl o Ar output
 .Op Fl S Ar ssl_options
 .Op Fl s Ar srcaddr
+.Op Fl U Ar useragent
 .Sm off
 .No http[s]:// Oo Ar user : password No @
 .Oc Ar host Oo : Ar port
@@ -267,6 +268,11 @@ of the connection.
 Only useful on systems with more than one address.
 .It Fl t
 Enables packet tracing.
+.It Fl U Ar useragent
+Set
+.Ar useragent
+as the User-Agent for HTTP(S) URL requests.
+If not specified, the default User-Agent is ``OpenBSD ftp''.
 .It Fl V
 Disable verbose mode, overriding the default of enabled when input
 is from a terminal.
Index: ftp_var.h
===================================================================
RCS file: /cvs/src/usr.bin/ftp/ftp_var.h,v
retrieving revision 1.33
diff -u -p -r1.33 ftp_var.h
--- ftp_var.h   24 Dec 2013 13:00:59 -0000      1.33
+++ ftp_var.h   14 Jun 2014 02:45:41 -0000
@@ -181,6 +181,7 @@ char *httpport;                     /* port number to use 
 #ifndef SMALL
 char *httpsport;               /* port number to use for https connections */
 #endif /* !SMALL */
+char *httpuseragent;           /* user agent for http(s) connections */
 char *gateport;                        /* port number to use for gateftp 
connections */
 
 jmp_buf        toplevel;               /* non-local goto stuff for cmd scanner 
*/
Index: main.c
===================================================================
RCS file: /cvs/src/usr.bin/ftp/main.c,v
retrieving revision 1.87
diff -u -p -r1.87 main.c
--- main.c      23 Jan 2014 00:39:15 -0000      1.87
+++ main.c      14 Jun 2014 02:45:41 -0000
@@ -198,9 +198,10 @@ main(volatile int argc, char *argv[])
 #ifndef SMALL
        cookiefile = getenv("http_cookies");
 #endif /* !SMALL */
+       httpuseragent = NULL;
 
        while ((ch = getopt(argc, argv,
-                   "46AaCc:dD:Eegik:mno:pP:r:S:s:tvV")) != -1) {
+                   "46AaCc:dD:Eegik:mno:pP:r:S:s:tU:vV")) != -1) {
                switch (ch) {
                case '4':
                        family = PF_INET;
@@ -361,6 +362,21 @@ main(volatile int argc, char *argv[])
                        trace = 1;
                        break;
 
+               case 'U':
+#ifndef SMALL
+                       /* Prevent multiple User-Agents. */
+                       if (httpuseragent)
+                               errx(1, "User-Agent was already defined");
+                       /* Ensure that User-Agent value is in a single line. */
+                       if (strcspn(optarg, "\r\n") != strlen(optarg))
+                               errx(1, "Invalid User-Agent: %s.", optarg);
+                       if (asprintf(&httpuseragent, "User-Agent: %s",
+                           optarg) == -1)
+                               errx(1, "Can't allocate memory for HTTP(S) "
+                                   "User-Agent");
+#endif /* !SMALL */
+                       break;
+
                case 'v':
                        verbose = 1;
                        break;
@@ -852,7 +868,7 @@ usage(void)
 #ifndef SMALL
            "[-S ssl_options] "
            "[-s srcaddr]\n"
-           "           "
+           "           [-U useragent] "
 #endif /* !SMALL */
            "http"
 #ifndef SMALL

Reply via email to