xref: /PHP-8.4/sapi/phpdbg/phpdbg_out.c (revision 95889979)
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