1 /*
2 Copyright (C) 2014-2017,2018 John E. Davis
3
4 This file is part of the S-Lang Library.
5
6 The S-Lang Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
10
11 The S-Lang Library 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 GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this library; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 USA.
20 */
21 #include "config.h"
22 #include <stdio.h>
23 #include <string.h>
24 #include <slang.h>
25
26 #include "chksum.h"
27
28 SLANG_MODULE(chksum);
29
30 static int Chksum_Type_Id = 0;
31
32 typedef struct
33 {
34 SLFUTURE_CONST char *name;
35 SLChksum_Type *(*create)(char *);
36 }
37 Chksum_Def_Type;
38
39 typedef struct
40 {
41 char *name;
42 unsigned int numrefs;
43 SLChksum_Type *c;
44 }
45 Chksum_Object_Type;
46
47 static Chksum_Def_Type Chksum_Table[] =
48 {
49 {"md5", _pSLchksum_md5_new},
50 {"sha1", _pSLchksum_sha1_new},
51 {NULL, NULL}
52 };
53
lookup_chksum(char * name)54 static Chksum_Def_Type *lookup_chksum (char *name)
55 {
56 Chksum_Def_Type *t = Chksum_Table;
57
58 while (t->name != NULL)
59 {
60 if (0 == strcmp (t->name, name))
61 return t;
62 t++;
63 }
64
65 SLang_verror (SL_RunTime_Error, "Unsupported/Unknown checksum method `%s'", name);
66 return NULL;
67 }
68
chksum_push(Chksum_Object_Type * obj)69 static int chksum_push (Chksum_Object_Type *obj)
70 {
71 obj->numrefs++;
72
73 if (0 == SLclass_push_ptr_obj (Chksum_Type_Id, (VOID_STAR)obj))
74 return 0;
75
76 obj->numrefs--;
77 return -1;
78 }
79
chksum_free(Chksum_Object_Type * obj)80 static void chksum_free (Chksum_Object_Type *obj)
81 {
82 if (obj == NULL)
83 return;
84 if (obj->numrefs > 1)
85 {
86 obj->numrefs--;
87 return;
88 }
89 if (obj->c != NULL)
90 (void) obj->c->close (obj->c, NULL);
91 SLfree ((char *)obj);
92 }
93
chksum_new(char * name)94 static void chksum_new (char *name)
95 {
96 Chksum_Def_Type *t;
97 Chksum_Object_Type *obj;
98
99 t = lookup_chksum (name);
100 if (t == NULL)
101 return;
102
103 obj = (Chksum_Object_Type *)SLmalloc (sizeof (Chksum_Object_Type));
104 if (obj == NULL)
105 return;
106 memset ((char *)obj, 0, sizeof(SLChksum_Type));
107
108 obj->numrefs = 1;
109 if (NULL == (obj->c = t->create (name)))
110 {
111 SLfree ((char *)obj);
112 return;
113 }
114
115 (void) chksum_push (obj);
116 chksum_free (obj);
117 }
118
119 /* s is assumed to be at least 2*len+1 bytes. */
hexify_string(unsigned char * s,unsigned int len)120 static void hexify_string (unsigned char *s, unsigned int len)
121 {
122 unsigned char *s0, *s1;
123
124 s0 = s + len;
125 s1 = s0 + len;
126 *s1-- = 0;
127 while (s0 > s)
128 {
129 unsigned char ch;
130 unsigned char buf[3];
131
132 s0--;
133 ch = *s0;
134 sprintf ((char *)buf, "%02x", ch);
135 *s1-- = buf[1];
136 *s1-- = buf[0];
137 }
138 }
139
chksum_close(Chksum_Object_Type * obj)140 static void chksum_close (Chksum_Object_Type *obj)
141 {
142 unsigned char *digest;
143 unsigned int digest_len;
144 SLChksum_Type *c;
145
146 if (NULL == (c = obj->c))
147 {
148 (void) SLang_push_null ();
149 return;
150 }
151
152 digest_len = c->digest_len;
153 if (NULL == (digest = (unsigned char *)SLmalloc(2*digest_len+1)))
154 return;
155
156 if (-1 == c->close (c, digest))
157 {
158 SLfree ((char *)digest);
159 return;
160 }
161 obj->c = NULL;
162
163 hexify_string (digest, digest_len);
164
165 (void) SLang_push_malloced_string ((char *)digest);
166 }
167
chksum_accumulate(Chksum_Object_Type * obj,SLang_BString_Type * b)168 static void chksum_accumulate (Chksum_Object_Type *obj, SLang_BString_Type *b)
169 {
170 SLChksum_Type *c;
171 SLstrlen_Type len;
172 unsigned char *s;
173
174 if (NULL == (c = obj->c))
175 {
176 SLang_verror (SL_InvalidParm_Error, "Checksum object is invalid");
177 return;
178 }
179 if (NULL == (s = SLbstring_get_pointer (b, &len)))
180 return;
181
182 (void) c->accumulate (c, s, len);
183 }
184
185 #define DUMMY_CHKSUM_TYPE ((unsigned int)-1)
186 static SLang_Intrin_Fun_Type Intrinsics [] =
187 {
188 MAKE_INTRINSIC_1 ("_chksum_new", chksum_new, SLANG_VOID_TYPE, SLANG_STRING_TYPE),
189 MAKE_INTRINSIC_2 ("_chksum_accumulate", chksum_accumulate, SLANG_VOID_TYPE, DUMMY_CHKSUM_TYPE, SLANG_BSTRING_TYPE),
190 MAKE_INTRINSIC_1 ("_chksum_close", chksum_close, SLANG_VOID_TYPE, DUMMY_CHKSUM_TYPE),
191 SLANG_END_INTRIN_FUN_TABLE
192 };
193
destroy_chksum_type(SLtype type,VOID_STAR ptr)194 static void destroy_chksum_type (SLtype type, VOID_STAR ptr)
195 {
196 (void) type;
197 chksum_free (*(Chksum_Object_Type **)ptr);
198 }
199
push_chksum_type(SLtype type,VOID_STAR ptr)200 static int push_chksum_type (SLtype type, VOID_STAR ptr)
201 {
202 (void) type;
203 return chksum_push (*(Chksum_Object_Type **)ptr);
204 }
205
register_chksum_type(void)206 static int register_chksum_type (void)
207 {
208 SLang_Class_Type *cl;
209
210 if (Chksum_Type_Id != 0)
211 return 0;
212
213 if (NULL == (cl = SLclass_allocate_class ("Chksum_Type")))
214 return -1;
215
216 if (-1 == SLclass_set_destroy_function (cl, destroy_chksum_type))
217 return -1;
218
219 if (-1 == SLclass_set_push_function (cl, push_chksum_type))
220 return -1;
221
222 /* By registering as SLANG_VOID_TYPE, slang will dynamically allocate a
223 * type.
224 */
225 if (-1 == SLclass_register_class (cl, SLANG_VOID_TYPE, sizeof (Chksum_Object_Type *), SLANG_CLASS_TYPE_PTR))
226 return -1;
227
228 Chksum_Type_Id = SLclass_get_class_id (cl);
229
230 if (-1 == SLclass_patch_intrin_fun_table1 (Intrinsics, DUMMY_CHKSUM_TYPE, Chksum_Type_Id))
231 return -1;
232
233 return 0;
234 }
235
init_chksum_module_ns(char * ns_name)236 int init_chksum_module_ns (char *ns_name)
237 {
238 SLang_NameSpace_Type *ns;
239
240 ns = SLns_create_namespace (ns_name);
241 if (ns == NULL)
242 return -1;
243
244 if (-1 == register_chksum_type ())
245 return -1;
246
247 if (-1 == SLns_add_intrin_fun_table (ns, Intrinsics, NULL))
248 return -1;
249
250 return 0;
251 }
252
deinit_chksum_module(void)253 void deinit_chksum_module (void)
254 {
255 }
256