1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
# md4c.tcl - Copyright (C) 2003 Pat Thoyts <patthoyts@users.sourceforge.net>
#
# This provides a C implementation of MD4 using the sample code from RFC1320
# and wrapping this up in a Tcl package.
#
# The tcl interface code is based upon the md5c code from critcl by JCW.
#
# INSTALLATION
# ------------
# This package uses critcl (http://wiki.tcl.tk/critcl). To build do:
# critcl -libdir <your-tcl-lib-dir> -pkg md4c md4c
#
# $Id: md4c.tcl,v 1.6 2009/05/06 22:57:50 patthoyts Exp $
package require critcl
# @sak notprovided md4c
package provide md4c 1.1.0
critcl::cheaders md4.h
critcl::csources md4.c
namespace eval ::md4 {
critcl::ccode {
#include <string.h>
#include "md4.h"
/*
* define a Tcl object type for the MD4 state
*/
static Tcl_ObjType md4_type;
static void md4_free_rep(Tcl_Obj *obj)
{
MD4_CTX *ctx = (MD4_CTX *)obj->internalRep.otherValuePtr;
Tcl_Free((char *)ctx);
}
static void md4_dup_rep(Tcl_Obj *obj, Tcl_Obj *dup)
{
MD4_CTX *ctx = (MD4_CTX *)obj->internalRep.otherValuePtr;
dup->internalRep.otherValuePtr = (MD4_CTX *)Tcl_Alloc(sizeof(MD4_CTX));
memcpy(dup->internalRep.otherValuePtr, ctx, sizeof(MD4_CTX));
dup->typePtr = &md4_type;
}
static void md4_string_rep(Tcl_Obj* obj)
{
unsigned char buf[16];
Tcl_Obj* temp;
char* str;
MD4_CTX *dup = (MD4_CTX *)obj->internalRep.otherValuePtr;
MD4Final(buf, dup);
/* convert via a byte array to properly handle null bytes */
temp = Tcl_NewByteArrayObj(buf, sizeof buf);
Tcl_IncrRefCount(temp);
str = Tcl_GetStringFromObj(temp, &obj->length);
obj->bytes = Tcl_Alloc(obj->length + 1);
memcpy(obj->bytes, str, obj->length + 1);
Tcl_DecrRefCount(temp);
}
static int md4_from_any(Tcl_Interp* interp, Tcl_Obj* obj)
{
/* assert(0); */
return TCL_ERROR;
}
static Tcl_ObjType md4_type = {
"md4c", md4_free_rep, md4_dup_rep, md4_string_rep, md4_from_any
};
}
critcl::ccommand md4c {dummy interp objc objv} {
MD4_CTX *ctx;
unsigned char *data;
int size;
Tcl_Obj *obj;
if (objc < 2 || objc > 3) {
Tcl_WrongNumArgs(interp, 1, objv, "data ?context?");
return TCL_ERROR;
}
if (objc == 3) {
if (objv[2]->typePtr != &md4_type
&& md4_from_any(interp, objv[2]) != TCL_OK) {
return TCL_ERROR;
}
obj = objv[2];
if (Tcl_IsShared(obj)) {
obj = Tcl_DuplicateObj(obj);
}
} else {
ctx = (MD4_CTX *)Tcl_Alloc(sizeof(MD4_CTX));
MD4Init(ctx);
obj = Tcl_NewObj();
Tcl_InvalidateStringRep(obj);
obj->internalRep.otherValuePtr = ctx;
obj->typePtr = &md4_type;
}
ctx = (MD4_CTX *)obj->internalRep.otherValuePtr;
data = Tcl_GetByteArrayFromObj(objv[1], &size);
MD4Update(ctx, data, size);
Tcl_SetObjResult(interp, obj);
return TCL_OK;
}
}
# Local variables:
# mode: tcl
# indent-tabs-mode: nil
# End:
|