Much, much smaller. :)
authorMichael Brown <mcb30@etherboot.org>
Thu, 28 Apr 2005 13:20:02 +0000 (13:20 +0000)
committerMichael Brown <mcb30@etherboot.org>
Thu, 28 Apr 2005 13:20:02 +0000 (13:20 +0000)
src/core/url.c

index dd5d1a9..2a156e8 100644 (file)
-#include "stdlib.h"
 #include "string.h"
-#include "proto.h"
-#include "resolv.h"
 #include "url.h"
 
-static struct protocol protocols[0] __protocol_start;
-static struct protocol default_protocols[0] __default_protocol_start;
-static struct protocol protocols_end[0] __protocol_end;
-
 /*
- * Parse protocol portion of a URL.  Return 0 if no "proto://" is
- * present.
+ * Parse a URL string into its constituent parts.
  *
- */
-static inline int parse_protocol ( struct url_info *info, const char **p ) {
-       const char *q = *p;
-
-       info->protocol = q;
-       for ( ; *q ; q++ ) {
-               if ( memcmp ( q, "://", 3 ) == 0 ) {
-                       info->protocol_len = q - info->protocol;
-                       *p = q + 3;
-                       return 1;
-               }
-       }
-       return 0;
-}
-
-/*
- * Parse the host:port portion of a URL.  Also fills in sin_port.
+ * We accept URLs of the form
  *
- */
-static inline void parse_host_port ( struct url_info *info, const char **p ) {
-       info->host = *p;
-       for ( ; **p && ( **p != '/' ) ; (*p)++ ) {
-               if ( **p == ':' ) {
-                       info->host_len = *p - info->host;
-                       info->port = ++(*p);
-                       info->sin.sin_port = strtoul ( *p, p, 10 );
-                       info->port_len = *p - info->port;
-                       return;
-               }
-       }
-       /* No ':' separator seen; it's all the host part */
-       info->host_len = *p - info->host;
-}
-
-/*
- * Identify the protocol
+ *   [protocol://[host][:port]/]path/to/file
+ *
+ * We return true for success, 0 for failure (e.g. unknown protocol).
+ * The URL string will be modified by having NULs inserted after
+ * "protocol", "host" and "port".  The original URL can be
+ * reconstructed by calling unparse_url.
  *
  */
-static inline int identify_protocol ( struct url_info *info ) {
-       struct protocol *proto;
+void parse_url ( struct url_info *info, char *url ) {
+       char *p;
 
-       if ( info->protocol_len ) {
-               char *terminator;
-               char temp;
+       /* Zero the structure */
+       memset ( info, 0, sizeof ( *info ) );
 
-               /* Explcitly specified protocol */
-               terminator = ( char * ) &info->protocol[info->protocol_len];
-               temp = *terminator;
-               *terminator = '\0';
-               for ( proto = protocols ; proto < protocols_end ; proto++ ) {
-                       if ( memcmp ( proto->name, info->protocol,
-                                     info->protocol_len + 1 ) == 0 ) {
-                               info->proto = proto;
+       /* Search for a protocol delimiter */
+       for ( p = url ; *p ; p++ ) {
+               if ( memcmp ( p, "://", 3 ) != 0 )
+                       continue;
+
+               /* URL has an explicit protocol */
+               info->protocol = url;
+               *p = '\0';
+               p += 3;
+               info->host = p;
+
+               /* Search for port or file delimiter */
+               for ( ; *p ; p++ ) {
+                       if ( *p == ':' ) {
+                               *p = '\0';
+                               info->port = p + 1;
+                               continue;
+                       }
+                       if ( *p == '/' ) {
+                               *(p++) = '\0';
                                break;
                        }
                }
-               *terminator = temp;
-       } else {
-               /* No explicitly specified protocol */
-               if ( default_protocols < protocols_end )
-                       info->proto = default_protocols;
+               info->file = p;
+               return;
        }
-       return ( ( int ) info->proto ); /* NULL indicates failure */
-}
 
-/*
- * Resolve the host portion of the URL
- *
- */
-static inline int resolve_host ( struct url_info *info ) {
-       char *terminator;
-       char temp;
-       int success;
-
-       if ( ! info->host_len ) {
-               /* No host specified - leave sin.sin_addr empty to
-                * indicate use of DHCP-supplied next-server
-                */
-               return 1;
-       }
-
-       terminator = ( char * ) &info->host[info->host_len];
-       temp = *terminator;
-       *terminator = '\0';
-       success = resolv ( &info->sin.sin_addr, info->host );
-       *terminator = temp;
-       return success;
+       /* URL has no explicit protocol; is just a filename */
+       info->file = url;
 }
 
 /*
- * Parse a URL string into its constituent parts.  Perform name
- * resolution if required (and if resolver code is linked in), and
- * identify the protocol.
- *
- * We accept URLs of the form
- *
- *   [protocol://[host][:port]/]path/to/file
- *
- * We return true for success, 0 for failure (e.g. unknown protocol).
- * Note that the "/" before path/to/file *will* be counted as part of
- * the filename, if it is present.
+ * Restore a parsed URL to its original pristine form.
  *
  */
-int parse_url ( struct url_info *info, const char *url ) {
-       const char *p;
-
-       /* Fill in initial values */
-       memset ( info, 0, sizeof ( *info ) );
-       info->url = url;
-       info->protocol = url;
-       info->host = url;
-       info->port = url;
-       info->file = url;
-
-       /* Split the URL into substrings, and fill in sin.sin_port */
-       p = url;
-       if ( parse_protocol ( info, &p ) )
-               parse_host_port ( info, &p );
-       info->file = p;
-
-       /* Identify the protocol */
-       if ( ! identify_protocol ( info ) )
-               return 0;
-
-       /* Resolve the host name to an IP address */
-       if ( ! resolve_host ( info ) )
-               return 0;
-
-       return 1;
+char * unparse_url ( struct url_info *info ) {
+       if ( info->protocol ) {
+               /* URL had a protocol: fill in the deleted separators */
+               info->file[-1] = '/';
+               if ( info->port ) {
+                       info->port[-1] = ':';
+               }
+               info->host[-3] = ':';
+               return info->protocol;
+       } else {
+               /* URL had no protocol; was just a filename */
+               return info->file;
+       }
 }