Skip site navigation (1)Skip section navigation (2)
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>