xref: /PHP-7.0/sapi/phpdbg/phpdbg_eol.c (revision 478f119a)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2017 The PHP Group                                |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP license,      |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.php.net/license/3_01.txt                                  |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Authors: Anatol Belski <ab@php.net>                                  |
16    +----------------------------------------------------------------------+
17 */
18 
19 #ifdef HAVE_CONFIG_H
20 #	include "config.h"
21 #endif
22 
23 #include "phpdbg.h"
24 #include "phpdbg_eol.h"
25 
26 ZEND_EXTERN_MODULE_GLOBALS(phpdbg)
27 
28 #define EOL_LIST_LEN 4
29 struct phpdbg_eol_rep phpdbg_eol_list[EOL_LIST_LEN] = {
30 	{"CRLF", "\r\n", PHPDBG_EOL_CRLF},
31 /*	{"LFCR", "\n\r", PHPDBG_EOL_LFCR},*/
32 	{"LF", "\n", PHPDBG_EOL_LF},
33 	{"CR", "\r", PHPDBG_EOL_CR},
34 };
35 
phpdbg_eol_global_update(char * name)36 int phpdbg_eol_global_update(char *name)
37 {
38 
39 	if (0 == memcmp(name, "CRLF", 4) || 0 == memcmp(name, "crlf", 4) || 0 == memcmp(name, "DOS", 3) || 0 == memcmp(name, "dos", 3)) {
40 		PHPDBG_G(eol) = PHPDBG_EOL_CRLF;
41 	} else if (0 == memcmp(name, "LF", 2) || 0 == memcmp(name, "lf", 2) || 0 == memcmp(name, "UNIX", 4) || 0 == memcmp(name, "unix", 4)) {
42 		PHPDBG_G(eol) = PHPDBG_EOL_LF;
43 	} else if (0 == memcmp(name, "CR", 2) || 0 == memcmp(name, "cr", 2) || 0 == memcmp(name, "MAC", 3) || 0 == memcmp(name, "mac", 3)) {
44 		PHPDBG_G(eol) = PHPDBG_EOL_CR;
45 	} else {
46 		return FAILURE;
47 	}
48 
49 	return SUCCESS;
50 }
51 
phpdbg_eol_name(int id)52 char *phpdbg_eol_name(int id)
53 {
54 	size_t i = 0;
55 
56 	while (i < EOL_LIST_LEN) {
57 
58 		if (id == phpdbg_eol_list[i].id) {
59 			return phpdbg_eol_list[i].name;
60 		}
61 
62 		i++;
63 	}
64 
65 	return NULL;
66 }
67 
phpdbg_eol_rep(int id)68 char *phpdbg_eol_rep(int id)
69 {
70 	size_t i = 0;
71 
72 	while (i < EOL_LIST_LEN) {
73 
74 		if (id == phpdbg_eol_list[i].id) {
75 			return phpdbg_eol_list[i].rep;
76 		}
77 
78 		i++;
79 	}
80 
81 	return NULL;
82 }
83 
84 
85 /* Inspired by https://ccrma.stanford.edu/~craig/utility/flip/flip.cpp */
phpdbg_eol_convert(char ** str,int * len)86 void phpdbg_eol_convert(char **str, int *len)
87 {
88 	char *in = *str, *out ;
89 	int in_len = *len, out_len, cursor, i;
90 	char last, cur;
91 
92 	if ((PHPDBG_G(flags) & PHPDBG_IS_REMOTE) != PHPDBG_IS_REMOTE) {
93 		return;
94 	}
95 
96 	out_len = *len;
97 	if (PHPDBG_EOL_CRLF == PHPDBG_G(eol)) { /* XXX add LFCR case if it's gonna be needed */
98 		/* depending on the source EOL the out str will have all CR/LF duplicated */
99 		for (i = 0; i < in_len; i++) {
100 			if (0x0a == in[i] || 0x0d == in[i]) {
101 				out_len++;
102 			}
103 		}
104 		out = (char *)emalloc(out_len);
105 
106 		last = cur = in[0];
107 		i = cursor = 0;
108 		for (; i < in_len;) {
109 			if (0x0a == cur && last != 0x0d) {
110 				out[cursor] = 0x0d;
111 				cursor++;
112 				out[cursor] = cur;
113 			} else if(0x0d == cur) {
114 				if (i + 1 < in_len && 0x0a != in[i+1]) {
115 					out[cursor] = cur;
116 					cursor++;
117 					out[cursor] = 0x0a;
118 					last = 0x0a;
119 				} else {
120 					out[cursor] = 0x0d;
121 					last = 0x0d;
122 				}
123 			} else {
124 				out[cursor] = cur;
125 				last = cur;
126 			}
127 
128 			i++;
129 			cursor++;
130 			cur = in[i];
131 		}
132 
133 	} else if (PHPDBG_EOL_LF == PHPDBG_G(eol) || PHPDBG_EOL_CR == PHPDBG_G(eol)) {
134 		char want, kick;
135 
136 		if (PHPDBG_EOL_LF == PHPDBG_G(eol)) {
137 			want = 0x0a;
138 			kick = 0x0d;
139 		} else {
140 			want = 0x0d;
141 			kick = 0x0a;
142 		}
143 
144 		/* We gonna have a smaller or equally long string, estimation is almost neglecting */
145 		out = (char *)emalloc(out_len);
146 
147 		last = cur = in[0];
148 		i = cursor = 0;
149 		for (; cursor < in_len;) {
150 			if (kick == cur) {
151 				out[cursor] = want;
152 			} else if (want == cur) {
153 				if (kick != last) {
154 					out[cursor] = want;
155 				}
156 			} else {
157 				out[cursor] = cur;
158 			}
159 
160 			last = cur;
161 			cursor++;
162 			cur = in[cursor];
163 		}
164 	} else {
165 		return;
166 	}
167 
168 	efree(*str);
169 	*str = erealloc(out, cursor);
170 	*len = cursor;
171 	in = NULL;
172 }
173