📄 md5.xs
字号:
} while (--blocks); ctx->A = A; ctx->B = B; ctx->C = C; ctx->D = D;}#ifdef MD5_DEBUGstatic char*ctx_dump(MD5_CTX* ctx){ static char buf[1024]; sprintf(buf, "{A=%x,B=%x,C=%x,D=%x,%d,%d(%d)}", ctx->A, ctx->B, ctx->C, ctx->D, ctx->bytes_low, ctx->bytes_high, (ctx->bytes_low&0x3F)); return buf;}#endifstatic voidMD5Update(MD5_CTX* ctx, const U8* buf, STRLEN len){ STRLEN blocks; STRLEN fill = ctx->bytes_low & 0x3F;#ifdef MD5_DEBUG static int ucount = 0; fprintf(stderr,"%5i: Update(%s, %p, %d)\n", ++ucount, ctx_dump(ctx), buf, len);#endif ctx->bytes_low += len; if (ctx->bytes_low < len) /* wrap around */ ctx->bytes_high++; if (fill) { STRLEN missing = 64 - fill; if (len < missing) { Copy(buf, ctx->buffer + fill, len, U8); return; } Copy(buf, ctx->buffer + fill, missing, U8); MD5Transform(ctx, ctx->buffer, 1); buf += missing; len -= missing; } blocks = len >> 6; if (blocks) MD5Transform(ctx, buf, blocks); if ( (len &= 0x3F)) { Copy(buf + (blocks << 6), ctx->buffer, len, U8); }}static voidMD5Final(U8* digest, MD5_CTX *ctx){ STRLEN fill = ctx->bytes_low & 0x3F; STRLEN padlen = (fill < 56 ? 56 : 120) - fill; U32 bits_low, bits_high;#ifdef MD5_DEBUG fprintf(stderr," Final: %s\n", ctx_dump(ctx));#endif Copy(PADDING, ctx->buffer + fill, padlen, U8); fill += padlen; bits_low = ctx->bytes_low << 3; bits_high = (ctx->bytes_high << 3) | (ctx->bytes_low >> 29);#ifdef BYTESWAP *(U32*)(ctx->buffer + fill) = BYTESWAP(bits_low); fill += 4; *(U32*)(ctx->buffer + fill) = BYTESWAP(bits_high); fill += 4;#else u2s(bits_low, ctx->buffer + fill); fill += 4; u2s(bits_high, ctx->buffer + fill); fill += 4;#endif MD5Transform(ctx, ctx->buffer, fill >> 6);#ifdef MD5_DEBUG fprintf(stderr," Result: %s\n", ctx_dump(ctx));#endif#ifdef BYTESWAP *(U32*)digest = BYTESWAP(ctx->A); digest += 4; *(U32*)digest = BYTESWAP(ctx->B); digest += 4; *(U32*)digest = BYTESWAP(ctx->C); digest += 4; *(U32*)digest = BYTESWAP(ctx->D);#else u2s(ctx->A, digest); u2s(ctx->B, digest+4); u2s(ctx->C, digest+8); u2s(ctx->D, digest+12);#endif}#ifndef INT2PTR#define INT2PTR(any,d) (any)(d)#endifstatic MD5_CTX* get_md5_ctx(pTHX_ SV* sv){ if (SvROK(sv)) { sv = SvRV(sv); if (SvIOK(sv)) { MD5_CTX* ctx = INT2PTR(MD5_CTX*, SvIV(sv)); if (ctx && ctx->signature == MD5_CTX_SIGNATURE) { return ctx; } } } croak("Not a reference to a Digest::MD5 object"); return (MD5_CTX*)0; /* some compilers insist on a return value */}static char* hex_16(const unsigned char* from, char* to){ static const char hexdigits[] = "0123456789abcdef"; const unsigned char *end = from + 16; char *d = to; while (from < end) { *d++ = hexdigits[(*from >> 4)]; *d++ = hexdigits[(*from & 0x0F)]; from++; } *d = '\0'; return to;}static char* base64_16(const unsigned char* from, char* to){ static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; const unsigned char *end = from + 16; unsigned char c1, c2, c3; char *d = to; while (1) { c1 = *from++; *d++ = base64[c1>>2]; if (from == end) { *d++ = base64[(c1 & 0x3) << 4]; break; } c2 = *from++; c3 = *from++; *d++ = base64[((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)]; *d++ = base64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)]; *d++ = base64[c3 & 0x3F]; } *d = '\0'; return to;}/* Formats */#define F_BIN 0#define F_HEX 1#define F_B64 2static SV* make_mortal_sv(pTHX_ const unsigned char *src, int type){ STRLEN len; char result[33]; char *ret; switch (type) { case F_BIN: ret = (char*)src; len = 16; break; case F_HEX: ret = hex_16(src, result); len = 32; break; case F_B64: ret = base64_16(src, result); len = 22; break; default: croak("Bad convertion type (%d)", type); break; } return sv_2mortal(newSVpv(ret,len));}/********************************************************************/typedef PerlIO* InputStream;MODULE = Digest::MD5 PACKAGE = Digest::MD5PROTOTYPES: DISABLEvoidnew(xclass) SV* xclass PREINIT: MD5_CTX* context; PPCODE: if (!SvROK(xclass)) { STRLEN my_na; char *sclass = SvPV(xclass, my_na); New(55, context, 1, MD5_CTX); context->signature = MD5_CTX_SIGNATURE; ST(0) = sv_newmortal(); sv_setref_pv(ST(0), sclass, (void*)context); SvREADONLY_on(SvRV(ST(0))); } else { context = get_md5_ctx(aTHX_ xclass); } MD5Init(context); XSRETURN(1);voidclone(self) SV* self PREINIT: MD5_CTX* cont = get_md5_ctx(aTHX_ self); const char *myname = sv_reftype(SvRV(self),TRUE); MD5_CTX* context; PPCODE: New(55, context, 1, MD5_CTX); ST(0) = sv_newmortal(); sv_setref_pv(ST(0), myname , (void*)context); SvREADONLY_on(SvRV(ST(0))); memcpy(context,cont,sizeof(MD5_CTX)); XSRETURN(1);voidDESTROY(context) MD5_CTX* context CODE: Safefree(context);voidadd(self, ...) SV* self PREINIT: MD5_CTX* context = get_md5_ctx(aTHX_ self); int i; unsigned char *data; STRLEN len; PPCODE: for (i = 1; i < items; i++) { data = (unsigned char *)(SvPVbyte(ST(i), len)); MD5Update(context, data, len); } XSRETURN(1); /* self */voidaddfile(self, fh) SV* self InputStream fh PREINIT: MD5_CTX* context = get_md5_ctx(aTHX_ self); STRLEN fill = context->bytes_low & 0x3F;#ifdef USE_HEAP_INSTEAD_OF_STACK unsigned char* buffer;#else unsigned char buffer[4096];#endif int n; CODE: if (fh) {#ifdef USE_HEAP_INSTEAD_OF_STACK New(0, buffer, 4096, unsigned char); assert(buffer);#endif if (fill) { /* The MD5Update() function is faster if it can work with * complete blocks. This will fill up any buffered block * first. */ STRLEN missing = 64 - fill; if ( (n = PerlIO_read(fh, buffer, missing)) > 0) MD5Update(context, buffer, n); else XSRETURN(1); /* self */ } /* Process blocks until EOF or error */ while ( (n = PerlIO_read(fh, buffer, sizeof(buffer))) > 0) { MD5Update(context, buffer, n); }#ifdef USE_HEAP_INSTEAD_OF_STACK Safefree(buffer);#endif if (PerlIO_error(fh)) { croak("Reading from filehandle failed"); } } else { croak("No filehandle passed"); } XSRETURN(1); /* self */voiddigest(context) MD5_CTX* context ALIAS: Digest::MD5::digest = F_BIN Digest::MD5::hexdigest = F_HEX Digest::MD5::b64digest = F_B64 PREINIT: unsigned char digeststr[16]; PPCODE: MD5Final(digeststr, context); MD5Init(context); /* In case it is reused */ ST(0) = make_mortal_sv(aTHX_ digeststr, ix); XSRETURN(1);voidmd5(...) ALIAS: Digest::MD5::md5 = F_BIN Digest::MD5::md5_hex = F_HEX Digest::MD5::md5_base64 = F_B64 PREINIT: MD5_CTX ctx; int i; unsigned char *data; STRLEN len; unsigned char digeststr[16]; PPCODE: MD5Init(&ctx); if (DOWARN) { char *msg = 0; if (items == 1) { if (SvROK(ST(0))) { SV* sv = SvRV(ST(0)); if (SvOBJECT(sv) && strEQ(HvNAME(SvSTASH(sv)), "Digest::MD5")) msg = "probably called as method"; else msg = "called with reference argument"; } } else if (items > 1) { data = (unsigned char *)SvPVbyte(ST(0), len); if (len == 11 && memEQ("Digest::MD5", data, 11)) { msg = "probably called as class method"; } } if (msg) { const char *f = (ix == F_BIN) ? "md5" : (ix == F_HEX) ? "md5_hex" : "md5_base64"; warn("&Digest::MD5::%s function %s", f, msg); } } for (i = 0; i < items; i++) { data = (unsigned char *)(SvPVbyte(ST(i), len)); MD5Update(&ctx, data, len); } MD5Final(digeststr, &ctx); ST(0) = make_mortal_sv(aTHX_ digeststr, ix); XSRETURN(1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -