Skip to content

Commit

Permalink
Merge pull request #188 from cloudwu/dev
Browse files Browse the repository at this point in the history
release v0.8.0
  • Loading branch information
cloudwu committed Oct 27, 2014
2 parents 8cb5378 + 73bd788 commit 0f4a771
Show file tree
Hide file tree
Showing 11 changed files with 1,298 additions and 23 deletions.
372 changes: 372 additions & 0 deletions 3rd/lua-mysqlaux/lua_mysqlaux.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,372 @@
//
// lua_mysqlaux.c
//
// Created by changfeng on 6/17/14.
// Copyright (c) 2014 changfeng. All rights reserved.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <lua.h>
#include <lauxlib.h>

#define SHA1SIZE 20
#define ROTL(bits,word) (((word) << (bits)) | ((word) >> (32-(bits))))
typedef unsigned int uint32_t;

struct sha
{
uint32_t digest[5];
uint32_t w[80];
uint32_t a,b,c,d,e,f;
int err;
};


static uint32_t padded_length_in_bits(uint32_t len)
{
if(len%64 == 56)
{
len++;
}
while((len%64)!=56)
{
len++;
}
return len*8;
}


static int calculate_sha1(struct sha *sha1, const unsigned char *text, uint32_t length)
{
unsigned int i,j;
unsigned char *buffer=NULL, *pbuffer=NULL;
uint32_t bits=0;
uint32_t temp=0,k=0;
uint32_t lb = length*8;

if (!sha1)
{
return 0;
}
// initialize the default digest values
sha1->digest[0] = 0x67452301;
sha1->digest[1] = 0xEFCDAB89;
sha1->digest[2] = 0x98BADCFE;
sha1->digest[3] = 0x10325476;
sha1->digest[4] = 0xC3D2E1F0;
sha1->a=sha1->b=sha1->c=sha1->d=sha1->e=sha1->f=0;
if (!text || !length)
{
return 0;
}

bits = padded_length_in_bits(length);
buffer = (unsigned char *) malloc((bits/8)+8);
memset(buffer,0,(bits/8)+8);
if(buffer == NULL)
{
return 1;
}
pbuffer = buffer;
memcpy(buffer, text, length);


//add 1 on the last of the message..
*(buffer+length) = 0x80;
for(i=length+1; i<(bits/8); i++)
{
*(buffer+i) = 0x00;
}

*(buffer +(bits/8)+4+0) = (lb>>24) & 0xFF;
*(buffer +(bits/8)+4+1) = (lb>>16) & 0xFF;
*(buffer +(bits/8)+4+2) = (lb>>8) & 0xFF;
*(buffer +(bits/8)+4+3) = (lb>>0) & 0xFF;


//main loop
for(i=0; i<((bits+64)/512); i++)
{
//first empty the block for each pass..
for(j=0; j<80; j++)
{
sha1->w[j] = 0x00;
}


//fill the first 16 words with the characters read directly from the buffer.
for(j=0; j<16; j++)
{
sha1->w[j] =buffer[j*4+0];
sha1->w[j] = sha1->w[j]<<8;
sha1->w[j] |= buffer[j*4+1];
sha1->w[j] = sha1->w[j]<<8;
sha1->w[j] |= buffer[j*4+2];
sha1->w[j] = sha1->w[j]<<8;
sha1->w[j] |= buffer[j*4+3];
}

//fill the rest 64 words using the formula
for(j=16; j<80; j++)
{
sha1->w[j] = (ROTL(1,(sha1->w[j-3] ^ sha1->w[j-8] ^ sha1->w[j-14] ^ sha1->w[j-16])));
}


//initialize hash for this chunck reading that has been stored in the structure digest
sha1->a = sha1->digest[0];
sha1->b = sha1->digest[1];
sha1->c = sha1->digest[2];
sha1->d = sha1->digest[3];
sha1->e = sha1->digest[4];

//for all the 80 32bit blocks calculate f and use k accordingly per specification.
for(j=0; j<80; j++)
{
if((j>=0) && (j<20))
{
sha1->f = ((sha1->b)&(sha1->c)) | ((~(sha1->b))&(sha1->d));
k = 0x5A827999;

}
else if((j>=20) && (j<40))
{
sha1->f = (sha1->b)^(sha1->c)^(sha1->d);
k = 0x6ED9EBA1;
}
else if((j>=40) && (j<60))
{
sha1->f = ((sha1->b)&(sha1->c)) | ((sha1->b)&(sha1->d)) | ((sha1->c)&(sha1->d));
k = 0x8F1BBCDC;
}
else if((j>=60) && (j<80))
{
sha1->f = (sha1->b)^(sha1->c)^(sha1->d);
k = 0xCA62C1D6;
}

temp = ROTL(5,(sha1->a)) + (sha1->f) + (sha1->e) + k + sha1->w[j];
sha1->e = (sha1->d);
sha1->d = (sha1->c);
sha1->c = ROTL(30,(sha1->b));
sha1->b = (sha1->a);
sha1->a = temp;

//reset temp to 0 to be in safe side only, not mandatory.
temp =0x00;


}

// append to total hash.
sha1->digest[0] += sha1->a;
sha1->digest[1] += sha1->b;
sha1->digest[2] += sha1->c;
sha1->digest[3] += sha1->d;
sha1->digest[4] += sha1->e;


//since we used 512bit size block per each pass, let us update the buffer pointer accordingly.
buffer = buffer+64;

}
free(pbuffer);
return 0;
}

static void int2ch4(int intVal,unsigned char *result)
{
result[0]= (unsigned char)((intVal>>24) & 0x000000ff);
result[1]= (unsigned char)((intVal>>16) & 0x000000ff);
result[2]= (unsigned char)((intVal>> 8) & 0x000000ff);
result[3]= (unsigned char)((intVal>> 0) & 0x000000ff);
}


static int sha1_bin (lua_State *L) {
const void * msg = NULL;
size_t len =0;

if( lua_gettop(L) != 1 ){
return 0;
}
if( lua_isnil(L,1) ) {
msg = NULL;
len =0;
}else{
msg=luaL_checklstring(L,1,&len);
}
struct sha tmpsha;
calculate_sha1( &tmpsha, msg, (uint32_t)len);
unsigned char tmpret[SHA1SIZE+8];
memset(tmpret,0,SHA1SIZE+8);
int i=0;
for ( i=0; i<5; i++)
{
int2ch4(tmpsha.digest[i], tmpret+i*4);
}

lua_pushlstring(L, (char *)tmpret, SHA1SIZE);
return 1;
}

static unsigned int num_escape_sql_str(unsigned char *dst, unsigned char *src, size_t size)
{
unsigned int n =0;
while (size) {
/* the highest bit of all the UTF-8 chars
* is always 1 */
if ((*src & 0x80) == 0) {
switch (*src) {
case '\0':
case '\b':
case '\n':
case '\r':
case '\t':
case 26: /* \z */
case '\\':
case '\'':
case '"':
n++;
break;
default:
break;
}
}
src++;
size--;
}
return n;
}
static unsigned char*
escape_sql_str(unsigned char *dst, unsigned char *src, size_t size)
{

while (size) {
if ((*src & 0x80) == 0) {
switch (*src) {
case '\0':
*dst++ = '\\';
*dst++ = '0';
break;

case '\b':
*dst++ = '\\';
*dst++ = 'b';
break;

case '\n':
*dst++ = '\\';
*dst++ = 'n';
break;

case '\r':
*dst++ = '\\';
*dst++ = 'r';
break;

case '\t':
*dst++ = '\\';
*dst++ = 't';
break;

case 26:
*dst++ = '\\';
*dst++ = 'z';
break;

case '\\':
*dst++ = '\\';
*dst++ = '\\';
break;

case '\'':
*dst++ = '\\';
*dst++ = '\'';
break;

case '"':
*dst++ = '\\';
*dst++ = '"';
break;

default:
*dst++ = *src;
break;
}
} else {
*dst++ = *src;
}
src++;
size--;
} /* while (size) */

return dst;
}




static int
quote_sql_str(lua_State *L)
{
size_t len, dlen, escape;
unsigned char *p;
unsigned char *src, *dst;

if (lua_gettop(L) != 1) {
return luaL_error(L, "expecting one argument");
}

src = (unsigned char *) luaL_checklstring(L, 1, &len);

if (len == 0) {
dst = (unsigned char *) "''";
dlen = sizeof("''") - 1;
lua_pushlstring(L, (char *) dst, dlen);
return 1;
}

escape = num_escape_sql_str(NULL, src, len);

dlen = sizeof("''") - 1 + len + escape;
p = lua_newuserdata(L, dlen);

dst = p;

*p++ = '\'';

if (escape == 0) {
memcpy(p, src, len);
p+=len;
} else {
p = (unsigned char *) escape_sql_str(p, src, len);
}

*p++ = '\'';

if (p != dst + dlen) {
return luaL_error(L, "quote sql string error");
}

lua_pushlstring(L, (char *) dst, p - dst);

return 1;
}


static struct luaL_Reg mysqlauxlib[] = {
{"sha1_bin", sha1_bin},
{"quote_sql_str",quote_sql_str},
{NULL, NULL}
};


int luaopen_mysqlaux_c (lua_State *L) {
lua_newtable(L);
luaL_setfuncs(L, mysqlauxlib, 0);
return 1;
}

5 changes: 5 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
v0.8.0 (2014-10-27)
-----------
* Add mysql client driver
* Bugfix : skynet.queue

v0.7.4 (2014-10-13)
-----------
* Bugfix : clear coroutine pool when GC
Expand Down
Loading

0 comments on commit 0f4a771

Please sign in to comment.