| [ Index ] |
PHP Cross Reference of Drupal 6 (yi-drupal) |
[Summary view] [Print] [Text view]
1 <?php 2 /* 3 * Gallery - a web based photo album viewer and editor 4 * Copyright (C) 2000-2006 Bharat Mediratta 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or (at 9 * your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. 19 */ 20 /** 21 * @version $Revision: 1.3.2.2 $ $Date: 2007/11/27 18:10:32 $ 22 * @package GalleryCore 23 * @author Andy Staudacher <ast@gmx.ch> 24 */ 25 26 /** 27 * A collection of useful G2Embed related utilities to find the correct GalleryEmbed::init 28 * parameters 29 * 30 * @package GalleryCore 31 * @subpackage GalleryEmbed 32 * @static 33 */ 34 class G2EmbedDiscoveryUtilities { 35 /** 36 * Documentation: 37 * To use GalleryEmbed and its GalleryEmbed::init method to initialize G2, you need: 38 * a) the absolute filesystem path to embed.php 39 * b) embedUri, the URL of the entry point to your embedding application / embedded G2 40 * e.g. http://example.com/ or just / , or http://example.com/index.php?mod=gallery 41 * c) g2Uri, the URL path to G2, e.g. http://example.com/gallery2/ or just /gallery2/ 42 * 43 * Methods to finding out the path to embed.php: 44 * ============================================ 45 * 46 * - It's a good assumption that you can find out or define embedUri easily 47 * - g2Uri must be entered by the admin that configures the integration, just copy and paste 48 * the URL of G2 49 * - finding out embed.php is a little tricky. 50 * 51 * We offer two methods to get embed.php. Do NOT call them for each request. Call them once 52 * when configuring / installing your integration. Else you get a performance penalty. 53 * 54 * 1. If you ask the user to enter the g2Uri, you can call: 55 * list ($success, $embedPhpPath, $errorString) = 56 * G2EmbedDiscoveryUtilities::getG2EmbedPathByG2Uri($g2Uri); 57 * if (!$success) { 58 * print $errorString; 59 * /* Tell the admin to enter the correct input 60 * } else { 61 * /* embedPhpPath is correct and you can store it in your config for later use 62 * } 63 * 64 * 2. If you ask only for the g2Uri, you also need to provide the filesystem path to the 65 * entry point (the filesystem path to the file that embedUri points to) 66 * list ($success, $embedPhpPath, $errorString) = 67 * G2EmbedDiscoveryUtilities::getG2EmbedPathByG2UriEmbedUriAndLocation( 68 * $g2Uri, $embedUri, dirname(dirname(__FILE__))); 69 * if (!$success) { 70 * print $errorString; 71 * /* Tell the admin to enter the correct input 72 * } else { 73 * /* embedPhpPath is correct and you can store it in your config for later use 74 * } 75 * Disadvantage of this method: it's less reliable. It won't work with Apache Alias, 76 * or with subdomains, ... 77 * 78 * 79 * Method to normalize the g2Uri and embedUri before using them in GalleryEmbed::init: 80 * ================================================================================== 81 * 82 * Do NOT call them on each request. Call them once to verify / sanitize user input 83 * and then store them in your configuration. 84 * - These methods try their best to be tolerant to common user mistakes and return a 85 * string that GalleryEmbd::init accepts 86 * - You don't have to call these methods before calling the above methods to get 87 * embed.php, since it does that already internally 88 * 89 * 1. $g2Uri = G2EmbedDiscoveryUtilities::normalizeG2Uri($g2Uri); 90 * 2. $embedUri = G2EmbedDiscoveryUtilities::normalizeEmbedUri($embedUri); 91 */ 92 93 /** 94 * The format for g2Uri accepted by GalleryEmbed::init is quite strict and well defined 95 * missing traling / leading slashes have a meaning. 96 * This function is more tolerant for incorrect user input and tries to normalize the 97 * given g2Uri to a value that is probably what the user meant to provide 98 * 99 * The returned URI is either a server-relative URI (e.g. /gallery2/) or an absolute URI 100 * including the schema (e.g. http://example.com/gallery/) 101 * 102 * The file / query string part is always removed) 103 * 104 * @param string g2Uri 105 * @return string normalized g2Uri 106 */ 107 function normalizeG2Uri($g2Uri) { 108 list ($schemaAndHost, $path, $file, $queryString, $fragment) = 109 G2EmbedDiscoveryUtilities::_normalizeUri($g2Uri); 110 111 return $schemaAndHost . $path; 112 } 113 114 /** 115 * @see normalizeG2Uri 116 * 117 * Very similar, but file / query string is kept in the result 118 */ 119 function normalizeEmbedUri($embedUri) { 120 list ($schemaAndHost, $path, $file, $queryString, $fragment) = 121 G2EmbedDiscoveryUtilities::_normalizeUri($embedUri); 122 123 return $schemaAndHost . $path . $file . $queryString . $fragment; 124 } 125 126 /** 127 * Find the absolute filesystem path to G2's embed.php when given the g2Uri 128 * 129 * Returns false if the g2Uri is wrong. Can also fail if G2 and emApp are 130 * on different (sub)domains / IPs 131 * 132 * @param string the g2Uri, a full URL or a server-relative URI 133 * @return array boolean success, 134 * string filesystem path of embed.php 135 * string error string 136 */ 137 function getG2EmbedPathByG2Uri($g2Uri) { 138 $g2Uri = trim($g2Uri); 139 if (empty($g2Uri)) { 140 return array (false, null, "Bad parameter: the provided g2Uri is empty"); 141 } 142 143 $g2Uri = G2EmbedDiscoveryUtilities::normalizeG2Uri($g2Uri); 144 145 /* Add a schema / host part to the g2Uri if necessary */ 146 if (strpos($g2Uri, 'http') !== 0) { 147 $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http'; 148 $host = !empty($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '127.0.0.1'; 149 $g2Uri = sprintf('%s://%s%s', $protocol, $host, $g2Uri); 150 } 151 152 $components = @parse_url($g2Uri); 153 if (!$components) { 154 return array(false, null, "Unable to parse normalized URL $g2Uri. Please enter the " . 155 "full address of your Gallery 2 installation."); 156 } 157 $port = empty($components['port']) ? 80 : $components['port']; 158 if (empty($components['path'])) { 159 $components['path'] = '/'; 160 } 161 162 $fd = @fsockopen($components['host'], $port, $errno, $errstr, 1); 163 if (empty($fd)) { 164 return array(false, null, "Error $errno: '$errstr' retrieving $g2Uri"); 165 } 166 167 $get = $components['path'] . 'embed.php?getEmbedPath=1'; 168 169 /* Read the web page into a buffer */ 170 $ok = fwrite($fd, sprintf("GET %s HTTP/1.0\r\n" . 171 "Host: %s\r\n" . 172 "\r\n", 173 $get, 174 $components['host'])); 175 if (!$ok) { 176 /* Zero bytes written or false was returned */ 177 $errorStr = "Verification of Gallery 2 location failed. fwrite call failed for $g2Uri"; 178 if ($ok === false) { 179 $errorStr .= "\nreturn value was false"; 180 } 181 return array(false, null, $errorStr); 182 } 183 $ok = fflush($fd); 184 if (!$ok) { 185 if (version_compare(phpversion(), '4.2.0', '>=')) { 186 /* Ignore false returned from fflush on PHP 4.1 */ 187 return array(false, null, "Verification of Gallery 2 location failed. " . 188 "fflush call failed for $g2Uri"); 189 } 190 } 191 192 /* 193 * Read the response code. fgets stops after newlines. 194 * The first line contains only the status code (200, 404, etc.). 195 */ 196 $headers = array(); 197 $response = trim(fgets($fd, 4096)); 198 199 /* if the HTTP response code did not begin with a 2 this request was not successful */ 200 if (!preg_match("/^HTTP\/\d+\.\d+\s2\d{2}/", $response)) { 201 return array(false, null, "URL derived from $g2Uri is invalid"); 202 } 203 204 /* Read the headers. */ 205 while (!feof($fd)) { 206 $line = trim(fgets($fd, 4096)); 207 if (empty($line)) { 208 break; 209 } 210 /* Normalize the line endings */ 211 $line = str_replace("\r", '', $line); 212 213 list ($key, $value) = explode(':', $line, 2); 214 $headers[$key] = trim($value); 215 } 216 217 $embedPhpPath = ''; 218 if (isset($headers['X-G2-EMBED-PATH'])) { 219 $embedPhpPath = $headers['X-G2-EMBED-PATH']; 220 } else { 221 return array(false, null, "Either your server does not support the automated " . 222 "verification of the Gallery 2 location or the supplied g2Uri " . 223 "points to a incompatible Gallery 2 version (older than 2.1)"); 224 } 225 226 if (empty($embedPhpPath)) { 227 return array(false, null, "Correct URL, but the returned " . 228 "embed.php path is empty (server error?!)"); 229 } 230 231 /* Verify path */ 232 list ($ok, $errorString) = @G2EmbedDiscoveryUtilities::isFileReadable($embedPhpPath); 233 if (!$ok) { 234 return array(false, null, $errorString); 235 } else { 236 return array(true, $embedPhpPath, null); 237 } 238 } 239 240 /** 241 * Get the absolute filesystem path to embed.php from the given g2Uri, embedUri and the 242 * absolute filesystem path of the entry point file of your embedding application 243 * 244 * Can be unreliable if short URLs are entered or if apache alias / symlinks are used 245 * 246 * @param string g2Uri 247 * @param string embedUri 248 * @param string the dirname of the location of the entry point of your embedding application 249 * e.g. dirname(__FILE__) if your embedUri points right to your wrapper file or if your 250 * wrapper file is in the same directory as the entry point to your emApp 251 * e.g. dirname(dirname(dirname(__FILE__))) if your wrapper is in a 252 * modules/g2integration/wrapper.inc.php file, which is 2 subdirectories deeper than 253 * the actual entry point that embedUri is pointing to 254 * @return array boolean success, 255 * string absolute filesystem path to embed.php, 256 * string errorString 257 */ 258 259 function getG2EmbedPathByG2UriEmbedUriAndLocation($g2Uri, $embedUri, $dirnameOfEmApp) { 260 if (empty($dirnameOfEmApp)) { 261 return array(false, null, 'dirname of embedding application is empty'); 262 } 263 /* Normalize g2Uri, embedUri */ 264 list ($schemaAndHost, $path, $file, $queryString, $fragment) = 265 G2EmbedDiscoveryUtilities::_normalizeUri($g2Uri); 266 $g2Path = $path; 267 list ($schemaAndHost, $path, $file, $queryString, $fragment) = 268 G2EmbedDiscoveryUtilities::_normalizeUri($embedUri); 269 $embedPath = $path; 270 271 /* Normalize path separators */ 272 $dirnameOfEmApp = str_replace(DIRECTORY_SEPARATOR, '/', $dirnameOfEmApp); 273 /* Remove trailing slash */ 274 if (substr($dirnameOfEmApp, -1) == '/') { 275 $dirnameOfEmApp = substr($dirnameOfEmApp, 0, strlen($dirnameOfEmApp) - 1); 276 } 277 278 /* 279 * Do some directory traversal to translate g2Path + embedPath + dirnameOfEmApp 280 * to path to embed.php 281 * path 282 * Example: g2Path = /baz/bar/gallery2/ , embedPath = /baz/cms/foo/ , 283 * dirnameOfEmApp = /home/john/www/cms/foo/ 284 * 1. Remove as many dirs from the end of dirnameOfEmApp as embedPath has 285 * 2. append g2Path to dirnameOfEmApp 286 */ 287 $numberOfSubDirs = count(explode('/', $embedPath)); 288 /* Don't count the one before the leading and after the traling slash */ 289 $numberOfSubDirs -= 2; 290 291 $pathElements = explode('/', $dirnameOfEmApp); 292 $max = 30; /* prevent infinite loop */ 293 while ($numberOfSubDirs-- > 0 && $max-- > 0) { 294 array_pop($pathElements); 295 } 296 297 $embedPhpPath = join('/', $pathElements) . $g2Path . 'embed.php'; 298 299 /* Convert / back to platform specific directory separator */ 300 $embedPhpPath = str_replace('/', DIRECTORY_SEPARATOR, $embedPhpPath); 301 302 /* Verify path */ 303 list ($ok, $errorString) = @G2EmbedDiscoveryUtilities::isFileReadable($embedPhpPath); 304 if (!$ok) { 305 return array(false, null, $errorString); 306 } else { 307 return array(true, $embedPhpPath, null); 308 } 309 } 310 311 /** 312 * Helper function for normalizeG2Uri and normalizeEmbedUri 313 * 314 * @access private 315 */ 316 function _normalizeUri($uri) { 317 $uri = trim($uri); 318 if (empty($uri)) { 319 return array('', '/', '', '', ''); 320 } 321 $schema = $host = $schemaAndHost = $path = $file = ''; 322 $fragment = $queryString = ''; 323 324 /* Normalize path separators */ 325 $uri = str_replace("\\", '/', $uri); 326 327 /* 328 * With schema (http://) -> easy to identify host 329 * A single slash: 330 * www.example.com/ 331 * www.example.com/gallery2 332 * www.example.com/index.php 333 * gallery2/ 334 * / 335 * /gallery2 336 * /index.php 337 * gallery2/index.php 338 * Multiple slashes: 339 * www.example.com/gallery2/ 340 * /gallery2/ 341 * .... 342 * Problem: Differentiate between host, path and file 343 * @files: .php|.html? is recognized as file 344 * @host: (?:\w+:\w+@)[\w\.]*\w+\.\w{2-4}(?::\d+) is most likely a host string 345 * localhost or other host strings without a dot are impossible to 346 * differentiate from path names ->only http://localhost accepted 347 * @path: everything that is not a file or a host 348 */ 349 350 /* Remove fragment / query string */ 351 if (($pos = strpos($uri, '#')) !== false) { 352 $fragment = substr($uri, $pos); 353 $uri = substr($uri, 0, $pos); 354 } 355 if (($pos = strpos($uri, '?')) !== false) { 356 $queryString = substr($uri, $pos); 357 $uri = substr($uri, 0, $pos); 358 } 359 360 /* Handle and remove file part */ 361 if (preg_match('{(.*/)?([\w\.]+\.(?:php|html?))$}i', $uri, $matches)) { 362 $uri = empty($matches[1]) ? '/' : $matches[1]; 363 $file = $matches[2]; 364 } 365 366 /* Get the schema and host for absolute URLs */ 367 if (preg_match('{^(https?://)([^/]+)(.*)$}i', $uri, $matches)) { 368 $schema = strtolower($matches[1]); 369 $host = $matches[2]; 370 $schemaAndHost = $schema . $host; 371 $uri = empty($matches[3]) ? '/' : $matches[3]; 372 $uri = $uri{0} != '/' ? '/' . $uri : $uri; 373 } else { 374 /* Get the host string, e.g. from www.example.com/foo or www.example.com */ 375 if (preg_match('{^((?:\w+:\w+@)?[\w\.]*\w+\.\w+(?::\d+)?)(.*)$}', $uri, $matches)) { 376 $host = $matches[1]; 377 $schema = 'http://'; 378 if ( !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') { 379 $schema = 'https://'; 380 } 381 $schemaAndHost = $schema . $host;; 382 $uri = empty($matches[2]) ? '/' : $matches[2]; 383 $uri = $uri{0} != '/' ? '/' . $uri : $uri; 384 } 385 } 386 387 /* Add leading / trailing slash to path */ 388 $path = $uri{0} != '/' ? '/' . $uri : $uri; 389 $path .= substr($path, -1) != '/' ? '/' : ''; 390 391 return array($schemaAndHost, $path, $file, $queryString, $fragment); 392 } 393 394 function isFileReadable($path) { 395 if (@file_exists($path) && @is_readable($path)) { 396 return array(true, null); 397 } else if (@G2EmbedDiscoveryUtilities::_isRestrictedByOpenBaseDir($path)) { 398 return array(false, "file $path is restricted by PHP open_basedir"); 399 } else if (@file_exists($path) && !@is_readable($path)) { 400 return array(false, "file $path exists but is not readable"); 401 } else { 402 return array(false, "file $path does not exist"); 403 } 404 } 405 406 /** 407 * Return true if the path provided is not allowed by the current open_basedir configuration. 408 * 409 * Copied from GalleryPlatform and adjusted to be independent of the G2 framework 410 * 411 * @return true if the path is restricted 412 */ 413 function _isRestrictedByOpenBaseDir($path) { 414 $slash = DIRECTORY_SEPARATOR; 415 if (!strncasecmp(PHP_OS, 'win', 3)) { 416 $separator = ';'; 417 $caseSensitive = false; 418 } else { 419 $separator = ':'; 420 $caseSensitive = true; 421 } 422 423 $openBasedir = @ini_get('open_basedir'); 424 if (empty($openBasedir)) { 425 return false; 426 } 427 428 if (($realpath = realpath($path)) === false) { 429 /* 430 * PHP's open_basedir will actually take an invalid path, resolve relative 431 * paths, parse out .. and . and then check against the dir list.. 432 * Here we do an ok job of doing the same, though it isn't perfect. 433 */ 434 $s = '\\\/'; /* do this by hand because preg_quote() isn't reliable */ 435 if (!preg_match("{^([a-z]+:)?[$s]}i", $path)) { 436 $path = getcwd() . $slash . $path; 437 } 438 for ($realpath = $path, $lastpath = ''; $realpath != $lastpath;) { 439 $realpath = preg_replace("#[$s]\.([$s]|\$)#", $slash, $lastpath = $realpath); 440 } 441 442 for ($lastpath = ''; $realpath != $lastpath;) { 443 $realpath = preg_replace("#[$s][^$s]+[$s]\.\.([$s]|\$)#", 444 $slash, $lastpath = $realpath); 445 } 446 } 447 448 $function = $caseSensitive ? 'strncmp' : 'strncasecmp'; 449 foreach (explode($separator, $openBasedir) as $baseDir) { 450 if (($baseDirMatch = realpath($baseDir)) === false) { 451 $baseDirMatch = $baseDir; 452 } else if ($baseDir{strlen($baseDir)-1} == $slash) { 453 /* Realpath will remove a trailing slash.. add it back to avoid prefix match */ 454 $baseDirMatch .= $slash; 455 } 456 /* Add slash on path so /dir is accepted if /dir/ is a valid basedir */ 457 if (!$function($baseDirMatch, $realpath . $slash, strlen($baseDirMatch))) { 458 return false; 459 } 460 } 461 462 return true; 463 } 464 } 465 466 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Jul 9 18:01:44 2012 | Cross-referenced by PHPXref 0.7 |