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