blob: 72d3cfbae86023ec6bcc9a92d445ccfaab282013 [file] [log] [blame]
Andrey Andreevc5536aa2012-11-01 17:33:58 +02001<?php
Derek Allard2067d1a2008-11-13 22:59:24 +00002/**
3 * CodeIgniter
4 *
Andrey Andreevfe9309d2015-01-09 17:48:58 +02005 * An open source application development framework for PHP
Derek Allard2067d1a2008-11-13 22:59:24 +00006 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +02007 * This content is released under the MIT License (MIT)
Andrey Andreev76cc9202011-12-22 20:02:04 +02008 *
Andrey Andreev125ef472016-01-11 12:33:00 +02009 * Copyright (c) 2014 - 2016, British Columbia Institute of Technology
Andrey Andreev76cc9202011-12-22 20:02:04 +020010 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020011 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
Derek Jonesf4a4bd82011-10-20 12:18:42 -050017 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020018 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 * THE SOFTWARE.
28 *
29 * @package CodeIgniter
30 * @author EllisLab Dev Team
Andrey Andreev1924e872016-01-11 12:55:34 +020031 * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
Andrey Andreev125ef472016-01-11 12:33:00 +020032 * @copyright Copyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020033 * @license http://opensource.org/licenses/MIT MIT License
Andrey Andreevbd202c92016-01-11 12:50:18 +020034 * @link https://codeigniter.com
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020035 * @since Version 1.0.0
Derek Allard2067d1a2008-11-13 22:59:24 +000036 * @filesource
37 */
Andrey Andreevc5536aa2012-11-01 17:33:58 +020038defined('BASEPATH') OR exit('No direct script access allowed');
Derek Allard2067d1a2008-11-13 22:59:24 +000039
Derek Allard2067d1a2008-11-13 22:59:24 +000040/**
41 * Logging Class
42 *
43 * @package CodeIgniter
44 * @subpackage Libraries
45 * @category Logging
Derek Jonesf4a4bd82011-10-20 12:18:42 -050046 * @author EllisLab Dev Team
Andrey Andreevbd202c92016-01-11 12:50:18 +020047 * @link https://codeigniter.com/user_guide/general/errors.html
Derek Allard2067d1a2008-11-13 22:59:24 +000048 */
49class CI_Log {
50
Timothy Warrenb82bc3a2012-04-27 09:12:58 -040051 /**
52 * Path to save log files
53 *
54 * @var string
55 */
Greg Aker2eaa4072010-12-21 11:44:08 -060056 protected $_log_path;
Andrey Andreev56454792012-05-17 14:32:19 +030057
Timothy Warrenb82bc3a2012-04-27 09:12:58 -040058 /**
Andrey Andreev45965742014-08-27 20:40:11 +030059 * File permissions
60 *
61 * @var int
62 */
63 protected $_file_permissions = 0644;
64
65 /**
Timothy Warrenb82bc3a2012-04-27 09:12:58 -040066 * Level of logging
67 *
68 * @var int
69 */
Andrey Andreev45965742014-08-27 20:40:11 +030070 protected $_threshold = 1;
Andrey Andreev56454792012-05-17 14:32:19 +030071
Timothy Warrenb82bc3a2012-04-27 09:12:58 -040072 /**
Timothy Warrenb82bc3a2012-04-27 09:12:58 -040073 * Array of threshold levels to log
74 *
75 * @var array
76 */
Andrey Andreev45965742014-08-27 20:40:11 +030077 protected $_threshold_array = array();
Andrey Andreev56454792012-05-17 14:32:19 +030078
Timothy Warrenb82bc3a2012-04-27 09:12:58 -040079 /**
80 * Format of timestamp for log files
81 *
82 * @var string
83 */
Andrey Andreev45965742014-08-27 20:40:11 +030084 protected $_date_fmt = 'Y-m-d H:i:s';
Andrey Andreev56454792012-05-17 14:32:19 +030085
Timothy Warrenb82bc3a2012-04-27 09:12:58 -040086 /**
Andrey Andreeva107a0f2013-02-15 22:30:31 +020087 * Filename extension
88 *
89 * @var string
90 */
91 protected $_file_ext;
92
93 /**
Timothy Warrenb82bc3a2012-04-27 09:12:58 -040094 * Whether or not the logger can write to the log files
95 *
96 * @var bool
97 */
Andrey Andreev45965742014-08-27 20:40:11 +030098 protected $_enabled = TRUE;
Andrey Andreev56454792012-05-17 14:32:19 +030099
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400100 /**
101 * Predefined logging levels
102 *
103 * @var array
104 */
Andrey Andreev45965742014-08-27 20:40:11 +0300105 protected $_levels = array('ERROR' => 1, 'DEBUG' => 2, 'INFO' => 3, 'ALL' => 4);
Derek Allard2067d1a2008-11-13 22:59:24 +0000106
Andrey Andreeva107a0f2013-02-15 22:30:31 +0200107 // --------------------------------------------------------------------
108
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400109 /**
Andrey Andreeva107a0f2013-02-15 22:30:31 +0200110 * Class constructor
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400111 *
Andrey Andreev56454792012-05-17 14:32:19 +0300112 * @return void
Timothy Warrenb82bc3a2012-04-27 09:12:58 -0400113 */
Greg Akera9263282010-11-10 15:26:43 -0600114 public function __construct()
Derek Allard2067d1a2008-11-13 22:59:24 +0000115 {
116 $config =& get_config();
Barry Mienydd671972010-10-04 16:33:58 +0200117
Alex Bilbied261b1e2012-06-02 11:12:16 +0100118 $this->_log_path = ($config['log_path'] !== '') ? $config['log_path'] : APPPATH.'logs/';
Andrey Andreeva107a0f2013-02-15 22:30:31 +0200119 $this->_file_ext = (isset($config['log_file_extension']) && $config['log_file_extension'] !== '')
120 ? ltrim($config['log_file_extension'], '.') : 'php';
Chris Passas0bd6b282013-02-13 14:16:18 -0500121
Andrey Andreev45965742014-08-27 20:40:11 +0300122 file_exists($this->_log_path) OR mkdir($this->_log_path, 0755, TRUE);
Andrey Andreev9f690f12013-01-21 15:30:25 +0200123
Greg Aker2eaa4072010-12-21 11:44:08 -0600124 if ( ! is_dir($this->_log_path) OR ! is_really_writable($this->_log_path))
Derek Allard2067d1a2008-11-13 22:59:24 +0000125 {
126 $this->_enabled = FALSE;
127 }
Barry Mienydd671972010-10-04 16:33:58 +0200128
Derek Allard2067d1a2008-11-13 22:59:24 +0000129 if (is_numeric($config['log_threshold']))
130 {
Andrey Andreev76cc9202011-12-22 20:02:04 +0200131 $this->_threshold = (int) $config['log_threshold'];
Derek Allard2067d1a2008-11-13 22:59:24 +0000132 }
Nithin333f9f92011-08-21 16:52:06 -0400133 elseif (is_array($config['log_threshold']))
134 {
Andrey Andreevfd08d022015-03-03 12:36:11 +0200135 $this->_threshold = 0;
Nithin333f9f92011-08-21 16:52:06 -0400136 $this->_threshold_array = array_flip($config['log_threshold']);
137 }
Barry Mienydd671972010-10-04 16:33:58 +0200138
Andrey Andreev45965742014-08-27 20:40:11 +0300139 if ( ! empty($config['log_date_format']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000140 {
141 $this->_date_fmt = $config['log_date_format'];
142 }
Andrey Andreev45965742014-08-27 20:40:11 +0300143
Andrey Andreevdc0ad202014-09-17 10:34:04 +0300144 if ( ! empty($config['log_file_permissions']) && is_int($config['log_file_permissions']))
Andrey Andreev45965742014-08-27 20:40:11 +0300145 {
146 $this->_file_permissions = $config['log_file_permissions'];
147 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000148 }
Barry Mienydd671972010-10-04 16:33:58 +0200149
Derek Allard2067d1a2008-11-13 22:59:24 +0000150 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200151
Derek Allard2067d1a2008-11-13 22:59:24 +0000152 /**
153 * Write Log File
154 *
155 * Generally this function will be called using the global log_message() function
156 *
vlakoffd0c30ab2013-05-07 07:49:23 +0200157 * @param string the error level: 'error', 'debug' or 'info'
Derek Allard2067d1a2008-11-13 22:59:24 +0000158 * @param string the error message
Derek Allard2067d1a2008-11-13 22:59:24 +0000159 * @return bool
Barry Mienydd671972010-10-04 16:33:58 +0200160 */
Andrey Andreev838c9a92013-09-13 14:05:13 +0300161 public function write_log($level, $msg)
Barry Mienydd671972010-10-04 16:33:58 +0200162 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000163 if ($this->_enabled === FALSE)
164 {
165 return FALSE;
166 }
Barry Mienydd671972010-10-04 16:33:58 +0200167
Derek Allard2067d1a2008-11-13 22:59:24 +0000168 $level = strtoupper($level);
Barry Mienydd671972010-10-04 16:33:58 +0200169
Andrey Andreev76cc9202011-12-22 20:02:04 +0200170 if (( ! isset($this->_levels[$level]) OR ($this->_levels[$level] > $this->_threshold))
Andrey Andreev443bbd92012-04-03 15:49:11 +0300171 && ! isset($this->_threshold_array[$this->_levels[$level]]))
Derek Allard2067d1a2008-11-13 22:59:24 +0000172 {
Andrey Andreev76cc9202011-12-22 20:02:04 +0200173 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000174 }
Barry Mienydd671972010-10-04 16:33:58 +0200175
Andrey Andreeva107a0f2013-02-15 22:30:31 +0200176 $filepath = $this->_log_path.'log-'.date('Y-m-d').'.'.$this->_file_ext;
177 $message = '';
Barry Mienydd671972010-10-04 16:33:58 +0200178
Derek Allard2067d1a2008-11-13 22:59:24 +0000179 if ( ! file_exists($filepath))
180 {
Jeroen van der Gulik2835e082011-12-04 14:19:38 +0100181 $newfile = TRUE;
Andrey Andreeva107a0f2013-02-15 22:30:31 +0200182 // Only add protection to php files
183 if ($this->_file_ext === 'php')
Chris Passasfb8de242013-02-14 09:01:24 -0500184 {
Andrey Andreeva107a0f2013-02-15 22:30:31 +0200185 $message .= "<?php defined('BASEPATH') OR exit('No direct script access allowed'); ?>\n\n";
Chris Passasfb8de242013-02-14 09:01:24 -0500186 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000187 }
Barry Mienydd671972010-10-04 16:33:58 +0200188
Andrey Andreev7cf682a2014-03-13 14:55:45 +0200189 if ( ! $fp = @fopen($filepath, 'ab'))
Derek Allard2067d1a2008-11-13 22:59:24 +0000190 {
191 return FALSE;
192 }
193
Gabriel Potkány53e83032014-12-20 00:00:23 +0100194 // Instantiating DateTime with microseconds appended to initial date is needed for proper support of this format
195 if (strpos($this->_date_fmt, 'u') !== FALSE)
196 {
197 $microtime_full = microtime(TRUE);
198 $microtime_short = sprintf("%06d", ($microtime_full - floor($microtime_full)) * 1000000);
199 $date = new DateTime(date('Y-m-d H:i:s.'.$microtime_short, $microtime_full));
200 $date = $date->format($this->_date_fmt);
201 }
202 else
203 {
204 $date = date($this->_date_fmt);
205 }
Gabriel Potkányf83262e2014-12-19 12:35:00 +0100206
Gabriel Potkány53e83032014-12-20 00:00:23 +0100207 $message .= $level.' - '.$date.' --> '.$msg."\n";
Barry Mienydd671972010-10-04 16:33:58 +0200208
209 flock($fp, LOCK_EX);
Andrey Andreevd8b1ad32014-01-15 17:42:52 +0200210
211 for ($written = 0, $length = strlen($message); $written < $length; $written += $result)
212 {
213 if (($result = fwrite($fp, substr($message, $written))) === FALSE)
214 {
215 break;
216 }
217 }
218
Derek Allard2067d1a2008-11-13 22:59:24 +0000219 flock($fp, LOCK_UN);
220 fclose($fp);
Barry Mienydd671972010-10-04 16:33:58 +0200221
Andrey Andreev443bbd92012-04-03 15:49:11 +0300222 if (isset($newfile) && $newfile === TRUE)
Jeroen van der Gulik2835e082011-12-04 14:19:38 +0100223 {
Andrey Andreev45965742014-08-27 20:40:11 +0300224 chmod($filepath, $this->_file_permissions);
Jeroen van der Gulik2835e082011-12-04 14:19:38 +0100225 }
Andrey Andreev443bbd92012-04-03 15:49:11 +0300226
Andrey Andreevd8b1ad32014-01-15 17:42:52 +0200227 return is_int($result);
Derek Allard2067d1a2008-11-13 22:59:24 +0000228 }
229
230}