/* * Copyright (C) 2006 Richard Kotal * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published * by the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ static Tcl_Obj * ns_mhash_NewHashObj (MHASH td, char *name) { Tcl_Obj *out = NULL; if (td == NULL) return out; out = Tcl_NewObj (); if (out == NULL) return out; Tcl_InvalidateStringRep(out); Tcl_IncrRefCount (out); out->internalRep.otherValuePtr = (void *) td; out->typePtr = &tclMhashType; if (name != NULL) { out->bytes = name; out->length = strlen (name); } else { out->bytes = NULL; out->length = 0; } return out; } static void ns_mhash_DestroyHashPtr (MHASH td, char *type) { char *buf = NULL; if (td == NULL || td == MHASH_FAILED || type == NULL) return; if (STREQ (type, STR_HASH)) buf = mhash_end (td); else if (STREQ (type, STR_HMAC)) buf = mhash_hmac_end (td); if (buf != NULL) mutils_free (buf); return; } static char * ns_mhash_DeleteHashObj (Tcl_Obj * obj, char *type) { MHASH td = NULL; char *buf = NULL; if (type == NULL || ns_mhash_IsHashObj (obj, type) != NS_TRUE) return buf; td = (MHASH) obj->internalRep.otherValuePtr; if (td != NULL) { if (STREQ (type, STR_HASH)) buf = mhash_end (td); else if (STREQ (type, STR_HMAC)) buf = mhash_hmac_end (td); obj->internalRep.otherValuePtr = NULL; } obj->bytes = NULL; obj->length = 0; Tcl_DecrRefCount (obj); return buf; } static int ns_mhash_DestroyHashObj (Tcl_Obj * obj, char *type) { void *buf = NULL; int ret = TCL_ERROR; if (type == NULL || ns_mhash_IsHashObj (obj, type) != NS_TRUE) return ret; buf = ns_mhash_DeleteHashObj (obj, type); if (buf != NULL) mutils_free (buf); return TCL_OK; } static void FreeMhashInternalRep(Tcl_Obj *obj) { Tcl_DString type; int len = 0; if (obj == NULL) return; if (obj->bytes == NULL) return; len = obj->length; Tcl_DStringInit(&type); Tcl_DStringAppend(&type,obj->bytes,len); ns_mhash_DestroyHashObj (obj, Tcl_DStringValue(&type)); Tcl_DStringFree(&type); return; } static int ns_mhash_DigestPrintFromHash (Tcl_Interp * interp, Tcl_Obj * obj, int bin, char *type) { char *buf = NULL; int hashid = -1; MHASH td = NULL; int len = 0; int ret = TCL_ERROR; if (type == NULL || ns_mhash_IsHashObj (obj, type) != NS_TRUE) return ret; td = (MHASH) obj->internalRep.otherValuePtr; if (td != NULL) hashid = mhash_get_mhash_algo (td); buf = ns_mhash_DeleteHashObj (obj, type); if (buf == NULL || hashid == -1) { if (buf != NULL) mutils_free (buf); Tcl_SetResult (interp, "Hash object is NULL or hash algorithm is bad.", TCL_STATIC); return ret; } len = mhash_get_block_size (hashid); switch (bin) { case 2: { // int size = (1 + (len * 4) / 3); int size = (1 + (len * 2) ); unsigned char b64[size]; bzero(b64,size); Ns_HtuuEncode ((unsigned char *) buf, len, b64); Tcl_AppendResult (interp, b64, NULL); break; } case 1: { Tcl_Obj *bytearray = NULL; bytearray = Tcl_NewByteArrayObj (buf, len); Tcl_SetObjResult (interp, bytearray); break; } default: { char *tmp = NULL; tmp = mutils_asciify (buf, len); Tcl_AppendResult (interp, tmp, NULL); mutils_free (tmp); break; } } mutils_free (buf); return TCL_OK; } static int ns_mhash_UpdateHash (Tcl_Interp * interp, Tcl_Obj * obj, char *txt, int len, char *type) { MHASH td = NULL; int ret = TCL_ERROR; if (type == NULL || ns_mhash_IsHashObj (obj, type) != NS_TRUE || txt == NULL) return ret; td = (MHASH) obj->internalRep.otherValuePtr; if (td == NULL) { Tcl_SetResult (interp, "Hash object is NULL.", TCL_STATIC); return ret; } mhash (td, txt, len); return TCL_OK; } static void UpdateStringOfMhash(Tcl_Obj *obj) { return; } static int SetMhashFromAny( Tcl_Interp *interp, Tcl_Obj *objPtr) { return TCL_ERROR; } static void DupMhashInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr) { MHASH dest = MHASH_FAILED; MHASH src = MHASH_FAILED; if (srcPtr == NULL) return; src = (MHASH) srcPtr->internalRep.otherValuePtr; if (src == NULL || src == MHASH_FAILED) return; dest = mhash_cp (src); if (dest == MHASH_FAILED) return; Tcl_IncrRefCount (copyPtr); copyPtr->internalRep.otherValuePtr = (void *) dest; copyPtr->typePtr = &tclMhashType; copyPtr->bytes = srcPtr->bytes; copyPtr->length = srcPtr->length; return; } static int ns_mhash_CopyHashObj (Tcl_Interp * interp, Tcl_Obj * obj, char *type) { MHASH dest = MHASH_FAILED; MHASH src = MHASH_FAILED; Tcl_Obj *out = NULL; int ret = TCL_ERROR; if (interp == NULL) return ret; if (type == NULL || ns_mhash_IsHashObj (obj, type) != NS_TRUE) { Tcl_SetResult (interp, "Hash object is NULL or this is bad type of object.", TCL_STATIC); return ret; } src = (MHASH) obj->internalRep.otherValuePtr; if (src == NULL || src == MHASH_FAILED) { Tcl_SetResult (interp, "Hash object is NULL.", TCL_STATIC); return ret; } dest = mhash_cp (src); if (dest == MHASH_FAILED) { Tcl_SetResult (interp, "Cannot copy hash object.", TCL_STATIC); return ret; } out = ns_mhash_NewHashObj (dest, type); if (ns_mhash_IsHashObj (out, type) != NS_TRUE) { ns_mhash_DestroyHashPtr (dest, type); Tcl_SetResult (interp, "Cannot create new hash object.", TCL_STATIC); return ret; } Tcl_SetObjResult (interp, out); return TCL_OK; } static int ns_mhash_PutShareHashObj (Tcl_Interp * interp, Tcl_Obj * obj, char *type) { int ret = TCL_ERROR; if (interp == NULL || type == NULL || ns_mhash_IsHashObj (obj, type) != NS_TRUE) return ret; Tcl_IncrRefCount (obj); Tcl_SetIntObj (Tcl_GetObjResult (interp), (int) obj); return TCL_OK; } static int ns_mhash_GetShareHashObj (Tcl_Interp * interp, Tcl_Obj * obj, char *type) { Tcl_Obj *out = NULL; int buf; int ret = TCL_ERROR; if (interp == NULL || type == NULL || obj == NULL) return ret; Tcl_GetIntFromObj (interp, obj, &buf); out = (Tcl_Obj *) buf; if (ns_mhash_IsHashObj (out, type) != NS_TRUE) { Tcl_SetResult (interp, "Cannot create hash object.", TCL_STATIC); return ret; } Tcl_DecrRefCount (out); Tcl_SetObjResult (interp, out); return TCL_OK; } static MHASH ns_mhash_HashCreate (char *name) { int hashid = -1; MHASH td = MHASH_FAILED; hashid = ns_mhash_GetHashId (name); if (hashid == -1) { return td; } td = mhash_init (hashid); return td; } static int ns_mhash_HashNew (Tcl_Interp * interp, char *name) { Tcl_Obj *out = NULL; MHASH td = MHASH_FAILED; int ret = TCL_ERROR; if (interp == NULL) return ret; td = ns_mhash_HashCreate (name); if (td == MHASH_FAILED) { Tcl_SetResult (interp, "Cannot create hash object.", TCL_STATIC); return ret; } out = ns_mhash_NewHashObj (td, STR_HASH); if (ns_mhash_IsHashObj (out, STR_HASH) != NS_TRUE) { ns_mhash_DestroyHashPtr (td, STR_HASH); Tcl_SetResult (interp, "Cannot create hash object.", TCL_STATIC); return ret; } Tcl_SetObjResult (interp, out); return TCL_OK; } static void ns_mhash_HashAlgo (Tcl_Interp * interp, char *type) { size_t len = 0; int i = 0; __const mutils_word8 *algo = NULL; if (interp == NULL || type == NULL) return; len = mhash_count (); for (i = 0; i <= len; i++) { algo = mhash_get_hash_name_static (i); if (algo == NULL) continue; if (type == STR_HMAC && mhash_get_hash_pblock (i) == 0) continue; Tcl_AppendElement (interp, (char *) algo); } return; } static int ns_mhash_SerializeHashObj (Tcl_Interp * interp, Tcl_Obj * obj, char *type) { int ret = TCL_ERROR; mutils_word32 len = 0; mutils_word8 *buf = NULL; MHASH td = NULL; int size = 0; if (interp == NULL || type == NULL || ns_mhash_IsHashObj (obj, type) != NS_TRUE) { Tcl_SetResult (interp, "Hash object cannot be serialize.", TCL_STATIC); return ret; } td = (MHASH) obj->internalRep.otherValuePtr; if (td == NULL) { Tcl_SetResult (interp, "Hash object is NULL.", TCL_STATIC); return ret; } mhash_save_state_mem (td, buf, &len); if (len == 0) { Tcl_SetResult (interp, "Bad length of hash object.", TCL_STATIC); return ret; } buf = (mutils_word8 *) Ns_Malloc (len); mhash_save_state_mem (td, buf, &len); if (len == 0) { if (buf != NULL) Ns_Free (buf); Tcl_SetResult (interp, "Bad length of hash object.", TCL_STATIC); return ret; } if (ns_mhash_DestroyHashObj (obj, type) != TCL_OK) { if (buf != NULL) Ns_Free (buf); Tcl_SetResult (interp, "Cannot destroy hash object.", TCL_STATIC); return ret; } // size = (1 + (len * 4) / 3); size = (1 + (len * 2) ); { unsigned char b64[size]; bzero(b64,size); Ns_HtuuEncode ((unsigned char *) buf, len, b64); Tcl_AppendResult (interp, b64, NULL); if (buf != NULL) Ns_Free (buf); } return TCL_OK; } static int ns_mhash_UnserializeHashObj (Tcl_Interp * interp, Tcl_Obj * obj, char *type) { Tcl_Obj *out = NULL; unsigned char *buf = NULL; int ret = TCL_ERROR; char *b64 = NULL; int nbytes = 0; MHASH td = NULL; int size = 0; if (interp == NULL || type == NULL || obj == NULL) return ret; b64 = Tcl_GetStringFromObj (obj, &nbytes); if (b64 == NULL || nbytes == 0) { Tcl_SetResult (interp, "Serialize hash object is NULL.", TCL_STATIC); return ret; } // size = (3 + (nbytes * 3) / 4); size = (1 + (nbytes * 2)); buf = (unsigned char *) Ns_Malloc (size); bzero(buf,size); if (Ns_HtuuDecode (b64, buf, size) == 0) { if (buf != NULL) Ns_Free (buf); Tcl_SetResult (interp, "Cannot restore hash object.", TCL_STATIC); return ret; } td = mhash_restore_state_mem (buf); if (buf != NULL) Ns_Free (buf); if (td == MHASH_FAILED) { Tcl_SetResult (interp, "Cannot restore hash object.", TCL_STATIC); return ret; } out = ns_mhash_NewHashObj (td, type); if (ns_mhash_IsHashObj (out, type) != NS_TRUE) { ns_mhash_DestroyHashPtr (td, type); Tcl_SetResult (interp, "Cannot create hash object.", TCL_STATIC); return ret; } Tcl_SetObjResult (interp, out); return TCL_OK; }