/src/FreeRDP/winpr/libwinpr/utils/print.c
Line | Count | Source (jump to first uncovered line) |
1 | | /** |
2 | | * WinPR: Windows Portable Runtime |
3 | | * Print Utils |
4 | | * |
5 | | * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> |
6 | | * |
7 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
8 | | * you may not use this file except in compliance with the License. |
9 | | * You may obtain a copy of the License at |
10 | | * |
11 | | * http://www.apache.org/licenses/LICENSE-2.0 |
12 | | * |
13 | | * Unless required by applicable law or agreed to in writing, software |
14 | | * distributed under the License is distributed on an "AS IS" BASIS, |
15 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | | * See the License for the specific language governing permissions and |
17 | | * limitations under the License. |
18 | | */ |
19 | | |
20 | | #include <winpr/config.h> |
21 | | |
22 | | #include <stdio.h> |
23 | | #include <string.h> |
24 | | #include <stdarg.h> |
25 | | #include <errno.h> |
26 | | |
27 | | #include <winpr/crt.h> |
28 | | #include <winpr/print.h> |
29 | | |
30 | | #include "../log.h" |
31 | | |
32 | | #ifndef MIN |
33 | 53 | #define MIN(a, b) (a) < (b) ? (a) : (b) |
34 | | #endif |
35 | | |
36 | | void winpr_HexDump(const char* tag, UINT32 level, const void* data, size_t length) |
37 | 0 | { |
38 | 0 | wLog* log = WLog_Get(tag); |
39 | 0 | winpr_HexLogDump(log, level, data, length); |
40 | 0 | } |
41 | | |
42 | | void winpr_HexLogDump(wLog* log, UINT32 lvl, const void* data, size_t length) |
43 | 0 | { |
44 | 0 | const BYTE* p = data; |
45 | 0 | size_t i, line, offset = 0; |
46 | 0 | const size_t maxlen = 20; /* 64bit SIZE_MAX as decimal */ |
47 | | /* String line length: |
48 | | * prefix '[1234] ' |
49 | | * hexdump '01 02 03 04' |
50 | | * separator ' ' |
51 | | * ASIC line 'ab..cd' |
52 | | * zero terminator '\0' |
53 | | */ |
54 | 0 | const size_t blen = |
55 | 0 | (maxlen + 3) + (WINPR_HEXDUMP_LINE_LENGTH * 3) + 3 + WINPR_HEXDUMP_LINE_LENGTH + 1; |
56 | 0 | size_t pos = 0; |
57 | |
|
58 | 0 | char* buffer; |
59 | |
|
60 | 0 | if (!WLog_IsLevelActive(log, lvl)) |
61 | 0 | return; |
62 | | |
63 | 0 | if (!log) |
64 | 0 | return; |
65 | | |
66 | 0 | buffer = malloc(blen); |
67 | |
|
68 | 0 | if (!buffer) |
69 | 0 | { |
70 | 0 | WLog_Print(log, WLOG_ERROR, "malloc(%" PRIuz ") failed with [%" PRIuz "] %s", blen, errno, |
71 | 0 | strerror(errno)); |
72 | 0 | return; |
73 | 0 | } |
74 | | |
75 | 0 | while (offset < length) |
76 | 0 | { |
77 | 0 | int rc = _snprintf(&buffer[pos], blen - pos, "%04" PRIuz " ", offset); |
78 | |
|
79 | 0 | if (rc < 0) |
80 | 0 | goto fail; |
81 | | |
82 | 0 | pos += (size_t)rc; |
83 | 0 | line = length - offset; |
84 | |
|
85 | 0 | if (line > WINPR_HEXDUMP_LINE_LENGTH) |
86 | 0 | line = WINPR_HEXDUMP_LINE_LENGTH; |
87 | |
|
88 | 0 | for (i = 0; i < line; i++) |
89 | 0 | { |
90 | 0 | rc = _snprintf(&buffer[pos], blen - pos, "%02" PRIx8 " ", p[i]); |
91 | |
|
92 | 0 | if (rc < 0) |
93 | 0 | goto fail; |
94 | | |
95 | 0 | pos += (size_t)rc; |
96 | 0 | } |
97 | | |
98 | 0 | for (; i < WINPR_HEXDUMP_LINE_LENGTH; i++) |
99 | 0 | { |
100 | 0 | rc = _snprintf(&buffer[pos], blen - pos, " "); |
101 | |
|
102 | 0 | if (rc < 0) |
103 | 0 | goto fail; |
104 | | |
105 | 0 | pos += (size_t)rc; |
106 | 0 | } |
107 | | |
108 | 0 | for (i = 0; i < line; i++) |
109 | 0 | { |
110 | 0 | rc = _snprintf(&buffer[pos], blen - pos, "%c", |
111 | 0 | (p[i] >= 0x20 && p[i] < 0x7F) ? (char)p[i] : '.'); |
112 | |
|
113 | 0 | if (rc < 0) |
114 | 0 | goto fail; |
115 | | |
116 | 0 | pos += (size_t)rc; |
117 | 0 | } |
118 | | |
119 | 0 | WLog_Print(log, lvl, "%s", buffer); |
120 | 0 | offset += line; |
121 | 0 | p += line; |
122 | 0 | pos = 0; |
123 | 0 | } |
124 | | |
125 | 0 | WLog_Print(log, lvl, "[length=%" PRIuz "] ", length); |
126 | 0 | fail: |
127 | 0 | free(buffer); |
128 | 0 | } |
129 | | |
130 | | void winpr_CArrayDump(const char* tag, UINT32 level, const void* data, size_t length, size_t width) |
131 | 0 | { |
132 | 0 | const BYTE* p = data; |
133 | 0 | size_t i, offset = 0; |
134 | 0 | const size_t llen = ((length > width) ? width : length) * 4ull + 1ull; |
135 | 0 | size_t pos; |
136 | 0 | char* buffer = malloc(llen); |
137 | |
|
138 | 0 | if (!buffer) |
139 | 0 | { |
140 | 0 | WLog_ERR(tag, "malloc(%" PRIuz ") failed with [%d] %s", llen, errno, strerror(errno)); |
141 | 0 | return; |
142 | 0 | } |
143 | | |
144 | 0 | while (offset < length) |
145 | 0 | { |
146 | 0 | size_t line = length - offset; |
147 | |
|
148 | 0 | if (line > width) |
149 | 0 | line = width; |
150 | |
|
151 | 0 | pos = 0; |
152 | |
|
153 | 0 | for (i = 0; i < line; i++) |
154 | 0 | { |
155 | 0 | const int rc = _snprintf(&buffer[pos], llen - pos, "\\x%02" PRIX8 "", p[i]); |
156 | 0 | if (rc < 0) |
157 | 0 | goto fail; |
158 | 0 | pos += (size_t)rc; |
159 | 0 | } |
160 | | |
161 | 0 | WLog_LVL(tag, level, "%s", buffer); |
162 | 0 | offset += line; |
163 | 0 | p += line; |
164 | 0 | } |
165 | | |
166 | 0 | fail: |
167 | 0 | free(buffer); |
168 | 0 | } |
169 | | |
170 | | static BYTE value(char c) |
171 | 0 | { |
172 | 0 | if ((c >= '0') && (c <= '9')) |
173 | 0 | return c - '0'; |
174 | 0 | if ((c >= 'A') && (c <= 'F')) |
175 | 0 | return 10 + c - 'A'; |
176 | 0 | if ((c >= 'a') && (c <= 'f')) |
177 | 0 | return 10 + c - 'a'; |
178 | 0 | return 0; |
179 | 0 | } |
180 | | |
181 | | size_t winpr_HexStringToBinBuffer(const char* str, size_t strLength, BYTE* data, size_t dataLength) |
182 | 0 | { |
183 | 0 | size_t x, y = 0; |
184 | 0 | size_t maxStrLen; |
185 | 0 | if (!str || !data || (strLength == 0) || (dataLength == 0)) |
186 | 0 | return 0; |
187 | | |
188 | 0 | maxStrLen = strnlen(str, strLength); |
189 | 0 | for (x = 0; x < maxStrLen;) |
190 | 0 | { |
191 | 0 | BYTE val = value(str[x++]); |
192 | 0 | if (x < maxStrLen) |
193 | 0 | val = (BYTE)(val << 4) | (value(str[x++])); |
194 | 0 | if (x < maxStrLen) |
195 | 0 | { |
196 | 0 | if (str[x] == ' ') |
197 | 0 | x++; |
198 | 0 | } |
199 | 0 | data[y++] = val; |
200 | 0 | if (y >= dataLength) |
201 | 0 | return y; |
202 | 0 | } |
203 | 0 | return y; |
204 | 0 | } |
205 | | |
206 | | size_t winpr_BinToHexStringBuffer(const BYTE* data, size_t length, char* dstStr, size_t dstSize, |
207 | | BOOL space) |
208 | 53 | { |
209 | 53 | const size_t n = space ? 3 : 2; |
210 | 53 | const char bin2hex[] = "0123456789ABCDEF"; |
211 | 53 | const size_t maxLength = MIN(length, dstSize / n); |
212 | 53 | size_t i; |
213 | | |
214 | 53 | if (!data || !dstStr || (length == 0) || (dstSize == 0)) |
215 | 0 | return 0; |
216 | | |
217 | 8.38M | for (i = 0; i < maxLength; i++) |
218 | 8.38M | { |
219 | 8.38M | const int ln = data[i] & 0xF; |
220 | 8.38M | const int hn = (data[i] >> 4) & 0xF; |
221 | 8.38M | char* dst = &dstStr[i * n]; |
222 | | |
223 | 8.38M | dst[0] = bin2hex[hn]; |
224 | 8.38M | dst[1] = bin2hex[ln]; |
225 | | |
226 | 8.38M | if (space) |
227 | 0 | dst[2] = ' '; |
228 | 8.38M | } |
229 | | |
230 | 53 | if (space && (maxLength > 0)) |
231 | 0 | { |
232 | 0 | dstStr[maxLength * n - 1] = '\0'; |
233 | 0 | return maxLength * n - 1; |
234 | 0 | } |
235 | 53 | dstStr[maxLength * n] = '\0'; |
236 | 53 | return maxLength * n; |
237 | 53 | } |
238 | | |
239 | | char* winpr_BinToHexString(const BYTE* data, size_t length, BOOL space) |
240 | 53 | { |
241 | 53 | size_t rc; |
242 | 53 | const size_t n = space ? 3 : 2; |
243 | 53 | const size_t size = (length + 1ULL) * n; |
244 | 53 | char* p = (char*)malloc(size); |
245 | | |
246 | 53 | if (!p) |
247 | 0 | return NULL; |
248 | | |
249 | 53 | rc = winpr_BinToHexStringBuffer(data, length, p, size, space); |
250 | 53 | if (rc == 0) |
251 | 0 | { |
252 | 0 | free(p); |
253 | 0 | return NULL; |
254 | 0 | } |
255 | | |
256 | 53 | return p; |
257 | 53 | } |