Artifact 064d1bbac501034927aa7bd82a82212f648b9913:
- File
packages/string/lib/cdc.tcl
— part of check-in
[56ea300bbf]
at
2020-05-18 13:50:56
on branch trunk
— cdc
silenced some compiler warnings
gryp keep
first working encrypted remote file storage and retrieval
(user: pooryorick size: 5443)
#! /usr/bin/env tclsh package require {ycl chan clib} package require sha256c ::critcl::ccode { #include <string.h> #include <stdint.h> typedef struct state { char *channame; Tcl_Obj *list; /* current fragment size */ int fsize; uint64_t cursor; unsigned int min_fragment; unsigned int max_fragment; /* rolling hash for finding fragment boundaries */ uint32_t h; /* previous byte */ Tcl_UniChar c1; /* order 1 context -> predicted byte */ unsigned char o1[256]; SHA256_CTX *mp; SHA256_CTX *wholemp; } state; int initialized = 0; Tcl_HashTable chanchunks; void finalize (ClientData clientData); int process(ClientData clientData ,Tcl_UniChar uchar , Tcl_DString *output) { state *s = clientData; int fragtune = 6; unsigned char byte; Tcl_Obj *cursorobj ,*tmp; uint8_t hash[SHA256_HASH_SIZE]; Tcl_Obj *hashobj; if (uchar == s->o1[s->c1]) { s->h = (s->h + uchar + 1) * 31415926u; } else { s->h = (s->h + uchar + 1) * 271828182u; } Tcl_Channel *chan = Tcl_GetStdChannel(TCL_STDOUT); /* tmp = Tcl_NewWideIntObj(s->h); Tcl_WriteObj(chan ,tmp); Tcl_DecrRefCount(tmp); Tcl_Write(chan ,"\n", -1); tmp = Tcl_NewWideIntObj(s->h & 0x1f); Tcl_WriteObj(chan ,Tcl_NewWideIntObj(s->h & 0x1f)); Tcl_DecrRefCount(tmp); Tcl_Write(chan ,"\n\n", -1); */ if ((s->h < (1u <<(22-fragtune)) && s->fsize >= s->min_fragment) || s->fsize >= s->max_fragment) { cursorobj = Tcl_NewWideIntObj(s->cursor); /* Tcl_Write(chan ,"\n", -1); Tcl_WriteObj(chan ,cursorobj); Tcl_Write(chan ,"\n\n", -1); */ SHA256Final(s->mp ,hash); hashobj = Tcl_NewByteArrayObj(hash ,SHA256_HASH_SIZE); SHA256Init(s->mp); Tcl_ListObjAppendElement(NULL ,s->list ,cursorobj); Tcl_ListObjAppendElement(NULL ,s->list ,hashobj); s->h = 0; s->fsize = 0; } /* cursorobj = Tcl_NewWideIntObj(s->cursor); Tcl_Write(chan ,"\n", -1); Tcl_WriteObj(chan ,cursorobj); Tcl_DecrRefCount(cursorobj); */ byte = uchar; SHA256Update(s->mp ,&byte ,1); SHA256Update(s->wholemp ,&byte ,1); s->fsize++; s->o1[s->c1] = uchar; s->c1 = uchar; s->cursor++; return TCL_OK; } int closeProc (Tcl_Interp *interp ,ClientData clientData , Tcl_DString *output, int flags) { state *s = clientData; uint8_t hash[SHA256_HASH_SIZE]; Tcl_Obj *cursorobj ,*hashobj; if (flags & TCL_CLOSE_READ) { } else if (flags & TCL_CLOSE_WRITE) { } else { if (s->fsize > 0) { cursorobj = Tcl_NewWideIntObj(s->cursor); Tcl_ListObjAppendElement(NULL ,s->list ,cursorobj); SHA256Final(s->mp ,hash); hashobj = Tcl_NewByteArrayObj(hash ,SHA256_HASH_SIZE); Tcl_ListObjAppendElement(NULL ,s->list ,hashobj); s->fsize = 0; } finalize(s); } return TCL_OK; } int eofProc (ClientData clientData) { state *s = clientData; Tcl_Obj *cursorobj ,*hashobj; uint8_t hash[SHA256_HASH_SIZE]; if (s->fsize > 0) { cursorobj = Tcl_NewWideIntObj(s->cursor); Tcl_ListObjAppendElement(NULL ,s->list ,cursorobj); SHA256Final(s->mp ,hash); hashobj = Tcl_NewByteArrayObj(hash ,SHA256_HASH_SIZE); Tcl_ListObjAppendElement(NULL ,s->list ,hashobj); SHA256Init(s->mp); s->fsize = 0; } return TCL_OK; } void finalize (ClientData clientData) { state *s = clientData; char *name = s->channame; /* drop the refCount of this private Tcl_Obj to -1 */ Tcl_DecrRefCount(s->list); Tcl_HashEntry *entry = Tcl_FindHashEntry(&chanchunks ,s->channame); Tcl_DeleteHashEntry(entry); ckfree(s->mp); ckfree(s->wholemp); ckfree(s->channame); ckfree(s); return; } } critcl::cproc cut { Tcl_Interp* interp char* channame} object { char * channame2; int isnew; if (initialized == 0) { Tcl_InitHashTable(&chanchunks ,TCL_STRING_KEYS); initialized = 1; } Tcl_HashEntry *entry = Tcl_CreateHashEntry(&chanchunks ,channame ,&isnew); Tcl_Obj *list, *res; state *s = (state *)ckalloc(sizeof(state)); memset(s ,0 ,sizeof(state)); list = Tcl_NewListObj(0, NULL); Tcl_SetHashValue(entry ,s); channame2 = ckalloc(strlen(channame) + 1); memmove(channame2 ,channame ,(strlen(channame) + 1)); s->channame = channame2; s->min_fragment = 8192; s->max_fragment = 16536; s->list = list; s->mp = (void *)ckalloc(sizeof(*s->mp)); SHA256Init(s->mp); s->wholemp = (void *)ckalloc(sizeof(*s->mp)); SHA256Init(s->wholemp); res = Tcl_NewObj(); Tcl_IncrRefCount(res); if (pushTransform(interp ,(char *)channame, s, process ,eofProc ,closeProc ,requireBinary()) != TCL_OK) { Tcl_DecrRefCount(res); finalize(s); return NULL; } return res; } critcl::cproc cuts {char* channame} object { Tcl_Obj *list ,*newlist; Tcl_HashEntry *entry; state *s; entry = Tcl_FindHashEntry(&chanchunks, channame); if (entry == NULL) { return NULL; } s = Tcl_GetHashValue(entry); list = s->list; s->list = Tcl_NewListObj(0 ,NULL); Tcl_IncrRefCount(list); return list; } critcl::cproc signature_sha256 {char* channame} object { Tcl_Obj *hashobj; uint8_t hash[SHA256_HASH_SIZE]; Tcl_HashEntry *entry = Tcl_FindHashEntry(&chanchunks, channame); if (entry == NULL) { return NULL; } state *s = Tcl_GetHashValue(entry); SHA256Final(s->wholemp ,hash); hashobj = Tcl_NewByteArrayObj(hash ,SHA256_HASH_SIZE); Tcl_IncrRefCount(hashobj); SHA256Init(s->wholemp); return hashobj; } ::critcl::api import sha256c 1 ::critcl::api import ycl_chan_clib 0.1 ::critcl::debug symbols critcl::load