1<?php
2/**
3 * Copyright 2013-2017 Horde LLC (http://www.horde.org/)
4 *
5 * See the enclosed file COPYING for license information (LGPL). If you
6 * did not receive this file, see http://www.horde.org/licenses/lgpl21.
7 *
8 * @category  Horde
9 * @copyright 2013-2017 Horde LLC
10 * @license   http://www.horde.org/licenses/lgpl21 LGPL 2.1
11 * @package   Smtp
12 */
13
14/**
15 * Handles debugging output for a Horde_Smtp object.
16 *
17 * NOTE: This class is NOT intended to be accessed outside of the Smtp package.
18 * There is NO guarantees that the API of this class will not change across
19 * versions.
20 *
21 * @author    Michael Slusarz <slusarz@horde.org>
22 * @category  Horde
23 * @copyright 2013-2017 Horde LLC
24 * @internal
25 * @license   http://www.horde.org/licenses/lgpl21 LGPL 2.1
26 * @package   Smtp
27 */
28class Horde_Smtp_Debug
29{
30    /* Time, in seconds, to be labeled a slow command. */
31    const SLOW_CMD = 5;
32
33    /**
34     * Is debugging active?
35     *
36     * @var boolean
37     */
38    public $active = true;
39
40    /**
41     * The debug stream.
42     *
43     * @var resource
44     */
45    protected $_stream;
46
47    /**
48     * Timestamp of last command.
49     *
50     * @var integer
51     */
52    protected $_time = null;
53
54    /**
55     * Constructor.
56     *
57     * @param mixed $debug  The debug target.
58     */
59    public function __construct($debug)
60    {
61        $this->_stream = is_resource($debug)
62            ? $debug
63            : @fopen($debug, 'a');
64        register_shutdown_function(array($this, 'shutdown'));
65    }
66
67    /**
68     * Shutdown function.
69     */
70    public function shutdown()
71    {
72        if (is_resource($this->_stream)) {
73            fflush($this->_stream);
74            fclose($this->_stream);
75            $this->_stream = null;
76        }
77    }
78
79    /**
80     * Write client output to debug log.
81     *
82     * @param string $msg   Debug message.
83     * @param boolean $eol  Output EOL?
84     */
85    public function client($msg, $eol = true)
86    {
87        $this->_write($msg . ($eol ? "\n" : ''), 'C: ');
88    }
89
90    /**
91     * Write informational message to debug log.
92     *
93     * @param string $msg  Debug message.
94     */
95    public function info($msg)
96    {
97        $this->_write($msg . "\n", '>> ');
98    }
99
100    /**
101     * Write server output to debug log.
102     *
103     * @param string $msg  Debug message.
104     */
105    public function raw($msg)
106    {
107        $this->_write($msg);
108    }
109
110    /**
111     * Write server output to debug log.
112     *
113     * @param string $msg  Debug message.
114     */
115    public function server($msg)
116    {
117        $this->_write($msg . "\n", 'S: ');
118    }
119
120    /**
121     * Write debug information to the output stream.
122     *
123     * @param string $msg  Debug data.
124     * @param string $pre  Prefix.
125     */
126    protected function _write($msg, $pre = null)
127    {
128        if (!$this->_stream || !$this->active) {
129            return;
130        }
131
132        if (!is_null($pre)) {
133            $new_time = microtime(true);
134
135            if (is_null($this->_time)) {
136                fwrite(
137                    $this->_stream,
138                    str_repeat('-', 30) . "\n" . '>> ' . date('r') . "\n"
139                );
140            } elseif (($diff = ($new_time - $this->_time)) > self::SLOW_CMD) {
141                fwrite(
142                    $this->_stream,
143                    '>> Slow Command: ' . round($diff, 3) . " seconds\n"
144                );
145            }
146
147            $this->_time = $new_time;
148        }
149
150        fwrite($this->_stream, $pre . $msg);
151    }
152
153}
154