| 
				
			 | 
			
			
				
				@@ -76,6 +76,7 @@ struct uri * parse_uri ( const char *uri_string ) { 
			 | 
		
		
	
		
			
			| 
				76
			 | 
			
				76
			 | 
			
			
				
				 	char *tmp; 
			 | 
		
		
	
		
			
			| 
				77
			 | 
			
				77
			 | 
			
			
				
				 	char *path = NULL; 
			 | 
		
		
	
		
			
			| 
				78
			 | 
			
				78
			 | 
			
			
				
				 	char *authority = NULL; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				79
			 | 
			
			
				
				+	int i; 
			 | 
		
		
	
		
			
			| 
				79
			 | 
			
				80
			 | 
			
			
				
				 	size_t raw_len; 
			 | 
		
		
	
		
			
			| 
				80
			 | 
			
				81
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				81
			 | 
			
				82
			 | 
			
			
				
				 	/* Allocate space for URI struct and a copy of the string */ 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -171,6 +172,14 @@ struct uri * parse_uri ( const char *uri_string ) { 
			 | 
		
		
	
		
			
			| 
				171
			 | 
			
				172
			 | 
			
			
				
				 		uri->port = tmp; 
			 | 
		
		
	
		
			
			| 
				172
			 | 
			
				173
			 | 
			
			
				
				 	} 
			 | 
		
		
	
		
			
			| 
				173
			 | 
			
				174
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				175
			 | 
			
			
				
				+	/* Decode fields that should be decoded */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				176
			 | 
			
			
				
				+	for ( i = URI_FIRST_FIELD; i <= URI_LAST_FIELD; i++ ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				177
			 | 
			
			
				
				+		const char *field = uri_get_field ( uri, i ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				178
			 | 
			
			
				
				+		if ( field && ( URI_ENCODED & ( 1 << i ) ) ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				179
			 | 
			
			
				
				+			uri_decode ( field, ( char * ) field, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				180
			 | 
			
			
				
				+				     strlen ( field ) + 1 /* NUL */ ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				181
			 | 
			
			
				
				+	} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				182
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				174
			 | 
			
				183
			 | 
			
			
				
				  done: 
			 | 
		
		
	
		
			
			| 
				175
			 | 
			
				184
			 | 
			
			
				
				 	DBG ( "URI \"%s\" split into", uri_string ); 
			 | 
		
		
	
		
			
			| 
				176
			 | 
			
				185
			 | 
			
			
				
				 	dump_uri ( uri ); 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -198,10 +207,19 @@ unsigned int uri_port ( struct uri *uri, unsigned int default_port ) { 
			 | 
		
		
	
		
			
			| 
				198
			 | 
			
				207
			 | 
			
			
				
				  * @v buf		Buffer to fill with URI string 
			 | 
		
		
	
		
			
			| 
				199
			 | 
			
				208
			 | 
			
			
				
				  * @v size		Size of buffer 
			 | 
		
		
	
		
			
			| 
				200
			 | 
			
				209
			 | 
			
			
				
				  * @v uri		URI to write into buffer, or NULL 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				210
			 | 
			
			
				
				+ * @v fields		Bitmask of fields to include in URI string, or URI_ALL 
			 | 
		
		
	
		
			
			| 
				201
			 | 
			
				211
			 | 
			
			
				
				  * @ret len		Length of URI string 
			 | 
		
		
	
		
			
			| 
				202
			 | 
			
				212
			 | 
			
			
				
				  */ 
			 | 
		
		
	
		
			
			| 
				203
			 | 
			
				
			 | 
			
			
				
				-int unparse_uri ( char *buf, size_t size, struct uri *uri ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				213
			 | 
			
			
				
				+int unparse_uri ( char *buf, size_t size, struct uri *uri, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				214
			 | 
			
			
				
				+		  unsigned int fields ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				215
			 | 
			
			
				
				+	/* List of characters that typically go before certain fields */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				216
			 | 
			
			
				
				+	static char separators[] = { /* scheme */ 0, /* opaque */ ':', 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				217
			 | 
			
			
				
				+				     /* user */ 0, /* password */ ':', 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				218
			 | 
			
			
				
				+				     /* host */ '@', /* port */ ':', 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				219
			 | 
			
			
				
				+				     /* path */ 0, /* query */ '?', 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				220
			 | 
			
			
				
				+				     /* fragment */ '#' }; 
			 | 
		
		
	
		
			
			| 
				204
			 | 
			
				221
			 | 
			
			
				
				 	int used = 0; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				222
			 | 
			
			
				
				+	int i; 
			 | 
		
		
	
		
			
			| 
				205
			 | 
			
				223
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				206
			 | 
			
				224
			 | 
			
			
				
				 	DBG ( "URI unparsing" ); 
			 | 
		
		
	
		
			
			| 
				207
			 | 
			
				225
			 | 
			
			
				
				 	dump_uri ( uri ); 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -214,55 +232,39 @@ int unparse_uri ( char *buf, size_t size, struct uri *uri ) { 
			 | 
		
		
	
		
			
			| 
				214
			 | 
			
				232
			 | 
			
			
				
				 		return 0; 
			 | 
		
		
	
		
			
			| 
				215
			 | 
			
				233
			 | 
			
			
				
				 	} 
			 | 
		
		
	
		
			
			| 
				216
			 | 
			
				234
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				217
			 | 
			
				
			 | 
			
			
				
				-	/* Special-case opaque URIs */ 
			 | 
		
		
	
		
			
			| 
				218
			 | 
			
				
			 | 
			
			
				
				-	if ( uri->opaque ) { 
			 | 
		
		
	
		
			
			| 
				219
			 | 
			
				
			 | 
			
			
				
				-		return ssnprintf ( ( buf + used ), ( size - used ), 
			 | 
		
		
	
		
			
			| 
				220
			 | 
			
				
			 | 
			
			
				
				-				   "%s:%s", uri->scheme, uri->opaque ); 
			 | 
		
		
	
		
			
			| 
				221
			 | 
			
				
			 | 
			
			
				
				-	} 
			 | 
		
		
	
		
			
			| 
				222
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				223
			 | 
			
				
			 | 
			
			
				
				-	/* scheme:// */ 
			 | 
		
		
	
		
			
			| 
				224
			 | 
			
				
			 | 
			
			
				
				-	if ( uri->scheme ) { 
			 | 
		
		
	
		
			
			| 
				225
			 | 
			
				
			 | 
			
			
				
				-		used += ssnprintf ( ( buf + used ), ( size - used ), 
			 | 
		
		
	
		
			
			| 
				226
			 | 
			
				
			 | 
			
			
				
				-				    "%s://", uri->scheme ); 
			 | 
		
		
	
		
			
			| 
				227
			 | 
			
				
			 | 
			
			
				
				-	} 
			 | 
		
		
	
		
			
			| 
				228
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				229
			 | 
			
				
			 | 
			
			
				
				-	/* [user[:password]@]host[:port] */ 
			 | 
		
		
	
		
			
			| 
				230
			 | 
			
				
			 | 
			
			
				
				-	if ( uri->host ) { 
			 | 
		
		
	
		
			
			| 
				231
			 | 
			
				
			 | 
			
			
				
				-		if ( uri->user ) { 
			 | 
		
		
	
		
			
			| 
				232
			 | 
			
				
			 | 
			
			
				
				-			used += ssnprintf ( ( buf + used ), ( size - used ), 
			 | 
		
		
	
		
			
			| 
				233
			 | 
			
				
			 | 
			
			
				
				-					    "%s", uri->user ); 
			 | 
		
		
	
		
			
			| 
				234
			 | 
			
				
			 | 
			
			
				
				-			if ( uri->password ) { 
			 | 
		
		
	
		
			
			| 
				235
			 | 
			
				
			 | 
			
			
				
				-				used += ssnprintf ( ( buf + used ), 
			 | 
		
		
	
		
			
			| 
				236
			 | 
			
				
			 | 
			
			
				
				-						    ( size - used ), 
			 | 
		
		
	
		
			
			| 
				237
			 | 
			
				
			 | 
			
			
				
				-						    ":%s", uri->password ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				235
			 | 
			
			
				
				+	/* Iterate through requested fields */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				236
			 | 
			
			
				
				+	for ( i = URI_FIRST_FIELD; i <= URI_LAST_FIELD; i++ ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				237
			 | 
			
			
				
				+		const char *field = uri_get_field ( uri, i ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				238
			 | 
			
			
				
				+		char sep = separators[i]; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				239
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				240
			 | 
			
			
				
				+		/* Ensure `fields' only contains bits for fields that exist */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				241
			 | 
			
			
				
				+		if ( ! field ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				242
			 | 
			
			
				
				+			fields &= ~( 1 << i ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				243
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				244
			 | 
			
			
				
				+		/* Store this field if we were asked to */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				245
			 | 
			
			
				
				+		if ( fields & ( 1 << i ) ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				246
			 | 
			
			
				
				+			/* Print :// if we're non-opaque and had a scheme */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				247
			 | 
			
			
				
				+			if ( ( fields & URI_SCHEME_BIT ) && 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				248
			 | 
			
			
				
				+			     ( i > URI_OPAQUE ) ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				249
			 | 
			
			
				
				+				used += ssnprintf ( buf + used, size - used, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				250
			 | 
			
			
				
				+						    "://" ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				251
			 | 
			
			
				
				+				/* Only print :// once */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				252
			 | 
			
			
				
				+				fields &= ~URI_SCHEME_BIT; 
			 | 
		
		
	
		
			
			| 
				238
			 | 
			
				253
			 | 
			
			
				
				 			} 
			 | 
		
		
	
		
			
			| 
				239
			 | 
			
				
			 | 
			
			
				
				-			used += ssnprintf ( ( buf + used ), ( size - used ), 
			 | 
		
		
	
		
			
			| 
				240
			 | 
			
				
			 | 
			
			
				
				-					    "@" ); 
			 | 
		
		
	
		
			
			| 
				241
			 | 
			
				
			 | 
			
			
				
				-		} 
			 | 
		
		
	
		
			
			| 
				242
			 | 
			
				
			 | 
			
			
				
				-		used += ssnprintf ( ( buf + used ), ( size - used ), "%s", 
			 | 
		
		
	
		
			
			| 
				243
			 | 
			
				
			 | 
			
			
				
				-				    uri->host ); 
			 | 
		
		
	
		
			
			| 
				244
			 | 
			
				
			 | 
			
			
				
				-		if ( uri->port ) { 
			 | 
		
		
	
		
			
			| 
				245
			 | 
			
				
			 | 
			
			
				
				-			used += ssnprintf ( ( buf + used ), ( size - used ), 
			 | 
		
		
	
		
			
			| 
				246
			 | 
			
				
			 | 
			
			
				
				-					    ":%s", uri->port ); 
			 | 
		
		
	
		
			
			| 
				247
			 | 
			
				
			 | 
			
			
				
				-		} 
			 | 
		
		
	
		
			
			| 
				248
			 | 
			
				
			 | 
			
			
				
				-	} 
			 | 
		
		
	
		
			
			| 
				249
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				250
			 | 
			
				
			 | 
			
			
				
				-	/* /path */ 
			 | 
		
		
	
		
			
			| 
				251
			 | 
			
				
			 | 
			
			
				
				-	if ( uri->path ) { 
			 | 
		
		
	
		
			
			| 
				252
			 | 
			
				
			 | 
			
			
				
				-		used += ssnprintf ( ( buf + used ), ( size - used ), 
			 | 
		
		
	
		
			
			| 
				253
			 | 
			
				
			 | 
			
			
				
				-				    "%s", uri->path ); 
			 | 
		
		
	
		
			
			| 
				254
			 | 
			
				
			 | 
			
			
				
				-	} 
			 | 
		
		
	
		
			
			| 
				255
			 | 
			
				254
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				256
			 | 
			
				
			 | 
			
			
				
				-	/* ?query */ 
			 | 
		
		
	
		
			
			| 
				257
			 | 
			
				
			 | 
			
			
				
				-	if ( uri->query ) { 
			 | 
		
		
	
		
			
			| 
				258
			 | 
			
				
			 | 
			
			
				
				-		used += ssnprintf ( ( buf + used ), ( size - used ), 
			 | 
		
		
	
		
			
			| 
				259
			 | 
			
				
			 | 
			
			
				
				-				    "?%s", uri->query ); 
			 | 
		
		
	
		
			
			| 
				260
			 | 
			
				
			 | 
			
			
				
				-	} 
			 | 
		
		
	
		
			
			| 
				261
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				262
			 | 
			
				
			 | 
			
			
				
				-	/* #fragment */ 
			 | 
		
		
	
		
			
			| 
				263
			 | 
			
				
			 | 
			
			
				
				-	if ( uri->fragment ) { 
			 | 
		
		
	
		
			
			| 
				264
			 | 
			
				
			 | 
			
			
				
				-		used += ssnprintf ( ( buf + used ), ( size - used ), 
			 | 
		
		
	
		
			
			| 
				265
			 | 
			
				
			 | 
			
			
				
				-				    "#%s", uri->fragment ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				255
			 | 
			
			
				
				+			/* Only print separator if an earlier field exists */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				256
			 | 
			
			
				
				+			if ( sep && ( fields & ( ( 1 << i ) - 1 ) ) ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				257
			 | 
			
			
				
				+				used += ssnprintf ( buf + used, size - used, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				258
			 | 
			
			
				
				+						    "%c", sep ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				259
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				260
			 | 
			
			
				
				+			/* Print contents of field, possibly encoded */ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				261
			 | 
			
			
				
				+			if ( URI_ENCODED & ( 1 << i ) ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				262
			 | 
			
			
				
				+				used += uri_encode ( field, buf + used, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				263
			 | 
			
			
				
				+						     size - used, i ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				264
			 | 
			
			
				
				+			else 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				265
			 | 
			
			
				
				+				used += ssnprintf ( buf + used, size - used, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				266
			 | 
			
			
				
				+						    "%s", field ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				267
			 | 
			
			
				
				+		} 
			 | 
		
		
	
		
			
			| 
				266
			 | 
			
				268
			 | 
			
			
				
				 	} 
			 | 
		
		
	
		
			
			| 
				267
			 | 
			
				269
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				268
			 | 
			
				270
			 | 
			
			
				
				 	return used; 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -277,10 +279,10 @@ int unparse_uri ( char *buf, size_t size, struct uri *uri ) { 
			 | 
		
		
	
		
			
			| 
				277
			 | 
			
				279
			 | 
			
			
				
				  * Creates a modifiable copy of a URI. 
			 | 
		
		
	
		
			
			| 
				278
			 | 
			
				280
			 | 
			
			
				
				  */ 
			 | 
		
		
	
		
			
			| 
				279
			 | 
			
				281
			 | 
			
			
				
				 struct uri * uri_dup ( struct uri *uri ) { 
			 | 
		
		
	
		
			
			| 
				280
			 | 
			
				
			 | 
			
			
				
				-	size_t len = ( unparse_uri ( NULL, 0, uri ) + 1 ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				282
			 | 
			
			
				
				+	size_t len = ( unparse_uri ( NULL, 0, uri, URI_ALL ) + 1 ); 
			 | 
		
		
	
		
			
			| 
				281
			 | 
			
				283
			 | 
			
			
				
				 	char buf[len]; 
			 | 
		
		
	
		
			
			| 
				282
			 | 
			
				284
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				283
			 | 
			
				
			 | 
			
			
				
				-	unparse_uri ( buf, len, uri ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				285
			 | 
			
			
				
				+	unparse_uri ( buf, len, uri, URI_ALL ); 
			 | 
		
		
	
		
			
			| 
				284
			 | 
			
				286
			 | 
			
			
				
				 	return parse_uri ( buf ); 
			 | 
		
		
	
		
			
			| 
				285
			 | 
			
				287
			 | 
			
			
				
				 } 
			 | 
		
		
	
		
			
			| 
				286
			 | 
			
				288
			 | 
			
			
				
				  
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -393,16 +395,31 @@ struct uri * resolve_uri ( struct uri *base_uri, 
			 | 
		
		
	
		
			
			| 
				393
			 | 
			
				395
			 | 
			
			
				
				  * Test for unreserved URI characters 
			 | 
		
		
	
		
			
			| 
				394
			 | 
			
				396
			 | 
			
			
				
				  * 
			 | 
		
		
	
		
			
			| 
				395
			 | 
			
				397
			 | 
			
			
				
				  * @v c			Character to test 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				398
			 | 
			
			
				
				+ * @v field		Field of URI in which character lies 
			 | 
		
		
	
		
			
			| 
				396
			 | 
			
				399
			 | 
			
			
				
				  * @ret is_unreserved	Character is an unreserved character 
			 | 
		
		
	
		
			
			| 
				397
			 | 
			
				400
			 | 
			
			
				
				  */ 
			 | 
		
		
	
		
			
			| 
				398
			 | 
			
				
			 | 
			
			
				
				-static int is_unreserved_uri_char ( int c ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				401
			 | 
			
			
				
				+static int is_unreserved_uri_char ( int c, int field ) { 
			 | 
		
		
	
		
			
			| 
				399
			 | 
			
				402
			 | 
			
			
				
				 	/* According to RFC3986, the unreserved character set is 
			 | 
		
		
	
		
			
			| 
				400
			 | 
			
				403
			 | 
			
			
				
				 	 * 
			 | 
		
		
	
		
			
			| 
				401
			 | 
			
				404
			 | 
			
			
				
				 	 * A-Z a-z 0-9 - _ . ~ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				405
			 | 
			
			
				
				+	 * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				406
			 | 
			
			
				
				+	 * but we also pass & ; = in queries, / in paths, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				407
			 | 
			
			
				
				+	 * and everything in opaques 
			 | 
		
		
	
		
			
			| 
				402
			 | 
			
				408
			 | 
			
			
				
				 	 */ 
			 | 
		
		
	
		
			
			| 
				403
			 | 
			
				
			 | 
			
			
				
				-	return ( isupper ( c ) || islower ( c ) || isdigit ( c ) || 
			 | 
		
		
	
		
			
			| 
				404
			 | 
			
				
			 | 
			
			
				
				-		 ( c == '-' ) || ( c == '_' ) || 
			 | 
		
		
	
		
			
			| 
				405
			 | 
			
				
			 | 
			
			
				
				-		 ( c == '.' ) || ( c == '~' ) ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				409
			 | 
			
			
				
				+	int ok = ( isupper ( c ) || islower ( c ) || isdigit ( c ) || 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				410
			 | 
			
			
				
				+		    ( c == '-' ) || ( c == '_' ) || 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				411
			 | 
			
			
				
				+		    ( c == '.' ) || ( c == '~' ) ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				412
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				413
			 | 
			
			
				
				+	if ( field == URI_QUERY ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				414
			 | 
			
			
				
				+		ok = ok || ( c == ';' ) || ( c == '&' ) || ( c == '=' ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				415
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				416
			 | 
			
			
				
				+	if ( field == URI_PATH ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				417
			 | 
			
			
				
				+		ok = ok || ( c == '/' ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				418
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				419
			 | 
			
			
				
				+	if ( field == URI_OPAQUE ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				420
			 | 
			
			
				
				+		ok = 1; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				421
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				422
			 | 
			
			
				
				+	return ok; 
			 | 
		
		
	
		
			
			| 
				406
			 | 
			
				423
			 | 
			
			
				
				 } 
			 | 
		
		
	
		
			
			| 
				407
			 | 
			
				424
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				408
			 | 
			
				425
			 | 
			
			
				
				 /** 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -411,18 +428,20 @@ static int is_unreserved_uri_char ( int c ) { 
			 | 
		
		
	
		
			
			| 
				411
			 | 
			
				428
			 | 
			
			
				
				  * @v raw_string	String to be URI-encoded 
			 | 
		
		
	
		
			
			| 
				412
			 | 
			
				429
			 | 
			
			
				
				  * @v buf		Buffer to contain encoded string 
			 | 
		
		
	
		
			
			| 
				413
			 | 
			
				430
			 | 
			
			
				
				  * @v len		Length of buffer 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				431
			 | 
			
			
				
				+ * @v field		Field of URI in which string lies 
			 | 
		
		
	
		
			
			| 
				414
			 | 
			
				432
			 | 
			
			
				
				  * @ret len		Length of encoded string (excluding NUL) 
			 | 
		
		
	
		
			
			| 
				415
			 | 
			
				433
			 | 
			
			
				
				  */ 
			 | 
		
		
	
		
			
			| 
				416
			 | 
			
				
			 | 
			
			
				
				-size_t uri_encode ( const char *raw_string, char *buf, size_t len ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				434
			 | 
			
			
				
				+size_t uri_encode ( const char *raw_string, char *buf, ssize_t len, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				435
			 | 
			
			
				
				+		    int field ) { 
			 | 
		
		
	
		
			
			| 
				417
			 | 
			
				436
			 | 
			
			
				
				 	ssize_t remaining = len; 
			 | 
		
		
	
		
			
			| 
				418
			 | 
			
				437
			 | 
			
			
				
				 	size_t used; 
			 | 
		
		
	
		
			
			| 
				419
			 | 
			
				438
			 | 
			
			
				
				 	unsigned char c; 
			 | 
		
		
	
		
			
			| 
				420
			 | 
			
				439
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				421
			 | 
			
				
			 | 
			
			
				
				-	if ( len ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				440
			 | 
			
			
				
				+	if ( len > 0 ) 
			 | 
		
		
	
		
			
			| 
				422
			 | 
			
				441
			 | 
			
			
				
				 		buf[0] = '\0'; 
			 | 
		
		
	
		
			
			| 
				423
			 | 
			
				442
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				424
			 | 
			
				443
			 | 
			
			
				
				 	while ( ( c = *(raw_string++) ) ) { 
			 | 
		
		
	
		
			
			| 
				425
			 | 
			
				
			 | 
			
			
				
				-		if ( is_unreserved_uri_char ( c ) ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				444
			 | 
			
			
				
				+		if ( is_unreserved_uri_char ( c, field ) ) { 
			 | 
		
		
	
		
			
			| 
				426
			 | 
			
				445
			 | 
			
			
				
				 			used = ssnprintf ( buf, remaining, "%c", c ); 
			 | 
		
		
	
		
			
			| 
				427
			 | 
			
				446
			 | 
			
			
				
				 		} else { 
			 | 
		
		
	
		
			
			| 
				428
			 | 
			
				447
			 | 
			
			
				
				 			used = ssnprintf ( buf, remaining, "%%%02X", c ); 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -441,17 +460,17 @@ size_t uri_encode ( const char *raw_string, char *buf, size_t len ) { 
			 | 
		
		
	
		
			
			| 
				441
			 | 
			
				460
			 | 
			
			
				
				  * @v buf		Buffer to contain decoded string 
			 | 
		
		
	
		
			
			| 
				442
			 | 
			
				461
			 | 
			
			
				
				  * @v len		Length of buffer 
			 | 
		
		
	
		
			
			| 
				443
			 | 
			
				462
			 | 
			
			
				
				  * @ret len		Length of decoded string (excluding NUL) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				463
			 | 
			
			
				
				+ * 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				464
			 | 
			
			
				
				+ * This function may be used in-place, with @a buf the same as 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				465
			 | 
			
			
				
				+ * @a encoded_string. 
			 | 
		
		
	
		
			
			| 
				444
			 | 
			
				466
			 | 
			
			
				
				  */ 
			 | 
		
		
	
		
			
			| 
				445
			 | 
			
				
			 | 
			
			
				
				-size_t uri_decode ( const char *encoded_string, char *buf, size_t len ) { 
			 | 
		
		
	
		
			
			| 
				446
			 | 
			
				
			 | 
			
			
				
				-	ssize_t remaining = len; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				467
			 | 
			
			
				
				+size_t uri_decode ( const char *encoded_string, char *buf, ssize_t len ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				468
			 | 
			
			
				
				+	ssize_t remaining; 
			 | 
		
		
	
		
			
			| 
				447
			 | 
			
				469
			 | 
			
			
				
				 	char hexbuf[3]; 
			 | 
		
		
	
		
			
			| 
				448
			 | 
			
				470
			 | 
			
			
				
				 	char *hexbuf_end; 
			 | 
		
		
	
		
			
			| 
				449
			 | 
			
				471
			 | 
			
			
				
				 	unsigned char c; 
			 | 
		
		
	
		
			
			| 
				450
			 | 
			
				472
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				451
			 | 
			
				
			 | 
			
			
				
				-	if ( len ) 
			 | 
		
		
	
		
			
			| 
				452
			 | 
			
				
			 | 
			
			
				
				-		buf[0] = '\0'; 
			 | 
		
		
	
		
			
			| 
				453
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				454
			 | 
			
				
			 | 
			
			
				
				-	while ( *encoded_string ) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				473
			 | 
			
			
				
				+	for ( remaining = len; *encoded_string; remaining-- ) { 
			 | 
		
		
	
		
			
			| 
				455
			 | 
			
				474
			 | 
			
			
				
				 		if ( *encoded_string == '%' ) { 
			 | 
		
		
	
		
			
			| 
				456
			 | 
			
				475
			 | 
			
			
				
				 			encoded_string++; 
			 | 
		
		
	
		
			
			| 
				457
			 | 
			
				476
			 | 
			
			
				
				 			snprintf ( hexbuf, sizeof ( hexbuf ), "%s", 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -461,7 +480,12 @@ size_t uri_decode ( const char *encoded_string, char *buf, size_t len ) { 
			 | 
		
		
	
		
			
			| 
				461
			 | 
			
				480
			 | 
			
			
				
				 		} else { 
			 | 
		
		
	
		
			
			| 
				462
			 | 
			
				481
			 | 
			
			
				
				 			c = *(encoded_string++); 
			 | 
		
		
	
		
			
			| 
				463
			 | 
			
				482
			 | 
			
			
				
				 		} 
			 | 
		
		
	
		
			
			| 
				464
			 | 
			
				
			 | 
			
			
				
				-		ssnprintf ( buf++, remaining--, "%c", c ); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				483
			 | 
			
			
				
				+		if ( remaining > 1 ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				484
			 | 
			
			
				
				+			*buf++ = c; 
			 | 
		
		
	
		
			
			| 
				465
			 | 
			
				485
			 | 
			
			
				
				 	} 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				486
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				487
			 | 
			
			
				
				+	if ( len ) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				488
			 | 
			
			
				
				+		*buf = 0; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				489
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				466
			 | 
			
				490
			 | 
			
			
				
				 	return ( len - remaining ); 
			 | 
		
		
	
		
			
			| 
				467
			 | 
			
				491
			 | 
			
			
				
				 } 
			 |