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 | http://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: Anatol Belski <ab@php.net> |
14 +----------------------------------------------------------------------+
15 */
16
17 #ifdef HAVE_CONFIG_H
18 # include "config.h"
19 #endif
20
21 #include "phpdbg.h"
22 #include "phpdbg_eol.h"
23
24 ZEND_EXTERN_MODULE_GLOBALS(phpdbg)
25
26 #define EOL_LIST_LEN 4
27 struct phpdbg_eol_rep phpdbg_eol_list[EOL_LIST_LEN] = {
28 {"CRLF", "\r\n", PHPDBG_EOL_CRLF},
29 /* {"LFCR", "\n\r", PHPDBG_EOL_LFCR},*/
30 {"LF", "\n", PHPDBG_EOL_LF},
31 {"CR", "\r", PHPDBG_EOL_CR},
32 };
33
phpdbg_eol_global_update(char * name)34 int phpdbg_eol_global_update(char *name)
35 {
36
37 if (0 == strcmp(name, "CRLF") || 0 == strcmp(name, "crlf") || 0 == strcmp(name, "DOS") || 0 == strcmp(name, "dos")) {
38 PHPDBG_G(eol) = PHPDBG_EOL_CRLF;
39 } else if (0 == strcmp(name, "LF") || 0 == strcmp(name, "lf") || 0 == strcmp(name, "UNIX") || 0 == strcmp(name, "unix")) {
40 PHPDBG_G(eol) = PHPDBG_EOL_LF;
41 } else if (0 == strcmp(name, "CR") || 0 == strcmp(name, "cr") || 0 == strcmp(name, "MAC") || 0 == strcmp(name, "mac")) {
42 PHPDBG_G(eol) = PHPDBG_EOL_CR;
43 } else {
44 return FAILURE;
45 }
46
47 return SUCCESS;
48 }
49
phpdbg_eol_name(int id)50 char *phpdbg_eol_name(int id)
51 {
52 size_t i = 0;
53
54 while (i < EOL_LIST_LEN) {
55
56 if (id == phpdbg_eol_list[i].id) {
57 return phpdbg_eol_list[i].name;
58 }
59
60 i++;
61 }
62
63 return NULL;
64 }
65
phpdbg_eol_rep(int id)66 char *phpdbg_eol_rep(int id)
67 {
68 size_t i = 0;
69
70 while (i < EOL_LIST_LEN) {
71
72 if (id == phpdbg_eol_list[i].id) {
73 return phpdbg_eol_list[i].rep;
74 }
75
76 i++;
77 }
78
79 return NULL;
80 }
81
82 /* Marked as never_inline to work around a -Walloc-size-larger-than bug in GCC. */
count_lf_and_cr(const char * in,int in_len)83 static zend_never_inline int count_lf_and_cr(const char *in, int in_len) {
84 int i, count = 0;
85 for (i = 0; i < in_len; i++) {
86 if (0x0a == in[i] || 0x0d == in[i]) {
87 count++;
88 }
89 }
90 return count;
91 }
92
93 /* Inspired by https://ccrma.stanford.edu/~craig/utility/flip/flip.cpp */
phpdbg_eol_convert(char ** str,int * len)94 void phpdbg_eol_convert(char **str, int *len)
95 {
96 char *in = *str, *out;
97 int in_len = *len, cursor, i;
98 char last, cur;
99
100 if ((PHPDBG_G(flags) & PHPDBG_IS_REMOTE) != PHPDBG_IS_REMOTE) {
101 return;
102 }
103
104 if (PHPDBG_EOL_CRLF == PHPDBG_G(eol)) { /* XXX add LFCR case if it's gonna be needed */
105 out = (char *)emalloc(in_len + count_lf_and_cr(in, in_len));
106
107 last = cur = in[0];
108 i = cursor = 0;
109 for (; i < in_len;) {
110 if (0x0a == cur && last != 0x0d) {
111 out[cursor] = 0x0d;
112 cursor++;
113 out[cursor] = cur;
114 } else if(0x0d == cur) {
115 if (i + 1 < in_len && 0x0a != in[i+1]) {
116 out[cursor] = cur;
117 cursor++;
118 out[cursor] = 0x0a;
119 last = 0x0a;
120 } else {
121 out[cursor] = 0x0d;
122 last = 0x0d;
123 }
124 } else {
125 out[cursor] = cur;
126 last = cur;
127 }
128
129 i++;
130 cursor++;
131 cur = in[i];
132 }
133
134 } else if (PHPDBG_EOL_LF == PHPDBG_G(eol) || PHPDBG_EOL_CR == PHPDBG_G(eol)) {
135 char want, kick;
136
137 if (PHPDBG_EOL_LF == PHPDBG_G(eol)) {
138 want = 0x0a;
139 kick = 0x0d;
140 } else {
141 want = 0x0d;
142 kick = 0x0a;
143 }
144
145 /* We gonna have a smaller or equally long string, estimation is almost neglecting */
146 out = (char *)emalloc(in_len);
147
148 last = cur = in[0];
149 i = cursor = 0;
150 for (; cursor < in_len;) {
151 if (kick == cur) {
152 out[cursor] = want;
153 } else if (want == cur) {
154 if (kick != last) {
155 out[cursor] = want;
156 }
157 } else {
158 out[cursor] = cur;
159 }
160
161 last = cur;
162 cursor++;
163 cur = in[cursor];
164 }
165 } else {
166 return;
167 }
168
169 efree(*str);
170 *str = erealloc(out, cursor);
171 *len = cursor;
172 in = NULL;
173 }
174