Date: 4 Sep 2001 16:33:58 -0000 From: Mike Meyer <mwm@mired.org> To: FreeBSD-gnats-submit@freebsd.org Subject: bin/30318: [PATCH] libfetch needs extending or fixing Message-ID: <20010904163358.24787.qmail@guru.mired.org>
next in thread | raw e-mail | index | archive | help
>Number: 30318 >Category: bin >Synopsis: [PATCH] libfetch needs extending or fixing >Confidential: no >Severity: serious >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Tue Sep 04 09:40:01 PDT 2001 >Closed-Date: >Last-Modified: >Originator: Mike Meyer >Release: FreeBSD 4.4-RC i386 >Organization: Meyer Consulting >Environment: System: FreeBSD guru.mired.org 4.4-RC FreeBSD 4.4-RC #5: Sun Aug 26 15:14:14 CDT 2001 mwm@guru.mired.org:/sharetmp/obj/usr/src/sys/GURU i386 >Description: libfetch is a good start on being a general-purpose URL manipulation library. The one bit of real functionality missing - at least that I can see - is something that "undoes" fetchParseURL, allowing clients to paste parts of a URL together. A tool to make this facility available from the shell would also be nice. The other problem is that the URL parser isn't up to snuff. In particular, it doesn't handle the mailto scheme. Since fixing that potentially breaks the behavior described by the manual page, I've not done anything about it. There are other things that would be nice to have, like filling in default port numbers, relative URL handling, and fragment and query handing. Hower, some architectural decisions need to be made - like should there be a liburl that libfetch uses - before work starts on those. >How-To-Repeat: Read the "Should URL's be pervasive" thread on -hackers. Better yet, don't. >Fix: The attached shar file includes two things. First is a patch for libfetch that adds - and documents - fetchStrfURL, which does for struct url what strftime does for struct tm. The other files are a command - calledj url, as suggested in the above-named thread - which calls fetchParseURL then fetchStrfURL on it's argument. It could use some enhancing, but needs to wait more work on libfetch for that. diff -ruP ../src.orig/lib/libfetch/Makefile ./lib/libfetch/Makefile --- ../src.orig/lib/libfetch/Makefile Tue Sep 4 11:19:56 2001 +++ ./lib/libfetch/Makefile Tue Sep 4 11:25:56 2001 @@ -39,10 +39,10 @@ @echo "};" >> ${.TARGET} .for MP in fetchFreeURL fetchGet fetchGetFTP fetchGetFile fetchGetHTTP \ -fetchGetURL fetchList fetchListFTP fetchListFile fetchListHTTP fetchListURL \ -fetchMakeURL fetchParseURL fetchPut fetchPutFTP fetchPutFile fetchPutHTTP \ -fetchPutURL fetchStat fetchStatFTP fetchStatFile fetchStatHTTP fetchStatURL \ -fetchXGet fetchXGetFTP fetchXGetFile fetchXGetHTTP fetchXGetURL +fetchGetURL fetchList fetchStrfURL fetchListFTP fetchListFile fetchListHTTP \ +fetchListURL fetchMakeURL fetchParseURL fetchPut fetchPutFTP fetchPutFile \ +fetchPutHTTP fetchPutURL fetchStat fetchStatFTP fetchStatFile fetchStatHTTP \ +fetchStatURL fetchXGet fetchXGetFTP fetchXGetFile fetchXGetHTTP fetchXGetURL MLINKS+= fetch.3 ${MP}.3 .endfor diff -ruP ../src.orig/lib/libfetch/fetch.3 ./lib/libfetch/fetch.3 --- ../src.orig/lib/libfetch/fetch.3 Tue Sep 4 11:19:56 2001 +++ ./lib/libfetch/fetch.3 Tue Sep 4 11:25:56 2001 @@ -36,6 +36,7 @@ .Nm fetchPutURL , .Nm fetchStatURL , .Nm fetchListURL , +.Nm fetchStrfURL , .Nm fetchXGet , .Nm fetchGet , .Nm fetchPut , @@ -89,6 +90,8 @@ .Fn fetchStat "struct url *u" "struct url_stat *us" "const char *flags" .Ft struct url_ent * .Fn fetchList "struct url *u" "const char *flags" +.Ft size_t +.Fn fetchStrfURL "char *buf" "size_t s" "const char *fmt" "struct url *url" .Ft FILE * .Fn fetchXGetFile "struct url *u" "struct url_stat *us" "const char *flags" .Ft FILE * @@ -262,6 +265,72 @@ a .Vt struct url rather than a string. +.Pp +.Fn fetchStrfURL +formats the information from the +.Fa url +into +.Fa buf +according to the string pointed to by +.Fa fmt . +No more than +.Fa size +characters will be copied to +.Fa buf . +If the total number of characters including the terminating NUL is +less is less than +.Fa size , +then the number of characters copied not counting the terminating NUL +is returned. Otherwise, zero is returned and the contents of +.Fa buf +are indeterminate. +.Pp +The format string consists of ordinary characters and zero or more +conversion specifications. A conversion specification is a percent sign +.Dq Ql % +and one character. Conversion specifications are replaced by elements +from the url. See the description of +.Fn fetchParseURL +for the names of the cmoponents. +.Pp +Not all parts are present in all URLs; those missing will generate the null +string. The non-alphabetic characters separate the parts, with the exception +of the last +.Dq Ql / , +which is the first character in the file part. +.Pp +The conversion specifications map to the parts like so: +.Bl -tag -width "xxxx" +.It Cm %s +is replaced by the +.Vt scheme +from the URL. +.It Cm %u +is replaced by the +.Vt user +from the URL. +.It Cm %w +is replaced by the +.Vt pwd +from the URL. +.It Cm %h +is replaced by the +.Vt host +part of the URL. +.It Cm %p +is replaced by the +.Vt port +from the URL. +.It %d +is replaced by the +.Vt document +part of the URL, including any initial +.Dq Ql / +that may be present. +.It Cm %% +is replaced by +.Ql % . +.El .Pp All of the .Fn fetchXGetXXX , diff -ruP ../src.orig/lib/libfetch/fetch.c ./lib/libfetch/fetch.c --- ../src.orig/lib/libfetch/fetch.c Tue Sep 4 11:19:56 2001 +++ ./lib/libfetch/fetch.c Tue Sep 4 11:25:56 2001 @@ -414,6 +414,82 @@ } /* + * Format a URL into a string. + * + * This function formats the information from urlptr into buf + * according to format. No more than size characters will be copied to + * buf. If the total number of characters including the terminating + * NUL is less is less than size, then the number of characters copied + * not counting the terminating NUL is returned. Otherwise, zero is + * returned and the contents of buf are indeterminate. + * + * The format string consists of ordinary characters and zero or more + * conversion specifications. A conversion specification is a ``%'' + * sign and one character. Conversion specifications are replaced by + * elements from the url. The url is parsed into the following parts, + * as defined in RFC1738: + * + * scheme://user:password@host:port/file + * + * Not all parts are present in all URLs; those missing will generate + * the null string. The non-alphabetic characters separate the parts, + * with the exception of the last ``/'', which is the first character + * in the file part. + * + * The conversion specifications map to the parts like so: %s: scheme, + * %u: user, %w: password, %h: host, %p: port, %f: file. + * + * Any other character after the ``%'' in a conversion specification + * will replace the conversion specification, so that ``%%'' becomes + * ``%''. Using this mechanism for any character other than ``%'' and + * the documented specifications could lead to problems with later + * version of strfurl. + * + * Note for future expansion: capital letters for conversion to imply + * smarts, so that %P will become the default port for the scheme if + * none is provided? + */ +size_t +fetchStrfURL(char *const buf, size_t size, const char *format, + struct url *urlptr) +{ + char *pt, *ptlim ; + + for (pt = buf, ptlim = pt + size; pt < ptlim && *format; format += 1) + if (*format != '%') *pt++ = *format ; + else { + format += 1 ; + switch (*format) { + case 'd': + pt += snprintf(pt, ptlim - pt, "%s", urlptr->doc) ; + break ; + case 'h': + pt += snprintf(pt, ptlim - pt, "%s", urlptr->host) ; + break ; + case 'p': + pt += snprintf(pt, ptlim - pt, "%d", urlptr->port) ; + break ; + case 's': + pt += snprintf(pt, ptlim - pt, "%s", urlptr->scheme) ; + break ; + case 'u': + pt += snprintf(pt, ptlim - pt, "%s", urlptr->user) ; + break ; + case 'w': + pt += snprintf(pt, ptlim - pt, "%s", urlptr->pwd) ; + break ; + default: + *pt++ = *format ; + break ; + } + } + + if (pt >= ptlim) return 0 ; + *pt = '\0' ; + return pt - buf ; +} + +/* * Free a URL */ void diff -ruP ../src.orig/lib/libfetch/fetch.h ./lib/libfetch/fetch.h --- ../src.orig/lib/libfetch/fetch.h Tue Sep 4 11:19:56 2001 +++ ./lib/libfetch/fetch.h Tue Sep 4 11:25:56 2001 @@ -118,6 +118,7 @@ FILE *fetchPut(struct url *, const char *); int fetchStat(struct url *, struct url_stat *, const char *); struct url_ent *fetchList(struct url *, const char *); +size_t fetchStrfURL(char *, size_t, const char *, struct url *); /* URL parsing */ struct url *fetchMakeURL(const char *, const char *, int, diff -ruP ../src.orig/usr.bin/url/Makefile ./usr.bin/url/Makefile --- ../src.orig/usr.bin/url/Makefile Wed Dec 31 18:00:00 1969 +++ ./usr.bin/url/Makefile Tue Sep 4 11:25:56 2001 @@ -0,0 +1,6 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= url +LDADD= -lfetch + +.include <bsd.prog.mk> diff -ruP ../src.orig/usr.bin/url/url.1 ./usr.bin/url/url.1 --- ../src.orig/usr.bin/url/url.1 Wed Dec 31 18:00:00 1969 +++ ./usr.bin/url/url.1 Tue Sep 4 11:25:56 2001 @@ -0,0 +1,61 @@ +.\" Copyrithg 2001, Mike W. Meyer <mwm@mired.org> +.Dd September 4, 2001 +.Dt URL 1 +.Os +.Sh NAME +.Nm url +.Nd parse and reformat uniform resource locators +.Sh SYNOPSYS +.Nm +.Op Fl d | h | m | p | s | u | w | Cm + Ns Ar format +.Ar URL +.Sh DESCRIPTION +The +.Nm +command reads a URL from the command line, parses it with the +.Xr fetchParseURL 3 +routine, then reformats the components as specified by the option +and displays the results on standard out. The meaning of the component +names is in +.Xr fetchParseURL 3 . +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl d +Display the document part of the url. +.It Fl h +Display the host from the url. +.It Fl m +Display the user and host from the url as a valid mail address. +.It Fl p +Display the port part of the url. +.It Fl s +Display the scheme from the url. +.It Fl u +Display the user name part the url. +.It Fl w +Display the password part of the url. +.It Cm + Ns Ar format +The format string specifies a format in which to display the components +of the URL. The format string can contain any conversion +specifications described in the +.Xr fetchStrfURL 3 +manual page, as well as arbitrary text. +A newline +.Pl Ql \en +character is always output after the characters specified by the +format sting. +.El +.Pp +If no option is specified, +.Nm +chooses a format based on the scheme, which may result in the input +URL being displayed. +.Sh ERRORS +.Nm +exits 0 on success, >0 if an error occurs. +.Sh SEE ALSO +.Xr fetchParseURL 3 +.Xr fetchStrfURL 3 +.Sh AUTHORS +.An Mike Meyer Aq mwm@mired.org diff -ruP ../src.orig/usr.bin/url/url.c ./usr.bin/url/url.c --- ../src.orig/usr.bin/url/url.c Wed Dec 31 18:00:00 1969 +++ ./usr.bin/url/url.c Tue Sep 4 11:25:56 2001 @@ -0,0 +1,86 @@ +/* + * A small shell tool for manipulating URLs as parsed by libfetch. + * + * Copyright 2001, Mike W. Meyer + * <mwm@mired.org> + */ + +#include <sys/types.h> +#include <sys/param.h> +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <fetch.h> + +#define OPTIONS "fhmPpsU" + +struct formats { + char *name, *format ; +} ; + +static char * +searchfmtarray(const struct formats *array, const char *const name) { + for (;array->name != NULL; array += 1) + if (strcmp(array->name, name) == 0) return array->format ; + return NULL ; +} + +static struct formats schemes[] = { + {"ftp", "%h%f"}, + {"mailto", "%u@%h"} +} ; + + +static struct formats flags[] = { + {"d", "%d"} , + {"h", "%h"} , + {"m", "%u@%h"} , + {"p", "%p"} , + {"s", "%s"} , + {"u", "%u"} , + {"w", "%w"} , + {NULL, NULL} +} ; + +static void +usage(char *name) { + fprintf(stderr, + "usage: %s [-d | -h | -m | -p | -s | -u | -w | +format] URL\n", name) + ; + exit(EXIT_FAILURE) ; +} +#define URLBUFSIZE 10240 + +int +main(int argc, char **argv) { + char *fmt ; + char *in, *tmp, buf[URLBUFSIZE] ; + struct url *out ; + struct format *search ; + int res ; + + fmt = NULL ; + if (argc == 2) { + in = argv[1] ; + } else if (argc == 3) { + in = argv[2] ; + tmp = &argv[1][1] ; + if (argv[1][0] == '+') fmt = tmp ; + else if (argv[1][0] == '-') fmt = searchfmtarray(flags, tmp) ; + if (fmt == NULL) usage(argv[0]) ; + } else usage(argv[0]) ; + + if ((out = fetchParseURL(in)) == NULL) + errx(EXIT_FAILURE, "Failed to parse URL.") ; + else { + if (fmt == NULL) fmt = searchfmtarray(schemes, out->scheme) ; + if (fmt == NULL) puts(in) ; + else { + res = fetchStrfURL(buf, URLBUFSIZE, fmt, out) ; + if (res != 0) puts(buf) ; + else warnx("Output buffer size exceeded.") ; + } + fetchFreeURL(out) ; + } + exit(res == 0 ? EXIT_SUCCESS : EXIT_FAILURE) ; +} >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010904163358.24787.qmail>