YXg& bQT&4>qZ[tH;g_z1LWztF+Fc]^/}")pFheT8,0cE_[uEɮu&^]wBbg"L;3b ?#5M’F1z,I I,dwuZԵhj20\v#sX~*hፒ/ _i`jIg=Il u7ְۀ_ʓzsi/[t h[P4uIiM6t jV;A&Lbu " u X;A\G/A1̰F-]UCD&g&\vvxkel}S~'C%"a.Br ?ͬe{)$TX,ǥg,]'J fgx 72)FRy vA ( 0#[[5pN0Ό??S7bG>,u]T!g6!`ppLZy{X'Y}9]KED.Wl~Q+\6=?/غ+mʁ3׫[ZZqӱ0]-SnSqCMxe^с39jic:u75,y\_Œ2KBշ",3l\<%NJH0 {RbI=Ti:KkaI%~B;(F'l|bpʥ/ "JHO~2A?Ikx(`sI+_TJlng`P2N9 ׎E.8f80^zx'_-^gMQm ;S9g,qM> ?*_gha)KN"`UUdrWy3|\OڗBNtzG)GqǭBx*|ŇBi>PnaMɞ2ӥqR>^;O1r&T`rfng-.b4Ŀ&!IUǙcV6ϯ2UV 4ĈYlvԿ2"8I{44pq7p $4TP-ZB/m1aIprH n"^ /5ͺs+ge-g E62ɍĜP`$x&$Tm^g3O,NZ˾G:>Oσ5R|8ʎ,0qH,BzҢJƌD[Ì7yyoC:1vҷn.ArX噲?㮖\[LiPHhkM/k582tnu Yu<$zERԥ? ]̅!<- >ǬeۥF%#GM ? ĢQ$3D IDJ µ YfqX23d{q {Ԝfj ejT@Gw8 h ĢQ$3y,]G6/hN ĢQ$3<0R8]KYi"+Kq$ܽ*0g_Iڪ١ 'bmaI(X6i} %IZ:g0F Roۘ FjJ(mYvn4ziPGQsTO>dW)!<܉u]PrCEo^x;>ҠfszI=$=輴@dr:Ab(|({w b)!V};VX'o}ߞ(䲯Z D7Uâ2r1S -C?`N:|bl{3꼶l%|h1Z0אe=ECZ:9(.I; G@uaD]O lUSN)kJ! "=5Xz" /;(=ׅ+)m'$LYNII~CD4-吤hw43LjC]5E $2-uh!w.( = J 41" )<}{ؿ[K FY5;G-2{*ٿ词 oNN9! O4%Ze%ש5=҅}] ZClxYUHQTQ$6EeџڳhTV7 RuieUBTKp9 T R13sl狂OU'||ؿ,%80)uåA i [[(k[]،'C/Ui^uYnܸiR}aܰG@%_La2kZ/d~̾I  ;deQ˚e<"YfY) 5Si)b0}b- zlaչ YuiZ9AȖC{vjf8x恲I_ΦAsj.REZ1y܎㑿 ܁0z,X!xޢ}~=UJUab l&cL}i/sxe) ވ;Is әNzlAy1LUT.I/21˷f-Lץ1><%X7mTϙcbS3g*'jWFoռv)$6_s<xww0 h;Iy+,^\F$Bm+G[-6("wln8X|ĴK178 P; Df,3 '=ZVM4pdM~xB81*tO[)x[nڵR}nzM^.QsDcheme is present, so axe it when possible $def = $config->getDefinition('URI'); if ($def->defaultScheme === $this->scheme) { $this->scheme = null; } } // validate username if (!is_null($this->userinfo)) { $encoder = new HTMLPurifier_PercentEncoder($chars_sub_delims . ':'); $this->userinfo = $encoder->encode($this->userinfo); } // validate port if (!is_null($this->port)) { if ($this->port < 1 || $this->port > 65535) { $this->port = null; } } // validate path $segments_encoder = new HTMLPurifier_PercentEncoder($chars_pchar . '/'); if (!is_null($this->host)) { // this catches $this->host === '' // path-abempty (hier and relative) // http://www.example.com/my/path // //www.example.com/my/path (looks odd, but works, and // recognized by most browsers) // (this set is valid or invalid on a scheme by scheme // basis, so we'll deal with it later) // file:///my/path // ///my/path $this->path = $segments_encoder->encode($this->path); } elseif ($this->path !== '') { if ($this->path[0] === '/') { // path-absolute (hier and relative) // http:/my/path // /my/path if (strlen($this->path) >= 2 && $this->path[1] === '/') { // This could happen if both the host gets stripped // out // http://my/path // //my/path $this->path = ''; } else { $this->path = $segments_encoder->encode($this->path); } } elseif (!is_null($this->scheme)) { // path-rootless (hier) // http:my/path // Short circuit evaluation means we don't need to check nz $this->path = $segments_encoder->encode($this->path); } else { // path-noscheme (relative) // my/path // (once again, not checking nz) $segment_nc_encoder = new HTMLPurifier_PercentEncoder($chars_sub_delims . '@'); $c = strpos($this->path, '/'); if ($c !== false) { $this->path = $segment_nc_encoder->encode(substr($this->path, 0, $c)) . $segments_encoder->encode(substr($this->path, $c)); } else { $this->path = $segment_nc_encoder->encode($this->path); } } } else { // path-empty (hier and relative) $this->path = ''; // just to be safe } // qf = query and fragment $qf_encoder = new HTMLPurifier_PercentEncoder($chars_pchar . '/?'); if (!is_null($this->query)) { $this->query = $qf_encoder->encode($this->query); } if (!is_null($this->fragment)) { $this->fragment = $qf_encoder->encode($this->fragment); } return true; } /** * Convert URI back to string * @return string URI appropriate for output */ public function toString() { // reconstruct authority $authority = null; // there is a rendering difference between a null authority // (http:foo-bar) and an empty string authority // (http:///foo-bar). if (!is_null($this->host)) { $authority = ''; if (!is_null($this->userinfo)) { $authority .= $this->userinfo . '@'; } $authority .= $this->host; if (!is_null($this->port)) { $authority .= ':' . $this->port; } } // Reconstruct the result // One might wonder about parsing quirks from browsers after // this reconstruction. Unfortunately, parsing behavior depends // on what *scheme* was employed (file:///foo is handled *very* // differently than http:///foo), so unfortunately we have to // defer to the schemes to do the right thing. $result = ''; if (!is_null($this->scheme)) { $result .= $this->scheme . ':'; } if (!is_null($authority)) { $result .= '//' . $authority; } $result .= $this->path; if (!is_null($this->query)) { $result .= '?' . $this->query; } if (!is_null($this->fragment)) { $result .= '#' . $this->fragment; } return $result; } /** * Returns true if this URL might be considered a 'local' URL given * the current context. This is true when the host is null, or * when it matches the host supplied to the configuration. * * Note that this does not do any scheme checking, so it is mostly * only appropriate for metadata that doesn't care about protocol * security. isBenign is probably what you actually want. * @param HTMLPurifier_Config $config * @param HTMLPurifier_Context $context * @return bool */ public function isLocal($config, $context) { if ($this->host === null) { return true; } $uri_def = $config->getDefinition('URI'); if ($uri_def->host === $this->host) { return true; } return false; } /** * Returns true if this URL should be considered a 'benign' URL, * that is: * * - It is a local URL (isLocal), and * - It has a equal or better level of security * @param HTMLPurifier_Config $config * @param HTMLPurifier_Context $context * @return bool */ public function isBenign($config, $context) { if (!$this->isLocal($config, $context)) { return false; } $scheme_obj = $this->getSchemeObj($config, $context); if (!$scheme_obj) { return false; } // conservative approach $current_scheme_obj = $config->getDefinition('URI')->getDefaultScheme($config, $context); if ($current_scheme_obj->secure) { if (!$scheme_obj->secure) { return false; } } return true; } } // vim: et sw=4 sts=4