1. This patch replaces the encoded user info (user:password), that was kept in 
struct uri, with
   its decoded counterpart.  The decoded version should be much more useful.  
It also attempts
   to amend the other parts of the project appropriately.  The reference is 
section 3.2 of 
   RFC 3986.
2. I couldn't get along with git.  Maybe now, that the patch is kept in the 
archive of this list,
   I will give git a second chance.  I do hope that this patch truly represents 
the diff between 
   my branch and the one in the archive. 
3. There are 5 files concerned: include/gpxe/uri.h, core/uri.c, 
tests/uri_test.c, net/tcp/ftp.c,
   net/tcp/http.c.  I do hope this is an exhaustive list.
4. I used tests/uri_test.c for testing.  I have also tested the ftp method.  I 
did not test
   the http method in any way, other then get it compiled cleanly.
5. I think the only other file that is concerned is usr/imgmgmt.c.  As far as I 
can tell, it 
   should not be modified because of my work.

Please apply.

--- old/include/gpxe/uri.h    2009-12-18 02:00:17.000000000 +0100
+++ new/include/gpxe/uri.h    2009-12-18 01:51:17.000000000 +0100
@@ -47,9 +47,9 @@
     const char *scheme;
     /** Opaque part */
     const char *opaque;
-    /** User name */
+    /** Decoded user name */
     const char *user;
-    /** Password */
+    /** Decoded password */
     const char *password;
     /** Host name */
     const char *host;

--- old/core/uri.c    2009-12-18 02:00:17.000000000 +0100
+++ new/core/uri.c    2009-12-18 02:04:05.000000000 +0100
@@ -45,9 +45,9 @@
     if ( uri->opaque )
         DBG ( " opaque \"%s\"", uri->opaque );
     if ( uri->user )
-        DBG ( " user \"%s\"", uri->user );
+        DBG ( " decoded user \"%s\"", uri->user );
     if ( uri->password )
-        DBG ( " password \"%s\"", uri->password );
+        DBG ( " decoded password \"%s\"", uri->password );
     if ( uri->host )
         DBG ( " host \"%s\"", uri->host );
     if ( uri->port )
@@ -149,19 +149,25 @@
         uri->path = path;
     }
 
-    /* Split authority into user[:password] and host[:port] portions */
+    /* Split authority into user[:password] and host[:port]
+       portions.  Decode authority. */
     if ( ( tmp = strchr ( authority, '@' ) ) ) {
         /* Has user[:password] */
         *(tmp++) = '\0';
         uri->host = tmp;
+        uri_decode ( authority, authority /* in place */, 
+                strlen ( authority ) + 1 /* NULL */ );
+        /* assert ( uri->host>= ( authority + 
+                    strlen ( authority ) + 1 ) ); */
         uri->user = authority;
-        if ( ( tmp = strchr ( authority, ':' ) ) ) {
+        if ( ( tmp = strchr ( uri->user, ':' ) ) ) {
             /* Has password */
             *(tmp++) = '\0';
             uri->password = tmp;
         }
+
     } else {
-        /* No user:password */
+        /* No user[:password] */
         uri->host = authority;
     }
 
@@ -229,13 +235,14 @@
     /* [user[:passwo...@]host[:port] */
     if ( uri->host ) {
         if ( uri->user ) {
+            used += uri_encode ( uri->user, ( buf + used ),
+                         ( size - used ) );
             used += ssnprintf ( ( buf + used ), ( size - used ),
-                        "%s", uri->user );
-            if ( uri->password ) {
-                used += ssnprintf ( ( buf + used ),
-                            ( size - used ),
-                            ":%s", uri->password );
-            }
+                        ":" );
+            if ( uri->password ) 
+                used += uri_encode ( uri->password,
+                            ( buf + used ),
+                            ( size - used ) );
             used += ssnprintf ( ( buf + used ), ( size - used ),
                         "@" );
         }
@@ -435,12 +442,14 @@
 }
 
 /**
- * Decode URI-encoded string
+ * Decode URI-encoded string.
  *
  * @v encoded_string    URI-encoded string
  * @v buf        Buffer to contain decoded string
  * @v len        Length of buffer
  * @ret len        Length of decoded string (excluding NUL)
+ *
+ * Can be used when encoded_string and buf overlap and in place.
  */
 size_t uri_decode ( const char *encoded_string, char *buf, size_t len ) {
     ssize_t remaining = len;
@@ -448,10 +457,8 @@
     char *hexbuf_end;
     unsigned char c;
 
-    if ( len )
-        buf[0] = '\0';
-
-    while ( *encoded_string ) {
+    while ( *encoded_string  &&  
+            remaining> 1 /* a NULL is essential */ ) {
         if ( *encoded_string == '%' ) {
             encoded_string++;
             snprintf ( hexbuf, sizeof ( hexbuf ), "%s",
@@ -461,7 +468,11 @@
         } else {
             c = *(encoded_string++);
         }
-        ssnprintf ( buf++, remaining--, "%c", c );
+        *(remaining--, buf++) = c;
     }
+
+    if ( remaining )
+        *buf = '\0';
+
     return ( len - remaining );
 }

--- old/tests/uri_test.c    2009-12-18 02:00:17.000000000 +0100
+++ new/tests/uri_test.c    2009-12-18 01:51:17.000000000 +0100
@@ -14,12 +14,13 @@
 };
 
 static struct uri_test uri_tests[] = {
-    { "http://www.fensystems.co.uk";, "",
-      "http://www.fensystems.co.uk/"; },
-    { "http://etherboot.org/wiki/page1";, "page2",
-      "http://etherboot.org/wiki/page2"; },
-    { "http://etherboot.org/wiki/page1";, "../page3",
-      "http://etherboot.org/page3"; },
+    { "ftp://:user%[email protected]";, "",
+      "ftp://:user%[email protected]/"; },
+    { "https://user:pass%[email protected]/wiki/page1";, "page2",
+      "https://user:pass%[email protected]/wiki/page2"; },
+    { "http://user:gpxe%[email protected]/wiki/page1";,
+      "../page3",
+      "http://user:gpxe%[email protected]/page3"; },
     { "tftp://192.168.0.1/";, "/tftpboot/vmlinuz",
       "tftp://192.168.0.1/tftpboot/vmlinuz"; },
 #if 0
@@ -120,6 +121,7 @@
     int rc;
     int overall_rc = 0;
 
+    printf ( "Start uri_test () \n" );
     for ( i = 0 ; i < ( sizeof ( uri_tests ) /
                 sizeof ( uri_tests[0] ) ) ; i++ ) {
         uri_test = &uri_tests[i];
@@ -141,5 +143,6 @@
 
     if ( overall_rc )
         printf ( "URI tests failed: %s\n", strerror ( overall_rc ) );
+    printf ( "End uri_test () \n" );
     return overall_rc;
 }

--- old/net/tcp/ftp.c    2009-12-18 02:00:17.000000000 +0100
+++ new/net/tcp/ftp.c    2009-12-18 01:51:17.000000000 +0100
@@ -122,42 +122,44 @@
 };
 
 /**
- * Retrieve FTP user
+ * Retrieve FTP pathname
  *
- * @v ftp              FTP request
- * @ret user           FTP user
+ * @v ftp        FTP request
+ * @ret path        FTP pathname
  */
-static const char * ftp_uri_user ( struct ftp_request *ftp ) {
-    static char *ftp_default_user = "anonymous";
-    return ftp->uri->user ? ftp->uri->user : ftp_default_user;
+static const char * ftp_uri_path ( struct ftp_request *ftp ) {
+    return ftp->uri->path;
 }
 
 /**
- * Retrieve FTP password
+ * Retrieve FTP user
  *
- * @v ftp              FTP request
- * @ret password       FTP password
+ * @v ftp        FTP request
+ * @ret user        FTP user
  */
-static const char * ftp_uri_password ( struct ftp_request *ftp ) {
-    static char *ftp_default_password = "[email protected]";
-    return ftp->uri->password ? ftp->uri->password : ftp_default_password;
+static const char * ftp_user ( struct ftp_request *ftp ) {
+    static char *ftp_default_user = "anonymous";
+    return ftp->uri->user ? ftp->uri->user : ftp_default_user;
 }
 
 /**
- * Retrieve FTP pathname
+ * Retrieve FTP password
  *
  * @v ftp        FTP request
- * @ret path        FTP pathname
+ * @ret password    FTP password
  */
-static const char * ftp_uri_path ( struct ftp_request *ftp ) {
-    return ftp->uri->path;
+static const char * ftp_password ( struct ftp_request *ftp ) {
+    static char *ftp_default_password = 
+                    "[email protected]";
+    return ftp->uri->password ? 
+        ftp->uri->password : ftp_default_password;
 }
 
 /** FTP control channel strings */
 static struct ftp_control_string ftp_strings[] = {
     [FTP_CONNECT]    = { NULL, NULL },
-    [FTP_USER]    = { "USER ", ftp_uri_user },
-    [FTP_PASS]    = { "PASS ", ftp_uri_password },
+    [FTP_USER]    = { "USER ", ftp_user },
+    [FTP_PASS]    = { "PASS ", ftp_password },
     [FTP_TYPE]    = { "TYPE I", NULL },
     [FTP_PASV]    = { "PASV", NULL },
     [FTP_RETR]    = { "RETR ", ftp_uri_path },

--- old/net/tcp/http.c    2009-12-18 02:00:17.000000000 +0100
+++ new/net/tcp/http.c    2009-12-18 01:51:17.000000000 +0100
@@ -437,21 +437,8 @@
 
         /* Construct authorisation, if applicable */
         if ( user ) {
-            char *buf = user_pw;
-            ssize_t remaining = sizeof ( user_pw );
-            size_t len;
-
-            /* URI-decode the username and password */
-            len = uri_decode ( user, buf, remaining );
-            buf += len;
-            remaining -= len;
-            *(remaining--, buf++) = ':';
-            len = uri_decode ( password, buf, remaining );
-            buf += len;
-            remaining -= len;
-            assert ( remaining>= 0 );
-
-            /* Base64-encode the "user:password" string */
+            snprintf ( user_pw, user_pw_len + 1 /* NUL */,
+                   "%s:%s", user, password );
             base64_encode ( user_pw, user_pw_base64 );
         }
 


                                          
_________________________________________________________________
Windows Live Hotmail: Your friends can get your Facebook updates, right from 
Hotmail®.
http://www.microsoft.com/middleeast/windows/windowslive/see-it-in-action/social-network-basics.aspx?ocid=PID23461::T:WLMTAGL:ON:WL:en-xm:SI_SB_4:092009
_______________________________________________
gPXE mailing list
[email protected]
http://etherboot.org/mailman/listinfo/gpxe

Reply via email to