# # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # This function is indended to be the inverse of parse_url, with some sanity # checks against RFC 3986. function unparse_url($parts, $loose=FALSE) { $p_scheme = @$parts['scheme']; $p_host = @$parts['host']; $p_port = @$parts['port']; $p_user = @$parts['user']; $p_pass = @$parts['pass']; $p_path = @$parts['path']; $p_query = @$parts['query']; $p_fragment = @$parts['fragment']; if (!$loose) { $dec_octet = '(?:\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])'; $IPv4address = "(?:$dec_octet\\.$dec_octet\\.$dec_octet\\.$dec_octet)"; $h16 = '(?:[[:xdigit:]]{1,4})'; $ls32 = '(?:'.$h16.':'.$h16.'|'.$IPv4address.')'; $IPv6address = "(?:". "(?:$h16:){6}$ls32|". "::(?:$h16:){5}$ls32|". "$h16?::(?:$h16:){4}$ls32|". "(?:(?:$h16:){0,1}$h16)?::(?:$h16:){3}$ls32|". "(?:(?:$h16:){0,2}$h16)?::(?:$h16:){2}$ls32|". "(?:(?:$h16:){0,3}$h16)?::(?:$h16:){1}$ls32|". "(?:(?:$h16:){0,4}$h16)?::" . "$ls32|". "(?:(?:$h16:){0,5}$h16)?::" . "$h16|". "(?:(?:$h16:){0,6}$h16)?::". ")"; $unreserved = '[[:alpha:]\d\-\._~]'; $sub_delims = "[!\$&'()\*\+,;=]"; $IPvFuture = "(?:v[[:xdigit:]]+\\.[$unreserved$sub_delims\\:]+)"; $IP_literal = "(?:\\[(?:$IPv6address|$IPvFuture)\\])"; $pct_encoded = "(?:%[[:xdigit:]]{2})"; $reg_name = "(?:$unreserved|$pct_encoded|$sub_delims)*"; $pchar = "(?:$unreserved|$pct_encoded|$sub_delims|\:@)"; $segment = "$pchar*"; $segment_nz = "$pchar+"; $path_absolute = "(?:/(?:$segment_nz(?:/$segment)*)?)"; $path_rootless = "$segment_nz(?:/$segment)*"; # Validate the scheme part # scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) # NB: "file" is hard-coded in PHP if (isset($p_scheme) and !preg_match('|^[[:alpha:]][[:alpha:]\d\+\-\.]*$|s', $p_scheme)) { trigger_error('Illegal URI scheme', E_USER_WARNING); return FALSE; } # Validate the host part if (isset($p_host) and !preg_match("#^(?:$IP_literal|$IPv4address|$reg_name)\$#s", $p_host)) { trigger_error('Illegal host part', E_USER_WARNING); return FALSE; } # Validate the port part if (isset($p_port) and !preg_match("#^\d*\$#s", $p_port)) { trigger_error('Illegal port part', E_USER_WARNING); return FALSE; } # Validate the user part if (isset($p_user) and !preg_match("#^(?:$unreserved|$pct_encoded|$sub_delims)*\$#s", $p_user)) { trigger_error('Illegal user part', E_USER_WARNING); return FALSE; } # Validate the password part if (isset($p_pass) and !preg_match("#^(?:$unreserved|$pct_encoded|$sub_delims|:)*\$#s", $p_pass)) { trigger_error('Illegal pass part', E_USER_WARNING); return FALSE; } # Validate the path part if (isset($p_path) and !preg_match("#^$path_absolute|$path_rootless\$#s", $p_path)) { trigger_error('Illegal path part', E_USER_WARNING); return FALSE; } # Validate the query part if (isset($p_query) and !preg_match("#^(?:$pchar|/|\?)*\$#s", $p_query)) { trigger_error('Illegal query part', E_USER_WARNING); return FALSE; } # Validate the fragment part if (isset($p_fragment) and !preg_match("#^(?:$pchar|/|\?)*\$#s", $p_fragment)) { trigger_error('Illegal fragment part', E_USER_WARNING); return FALSE; } } # Build the URI $retval = ""; if (isset($p_scheme)) { $retval = $p_scheme . ":"; if (strtolower($p_scheme) == "file" and !isset($p_host)) { $retval .= "//"; } } if (isset($p_host)) { $retval .= "//"; if (isset($p_user) or isset($p_pass)) { $retval .= isset($p_user) ? $p_user : ""; $retval .= isset($p_pass) ? ":" . $p_pass : ""; $retval .= '@'; } $retval .= $p_host; if (isset($p_port)) { $retval .= ':' . $p_port; } } if (isset($p_path)) { $retval .= $p_path; } if (isset($p_query)) { $retval .= '?' . $p_query; } if (isset($p_fragment)) { $retval .= '#' . $p_fragment; } return $retval; } /* vim:set ts=4 sw=4 sts=4 expandtab: */