Beispiel #1
0
/**
 * Copy URI fields
 *
 * @v src		Source URI
 * @v dest		Destination URI, or NULL to calculate length
 * @ret len		Length of raw URI
 */
static size_t uri_copy_fields ( const struct uri *src, struct uri *dest ) {
	size_t len = sizeof ( *dest );
	char *out = ( ( void * ) dest + len );
	unsigned int field;
	size_t field_len;

	/* Copy existent fields */
	for ( field = 0 ; field < URI_FIELDS ; field++ ) {

		/* Skip non-existent fields */
		if ( ! uri_field ( src, field ) )
			continue;

		/* Calculate field length */
		field_len = ( strlen ( uri_field ( src, field ) )
			      + 1 /* NUL */ );
		len += field_len;

		/* Copy field, if applicable */
		if ( dest ) {
			memcpy ( out, uri_field ( src, field ), field_len );
			uri_field ( dest, field ) = out;
			out += field_len;
		}
	}
	return len;
}
Beispiel #2
0
/**
 * Format URI
 *
 * @v uri		URI
 * @v buf		Buffer to fill with URI string
 * @v size		Size of buffer
 * @ret len		Length of URI string
 */
size_t format_uri ( const struct uri *uri, char *buf, size_t len ) {
	static const char prefixes[URI_FIELDS] = {
		[URI_OPAQUE] = ':',
		[URI_PASSWORD] = ':',
		[URI_PORT] = ':',
		[URI_PATH] = '/',
		[URI_QUERY] = '?',
		[URI_FRAGMENT] = '#',
	};
	char prefix;
	size_t used = 0;
	unsigned int field;

	/* Ensure buffer is NUL-terminated */
	if ( len )
		buf[0] = '\0';

	/* Special-case NULL URI */
	if ( ! uri )
		return 0;

	/* Generate fields */
	for ( field = 0 ; field < URI_FIELDS ; field++ ) {

		/* Skip non-existent fields */
		if ( ! uri_field ( uri, field ) )
			continue;

		/* Prefix this field, if applicable */
		prefix = prefixes[field];
		if ( ( field == URI_HOST ) && ( uri->user != NULL ) )
			prefix = '@';
		if ( ( field == URI_PATH ) && ( uri->path[0] == '/' ) )
			prefix = '\0';
		if ( prefix ) {
			used += ssnprintf ( ( buf + used ), ( len - used ),
					    "%c", prefix );
		}

		/* Encode this field */
		used += uri_encode ( uri_field ( uri, field ), field,
				     ( buf + used ), ( len - used ) );

		/* Suffix this field, if applicable */
		if ( ( field == URI_SCHEME ) && ( ! uri->opaque ) ) {
			used += ssnprintf ( ( buf + used ), ( len - used ),
					    "://" );
		}
	}

	if ( len ) {
		DBGC ( uri, "URI formatted" );
		uri_dump ( uri );
		DBGC ( uri, " to \"%s%s\"\n", buf,
		       ( ( used > len ) ? "<TRUNCATED>" : "" ) );
	}

	return used;
}
Beispiel #3
0
Datei: uri.c Projekt: brain0/ipxe
/**
 * Decode URI field in-place
 *
 * @v uri		URI
 * @v field		URI field index
 */
static void uri_decode_inplace ( struct uri *uri, unsigned int field ) {
    const char *encoded = uri_field ( uri, field );
    char *decoded = ( ( char * ) encoded );
    size_t len;

    /* Do nothing if field is not present */
    if ( ! encoded )
        return;

    /* Decode field in place */
    len = uri_decode ( encoded, decoded, strlen ( encoded ) );

    /* Terminate decoded string */
    decoded[len] = '\0';
}
Beispiel #4
0
/**
 * Parse URI
 *
 * @v uri_string	URI as a string
 * @ret uri		URI
 *
 * Splits a URI into its component parts.  The return URI structure is
 * dynamically allocated and must eventually be freed by calling
 * uri_put().
 */
struct uri * parse_uri ( const char *uri_string ) {
	struct uri *uri;
	struct parameters *params;
	char *raw;
	char *tmp;
	char *path;
	char *authority;
	size_t raw_len;
	unsigned int field;

	/* Allocate space for URI struct and a copy of the string */
	raw_len = ( strlen ( uri_string ) + 1 /* NUL */ );
	uri = zalloc ( sizeof ( *uri ) + raw_len );
	if ( ! uri )
		return NULL;
	ref_init ( &uri->refcnt, uri_free );
	raw = ( ( ( void * ) uri ) + sizeof ( *uri ) );

	/* Copy in the raw string */
	memcpy ( raw, uri_string, raw_len );

	/* Identify the parameter list, if present */
	if ( ( tmp = strstr ( raw, "##params" ) ) ) {
		*tmp = '\0';
		tmp += 8 /* "##params" */;
		params = find_parameters ( *tmp ? ( tmp + 1 ) : NULL );
		if ( params ) {
			uri->params = claim_parameters ( params );
		} else {
			/* Ignore non-existent submission blocks */
		}
	}

	/* Chop off the fragment, if it exists */
	if ( ( tmp = strchr ( raw, '#' ) ) ) {
		*(tmp++) = '\0';
		uri->fragment = tmp;
	}

	/* Identify absolute/relative URI */
	if ( ( tmp = strchr ( raw, ':' ) ) ) {
		/* Absolute URI: identify hierarchical/opaque */
		uri->scheme = raw;
		*(tmp++) = '\0';
		if ( *tmp == '/' ) {
			/* Absolute URI with hierarchical part */
			path = tmp;
		} else {
			/* Absolute URI with opaque part */
			uri->opaque = tmp;
			path = NULL;
		}
	} else {
		/* Relative URI */
		path = raw;
	}

	/* If we don't have a path (i.e. we have an absolute URI with
	 * an opaque portion, we're already finished processing
	 */
	if ( ! path )
		goto done;

	/* Chop off the query, if it exists */
	if ( ( tmp = strchr ( path, '?' ) ) ) {
		*(tmp++) = '\0';
		uri->query = tmp;
	}

	/* If we have no path remaining, then we're already finished
	 * processing.
	 */
	if ( ! path[0] )
		goto done;

	/* Identify net/absolute/relative path */
	if ( strncmp ( path, "//", 2 ) == 0 ) {
		/* Net path.  If this is terminated by the first '/'
		 * of an absolute path, then we have no space for a
		 * terminator after the authority field, so shuffle
		 * the authority down by one byte, overwriting one of
		 * the two slashes.
		 */
		authority = ( path + 2 );
		if ( ( tmp = strchr ( authority, '/' ) ) ) {
			/* Shuffle down */
			uri->path = tmp;
			memmove ( ( authority - 1 ), authority,
				  ( tmp - authority ) );
			authority--;
			*(--tmp) = '\0';
		}
	} else {
		/* Absolute/relative path */
		uri->path = path;
		authority = NULL;
	}

	/* If we don't have an authority (i.e. we have a non-net
	 * path), we're already finished processing
	 */
	if ( ! authority )
		goto done;

	/* Split authority into user[:password] and host[:port] portions */
	if ( ( tmp = strchr ( authority, '@' ) ) ) {
		/* Has user[:password] */
		*(tmp++) = '\0';
		uri->host = tmp;
		uri->user = authority;
		if ( ( tmp = strchr ( authority, ':' ) ) ) {
			/* Has password */
			*(tmp++) = '\0';
			uri->password = tmp;
		}
	} else {
		/* No user:password */
		uri->host = authority;
	}

	/* Split host into host[:port] */
	if ( ( uri->host[ strlen ( uri->host ) - 1 ] != ']' ) &&
	     ( tmp = strrchr ( uri->host, ':' ) ) ) {
		*(tmp++) = '\0';
		uri->port = tmp;
	}

	/* Decode fields in-place */
	for ( field = 0 ; field < URI_FIELDS ; field++ ) {
		if ( uri_field ( uri, field ) )
			uri_decode ( ( char * ) uri_field ( uri, field ) );
	}

 done:
	DBGC ( uri, "URI parsed \"%s\" to", uri_string );
	uri_dump ( uri );
	DBGC ( uri, "\n" );

	return uri;
}