FreeRDP
print.c
1 
20 #include <winpr/config.h>
21 #include <winpr/debug.h>
22 
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdarg.h>
26 #include <errno.h>
27 
28 #include <winpr/crt.h>
29 #include <winpr/print.h>
30 
31 #include "../log.h"
32 
33 #ifndef MIN
34 #define MIN(a, b) (a) < (b) ? (a) : (b)
35 #endif
36 
37 void winpr_HexDump(const char* tag, UINT32 level, const void* data, size_t length)
38 {
39  wLog* log = WLog_Get(tag);
40  winpr_HexLogDump(log, level, data, length);
41 }
42 
43 void winpr_HexLogDump(wLog* log, UINT32 lvl, const void* data, size_t length)
44 {
45  const BYTE* p = data;
46  size_t line = 0;
47  size_t offset = 0;
48  const size_t maxlen = 20; /* 64bit SIZE_MAX as decimal */
49  /* String line length:
50  * prefix '[1234] '
51  * hexdump '01 02 03 04'
52  * separator ' '
53  * ASIC line 'ab..cd'
54  * zero terminator '\0'
55  */
56  const size_t blen = (maxlen + 3ULL) + (WINPR_HEXDUMP_LINE_LENGTH * 3ULL) + 3ULL +
57  WINPR_HEXDUMP_LINE_LENGTH + 1ULL;
58  size_t pos = 0;
59 
60  char* buffer = NULL;
61 
62  if (!WLog_IsLevelActive(log, lvl))
63  return;
64 
65  if (!log)
66  return;
67 
68  buffer = malloc(blen);
69 
70  if (!buffer)
71  {
72  char ebuffer[256] = { 0 };
73  WLog_Print(log, WLOG_ERROR, "malloc(%" PRIuz ") failed with [%" PRIuz "] %s", blen, errno,
74  winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
75  return;
76  }
77 
78  while (offset < length)
79  {
80  int rc = _snprintf(&buffer[pos], blen - pos, "%04" PRIuz " ", offset);
81 
82  if (rc < 0)
83  goto fail;
84 
85  pos += (size_t)rc;
86  line = length - offset;
87 
88  if (line > WINPR_HEXDUMP_LINE_LENGTH)
89  line = WINPR_HEXDUMP_LINE_LENGTH;
90 
91  size_t i = 0;
92  for (; i < line; i++)
93  {
94  rc = _snprintf(&buffer[pos], blen - pos, "%02" PRIx8 " ", p[i]);
95 
96  if (rc < 0)
97  goto fail;
98 
99  pos += (size_t)rc;
100  }
101 
102  for (; i < WINPR_HEXDUMP_LINE_LENGTH; i++)
103  {
104  rc = _snprintf(&buffer[pos], blen - pos, " ");
105 
106  if (rc < 0)
107  goto fail;
108 
109  pos += (size_t)rc;
110  }
111 
112  for (size_t j = 0; j < line; j++)
113  {
114  rc = _snprintf(&buffer[pos], blen - pos, "%c",
115  (p[j] >= 0x20 && p[j] < 0x7F) ? (char)p[j] : '.');
116 
117  if (rc < 0)
118  goto fail;
119 
120  pos += (size_t)rc;
121  }
122 
123  WLog_Print(log, lvl, "%s", buffer);
124  offset += line;
125  p += line;
126  pos = 0;
127  }
128 
129  WLog_Print(log, lvl, "[length=%" PRIuz "] ", length);
130 fail:
131  free(buffer);
132 }
133 
134 void winpr_CArrayDump(const char* tag, UINT32 level, const void* data, size_t length, size_t width)
135 {
136  const BYTE* p = data;
137  size_t offset = 0;
138  const size_t llen = ((length > width) ? width : length) * 4ull + 1ull;
139  size_t pos = 0;
140  char* buffer = malloc(llen);
141 
142  if (!buffer)
143  {
144  char ebuffer[256] = { 0 };
145  WLog_ERR(tag, "malloc(%" PRIuz ") failed with [%d] %s", llen, errno,
146  winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
147  return;
148  }
149 
150  while (offset < length)
151  {
152  size_t line = length - offset;
153 
154  if (line > width)
155  line = width;
156 
157  pos = 0;
158 
159  for (size_t i = 0; i < line; i++)
160  {
161  const int rc = _snprintf(&buffer[pos], llen - pos, "\\x%02" PRIX8 "", p[i]);
162  if (rc < 0)
163  goto fail;
164  pos += (size_t)rc;
165  }
166 
167  WLog_LVL(tag, level, "%s", buffer);
168  offset += line;
169  p += line;
170  }
171 
172 fail:
173  free(buffer);
174 }
175 
176 static BYTE value(char c)
177 {
178  if ((c >= '0') && (c <= '9'))
179  return c - '0';
180  if ((c >= 'A') && (c <= 'F'))
181  return 10 + c - 'A';
182  if ((c >= 'a') && (c <= 'f'))
183  return 10 + c - 'a';
184  return 0;
185 }
186 
187 size_t winpr_HexStringToBinBuffer(const char* str, size_t strLength, BYTE* data, size_t dataLength)
188 {
189  size_t y = 0;
190  size_t maxStrLen = 0;
191  if (!str || !data || (strLength == 0) || (dataLength == 0))
192  return 0;
193 
194  maxStrLen = strnlen(str, strLength);
195  for (size_t x = 0; x < maxStrLen;)
196  {
197  BYTE val = value(str[x++]);
198  if (x < maxStrLen)
199  val = (BYTE)(val << 4) | (value(str[x++]));
200  if (x < maxStrLen)
201  {
202  if (str[x] == ' ')
203  x++;
204  }
205  data[y++] = val;
206  if (y >= dataLength)
207  return y;
208  }
209  return y;
210 }
211 
212 size_t winpr_BinToHexStringBuffer(const BYTE* data, size_t length, char* dstStr, size_t dstSize,
213  BOOL space)
214 {
215  const size_t n = space ? 3 : 2;
216  const char bin2hex[] = "0123456789ABCDEF";
217  const size_t maxLength = MIN(length, dstSize / n);
218 
219  if (!data || !dstStr || (length == 0) || (dstSize == 0))
220  return 0;
221 
222  for (size_t i = 0; i < maxLength; i++)
223  {
224  const int ln = data[i] & 0xF;
225  const int hn = (data[i] >> 4) & 0xF;
226  char* dst = &dstStr[i * n];
227 
228  dst[0] = bin2hex[hn];
229  dst[1] = bin2hex[ln];
230 
231  if (space)
232  dst[2] = ' ';
233  }
234 
235  if (space && (maxLength > 0))
236  {
237  dstStr[maxLength * n - 1] = '\0';
238  return maxLength * n - 1;
239  }
240  dstStr[maxLength * n] = '\0';
241  return maxLength * n;
242 }
243 
244 char* winpr_BinToHexString(const BYTE* data, size_t length, BOOL space)
245 {
246  size_t rc = 0;
247  const size_t n = space ? 3 : 2;
248  const size_t size = (length + 1ULL) * n;
249  char* p = (char*)malloc(size);
250 
251  if (!p)
252  return NULL;
253 
254  rc = winpr_BinToHexStringBuffer(data, length, p, size, space);
255  if (rc == 0)
256  {
257  free(p);
258  return NULL;
259  }
260 
261  return p;
262 }