qa-index.php 6.61 KB
Newer Older
Scott committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
<?php
/*
	Question2Answer by Gideon Greenspan and contributors
	http://www.question2answer.org/

	File: qa-include/qa-index.php
	Description: The Grand Central of Q2A - most requests come through here


	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	More about this license: http://www.question2answer.org/license.php
*/

Scott committed
23
// Try our best to set base path here just in case it wasn't set in index.php (pre version 1.0.1)
Scott committed
24

Scott committed
25 26 27
if (!defined('QA_BASE_DIR')) {
	define('QA_BASE_DIR', dirname(empty($_SERVER['SCRIPT_FILENAME']) ? dirname(__FILE__) : $_SERVER['SCRIPT_FILENAME']) . '/');
}
Scott committed
28 29


Scott committed
30
// If this is an special non-page request, branch off here
Scott committed
31

Scott committed
32 33 34
if (isset($_POST['qa']) && $_POST['qa'] == 'ajax') {
	require 'qa-ajax.php';
}
Scott committed
35

Scott committed
36 37 38
elseif (isset($_GET['qa']) && $_GET['qa'] == 'image') {
	require 'qa-image.php';
}
Scott committed
39

Scott committed
40 41 42
elseif (isset($_GET['qa']) && $_GET['qa'] == 'blob') {
	require 'qa-blob.php';
}
Scott committed
43

Scott committed
44 45
else {
	// Otherwise, load the Q2A base file which sets up a bunch of crucial stuff
46
	$qa_autoconnect = false;
Scott committed
47
	require 'qa-base.php';
Scott committed
48

Scott committed
49 50 51 52 53 54 55 56 57 58
	/**
	 * Determine the request and root of the installation, and the requested start position used by many pages.
	 *
	 * Apache and Nginx behave slightly differently:
	 *   Apache qa-rewrite unescapes characters, converts `+` to ` `, cuts off at `#` or `&`
	 *   Nginx qa-rewrite unescapes characters, retains `+`, contains true path
	 */
	function qa_index_set_request()
	{
		if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
Scott committed
59

Scott committed
60
		$relativedepth = 0;
Scott committed
61

Scott committed
62 63 64 65 66
		if (isset($_GET['qa-rewrite'])) { // URLs rewritten by .htaccess or Nginx
			$urlformat = QA_URL_FORMAT_NEAT;
			$qa_rewrite = strtr(qa_gpc_to_string($_GET['qa-rewrite']), '+', ' '); // strtr required by Nginx
			$requestparts = explode('/', $qa_rewrite);
			unset($_GET['qa-rewrite']);
Scott committed
67

Scott committed
68 69 70
			if (!empty($_SERVER['REQUEST_URI'])) { // workaround for the fact that Apache unescapes characters while rewriting
				$origpath = $_SERVER['REQUEST_URI'];
				$_GET = array();
Scott committed
71

Scott committed
72 73 74
				$questionpos = strpos($origpath, '?');
				if (is_numeric($questionpos)) {
					$params = explode('&', substr($origpath, $questionpos + 1));
Scott committed
75

Scott committed
76 77 78 79
					foreach ($params as $param) {
						if (preg_match('/^([^\=]*)(\=(.*))?$/', $param, $matches)) {
							$argument = strtr(urldecode($matches[1]), '.', '_'); // simulate PHP's $_GET behavior
							$_GET[$argument] = qa_string_to_gpc(urldecode(@$matches[3]));
Scott committed
80 81 82
						}
					}

Scott committed
83
					$origpath = substr($origpath, 0, $questionpos);
Scott committed
84 85
				}

Scott committed
86 87 88 89 90 91 92 93 94 95 96 97 98
				// Generally we assume that $_GET['qa-rewrite'] has the right path depth, but this won't be the case if there's
				// a & or # somewhere in the middle of the path, due to Apache unescaping. So we make a special case for that.
				// If 'REQUEST_URI' and 'qa-rewrite' already match (as on Nginx), we can skip this.
				$normalizedpath = urldecode($origpath);
				if (substr($normalizedpath, -strlen($qa_rewrite)) !== $qa_rewrite) {
					$keepparts = count($requestparts);
					$requestparts = explode('/', urldecode($origpath)); // new request calculated from $_SERVER['REQUEST_URI']

					// loop forwards so we capture all parts
					for ($part = 0, $max = count($requestparts); $part < $max; $part++) {
						if (is_numeric(strpos($requestparts[$part], '&')) || is_numeric(strpos($requestparts[$part], '#'))) {
							$keepparts += count($requestparts) - $part - 1; // this is how many parts remain
							break;
Scott committed
99 100 101
						}
					}

Scott committed
102 103
					$requestparts = array_slice($requestparts, -$keepparts); // remove any irrelevant parts from the beginning
				}
Scott committed
104
			}
105

Scott committed
106 107 108 109 110 111 112 113 114 115 116
			$relativedepth = count($requestparts);
		} elseif (isset($_GET['qa'])) {
			if (strpos($_GET['qa'], '/') === false) {
				$urlformat = (empty($_SERVER['REQUEST_URI']) || strpos($_SERVER['REQUEST_URI'], '/index.php') !== false)
					? QA_URL_FORMAT_SAFEST : QA_URL_FORMAT_PARAMS;
				$requestparts = array(qa_gpc_to_string($_GET['qa']));

				for ($part = 1; $part < 10; $part++) {
					if (isset($_GET['qa_' . $part])) {
						$requestparts[] = qa_gpc_to_string($_GET['qa_' . $part]);
						unset($_GET['qa_' . $part]);
117 118
					}
				}
Scott committed
119 120 121 122
			} else {
				$urlformat = QA_URL_FORMAT_PARAM;
				$requestparts = explode('/', qa_gpc_to_string($_GET['qa']));
			}
Scott committed
123

Scott committed
124 125 126 127 128 129 130 131 132 133 134
			unset($_GET['qa']);
		} else {
			$normalizedpath = strtr($_SERVER['PHP_SELF'], '+', ' '); // seems necessary, and plus does not work with this scheme
			$indexpath = '/index.php/';
			$indexpos = strpos($normalizedpath, $indexpath);

			if (!empty($_SERVER['REQUEST_URI'])) { // workaround for the fact that Apache unescapes characters
				$origpath = $_SERVER['REQUEST_URI'];
				$questionpos = strpos($origpath, '?');
				if ($questionpos !== false) {
					$origpath = substr($origpath, 0, $questionpos);
Scott committed
135
				}
Scott committed
136 137 138

				$normalizedpath = urldecode($origpath);
				$indexpos = strpos($normalizedpath, $indexpath);
Scott committed
139 140
			}

Scott committed
141 142 143 144 145 146 147
			if (is_numeric($indexpos)) {
				$urlformat = QA_URL_FORMAT_INDEX;
				$requestparts = explode('/', substr($normalizedpath, $indexpos + strlen($indexpath)));
				$relativedepth = 1 + count($requestparts);
			} else {
				$urlformat = null; // at home page so can't identify path type
				$requestparts = array();
Scott committed
148
			}
Scott committed
149
		}
Scott committed
150

Scott committed
151 152 153 154
		foreach ($requestparts as $part => $requestpart) { // remove any blank parts
			if (!strlen($requestpart))
				unset($requestparts[$part]);
		}
Scott committed
155

Scott committed
156 157
		reset($requestparts);
		$key = key($requestparts);
Scott committed
158

Scott committed
159 160 161 162 163 164 165 166 167 168 169
		$requestkey = isset($requestparts[$key]) ? $requestparts[$key] : '';
		$replacement = array_search($requestkey, qa_get_request_map());
		if ($replacement !== false)
			$requestparts[$key] = $replacement;

		qa_set_request(
			implode('/', $requestparts),
			($relativedepth > 1 ? str_repeat('../', $relativedepth - 1) : './'),
			$urlformat
		);
	}
Scott committed
170

Scott committed
171
	qa_index_set_request();
Scott committed
172 173


Scott committed
174
	// Branch off to appropriate file for further handling
Scott committed
175

Scott committed
176
	$requestlower = strtolower(qa_request());
Scott committed
177

Scott committed
178 179 180 181 182 183 184
	if ($requestlower == 'install') {
		require QA_INCLUDE_DIR . 'qa-install.php';
	} elseif ($requestlower == 'url/test/' . QA_URL_TEST_STRING) {
		require QA_INCLUDE_DIR . 'qa-url-test.php';
	} else {
		// enable gzip compression for output (needs to come early)
		qa_initialize_buffering($requestlower);
Scott committed
185

Scott committed
186 187 188 189
		if (substr($requestlower, 0, 5) == 'feed/') {
			require QA_INCLUDE_DIR . 'qa-feed.php';
		} else {
			require QA_INCLUDE_DIR . 'qa-page.php';
Scott committed
190 191
		}
	}
Scott committed
192
}
Scott committed
193

Scott committed
194
qa_report_process_stage('shutdown');