{
/* Non-printing characters and whitespace should always be * escaped, since they cannot sensibly be displayed as part of * a coherent URL string. (This test also catches control * characters such as CR and LF, which could affect the * operation of line-based protocols such as HTTP.) * * We should also escape characters which would alter the * interpretation of the URL if not escaped, i.e. characters * which have significance to the URL parser. We should not * blindly escape all such characters, because this would lead * to some very strange-looking URLs (e.g. if we were to * always escape '/' as "%2F" even within the URI path). * * We do not need to be perfect. Our primary role is as a * consumer of URIs rather than a producer; the main situation * in which we produce a URI string is for display to a human * user, who can probably tolerate some variance from the * formal specification. The only situation in which we * currently produce a URI string to be consumed by a computer * is when constructing an HTTP request URI, which contains * only the path and query fields. * * We can therefore sacrifice some correctness for the sake of * code size. For example, colons within the URI host should * be escaped unless they form part of an IPv6 literal * address; doing this correctly would require the URI * formatter to be aware of whether or not the URI host * contained an IPv4 address, an IPv6 address, or a host name. * We choose to simplify and never escape colons within the * URI host field: in the event of a pathological hostname * containing colons, this could potentially produce a URI * string which could not be reparsed. * * After excluding non-printing characters, whitespace, and * '%', the full set of characters with significance to the * URL parser is "/#:@?". We choose for each URI field which * of these require escaping in our use cases. * * For the scheme field (equivalently, if field is zero), we * escape anything that has significance not just for our URI * parser but for any other URI parsers (e.g. HTTP query * string parsers, which care about '=' and '&'). */staticconstchar *escaped[URI_FIELDS] = {
/* Scheme or default: escape everything */
[URI_SCHEME] = "/#:@?=&",
/* Opaque part: escape characters which would affect * the reparsing of the URI, allowing everything else * (e.g. ':', which will appear in iSCSI URIs). */
[URI_OPAQUE] = "#",
/* User name: escape everything */
[URI_USER] = "/#:@?",
/* Password: escape everything */
[URI_PASSWORD] = "/#:@?",
/* Host name: escape everything except ':', which may * appear as part of an IPv6 literal address. */
[URI_HOST] = "/#@?",
/* Port number: escape everything */
[URI_PORT] = "/#:@?",
/* Path: escape everything except '/', which usually * appears within paths. */
[URI_PATH] = "#:@?",
/* Query: escape everything except '/', which * sometimes appears within queries. */
[URI_QUERY] = "#:@?",
/* Fragment: escape everything */
[URI_FRAGMENT] = "/#:@?",
};
return ( /* Always escape non-printing characters and whitespace */
( ! isprint ( c ) ) || ( c == ' ' ) ||
/* Always escape '%' */
( c == '%' ) ||
/* Escape field-specific characters */strchr ( escaped[field], c ) );
}

Takes a base path (e.g. "/var/lib/tftpboot/vmlinuz" and a relative path (e.g. "initrd.gz") and produces a new path (e.g. "/var/lib/tftpboot/initrd.gz"). Note that any non-directory portion of the base path will automatically be stripped; this matches the semantics used when resolving the path component of URIs.

PXE TFTP filenames specified via the DHCP next-server field often contain characters such as ':' or '#' which would confuse the generic URI parser. We provide a mechanism for directly constructing a TFTP URI from the next-server and filename.