[PATCH] Decodes struct uri.{user=2Cpassword} members.

gL2n30Y06arv2 gL2n30Y06arv2 at hotmail.com
Wed Oct 21 13:29:35 EDT 2009


This patch replaces the encoded user info (user:password)=2C that was
kept in struct uri=2C with its decoded counterpart.=A0 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 <gL2n30Y06arv2 at hotmail.com>
---
=A0src/core/uri.c=A0=A0=A0=A0=A0=A0=A0=A0 |=A0=A0 45 ++++++++++++++++++++++=
++++++-----------------
=A0src/include/gpxe/uri.h |=A0=A0=A0 4 ++--
=A0src/net/tcp/ftp.c=A0=A0=A0=A0=A0 |=A0=A0 28 ++++++++++++++++++++++++++--
=A0src/net/tcp/http.c=A0=A0=A0=A0 |=A0=A0 17 ++---------------
=A0src/tests/uri_test.c=A0=A0 |=A0=A0 15 +++++++++------
=A05 files changed=2C 67 insertions(+)=2C 42 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=2C9 +45=2C9 @@ static void dump_uri ( struct uri *uri ) {
=A0=A0=A0=A0 if ( uri->opaque )
=A0=A0=A0=A0 =A0=A0=A0 DBG ( " opaque \"%s\""=2C uri->opaque )=3B
=A0=A0=A0=A0 if ( uri->user )
-=A0=A0=A0 =A0=A0=A0 DBG ( " user \"%s\""=2C uri->user )=3B
+=A0=A0=A0 =A0=A0=A0 DBG ( " decoded user \"%s\""=2C uri->user )=3B
=A0=A0=A0=A0 if ( uri->password )
-=A0=A0=A0 =A0=A0=A0 DBG ( " password \"%s\""=2C uri->password )=3B
+=A0=A0=A0 =A0=A0=A0 DBG ( " decoded password \"%s\""=2C uri->password )=3B
=A0=A0=A0=A0 if ( uri->host )
=A0=A0=A0=A0 =A0=A0=A0 DBG ( " host \"%s\""=2C uri->host )=3B
=A0=A0=A0=A0 if ( uri->port )
@@ -149=2C19 +149=2C25 @@ struct uri * parse_uri ( const char *uri_string )=
 {
=A0=A0=A0=A0 =A0=A0=A0 uri->path =3D path=3B
=A0=A0=A0=A0 }
=A0
-=A0=A0=A0 /* Split authority into user[:password] and host[:port] portions=
 */
+=A0=A0=A0 /* Split authority into user[:password] and host[:port]
+=A0=A0=A0 =A0=A0 portions.=A0 Decodes authority. */
=A0=A0=A0=A0 if ( ( tmp =3D strchr ( authority=2C '@' ) ) ) {
=A0=A0=A0=A0 =A0=A0=A0 /* Has user[:password] */
=A0=A0=A0=A0 =A0=A0=A0 *(tmp++) =3D '\0'=3B
=A0=A0=A0=A0 =A0=A0=A0 uri->host =3D tmp=3B
+=A0=A0=A0 =A0=A0=A0 uri_decode ( authority=2C authority /* in place */=2C=
=20
+=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 strlen ( authority ) + 1 /* NULL *=
/ )=3B
+=A0=A0=A0 =A0=A0=A0 /* assert ( uri->host>=3D ( authority +=20
+=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 strlen ( authority ) + 1=
 ) )=3B */
=A0=A0=A0=A0 =A0=A0=A0 uri->user =3D authority=3B
-=A0=A0=A0 =A0=A0=A0 if ( ( tmp =3D strchr ( authority=2C ':' ) ) ) {
+=A0=A0=A0 =A0=A0=A0 if ( ( tmp =3D strchr ( uri->user=2C ':' ) ) ) {
=A0=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 /* Has password */
=A0=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 *(tmp++) =3D '\0'=3B
=A0=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 uri->password =3D tmp=3B
=A0=A0=A0=A0 =A0=A0=A0 }
+
=A0=A0=A0=A0 } else {
-=A0=A0=A0 =A0=A0=A0 /* No user:password */
+=A0=A0=A0 =A0=A0=A0 /* No user[:password] */
=A0=A0=A0=A0 =A0=A0=A0 uri->host =3D authority=3B
=A0=A0=A0=A0 }
=A0
@@ -229=2C13 +235=2C14 @@ int unparse_uri ( char *buf=2C size_t size=2C str=
uct uri *uri ) {
=A0=A0=A0=A0 /* [user[:password]@]host[:port] */
=A0=A0=A0=A0 if ( uri->host ) {
=A0=A0=A0=A0 =A0=A0=A0 if ( uri->user ) {
+=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 used +=3D uri_encode ( uri->user=2C ( buf + =
used )=2C
+=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0( size - us=
ed ) )=3B
=A0=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 used +=3D ssnprintf ( ( buf + used )=2C ( =
size - used )=2C
-=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 "%s"=2C uri->u=
ser )=3B
-=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 if ( uri->password ) {
-=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 used +=3D ssnprintf ( ( buf + used=
 )=2C
-=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 ( si=
ze - used )=2C
-=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 ":%s=
"=2C uri->password )=3B
-=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 }
+=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 ":" )=3B
+=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 if ( uri->password )=20
+=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 used +=3D uri_encode ( uri->passwo=
rd=2C
+=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 ( bu=
f + used )=2C
+=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 ( si=
ze - used ) )=3B
=A0=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 used +=3D ssnprintf ( ( buf + used )=2C ( =
size - used )=2C
=A0=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 "@" )=3B
=A0=A0=A0=A0 =A0=A0=A0 }
@@ -435=2C12 +442=2C14 @@ size_t uri_encode ( const char *raw_string=2C cha=
r *buf=2C size_t len ) {
=A0}
=A0
=A0/**
- * Decode URI-encoded string
+ * Decode URI-encoded string.
=A0 *
=A0 * @v encoded_string=A0=A0=A0 URI-encoded string
=A0 * @v buf=A0=A0=A0 =A0=A0=A0 Buffer to contain decoded string
=A0 * @v len=A0=A0=A0 =A0=A0=A0 Length of buffer
=A0 * @ret len=A0=A0=A0 =A0=A0=A0 Length of decoded string (excluding NUL)
+ *
+ * Can be used when encoded_string and buf overlap and in place.
=A0 */
=A0size_t uri_decode ( const char *encoded_string=2C char *buf=2C size_t le=
n ) {
=A0=A0=A0=A0 ssize_t remaining =3D len=3B
@@ -448=2C10 +457=2C8 @@ size_t uri_decode ( const char *encoded_string=2C =
char *buf=2C size_t len ) {
=A0=A0=A0=A0 char *hexbuf_end=3B
=A0=A0=A0=A0 unsigned char c=3B
=A0
-=A0=A0=A0 if ( len )
-=A0=A0=A0 =A0=A0=A0 buf[0] =3D '\0'=3B
-
-=A0=A0=A0 while ( *encoded_string ) {
+=A0=A0=A0 while ( *encoded_string=A0 &&=A0=20
+=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 remaining> 1 /* a NULL is essential */ ) {
=A0=A0=A0=A0 =A0=A0=A0 if ( *encoded_string =3D=3D '%' ) {
=A0=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 encoded_string++=3B
=A0=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 snprintf ( hexbuf=2C sizeof ( hexbuf )=2C =
"%s"=2C
@@ -461=2C7 +468=2C11 @@ size_t uri_decode ( const char *encoded_string=2C =
char *buf=2C size_t len ) {
=A0=A0=A0=A0 =A0=A0=A0 } else {
=A0=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 c =3D *(encoded_string++)=3B
=A0=A0=A0=A0 =A0=A0=A0 }
-=A0=A0=A0 =A0=A0=A0 ssnprintf ( buf++=2C remaining--=2C "%c"=2C c )=3B
+=A0=A0=A0 =A0=A0=A0 *(remaining--=2C buf++) =3D c=3B
=A0=A0=A0=A0 }
+
+=A0=A0=A0 if ( remaining )
+=A0=A0=A0 =A0=A0=A0 *buf =3D '\0'=3B
+
=A0=A0=A0=A0 return ( len - remaining )=3B
=A0}
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=2C9 +47=2C9 @@ struct uri {
=A0=A0=A0=A0 const char *scheme=3B
=A0=A0=A0=A0 /** Opaque part */
=A0=A0=A0=A0 const char *opaque=3B
-=A0=A0=A0 /** User name */
+=A0=A0=A0 /** Decoded user name */
=A0=A0=A0=A0 const char *user=3B
-=A0=A0=A0 /** Password */
+=A0=A0=A0 /** Decoded password */
=A0=A0=A0=A0 const char *password=3B
=A0=A0=A0=A0 /** Host name */
=A0=A0=A0=A0 const char *host=3B
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=2C11 +131=2C35 @@ static const char * ftp_uri_path ( struct ftp_req=
uest *ftp ) {
=A0=A0=A0=A0 return ftp->uri->path=3B
=A0}
=A0
+/**
+ * Retrieve FTP user
+ *
+ * @v ftp=A0=A0=A0 =A0=A0=A0 FTP request
+ * @ret user=A0=A0=A0 =A0=A0=A0 FTP user
+ */
+static const char * ftp_user ( struct ftp_request *ftp ) {
+=A0=A0=A0 static char *ftp_default_user =3D "anonymous"=3B
+=A0=A0=A0 return ftp->uri->user ? ftp->uri->user : ftp_default_user=3B
+}
+
+/**
+ * Retrieve FTP password
+ *
+ * @v ftp=A0=A0=A0 =A0=A0=A0 FTP request
+ * @ret password=A0=A0=A0 FTP password
+ */
+static const char * ftp_password ( struct ftp_request *ftp ) {
+=A0=A0=A0 static char *ftp_default_password =3D=20
+=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 "etherboot at etherboot.org=
"=3B
+=A0=A0=A0 return ftp->uri->password ?=20
+=A0=A0=A0 =A0=A0=A0 ftp->uri->password : ftp_default_password=3B
+}
+
=A0/** FTP control channel strings */
=A0static struct ftp_control_string ftp_strings[] =3D {
=A0=A0=A0=A0 [FTP_CONNECT]=A0=A0=A0 =3D { NULL=2C NULL }=2C
-=A0=A0=A0 [FTP_USER]=A0=A0=A0 =3D { "USER anonymous"=2C NULL }=2C
-=A0=A0=A0 [FTP_PASS]=A0=A0=A0 =3D { "PASS etherboot at etherboot.org"=2C NULL=
 }=2C
+=A0=A0=A0 [FTP_USER]=A0=A0=A0 =3D { "USER "=2C ftp_user }=2C
+=A0=A0=A0 [FTP_PASS]=A0=A0=A0 =3D { "PASS "=2C ftp_password }=2C
=A0=A0=A0=A0 [FTP_TYPE]=A0=A0=A0 =3D { "TYPE I"=2C NULL }=2C
=A0=A0=A0=A0 [FTP_PASV]=A0=A0=A0 =3D { "PASV"=2C NULL }=2C
=A0=A0=A0=A0 [FTP_RETR]=A0=A0=A0 =3D { "RETR "=2C ftp_uri_path }=2C
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=2C21 +437=2C8 @@ static void http_step ( struct process *process ) =
{
=A0
=A0=A0=A0=A0 =A0=A0=A0 /* Construct authorisation=2C if applicable */
=A0=A0=A0=A0 =A0=A0=A0 if ( user ) {
-=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 char *buf =3D user_pw=3B
-=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 ssize_t remaining =3D sizeof ( user_pw )=3B
-=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 size_t len=3B
-
-=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 /* URI-decode the username and password */
-=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 len =3D uri_decode ( user=2C buf=2C remainin=
g )=3B
-=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 buf +=3D len=3B
-=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 remaining -=3D len=3B
-=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 *(remaining--=2C buf++) =3D ':'=3B
-=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 len =3D uri_decode ( password=2C buf=2C rema=
ining )=3B
-=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 buf +=3D len=3B
-=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 remaining -=3D len=3B
-=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 assert ( remaining>=3D 0 )=3B
-
-=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 /* Base64-encode the "user:password" string =
*/
+=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 snprintf ( user_pw=2C user_pw_len + 1 /* NUL=
 */=2C
+=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0 "%s:%s"=2C user=2C password=
 )=3B
=A0=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 base64_encode ( user_pw=2C user_pw_base64 =
)=3B
=A0=A0=A0=A0 =A0=A0=A0 }
=A0
diff --git a/src/tests/uri_test.c b/src/tests/uri_test.c
index 2548760..8f5b3d1 100644
--- a/src/tests/uri_test.c
+++ b/src/tests/uri_test.c
@@ -14=2C12 +14=2C13 @@ struct uri_test {
=A0}=3B
=A0
=A0static struct uri_test uri_tests[] =3D {
-=A0=A0=A0 { "http://www.fensystems.co.uk"=2C ""=2C
-=A0=A0=A0 =A0 "http://www.fensystems.co.uk/" }=2C
-=A0=A0=A0 { "http://etherboot.org/wiki/page1"=2C "page2"=2C
-=A0=A0=A0 =A0 "http://etherboot.org/wiki/page2" }=2C
-=A0=A0=A0 { "http://etherboot.org/wiki/page1"=2C "../page3"=2C
-=A0=A0=A0 =A0 "http://etherboot.org/page3" }=2C
+=A0=A0=A0 { "ftp://:user%40isp.fr@www.fensystems.co.uk"=2C ""=2C
+=A0=A0=A0 =A0 "ftp://:user%40isp.fr@www.fensystems.co.uk/" }=2C
+=A0=A0=A0 { "https://user%40isp.fr:@etherboot.org/wiki/page1"=2C "page2"=
=2C
+=A0=A0=A0 =A0 "https://user%40isp.fr:@etherboot.org/wiki/page2" }=2C
+=A0=A0=A0 { "http://user:gpxe%40etherboot.org@etherboot.org/wiki/page1"=2C
+=A0=A0=A0 =A0 "../page3"=2C
+=A0=A0=A0 =A0 "http://user:gpxe%40etherboot.org@etherboot.org/page3" }=2C
=A0=A0=A0=A0 { "tftp://192.168.0.1/"=2C "/tftpboot/vmlinuz"=2C
=A0=A0=A0=A0 =A0 "tftp://192.168.0.1/tftpboot/vmlinuz" }=2C
=A0#if 0
@@ -120=2C6 +121=2C7 @@ int uri_test ( void ) {
=A0=A0=A0=A0 int rc=3B
=A0=A0=A0=A0 int overall_rc =3D 0=3B
=A0
+=A0=A0=A0 printf ( "Start uri_test () \n" )=3B
=A0=A0=A0=A0 for ( i =3D 0 =3B i < ( sizeof ( uri_tests ) /
=A0=A0=A0=A0 =A0=A0=A0 =A0=A0=A0 =A0=A0=A0 sizeof ( uri_tests[0] ) ) =3B i+=
+ ) {
=A0=A0=A0=A0 =A0=A0=A0 uri_test =3D &uri_tests[i]=3B
@@ -141=2C5 +143=2C6 @@ int uri_test ( void ) {
=A0
=A0=A0=A0=A0 if ( overall_rc )
=A0=A0=A0=A0 =A0=A0=A0 printf ( "URI tests failed: %s\n"=2C strerror ( over=
all_rc ) )=3B
+=A0=A0=A0 printf ( "End uri_test () \n" )=3B
=A0=A0=A0=A0 return overall_rc=3B
=A0}
--=20
1.6.5


 		 	   		 =20
_________________________________________________________________
Windows Live: Keep your friends up to date with what you do online.
http://www.microsoft.com/middleeast/windows/windowslive/see-it-in-action/so=
cial-network-basics.aspx?ocid=3DPID23461::T:WLMTAGL:ON:WL:en-xm:SI_SB_1:092=
010=


More information about the gPXE mailing list