> Date: Thu, 24 Dec 2009 17:01:21 +0000
> From: [email protected]
>
> Please resend as an attachment. The whitespace has been mangled and
> the patch doesn't apply.
>
> Thanks for adding test cases. Please leave the tests without a
> username:password and append the new test cases on the end. That way
> URIs without username:password remain tested.
>


  Trying both an inline, and an attachment, of the same thing.

>From a89c5fa96e32d56b00673ab2b0cddd39eca2c89b Mon Sep 17 00:00:00 2001
From: gL2n30Y06arv2 <[email protected]>
Date: Sat, 26 Dec 2009 01:28:37 +0200
Subject: [PATCH] Decodes struct uri.{user,password} members.

Replaces the encoded user info (user:password), that was kept in struct
uri, with its decoded counterpart.  The decoded version is expected to
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.

Signed-off-by: gL2n30Y06arv2 <[email protected]>
---
 src/core/uri.c         |   45 ++++++++++++++++++++++++++++-----------------
 src/include/gpxe/uri.h |    4 ++--
 src/net/tcp/ftp.c      |   28 ++++++++++++++++++++++++++--
 src/net/tcp/http.c     |   17 ++---------------
 src/tests/uri_test.c   |    7 +++++++
 5 files changed, 65 insertions(+), 36 deletions(-)

diff --git a/src/core/uri.c b/src/core/uri.c
index 50a96d3..63166e5 100644
--- a/src/core/uri.c
+++ b/src/core/uri.c
@@ -45,9 +45,9 @@ static void dump_uri ( struct uri *uri ) {
     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 @@ struct uri * parse_uri ( const char *uri_string ) {
         uri->path = path;
     }
 
-    /* Split authority into user[:password] and host[:port] portions */
+    /* Split authority into user[:password] and host[:port]
+       portions.  Decodes 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 @@ int unparse_uri ( char *buf, size_t size, struct uri *uri 
) {
     /* [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 @@ size_t uri_encode ( const char *raw_string, char *buf, 
size_t len ) {
 }
 
 /**
- * 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 @@ size_t uri_decode ( const char *encoded_string, char *buf, 
size_t len ) {
     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 @@ size_t uri_decode ( const char *encoded_string, char *buf, 
size_t len ) {
         } else {
             c = *(encoded_string++);
         }
-        ssnprintf ( buf++, remaining--, "%c", c );
+        *(remaining--, buf++) = c;
     }
+
+    if ( remaining )
+        *buf = '\0';
+
     return ( len - remaining );
 }
diff --git a/src/include/gpxe/uri.h b/src/include/gpxe/uri.h
index 03c88d2..de8d5a9 100644
--- a/src/include/gpxe/uri.h
+++ b/src/include/gpxe/uri.h
@@ -47,9 +47,9 @@ struct uri {
     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;
diff --git a/src/net/tcp/ftp.c b/src/net/tcp/ftp.c
index 0719bf7..26103f6 100644
--- a/src/net/tcp/ftp.c
+++ b/src/net/tcp/ftp.c
@@ -131,11 +131,35 @@ static const char * ftp_uri_path ( struct ftp_request 
*ftp ) {
     return ftp->uri->path;
 }
 
+/**
+ * Retrieve FTP user
+ *
+ * @v ftp        FTP request
+ * @ret user        FTP user
+ */
+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 password
+ *
+ * @v ftp        FTP request
+ * @ret password    FTP password
+ */
+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 anonymous", NULL },
-    [FTP_PASS]    = { "PASS [email protected]", NULL },
+    [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 },
diff --git a/src/net/tcp/http.c b/src/net/tcp/http.c
index a02408a..eda9f8b 100644
--- a/src/net/tcp/http.c
+++ b/src/net/tcp/http.c
@@ -437,21 +437,8 @@ static void http_step ( struct process *process ) {
 
         /* 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 );
         }
 
diff --git a/src/tests/uri_test.c b/src/tests/uri_test.c
index 2548760..aa84ace 100644
--- a/src/tests/uri_test.c
+++ b/src/tests/uri_test.c
@@ -23,6 +23,13 @@ static struct uri_test uri_tests[] = {
     { "tftp://192.168.0.1/";, "/tftpboot/vmlinuz",
       "tftp://192.168.0.1/tftpboot/vmlinuz"; },
 #if 0
+    { "ftp://:user%[email protected]";, "",
+      "ftp://:user%[email protected]/"; },
+    { "https://user%40isp.fr:@etherboot.org/wiki/page1";, "page2",
+      "https://user%40isp.fr:@etherboot.org/wiki/page2"; },
+    { "http://user:gpxe%[email protected]/wiki/page1";,
+      "../page3",
+      "http://user:gpxe%[email protected]/page3"; },
     "http://www.etherboot.org/wiki";,
     "mailto:[email protected]";,
     "ftp://joe:[email protected]:8081/hidden/path/to?what=is#this";,
-- 
1.6.5


                                          
_________________________________________________________________
Windows Live: Keep your friends up to date with what you do online.
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_1:092010

Attachment: uriWithDecodedUserInfo.patch
Description: Binary data

_______________________________________________
gPXE mailing list
[email protected]
http://etherboot.org/mailman/listinfo/gpxe

Reply via email to