1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Felipe Pena <felipe@php.net> |
14 | Authors: Joe Watkins <joe.watkins@live.co.uk> |
15 | Authors: Bob Weinand <bwoebi@php.net> |
16 +----------------------------------------------------------------------+
17 */
18
19 #include "zend.h"
20 #include "php.h"
21 #include "spprintf.h"
22 #include "phpdbg.h"
23 #include "phpdbg_io.h"
24 #include "ext/standard/html.h"
25
26 #ifdef _WIN32
27 # include "win32/time.h"
28 #endif
29
ZEND_EXTERN_MODULE_GLOBALS(phpdbg)30 ZEND_EXTERN_MODULE_GLOBALS(phpdbg)
31
32 PHPDBG_API int _phpdbg_asprintf(char **buf, const char *format, ...) {
33 int ret;
34 va_list va;
35
36 va_start(va, format);
37 ret = vasprintf(buf, format, va);
38 va_end(va);
39
40 return ret;
41 }
42
phpdbg_process_print(int fd,int type,const char * msg,int msglen)43 int phpdbg_process_print(int fd, int type, const char *msg, int msglen) {
44 char *msgout = NULL;
45 int msgoutlen = FAILURE;
46
47 switch (type) {
48 case P_ERROR:
49 if (!PHPDBG_G(last_was_newline)) {
50 phpdbg_mixed_write(fd, ZEND_STRL("\n"));
51 PHPDBG_G(last_was_newline) = 1;
52 }
53 if (PHPDBG_G(flags) & PHPDBG_IS_COLOURED) {
54 msgoutlen = phpdbg_asprintf(&msgout, "\033[%sm[%.*s]\033[0m\n", PHPDBG_G(colors)[PHPDBG_COLOR_ERROR]->code, msglen, msg);
55 } else {
56 msgoutlen = phpdbg_asprintf(&msgout, "[%.*s]\n", msglen, msg);
57 }
58 break;
59
60 case P_NOTICE:
61 if (!PHPDBG_G(last_was_newline)) {
62 phpdbg_mixed_write(fd, ZEND_STRL("\n"));
63 PHPDBG_G(last_was_newline) = 1;
64 }
65 if (PHPDBG_G(flags) & PHPDBG_IS_COLOURED) {
66 msgoutlen = phpdbg_asprintf(&msgout, "\033[%sm[%.*s]\033[0m\n", PHPDBG_G(colors)[PHPDBG_COLOR_NOTICE]->code, msglen, msg);
67 } else {
68 msgoutlen = phpdbg_asprintf(&msgout, "[%.*s]\n", msglen, msg);
69 }
70 break;
71
72 case P_WRITELN:
73 if (msg) {
74 msgoutlen = phpdbg_asprintf(&msgout, "%.*s\n", msglen, msg);
75 } else {
76 msgoutlen = 1;
77 msgout = strdup("\n");
78 }
79 PHPDBG_G(last_was_newline) = 1;
80 break;
81
82 case P_WRITE:
83 if (msg) {
84 msgout = pestrndup(msg, msglen, 1);
85 msgoutlen = msglen;
86 PHPDBG_G(last_was_newline) = msg[msglen - 1] == '\n';
87 } else {
88 msgoutlen = 0;
89 msgout = strdup("");
90 }
91 break;
92
93 case P_STDOUT:
94 case P_STDERR:
95 if (msg) {
96 PHPDBG_G(last_was_newline) = msg[msglen - 1] == '\n';
97 phpdbg_mixed_write(fd, msg, msglen);
98 }
99 return msglen;
100
101 /* no formatting on logging output */
102 case P_LOG:
103 if (msg) {
104 struct timeval tp;
105 if (gettimeofday(&tp, NULL) == SUCCESS) {
106 msgoutlen = phpdbg_asprintf(&msgout, "[%ld %.8F]: %.*s\n", tp.tv_sec, tp.tv_usec / 1000000., msglen, msg);
107 } else {
108 msgoutlen = FAILURE;
109 }
110 }
111 break;
112 EMPTY_SWITCH_DEFAULT_CASE()
113 }
114
115 if (msgoutlen != FAILURE) {
116 phpdbg_mixed_write(fd, msgout, msgoutlen);
117
118 free(msgout);
119 }
120 return msgoutlen;
121 } /* }}} */
122
phpdbg_vprint(int type,int fd,const char * strfmt,va_list args)123 PHPDBG_API int phpdbg_vprint(int type, int fd, const char *strfmt, va_list args) {
124 char *msg = NULL;
125 int msglen = 0;
126 int len;
127 va_list argcpy;
128
129 if (strfmt != NULL && strlen(strfmt) > 0L) {
130 va_copy(argcpy, args);
131 msglen = vasprintf(&msg, strfmt, argcpy);
132 va_end(argcpy);
133 }
134
135 if (PHPDBG_G(err_buf).active && type != P_STDOUT && type != P_STDERR) {
136 phpdbg_free_err_buf();
137
138 PHPDBG_G(err_buf).type = type;
139 PHPDBG_G(err_buf).fd = fd;
140 PHPDBG_G(err_buf).msg = msg;
141 PHPDBG_G(err_buf).msglen = msglen;
142
143 return msglen;
144 }
145
146 if (UNEXPECTED(msglen == 0)) {
147 len = 0;
148 } else {
149 len = phpdbg_process_print(fd, type, msg, msglen);
150 }
151
152 if (msg) {
153 free(msg);
154 }
155
156 return len;
157 }
158
phpdbg_free_err_buf(void)159 PHPDBG_API void phpdbg_free_err_buf(void) {
160 if (PHPDBG_G(err_buf).type == 0) {
161 return;
162 }
163
164 free(PHPDBG_G(err_buf).msg);
165
166 PHPDBG_G(err_buf).type = 0;
167 }
168
phpdbg_activate_err_buf(bool active)169 PHPDBG_API void phpdbg_activate_err_buf(bool active) {
170 PHPDBG_G(err_buf).active = active;
171 }
172
phpdbg_output_err_buf(const char * strfmt,...)173 PHPDBG_API int phpdbg_output_err_buf(const char *strfmt, ...) {
174 int len;
175 va_list args;
176 int errbuf_active = PHPDBG_G(err_buf).active;
177
178 if (PHPDBG_G(flags) & PHPDBG_DISCARD_OUTPUT) {
179 return 0;
180 }
181
182 PHPDBG_G(err_buf).active = 0;
183
184 va_start(args, strfmt);
185 len = phpdbg_vprint(PHPDBG_G(err_buf).type, PHPDBG_G(err_buf).fd, strfmt, args);
186 va_end(args);
187
188 PHPDBG_G(err_buf).active = errbuf_active;
189 phpdbg_free_err_buf();
190
191 return len;
192 }
193
phpdbg_print(int type,int fd,const char * strfmt,...)194 PHPDBG_API int phpdbg_print(int type, int fd, const char *strfmt, ...) {
195 va_list args;
196 int len;
197
198 if (PHPDBG_G(flags) & PHPDBG_DISCARD_OUTPUT) {
199 return 0;
200 }
201
202 va_start(args, strfmt);
203 len = phpdbg_vprint(type, fd, strfmt, args);
204 va_end(args);
205
206 return len;
207 }
208
phpdbg_log_internal(int fd,const char * fmt,...)209 PHPDBG_API int phpdbg_log_internal(int fd, const char *fmt, ...) {
210 va_list args;
211 char *buffer;
212 int buflen;
213 int len = 0;
214
215 va_start(args, fmt);
216 buflen = vasprintf(&buffer, fmt, args);
217 va_end(args);
218
219 len = phpdbg_mixed_write(fd, buffer, buflen);
220 free(buffer);
221
222 return len;
223 }
224
phpdbg_out_internal(int fd,const char * fmt,...)225 PHPDBG_API int phpdbg_out_internal(int fd, const char *fmt, ...) {
226 va_list args;
227 char *buffer;
228 int buflen;
229 int len = 0;
230
231 if (PHPDBG_G(flags) & PHPDBG_DISCARD_OUTPUT) {
232 return 0;
233 }
234
235 va_start(args, fmt);
236 buflen = vasprintf(&buffer, fmt, args);
237 va_end(args);
238
239 len = phpdbg_mixed_write(fd, buffer, buflen);
240
241 free(buffer);
242 return len;
243 }
244