1 <?php rcs_id('$Id: Request.php,v 1.15 2002-08-24 13:18:56 rurban Exp $');
3 // FIXME: write log entry.
8 $this->_fix_magic_quotes_gpc();
9 $this->_fix_multipart_form_data();
11 switch($this->get('REQUEST_METHOD')) {
14 $this->args = &$GLOBALS['HTTP_GET_VARS'];
17 $this->args = &$GLOBALS['HTTP_POST_VARS'];
20 $this->args = array();
24 $this->session = new Request_SessionVars;
25 $this->cookies = new Request_CookieVars;
28 $this->_log_entry = & new Request_AccessLogEntry($this,
31 $GLOBALS['request'] = $this;
35 $vars = &$GLOBALS['HTTP_SERVER_VARS'];
37 if (isset($vars[$key]))
42 $addr = $vars['REMOTE_ADDR'];
43 if (defined('ENABLE_REVERSE_DNS') && ENABLE_REVERSE_DNS)
44 return $vars[$key] = gethostbyaddr($addr);
52 function getArg($key) {
53 if (isset($this->args[$key]))
54 return $this->args[$key];
62 function setArg($key, $val) {
64 unset($this->args[$key]);
66 $this->args[$key] = $val;
69 // Well oh well. Do we really want to pass POST params back as GET?
70 function getURLtoSelf($args = false) {
71 $get_args = $this->args;
73 $get_args = array_merge($get_args, $args);
75 $get_args = array_merge($get_args, $GLOBALS['HTTP_GET_VARS']);
77 $pagename = $get_args['pagename'];
78 unset ($get_args['pagename']);
79 if ($get_args['action'] == 'browse')
80 unset($get_args['action']);
82 return WikiURL($pagename, $get_args);
86 return $this->get("REQUEST_METHOD") == "POST";
89 function redirect($url) {
90 header("Location: $url");
91 if (isset($this->_log_entry))
92 $this->_log_entry->setStatus(302);
95 function setStatus($status) {
96 if (preg_match('|^HTTP/.*?\s(\d+)|i', $status, $m)) {
101 $status = (integer) $status;
102 $reasons = array('200' => 'OK',
104 '400' => 'Bad Request',
105 '401' => 'Unauthorized',
106 '403' => 'Forbidden',
107 '404' => 'Not Found');
108 header(sprintf("HTTP/1.0 %d %s", $status, $reason[$status]));
111 if (isset($this->_log_entry))
112 $this->_log_entry->setStatus($status);
115 function compress_output() {
116 if (function_exists('ob_gzhandler')) {
117 ob_start('ob_gzhandler');
118 $this->_is_compressing_output = true;
123 if (!empty($this->_is_compressing_output))
127 function getSessionVar($key) {
128 return $this->session->get($key);
130 function setSessionVar($key, $val) {
131 return $this->session->set($key, $val);
133 function deleteSessionVar($key) {
134 return $this->session->delete($key);
137 function getCookieVar($key) {
138 return $this->cookies->get($key);
140 function setCookieVar($key, $val, $lifetime_in_days = false) {
141 return $this->cookies->set($key, $val, $lifetime_in_days);
143 function deleteCookieVar($key) {
144 return $this->cookies->delete($key);
147 function getUploadedFile($key) {
148 return Request_UploadedFile::getUploadedFile($key);
152 function _fix_magic_quotes_gpc() {
153 $needs_fix = array('HTTP_POST_VARS',
160 if (get_magic_quotes_gpc()) {
161 foreach ($needs_fix as $vars)
162 $this->_stripslashes($GLOBALS[$vars]);
166 function _stripslashes(&$var) {
167 if (is_array($var)) {
168 foreach ($var as $key => $val)
169 $this->_stripslashes($var[$key]);
171 elseif (is_string($var))
172 $var = stripslashes($var);
175 function _fix_multipart_form_data () {
176 if (preg_match('|^multipart/form-data|', $this->get('CONTENT_TYPE')))
177 $this->_strip_leading_nl($GLOBALS['HTTP_POST_VARS']);
180 function _strip_leading_nl(&$var) {
181 if (is_array($var)) {
182 foreach ($var as $key => $val)
183 $this->_strip_leading_nl($var[$key]);
185 elseif (is_string($var))
186 $var = preg_replace('|^\r?\n?|', '', $var);
190 class Request_SessionVars {
191 function Request_SessionVars() {
192 // Prevent cacheing problems with IE 5
193 session_cache_limiter('none');
199 $vars = &$GLOBALS['HTTP_SESSION_VARS'];
200 if (isset($vars[$key]))
205 function set($key, $val) {
206 $vars = &$GLOBALS['HTTP_SESSION_VARS'];
207 if (ini_get('register_globals')) {
208 // This is funky but necessary, at least in some PHP's
209 $GLOBALS[$key] = $val;
212 session_register($key);
215 function delete($key) {
216 $vars = &$GLOBALS['HTTP_SESSION_VARS'];
217 if (ini_get('register_globals'))
218 unset($GLOBALS[$key]);
220 session_unregister($key);
224 class Request_CookieVars {
227 $vars = &$GLOBALS['HTTP_COOKIE_VARS'];
228 if (isset($vars[$key])) {
229 @$val = unserialize($vars[$key]);
236 function set($key, $val, $persist_days = false) {
237 $vars = &$GLOBALS['HTTP_COOKIE_VARS'];
239 if (is_numeric($persist_days)) {
240 $expires = time() + (24 * 3600) * $persist_days;
246 $packedval = serialize($val);
247 $vars[$key] = $packedval;
248 setcookie($key, $packedval, $expires, '/');
251 function delete($key) {
252 $vars = &$GLOBALS['HTTP_COOKIE_VARS'];
258 class Request_UploadedFile {
259 function getUploadedFile($postname) {
260 global $HTTP_POST_FILES;
262 if (!isset($HTTP_POST_FILES[$postname]))
265 $fileinfo = &$HTTP_POST_FILES[$postname];
266 if (!is_uploaded_file($fileinfo['tmp_name']))
267 return false; // possible malicious attack.
269 return new Request_UploadedFile($fileinfo);
272 function Request_UploadedFile($fileinfo) {
273 $this->_info = $fileinfo;
277 return $this->_info['size'];
281 return $this->_info['name'];
285 return $this->_info['type'];
289 if ( ($fd = fopen($this->_info['tmp_name'], "rb")) ) {
290 if ($this->getSize() < filesize($this->_info['tmp_name'])) {
291 // FIXME: Some PHP's (or is it some browsers?) put
292 // HTTP/MIME headers in the file body, some don't.
294 // At least, I think that's the case. I know I used
295 // to need this code, now I don't.
297 // This code is more-or-less untested currently.
299 // Dump HTTP headers.
300 while ( ($header = fgets($fd, 4096)) ) {
301 if (trim($header) == '') {
304 else if (!preg_match('/^content-(length|type):/i', $header)) {
314 function getContents() {
316 $data = fread($fd, $this->getSize());
323 * Create NCSA "combined" log entry for current request.
325 class Request_AccessLogEntry
330 * The log entry will be automatically appended to the log file
331 * when the current request terminates.
333 * If you want to modify a Request_AccessLogEntry before it gets
334 * written (e.g. via the setStatus and setSize methods) you should
335 * use an '&' on the constructor, so that you're working with the
336 * original (rather than a copy) object.
339 * $log_entry = & new Request_AccessLogEntry($req, "/tmp/wiki_access_log");
340 * $log_entry->setStatus(401);
344 * @param $request object Request object for current request.
345 * @param $logfile string Log file name.
347 function Request_AccessLogEntry (&$request, $logfile) {
348 $this->logfile = $logfile;
350 $this->host = $request->get('REMOTE_HOST');
351 $this->ident = $request->get('REMOTE_IDENT');
354 $this->user = '-'; // FIXME: get logged-in user name
355 $this->time = time();
356 $this->request = join(' ', array($request->get('REQUEST_METHOD'),
357 $request->get('REQUEST_URI'),
358 $request->get('SERVER_PROTOCOL')));
361 $this->referer = (string) $request->get('HTTP_REFERER');
362 $this->user_agent = (string) $request->get('HTTP_USER_AGENT');
364 global $Request_AccessLogEntry_entries;
365 if (!isset($Request_AccessLogEntry_entries)) {
366 register_shutdown_function("Request_AccessLogEntry_shutdown_function");
368 $Request_AccessLogEntry_entries[] = &$this;
372 * Set result status code.
374 * @param $status integer HTTP status code.
376 function setStatus ($status) {
377 $this->status = $status;
383 * @param $size integer
385 function setSize ($size) {
390 * Get time zone offset.
392 * This is a static member function.
394 * @param $time integer Unix timestamp (defaults to current time).
395 * @return string Zone offset, e.g. "-0800" for PST.
397 function _zone_offset ($time = false) {
400 $offset = date("Z", $time);
405 $offhours = floor($offset / 3600);
406 $offmins = $offset / 60 - $offhours * 60;
407 return sprintf("%s%02d%02d", $negoffset, $offhours, $offmins);
411 * Format time in NCSA format.
413 * This is a static member function.
415 * @param $time integer Unix timestamp (defaults to current time).
416 * @return string Formatted date & time.
418 function _ncsa_time($time = false) {
422 return date("d/M/Y:H:i:s", $time) .
423 " " . $this->_zone_offset();
427 * Write entry to log file.
430 $entry = sprintf('%s %s %s [%s] "%s" %d %d "%s" "%s"',
431 $this->host, $this->ident, $this->user,
432 $this->_ncsa_time($this->time),
433 $this->request, $this->status, $this->size,
434 $this->referer, $this->user_agent);
436 //Error log doesn't provide locking.
437 //error_log("$entry\n", 3, $this->logfile);
440 if (($fp = fopen($this->logfile, "a"))) {
442 fputs($fp, "$entry\n");
452 * @see Request_AccessLogEntry
454 function Request_AccessLogEntry_shutdown_function ()
456 global $Request_AccessLogEntry_entries;
458 foreach ($Request_AccessLogEntry_entries as $entry) {
461 unset($Request_AccessLogEntry_entries);
468 // c-hanging-comment-ender-p: nil
469 // indent-tabs-mode: nil