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