1 // gnoMint: a graphical interface for managing a certification authority
2 // Copyright (C) 2006-2009 David Marín Carreño <davefx@gmail.com>
3 //
4 // This file is part of gnoMint.
5 //
6 // gnoMint is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20
21 #include "uint160.h"
22 #include <string.h>
23 #include <glib/gprintf.h>
24
uint160_new()25 UInt160 * uint160_new()
26 {
27 UInt160 *res = g_new0(UInt160, 1);
28 res->value0=0;
29 res->value1=0;
30 res->value2=0;
31
32 /* fprintf (stderr, "Creado nuevo Uint160: %u:%"G_GUINT64_FORMAT":%"G_GUINT64_FORMAT"\n", */
33 /* res->value2, res->value1, res->value0); */
34
35 return res;
36 }
37
uint160_assign(UInt160 * var,guint64 new_value)38 void uint160_assign (UInt160 *var, guint64 new_value)
39 {
40 /* fprintf (stderr, "Antes de asignar Uint160: %u:%"G_GUINT64_FORMAT":%"G_GUINT64_FORMAT"\n", */
41 /* var->value2, var->value1, var->value0); */
42
43 memset (var, 0, sizeof(UInt160));
44
45 var->value0=new_value;
46 var->value1=0;
47 var->value2=0;
48
49 /* fprintf (stderr, "Asignado valor %"G_GUINT64_FORMAT" Uint160: %u:%"G_GUINT64_FORMAT":%"G_GUINT64_FORMAT"\n", */
50 /* new_value, var->value2, var->value1, var->value0); */
51 return;
52 }
53
54
uint160_assign_hexstr(UInt160 * var,const gchar * new_value_hex)55 gboolean uint160_assign_hexstr (UInt160 *var, const gchar *new_value_hex)
56 {
57 guint i;
58 gchar c;
59
60 gchar * orig_stripped_value = g_strdup (new_value_hex);
61 gchar * stripped_value = g_strstrip (orig_stripped_value);
62
63 /* fprintf (stderr, "Antes de asignar Uint160=%s: %u:%"G_GUINT64_FORMAT":%"G_GUINT64_FORMAT"\n", */
64 /* stripped_value, var->value2, var->value1, var->value0); */
65
66 memset (var, 0, sizeof(UInt160));
67
68 for (i=0; i < strlen(stripped_value); i++) {
69
70 c = g_ascii_tolower(stripped_value[i]);
71
72 // Check if the character is valid
73
74 if (!((c >= '0' && c <= '9') ||
75 (c >= 'a' && c <= 'f'))) {
76 memset (var, 0, sizeof(UInt160));
77 fprintf (stderr, "Error al asignar valor %s Uint160: caracter «%c» encontrado.\n",
78 stripped_value, c);
79 g_free (orig_stripped_value);
80 return FALSE;
81 }
82
83 uint160_shift (var, 4);
84
85 switch(c) {
86 case '0':
87 break;
88 case '1':
89 uint160_add (var, 1);
90 break;
91 case '2':
92 uint160_add (var, 2);
93 break;
94 case '3':
95 uint160_add (var, 3);
96 break;
97 case '4':
98 uint160_add (var, 4);
99 break;
100 case '5':
101 uint160_add (var, 5);
102 break;
103 case '6':
104 uint160_add (var, 6);
105 break;
106 case '7':
107 uint160_add (var, 7);
108 break;
109 case '8':
110 uint160_add (var, 8);
111 break;
112 case '9':
113 uint160_add (var, 9);
114 break;
115 case 'a':
116 uint160_add (var, 10);
117 break;
118 case 'b':
119 uint160_add (var, 11);
120 break;
121 case 'c':
122 uint160_add (var, 12);
123 break;
124 case 'd':
125 uint160_add (var, 13);
126 break;
127 case 'e':
128 uint160_add (var, 14);
129 break;
130 case 'f':
131 uint160_add (var, 15);
132 break;
133 }
134
135 }
136
137
138 /* fprintf (stderr, "Asignado valor %s Uint160: %u:%"G_GUINT64_FORMAT":%"G_GUINT64_FORMAT"\n", */
139 /* stripped_value, var->value2, var->value1, var->value0); */
140 g_free (orig_stripped_value);
141 return TRUE;
142 }
143
uint160_add(UInt160 * var,guint64 new_value)144 void uint160_add (UInt160 *var, guint64 new_value)
145 {
146 guint64 value0_backup = var->value0;
147 guint64 value1_backup = var->value1;
148
149 /* fprintf (stderr, "Sumando %"G_GUINT64_FORMAT" a Uint160: %u:%"G_GUINT64_FORMAT":%"G_GUINT64_FORMAT"\n", */
150 /* new_value, var->value2, var->value1, var->value0); */
151
152 var->value0 = var->value0 + new_value;
153 if (var->value0 < value0_backup) {
154 var->value1++;
155 if (var->value1 < value1_backup)
156 var->value2++;
157 }
158
159 /* fprintf (stderr, "Resultado: %u:%"G_GUINT64_FORMAT":%"G_GUINT64_FORMAT"\n", */
160 /* var->value2, var->value1, var->value0); */
161
162 return;
163 }
164
uint160_inc(UInt160 * var)165 void uint160_inc (UInt160 *var)
166 {
167 uint160_add (var, 1);
168 return;
169 }
170
uint160_dec(UInt160 * var)171 void uint160_dec (UInt160 *var)
172 {
173 guint64 value0_backup = var->value0;
174 guint64 value1_backup = var->value1;
175
176
177 var->value0 --;
178 if (var->value0 > value0_backup) {
179 var->value1 --;
180 if (var->value1 > value1_backup)
181 var->value2--;
182 }
183
184 return;
185 }
186
187
uint160_shift(UInt160 * var,guint positions)188 void uint160_shift (UInt160 *var, guint positions)
189 {
190 /* fprintf (stderr, "Shifting %u a Uint160: %u:%"G_GUINT64_FORMAT":%"G_GUINT64_FORMAT"\n", */
191 /* positions, var->value2, var->value1, var->value0); */
192 guint64 carry0_to_1;
193 guint64 carry1_to_2;
194
195 if (positions > 0) {
196 carry0_to_1 = (var->value0 & G_GUINT64_CONSTANT(0x8000000000000000));
197 carry1_to_2 = (var->value1 & G_GUINT64_CONSTANT(0x8000000000000000));
198
199 var->value0 = var->value0 * 2;
200 var->value1 = (var->value1 * 2) + (carry0_to_1 ? 1 : 0);
201 var->value2 = (var->value2 * 2) + (carry1_to_2 ? 1 : 0);
202
203 uint160_shift (var, positions - 1);
204 }
205
206 return;
207 }
208
209
uint160_write(const UInt160 * var,guchar * buffer,gsize * max_size)210 gboolean uint160_write (const UInt160 *var, guchar *buffer, gsize * max_size)
211 {
212 if (*max_size < 20) {
213 *max_size = 20;
214 return FALSE;
215 }
216
217 buffer[0] = ((var->value2 & 0xFF000000) >> 24);
218 buffer[1] = ((var->value2 & 0x00FF0000) >> 16);
219 buffer[2] = ((var->value2 & 0x0000FF00) >> 8);
220 buffer[3] = ((var->value2 & 0x000000FF));
221
222 buffer[4] = ((var->value1 & G_GUINT64_CONSTANT(0xFF00000000000000)) >> 56);
223 buffer[5] = ((var->value1 & G_GUINT64_CONSTANT(0x00FF000000000000)) >> 48);
224 buffer[6] = ((var->value1 & G_GUINT64_CONSTANT(0x0000FF0000000000)) >> 40);
225 buffer[7] = ((var->value1 & G_GUINT64_CONSTANT(0x000000FF00000000)) >> 32);
226 buffer[8] = ((var->value1 & G_GUINT64_CONSTANT(0x00000000FF000000)) >> 24);
227 buffer[9] = ((var->value1 & G_GUINT64_CONSTANT(0x0000000000FF0000)) >> 16);
228 buffer[10] = ((var->value1 & G_GUINT64_CONSTANT(0x000000000000FF00)) >> 8);
229 buffer[11] = ((var->value1 & G_GUINT64_CONSTANT(0x00000000000000FF)));
230
231 buffer[12] = ((var->value0 & G_GUINT64_CONSTANT(0xFF00000000000000)) >> 56);
232 buffer[13] = ((var->value0 & G_GUINT64_CONSTANT(0x00FF000000000000)) >> 48);
233 buffer[14] = ((var->value0 & G_GUINT64_CONSTANT(0x0000FF0000000000)) >> 40);
234 buffer[15] = ((var->value0 & G_GUINT64_CONSTANT(0x000000FF00000000)) >> 32);
235 buffer[16] = ((var->value0 & G_GUINT64_CONSTANT(0x00000000FF000000)) >> 24);
236 buffer[17] = ((var->value0 & G_GUINT64_CONSTANT(0x0000000000FF0000)) >> 16);
237 buffer[18] = ((var->value0 & G_GUINT64_CONSTANT(0x000000000000FF00)) >> 8);
238 buffer[19] = ((var->value0 & G_GUINT64_CONSTANT(0x00000000000000FF)));
239
240 *max_size = 20;
241 return TRUE;
242
243 }
244
uint160_read(UInt160 * var,guchar * buffer,gsize buffer_size)245 gboolean uint160_read (UInt160 *var, guchar *buffer, gsize buffer_size)
246 {
247 gint start, i;
248 guchar c;
249
250 memset (var, 0, sizeof(UInt160));
251
252 var->value0=0;
253 var->value1=0;
254 var->value2=0;
255
256 start = 0;
257
258 while (start < buffer_size && buffer[start] == 0)
259 start++;
260
261 for (i=start; i < buffer_size; i++) {
262 c = buffer[i];
263 uint160_shift (var, 8);
264 uint160_add (var, c);
265 }
266 return TRUE;
267 }
268
uint160_write_escaped(const UInt160 * var,gchar * buffer,gsize * max_size)269 gboolean uint160_write_escaped (const UInt160 *var, gchar *buffer, gsize * max_size)
270 {
271 gsize size = 0;
272 guint32 value = 0;
273 gsize pos = 0;
274
275 if (var->value2 > 0)
276 size = 16 + 16 + 8 + 1;
277 else if (var->value1 > 0)
278 size = 16 + 16 + 1;
279 else
280 size = 16 + 1;
281
282 if (size > *max_size) {
283 *max_size = size;
284 return FALSE;
285 }
286
287 memset (buffer, 0, size);
288
289 if (var->value2 > 0) {
290 value = var->value2;
291 sprintf (&buffer[pos], "%08" G_GINT32_MODIFIER "x", value);
292 pos = pos + 8;
293 }
294
295 if (var->value2 > 0 || var->value1 > 0) {
296 value = (var->value1 / G_GUINT64_CONSTANT(0x100000000));
297 sprintf (&buffer[pos], "%08" G_GINT32_MODIFIER "x", value);
298 pos = pos + 8;
299
300 value = (var->value1 % G_GUINT64_CONSTANT(0x100000000));
301 sprintf (&buffer[pos], "%08" G_GINT32_MODIFIER "x", value);
302 pos = pos + 8;
303 }
304
305 value = (var->value0 / G_GUINT64_CONSTANT(0x100000000));
306 sprintf (&buffer[pos], "%08" G_GINT32_MODIFIER "x", value);
307 pos = pos + 8;
308
309 value = (var->value0 % G_GUINT64_CONSTANT(0x100000000));
310 sprintf (&buffer[pos], "%08" G_GINT32_MODIFIER "x", value);
311 pos = pos + 8;
312
313 return TRUE;
314
315 }
316
uint160_read_escaped(UInt160 * var,gchar * buffer,gsize buffer_size)317 gboolean uint160_read_escaped (UInt160 *var, gchar *buffer, gsize buffer_size)
318 {
319 gchar aux[2];
320 guint i;
321 guint num;
322 gboolean res = TRUE;
323
324 /* fprintf (stderr, "Uint160_read_escaped <%s>\n", buffer); */
325
326 memset (var, 0, sizeof (UInt160));
327 memset (aux, 0, 2);
328
329 for (i=0; i<buffer_size; i++) {
330 aux[0] = buffer[i];
331 if (sscanf (aux, "%x", &num)) {
332 /* fprintf (stderr, "pos: %d. Char: %s. Val: %d\n", i, aux, num); */
333 uint160_shift (var, 4);
334 uint160_add (var, num);
335 } else {
336 memset (var, 0, sizeof (UInt160));
337 res = FALSE;
338 break;
339 }
340 }
341
342 /* fprintf (stderr, "Uint160_read_escaped <%s> = : %u:%"G_GUINT64_FORMAT":%"G_GUINT64_FORMAT"\n", */
343 /* buffer, var->value2, var->value1, var->value0); */
344
345 return res;
346 }
347
348
uint160_read_escaped_old_format(UInt160 * var,gchar * buffer,gsize buffer_size)349 gboolean uint160_read_escaped_old_format (UInt160 *var, gchar *buffer, gsize buffer_size)
350 {
351 gint i;
352 guint num_chars;
353 guchar c;
354 guchar buffer_c[buffer_size];
355
356 memset (var, 0, sizeof (UInt160));
357
358 var->value0=0;
359 var->value1=0;
360 var->value2=0;
361
362 num_chars = 0;
363 for (i=0; i < buffer_size; i++) {
364 c = buffer[i];
365 if (c < 33) {
366 i++;
367 c = buffer[i] - 0x20;
368 }
369 buffer_c[num_chars] = c;
370 num_chars++;
371 }
372
373 for (i=num_chars - 1; i>=0; i--) {
374 c = buffer_c[i];
375 uint160_shift (var, 8);
376 uint160_add (var, c);
377 }
378 return TRUE;
379 }
380
uint160_strdup_printf(const UInt160 * var)381 gchar * uint160_strdup_printf (const UInt160 *var)
382 {
383
384 GString *string = g_string_new("");
385 guint64 val;
386 gsize size = 0;
387 guchar * pointer;
388 int i;
389
390 /* First, we calculate how many bytes are filled */
391 if (var->value2 != 0) {
392 size = 16;
393 val = var->value2;
394 while (val != 0) {
395 val = val >> 8;
396 size++;
397 }
398 } else if (var->value1 != 0) {
399 size = 8;
400 val = var->value1;
401 while (val != 0) {
402 val = val >> 8;
403 size ++;
404 }
405 } else if (var->value0 != 0) {
406 val = var->value0;
407 while (val != 0) {
408 val = val >> 8;
409 size ++;
410 }
411 }
412
413 for (i=size-1; i>=0; i--) {
414 if (i < 8) {
415 pointer = (guchar *) &(var->value0);
416 g_string_append_printf (string, "%s%02X", (i==(size-1)?"":":"), pointer[i]);
417 } else if (i < 16) {
418 pointer = (guchar *) &(var->value1);
419 g_string_append_printf (string, "%s%02X", (i==(size-1)?"":":"), pointer[i-8]);
420 } else {
421 pointer = (guchar *) &(var->value2);
422 g_string_append_printf (string, "%s%02X", (i==(size-1)?"":":"), pointer[i-16]);
423 }
424 }
425
426 return g_string_free (string, FALSE);
427
428 }
429
uint160_free(UInt160 * var)430 void uint160_free (UInt160 *var)
431 {
432 g_free (var);
433 }
434