Backend
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
#include "cfg.h"
|
||||
#include "libconfig.h++"
|
||||
#include <iostream>
|
||||
|
||||
using namespace libconfig;
|
||||
|
||||
Config cfg;
|
||||
|
||||
void CfgReadConfig() {
|
||||
try {
|
||||
/* Load the configuration.. */
|
||||
cfg.readFile(MERMSEMR_CONFIG\
|
||||
"/mermsemr_api.conf");
|
||||
} catch (...) {
|
||||
// failure
|
||||
}
|
||||
}
|
||||
|
||||
long CfgReadLong(const char* key) {
|
||||
if (key!=NULL) {
|
||||
try {
|
||||
Setting& s = cfg.lookup(key);
|
||||
long ret = s;
|
||||
return ret;
|
||||
} catch (...) {
|
||||
// failure
|
||||
std::cout << "missing: " << key << std::endl;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
std::string CfgReadString(const char* key) {
|
||||
if (key!=NULL) {
|
||||
try {
|
||||
return (std::string)cfg.lookup(key);
|
||||
} catch (...) {
|
||||
// failure
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
*/
|
||||
const char* CfgReadChar(const char* key) {
|
||||
if (key!=NULL) {
|
||||
try {
|
||||
return (const char*)cfg.lookup(key);
|
||||
} catch (...) {
|
||||
// failure
|
||||
std::cout << "missing: " << key << std::endl;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
/*
|
||||
vi:ts=2
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,42 @@
|
||||
#include "clog.h"
|
||||
#include "php_mermsemr_log.h"
|
||||
|
||||
void logfmt( TLogLevel level, const char * format, ... ) {
|
||||
try {
|
||||
//FILELog::ReportingLevel() = level;
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
if (level > FILELOG_MAX_LEVEL) ;
|
||||
else if (level > FILELog::ReportingLevel() || !Output2FILE::Stream()) ;
|
||||
else {
|
||||
FILE *f = Output2FILE::Stream();
|
||||
fprintf(f, "- %s %s [%ld]: %c",
|
||||
NowTime().c_str(),
|
||||
FILELog::ToString(level).c_str(),
|
||||
getpid(),
|
||||
(level > logDEBUG ? level - logDEBUG : 0, '\t'));
|
||||
vfprintf(f, format, args);
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
va_end (args);
|
||||
} catch(const std::exception& e) {
|
||||
FILE_LOG(logERROR) << e.what();
|
||||
}
|
||||
}
|
||||
/*
|
||||
void logfmt( TLogLevel level, const char * format, ... ) {
|
||||
try {
|
||||
//FILELog::ReportingLevel() = level;
|
||||
char buffer[2048];
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
vsprintf (buffer, format, args);
|
||||
//perror (buffer);
|
||||
va_end (args);
|
||||
FILE_LOG(level) << buffer;
|
||||
} catch(const std::exception& e) {
|
||||
FILE_LOG(logERROR) << e.what();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,415 @@
|
||||
#include <cassert>
|
||||
#include <cstdarg>
|
||||
#include <string>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "cvariables.h"
|
||||
#include "safestring.h"
|
||||
|
||||
CVariables::CVariables( )
|
||||
{
|
||||
var_top = NULL;
|
||||
};
|
||||
|
||||
|
||||
void CVariables::Cleanup()
|
||||
{
|
||||
L_Variables * v, *_v;
|
||||
|
||||
v = var_top;
|
||||
|
||||
while (v)
|
||||
{
|
||||
_v = v->next;
|
||||
|
||||
free( v->value );
|
||||
delete v;
|
||||
|
||||
v = _v;
|
||||
}
|
||||
|
||||
var_top = NULL; // Used when the desctructor is called explicitly to cleanup
|
||||
}
|
||||
|
||||
CVariables::~CVariables()
|
||||
{
|
||||
// LOG( "~CVariables()", LOG_MAX );
|
||||
Cleanup();
|
||||
// LOG( "/~CVariables()", LOG_MAX );
|
||||
}
|
||||
|
||||
L_Variables * CVariables::FindVariable( const char * var, bool create/*=false*/ )
|
||||
{
|
||||
L_Variables * v;
|
||||
|
||||
char _var[MAX_CGI_VAR_LEN+1];
|
||||
|
||||
tolower( var, _var, sizeof(_var) );
|
||||
|
||||
if (!var_top && !create)
|
||||
return NULL;
|
||||
|
||||
if (!var_top)
|
||||
{
|
||||
v = var_top = new L_Variables;
|
||||
}
|
||||
else
|
||||
{ // Search to see if such variable already exists
|
||||
v = var_top;
|
||||
do {
|
||||
if ( strcmp( v->name, _var )==0 )
|
||||
{
|
||||
return v;
|
||||
}
|
||||
if ( v->next)
|
||||
v = v->next;
|
||||
else
|
||||
break;
|
||||
} while ( 1 );
|
||||
|
||||
// no variable found
|
||||
|
||||
if ( create )
|
||||
{
|
||||
v->next = new L_Variables;
|
||||
v = v->next;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
v->next = NULL;
|
||||
strncpy( v->name, _var, MAX_CGI_VAR_LEN );
|
||||
|
||||
v->value = NULL; // So we know the space has not been allocated
|
||||
|
||||
return v;
|
||||
|
||||
}
|
||||
|
||||
|
||||
char * CVariables::GetVariable( const char * var )
|
||||
{
|
||||
L_Variables * v;
|
||||
|
||||
v = FindVariable( var );
|
||||
|
||||
if ( !v )
|
||||
return NULL;
|
||||
else
|
||||
return v->value;
|
||||
}
|
||||
|
||||
|
||||
bool CVariables::GetBool( char * var, bool test /*= false*/, char * section /*= ""*/ )
|
||||
{
|
||||
L_Variables * v;
|
||||
|
||||
v = FindVariable( var );
|
||||
|
||||
if ( !v )
|
||||
return false;
|
||||
else
|
||||
{
|
||||
char * s = v->value;
|
||||
return
|
||||
strcasecmp( s, "yes" )==0 ||
|
||||
strcasecmp( s, "on" )==0 ||
|
||||
strcasecmp( s, "1" )==0 ||
|
||||
strcasecmp( s, "enable" )==0 ||
|
||||
strcasecmp( s, "enabled" )==0 ||
|
||||
strcasecmp( s, "true" )==0 ;
|
||||
}
|
||||
}
|
||||
|
||||
char * CVariables::GetVariable( const char * var, bool test, char * section /*= ""*/ )
|
||||
{
|
||||
L_Variables * v;
|
||||
|
||||
char name_[MAX_CGI_VAR_LEN+1];
|
||||
strsafecpy( name_, test?".":"", sizeof( name_ ) );
|
||||
strsafecat( name_, section, sizeof(name_) );
|
||||
if (section[0])
|
||||
strsafecat( name_, "_", sizeof(name_) );
|
||||
strsafecat( name_, var, sizeof(name_) );
|
||||
|
||||
v = FindVariable( name_ );
|
||||
|
||||
if ( !v )
|
||||
return NULL;
|
||||
else
|
||||
return v->value;
|
||||
}
|
||||
|
||||
char * CVariables::GetVariable( const char * var, char * result, int size )
|
||||
{
|
||||
L_Variables * v;
|
||||
|
||||
v = FindVariable( var );
|
||||
|
||||
if ( !v )
|
||||
result[0] = 0;
|
||||
else
|
||||
{
|
||||
strncpy( result, v->value, size );
|
||||
result[size-1] = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
long CVariables::GetVariableLong( char * name, bool *valid /*= NULL*/ )
|
||||
{
|
||||
char var[20];
|
||||
GetVariable( name, var, sizeof(var) );
|
||||
|
||||
// if (!valid)
|
||||
// return atol( var );
|
||||
|
||||
char * ep;
|
||||
long res = strtol( var, &ep, 10 );
|
||||
if (valid)
|
||||
*valid = var[0] && !*ep;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
long CVariables::GetVariableLong( char * name, bool test, char * section /*= ""*/ )
|
||||
{
|
||||
char name_[MAX_CGI_VAR_LEN+1];
|
||||
strsafecpy( name_, test?".":"", sizeof( name_ ) );
|
||||
strsafecat( name_, section, sizeof(name_) );
|
||||
if (section[0])
|
||||
strsafecat( name_, "_", sizeof(name_) );
|
||||
strsafecat( name_, name, sizeof(name_) );
|
||||
|
||||
|
||||
char var[20];
|
||||
GetVariable( name_, var, sizeof(var) );
|
||||
return atol( var );
|
||||
}
|
||||
|
||||
|
||||
void CVariables::LetInt16( char * var, int value )
|
||||
{
|
||||
L_Variables * v;
|
||||
v = FindVariable( var, true );
|
||||
|
||||
if (v->value)
|
||||
free( v->value );
|
||||
|
||||
char st[10];
|
||||
snprintf( st, sizeof(st), "%d", value);
|
||||
|
||||
v->value = strdup( st );
|
||||
}
|
||||
|
||||
void CVariables::LetStr( const char * var, const char * value ) // NULL-terminated
|
||||
{
|
||||
L_Variables * v;
|
||||
v = FindVariable( var, true );
|
||||
|
||||
if (v->value)
|
||||
free( v->value );
|
||||
|
||||
if ( value )
|
||||
v->value = strdup( value );
|
||||
else
|
||||
v->value = strdup( "" );
|
||||
}
|
||||
|
||||
|
||||
void CVariables::RenameVariable( const char * name, const char * newname )
|
||||
{
|
||||
L_Variables * v;
|
||||
v = FindVariable( name, true );
|
||||
|
||||
//logfmt( FLOG_MAX, "RenameVariable(): '%s'->'%s'", name, newname );
|
||||
|
||||
if ( !v )
|
||||
{
|
||||
//logfmt( FLOG_MAX, "RenameVariable(): Variable '%s' not found", name );
|
||||
return;
|
||||
}
|
||||
|
||||
strsafecpy( v->name, newname, sizeof( v->name ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CVariables::vLetStrf( char * var, const char * format, va_list ap )
|
||||
{
|
||||
size_t buf_size = 512;
|
||||
char *buffer = new char[buf_size];
|
||||
|
||||
size_t length;
|
||||
|
||||
while (true) {
|
||||
if (!buffer) {
|
||||
assert(buffer); // to stop when debugging
|
||||
snprintf(buffer, buf_size, "<alloc problem>");
|
||||
break;
|
||||
}
|
||||
length = vsnprintf(buffer, buf_size, format, ap);
|
||||
|
||||
if (length >= 0 && length < buf_size - 1) {
|
||||
// string fits into current buffer
|
||||
break;
|
||||
}
|
||||
// otherwise resize buffer :
|
||||
buf_size *= 2;
|
||||
// fprintf(stderr, "Reallocating vstrf-buffer to size=%u\n", buf_size);
|
||||
delete [] buffer;
|
||||
buffer = new char[buf_size];
|
||||
}
|
||||
|
||||
L_Variables * v;
|
||||
v = FindVariable( var, true );
|
||||
|
||||
if (v->value)
|
||||
free( v->value );
|
||||
|
||||
if (buffer) {
|
||||
v->value = strdup( buffer );
|
||||
delete [] buffer;
|
||||
} else {
|
||||
v->value = strdup( "" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CVariables::LetStrf( char * var, const char * format, ... )
|
||||
{
|
||||
va_list ap;
|
||||
va_start( ap, format );
|
||||
|
||||
vLetStrf( var, format, ap );
|
||||
|
||||
va_end( ap );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void CVariables::LetStrf( char * var, const char * format, ... )
|
||||
{
|
||||
char tmp[1000];
|
||||
|
||||
va_list ap;
|
||||
va_start( ap, format );
|
||||
vsnprintf( tmp, sizeof(tmp), format, ap );
|
||||
va_end( ap );
|
||||
|
||||
|
||||
L_Variables * v;
|
||||
v = FindVariable( var, true );
|
||||
|
||||
if (v->value)
|
||||
free( v->value );
|
||||
|
||||
v->value = strdup( tmp );
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
void CVariables::StrCat( char * var, const char * format, ... )
|
||||
{
|
||||
char tmp[1000];
|
||||
L_Variables * v;
|
||||
|
||||
v = FindVariable( var, true );
|
||||
|
||||
va_list ap;
|
||||
va_start( ap, format );
|
||||
|
||||
if ( !v->value )
|
||||
vsnprintf( tmp, sizeof(tmp), format, ap );
|
||||
else
|
||||
{
|
||||
// logfmt( FLOG_MAX, "v->value='%s'", v->value );
|
||||
strsafecpy( tmp, v->value, sizeof(tmp) );
|
||||
strsafecat( tmp, "<br>", sizeof(tmp) );
|
||||
int len = strlen(tmp);
|
||||
vsnprintf( &tmp[len], sizeof(tmp)-len, format, ap );
|
||||
|
||||
}
|
||||
va_end( ap );
|
||||
|
||||
if (v->value)
|
||||
free( v->value );
|
||||
|
||||
v->value = strdup( tmp );
|
||||
|
||||
// logfmt( FLOG_MAX, "tmp='%s'", tmp );
|
||||
}
|
||||
|
||||
|
||||
void CVariables::StrCatf( char * var, const char * format, ... )
|
||||
{
|
||||
char tmp[5000];
|
||||
L_Variables * v;
|
||||
|
||||
v = FindVariable( var, true );
|
||||
|
||||
va_list ap;
|
||||
va_start( ap, format );
|
||||
|
||||
if ( !v->value )
|
||||
vsnprintf( tmp, sizeof(tmp), format, ap );
|
||||
else
|
||||
{
|
||||
// logfmt( FLOG_MAX, "v->value='%s'", v->value );
|
||||
strsafecpy( tmp, v->value, sizeof(tmp) );
|
||||
//strsafecat( tmp, "<br>", sizeof(tmp) );
|
||||
int len = strlen(tmp);
|
||||
vsnprintf( &tmp[len], sizeof(tmp)-len, format, ap );
|
||||
|
||||
}
|
||||
va_end( ap );
|
||||
|
||||
if (v->value)
|
||||
free( v->value );
|
||||
|
||||
v->value = strdup( tmp );
|
||||
|
||||
// logfmt( FLOG_MAX, "tmp='%s'", tmp );
|
||||
}
|
||||
|
||||
|
||||
void CVariables::LetStr( char * var, const char * value, int len ) // non-NULL terminated
|
||||
{
|
||||
L_Variables * v;
|
||||
v = FindVariable( var, true );
|
||||
|
||||
if (v->value)
|
||||
free( v->value );
|
||||
|
||||
if ( value )
|
||||
{
|
||||
v->value = (char*)malloc(len+1);
|
||||
memcpy( v->value, value, len );
|
||||
v->value[len] = 0;
|
||||
}
|
||||
else
|
||||
v->value = strdup( "" );
|
||||
}
|
||||
|
||||
|
||||
void CVariables::PrintVars( FILE * f /*= stdout*/ )
|
||||
{
|
||||
L_Variables * v;
|
||||
v = var_top;
|
||||
|
||||
fprintf( f, "\nVariable listing (NEW):\n\n" );
|
||||
while ( v )
|
||||
{
|
||||
fprintf( f, "%s[%d] = %s\n", v->name, strlen(v->value), v->value );
|
||||
v = v->next;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
vi:ts=2
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#include "exceptions.h"
|
||||
|
||||
#include "clog.h"
|
||||
|
||||
bad_parameter::bad_parameter( CVars &out, const char *name )
|
||||
{
|
||||
//in["bad_param"] = name;
|
||||
out["bad_param"] = name;
|
||||
|
||||
logfmt( FLOG_MAX, "Bad parameter exception: '%s'", name );
|
||||
}
|
||||
|
||||
err::err( char *msg ) {
|
||||
logfmt( FLOG_MAX, "ERROR: %s", msg );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,544 @@
|
||||
/*-
|
||||
* HMAC-SHA-224/256/384/512 implementation
|
||||
* Last update: 06/15/2005
|
||||
* Issue date: 06/15/2005
|
||||
*
|
||||
* Copyright (C) 2005 Olivier Gay <olivier.gay@a3.epfl.ch>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "hmac_sha2.h"
|
||||
|
||||
/* HMAC-SHA-224 functions */
|
||||
|
||||
void hmac_sha224_init(hmac_sha224_ctx *ctx, unsigned char *key,
|
||||
unsigned int key_size)
|
||||
{
|
||||
unsigned int fill;
|
||||
unsigned int num;
|
||||
|
||||
unsigned char *key_used;
|
||||
unsigned char key_temp[SHA224_DIGEST_SIZE];
|
||||
int i;
|
||||
|
||||
if (key_size == SHA224_BLOCK_SIZE) {
|
||||
key_used = key;
|
||||
num = SHA224_BLOCK_SIZE;
|
||||
} else {
|
||||
if (key_size > SHA224_BLOCK_SIZE){
|
||||
key_used = key_temp;
|
||||
num = SHA224_DIGEST_SIZE;
|
||||
sha224(key, key_size, key_used);
|
||||
} else { /* key_size > SHA224_BLOCK_SIZE */
|
||||
key_used = key;
|
||||
num = key_size;
|
||||
}
|
||||
fill = SHA224_BLOCK_SIZE - num;
|
||||
|
||||
memset(ctx->block_ipad + num, 0x36, fill);
|
||||
memset(ctx->block_opad + num, 0x5c, fill);
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
ctx->block_ipad[i] = key_used[i] ^ 0x36;
|
||||
ctx->block_opad[i] = key_used[i] ^ 0x5c;
|
||||
}
|
||||
|
||||
sha224_init(&ctx->ctx_inside);
|
||||
sha224_update(&ctx->ctx_inside, ctx->block_ipad, SHA224_BLOCK_SIZE);
|
||||
|
||||
sha224_init(&ctx->ctx_outside);
|
||||
sha224_update(&ctx->ctx_outside, ctx->block_opad,
|
||||
SHA224_BLOCK_SIZE);
|
||||
|
||||
/* for hmac_reinit */
|
||||
memcpy(&ctx->ctx_inside_reinit, &ctx->ctx_inside,
|
||||
sizeof(sha224_ctx));
|
||||
memcpy(&ctx->ctx_outside_reinit, &ctx->ctx_outside,
|
||||
sizeof(sha224_ctx));
|
||||
}
|
||||
|
||||
void hmac_sha224_reinit(hmac_sha224_ctx *ctx)
|
||||
{
|
||||
memcpy(&ctx->ctx_inside, &ctx->ctx_inside_reinit,
|
||||
sizeof(sha224_ctx));
|
||||
memcpy(&ctx->ctx_outside, &ctx->ctx_outside_reinit,
|
||||
sizeof(sha224_ctx));
|
||||
}
|
||||
|
||||
void hmac_sha224_update(hmac_sha224_ctx *ctx, unsigned char *message,
|
||||
unsigned int message_len)
|
||||
{
|
||||
sha224_update(&ctx->ctx_inside, message, message_len);
|
||||
}
|
||||
|
||||
void hmac_sha224_final(hmac_sha224_ctx *ctx, unsigned char *mac,
|
||||
unsigned int mac_size)
|
||||
{
|
||||
unsigned char digest_inside[SHA224_DIGEST_SIZE];
|
||||
unsigned char mac_temp[SHA224_DIGEST_SIZE];
|
||||
|
||||
sha224_final(&ctx->ctx_inside, digest_inside);
|
||||
sha224_update(&ctx->ctx_outside, digest_inside, SHA224_DIGEST_SIZE);
|
||||
sha224_final(&ctx->ctx_outside, mac_temp);
|
||||
memcpy(mac, mac_temp, mac_size);
|
||||
}
|
||||
|
||||
void hmac_sha224(unsigned char *key, unsigned int key_size,
|
||||
unsigned char *message, unsigned int message_len,
|
||||
unsigned char *mac, unsigned mac_size)
|
||||
{
|
||||
hmac_sha224_ctx ctx;
|
||||
|
||||
hmac_sha224_init(&ctx, key, key_size);
|
||||
hmac_sha224_update(&ctx, message, message_len);
|
||||
hmac_sha224_final(&ctx, mac, mac_size);
|
||||
}
|
||||
|
||||
/* HMAC-SHA-256 functions */
|
||||
|
||||
void hmac_sha256_init(hmac_sha256_ctx *ctx, unsigned char *key,
|
||||
unsigned int key_size)
|
||||
{
|
||||
unsigned int fill;
|
||||
unsigned int num;
|
||||
|
||||
unsigned char *key_used;
|
||||
unsigned char key_temp[SHA256_DIGEST_SIZE];
|
||||
int i;
|
||||
|
||||
if (key_size == SHA256_BLOCK_SIZE) {
|
||||
key_used = key;
|
||||
num = SHA256_BLOCK_SIZE;
|
||||
} else {
|
||||
if (key_size > SHA256_BLOCK_SIZE){
|
||||
key_used = key_temp;
|
||||
num = SHA256_DIGEST_SIZE;
|
||||
sha256(key, key_size, key_used);
|
||||
} else { /* key_size > SHA256_BLOCK_SIZE */
|
||||
key_used = key;
|
||||
num = key_size;
|
||||
}
|
||||
fill = SHA256_BLOCK_SIZE - num;
|
||||
|
||||
memset(ctx->block_ipad + num, 0x36, fill);
|
||||
memset(ctx->block_opad + num, 0x5c, fill);
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
ctx->block_ipad[i] = key_used[i] ^ 0x36;
|
||||
ctx->block_opad[i] = key_used[i] ^ 0x5c;
|
||||
}
|
||||
|
||||
sha256_init(&ctx->ctx_inside);
|
||||
sha256_update(&ctx->ctx_inside, ctx->block_ipad, SHA256_BLOCK_SIZE);
|
||||
|
||||
sha256_init(&ctx->ctx_outside);
|
||||
sha256_update(&ctx->ctx_outside, ctx->block_opad,
|
||||
SHA256_BLOCK_SIZE);
|
||||
|
||||
/* for hmac_reinit */
|
||||
memcpy(&ctx->ctx_inside_reinit, &ctx->ctx_inside,
|
||||
sizeof(sha256_ctx));
|
||||
memcpy(&ctx->ctx_outside_reinit, &ctx->ctx_outside,
|
||||
sizeof(sha256_ctx));
|
||||
}
|
||||
|
||||
void hmac_sha256_reinit(hmac_sha256_ctx *ctx)
|
||||
{
|
||||
memcpy(&ctx->ctx_inside, &ctx->ctx_inside_reinit,
|
||||
sizeof(sha256_ctx));
|
||||
memcpy(&ctx->ctx_outside, &ctx->ctx_outside_reinit,
|
||||
sizeof(sha256_ctx));
|
||||
}
|
||||
|
||||
void hmac_sha256_update(hmac_sha256_ctx *ctx, unsigned char *message,
|
||||
unsigned int message_len)
|
||||
{
|
||||
sha256_update(&ctx->ctx_inside, message, message_len);
|
||||
}
|
||||
|
||||
void hmac_sha256_final(hmac_sha256_ctx *ctx, unsigned char *mac,
|
||||
unsigned int mac_size)
|
||||
{
|
||||
unsigned char digest_inside[SHA256_DIGEST_SIZE];
|
||||
unsigned char mac_temp[SHA256_DIGEST_SIZE];
|
||||
|
||||
sha256_final(&ctx->ctx_inside, digest_inside);
|
||||
sha256_update(&ctx->ctx_outside, digest_inside, SHA256_DIGEST_SIZE);
|
||||
sha256_final(&ctx->ctx_outside, mac_temp);
|
||||
memcpy(mac, mac_temp, mac_size);
|
||||
}
|
||||
|
||||
void hmac_sha256(unsigned char *key, unsigned int key_size,
|
||||
unsigned char *message, unsigned int message_len,
|
||||
unsigned char *mac, unsigned mac_size)
|
||||
{
|
||||
hmac_sha256_ctx ctx;
|
||||
|
||||
hmac_sha256_init(&ctx, key, key_size);
|
||||
hmac_sha256_update(&ctx, message, message_len);
|
||||
hmac_sha256_final(&ctx, mac, mac_size);
|
||||
}
|
||||
|
||||
/* HMAC-SHA-384 functions */
|
||||
|
||||
void hmac_sha384_init(hmac_sha384_ctx *ctx, unsigned char *key,
|
||||
unsigned int key_size)
|
||||
{
|
||||
unsigned int fill;
|
||||
unsigned int num;
|
||||
|
||||
unsigned char *key_used;
|
||||
unsigned char key_temp[SHA384_DIGEST_SIZE];
|
||||
int i;
|
||||
|
||||
if (key_size == SHA384_BLOCK_SIZE) {
|
||||
key_used = key;
|
||||
num = SHA384_BLOCK_SIZE;
|
||||
} else {
|
||||
if (key_size > SHA384_BLOCK_SIZE){
|
||||
key_used = key_temp;
|
||||
num = SHA384_DIGEST_SIZE;
|
||||
sha384(key, key_size, key_used);
|
||||
} else { /* key_size > SHA384_BLOCK_SIZE */
|
||||
key_used = key;
|
||||
num = key_size;
|
||||
}
|
||||
fill = SHA384_BLOCK_SIZE - num;
|
||||
|
||||
memset(ctx->block_ipad + num, 0x36, fill);
|
||||
memset(ctx->block_opad + num, 0x5c, fill);
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
ctx->block_ipad[i] = key_used[i] ^ 0x36;
|
||||
ctx->block_opad[i] = key_used[i] ^ 0x5c;
|
||||
}
|
||||
|
||||
sha384_init(&ctx->ctx_inside);
|
||||
sha384_update(&ctx->ctx_inside, ctx->block_ipad, SHA384_BLOCK_SIZE);
|
||||
|
||||
sha384_init(&ctx->ctx_outside);
|
||||
sha384_update(&ctx->ctx_outside, ctx->block_opad,
|
||||
SHA384_BLOCK_SIZE);
|
||||
|
||||
/* for hmac_reinit */
|
||||
memcpy(&ctx->ctx_inside_reinit, &ctx->ctx_inside,
|
||||
sizeof(sha384_ctx));
|
||||
memcpy(&ctx->ctx_outside_reinit, &ctx->ctx_outside,
|
||||
sizeof(sha384_ctx));
|
||||
}
|
||||
|
||||
void hmac_sha384_reinit(hmac_sha384_ctx *ctx)
|
||||
{
|
||||
memcpy(&ctx->ctx_inside, &ctx->ctx_inside_reinit,
|
||||
sizeof(sha384_ctx));
|
||||
memcpy(&ctx->ctx_outside, &ctx->ctx_outside_reinit,
|
||||
sizeof(sha384_ctx));
|
||||
}
|
||||
|
||||
void hmac_sha384_update(hmac_sha384_ctx *ctx, unsigned char *message,
|
||||
unsigned int message_len)
|
||||
{
|
||||
sha384_update(&ctx->ctx_inside, message, message_len);
|
||||
}
|
||||
|
||||
void hmac_sha384_final(hmac_sha384_ctx *ctx, unsigned char *mac,
|
||||
unsigned int mac_size)
|
||||
{
|
||||
unsigned char digest_inside[SHA384_DIGEST_SIZE];
|
||||
unsigned char mac_temp[SHA384_DIGEST_SIZE];
|
||||
|
||||
sha384_final(&ctx->ctx_inside, digest_inside);
|
||||
sha384_update(&ctx->ctx_outside, digest_inside, SHA384_DIGEST_SIZE);
|
||||
sha384_final(&ctx->ctx_outside, mac_temp);
|
||||
memcpy(mac, mac_temp, mac_size);
|
||||
}
|
||||
|
||||
void hmac_sha384(unsigned char *key, unsigned int key_size,
|
||||
unsigned char *message, unsigned int message_len,
|
||||
unsigned char *mac, unsigned mac_size)
|
||||
{
|
||||
hmac_sha384_ctx ctx;
|
||||
|
||||
hmac_sha384_init(&ctx, key, key_size);
|
||||
hmac_sha384_update(&ctx, message, message_len);
|
||||
hmac_sha384_final(&ctx, mac, mac_size);
|
||||
}
|
||||
|
||||
/* HMAC-SHA-512 functions */
|
||||
|
||||
void hmac_sha512_init(hmac_sha512_ctx *ctx, unsigned char *key,
|
||||
unsigned int key_size)
|
||||
{
|
||||
unsigned int fill;
|
||||
unsigned int num;
|
||||
|
||||
unsigned char *key_used;
|
||||
unsigned char key_temp[SHA512_DIGEST_SIZE];
|
||||
int i;
|
||||
|
||||
if (key_size == SHA512_BLOCK_SIZE) {
|
||||
key_used = key;
|
||||
num = SHA512_BLOCK_SIZE;
|
||||
} else {
|
||||
if (key_size > SHA512_BLOCK_SIZE){
|
||||
key_used = key_temp;
|
||||
num = SHA512_DIGEST_SIZE;
|
||||
sha512(key, key_size, key_used);
|
||||
} else { /* key_size > SHA512_BLOCK_SIZE */
|
||||
key_used = key;
|
||||
num = key_size;
|
||||
}
|
||||
fill = SHA512_BLOCK_SIZE - num;
|
||||
|
||||
memset(ctx->block_ipad + num, 0x36, fill);
|
||||
memset(ctx->block_opad + num, 0x5c, fill);
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
ctx->block_ipad[i] = key_used[i] ^ 0x36;
|
||||
ctx->block_opad[i] = key_used[i] ^ 0x5c;
|
||||
}
|
||||
|
||||
sha512_init(&ctx->ctx_inside);
|
||||
sha512_update(&ctx->ctx_inside, ctx->block_ipad, SHA512_BLOCK_SIZE);
|
||||
|
||||
sha512_init(&ctx->ctx_outside);
|
||||
sha512_update(&ctx->ctx_outside, ctx->block_opad,
|
||||
SHA512_BLOCK_SIZE);
|
||||
|
||||
/* for hmac_reinit */
|
||||
memcpy(&ctx->ctx_inside_reinit, &ctx->ctx_inside,
|
||||
sizeof(sha512_ctx));
|
||||
memcpy(&ctx->ctx_outside_reinit, &ctx->ctx_outside,
|
||||
sizeof(sha512_ctx));
|
||||
}
|
||||
|
||||
void hmac_sha512_reinit(hmac_sha512_ctx *ctx)
|
||||
{
|
||||
memcpy(&ctx->ctx_inside, &ctx->ctx_inside_reinit,
|
||||
sizeof(sha512_ctx));
|
||||
memcpy(&ctx->ctx_outside, &ctx->ctx_outside_reinit,
|
||||
sizeof(sha512_ctx));
|
||||
}
|
||||
|
||||
void hmac_sha512_update(hmac_sha512_ctx *ctx, unsigned char *message,
|
||||
unsigned int message_len)
|
||||
{
|
||||
sha512_update(&ctx->ctx_inside, message, message_len);
|
||||
}
|
||||
|
||||
void hmac_sha512_final(hmac_sha512_ctx *ctx, unsigned char *mac,
|
||||
unsigned int mac_size)
|
||||
{
|
||||
unsigned char digest_inside[SHA512_DIGEST_SIZE];
|
||||
unsigned char mac_temp[SHA512_DIGEST_SIZE];
|
||||
|
||||
sha512_final(&ctx->ctx_inside, digest_inside);
|
||||
sha512_update(&ctx->ctx_outside, digest_inside, SHA512_DIGEST_SIZE);
|
||||
sha512_final(&ctx->ctx_outside, mac_temp);
|
||||
memcpy(mac, mac_temp, mac_size);
|
||||
}
|
||||
|
||||
void hmac_sha512(unsigned char *key, unsigned int key_size,
|
||||
unsigned char *message, unsigned int message_len,
|
||||
unsigned char *mac, unsigned mac_size)
|
||||
{
|
||||
hmac_sha512_ctx ctx;
|
||||
|
||||
hmac_sha512_init(&ctx, key, key_size);
|
||||
hmac_sha512_update(&ctx, message, message_len);
|
||||
hmac_sha512_final(&ctx, mac, mac_size);
|
||||
}
|
||||
|
||||
#ifdef TEST_VECTORS
|
||||
|
||||
/* IETF Validation tests */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void test(unsigned char *vector, unsigned char *digest,
|
||||
unsigned int digest_size)
|
||||
{
|
||||
unsigned char output[2 * SHA512_DIGEST_SIZE + 1];
|
||||
int i;
|
||||
|
||||
output[2 * digest_size] = '\0';
|
||||
|
||||
for (i = 0; i < digest_size ; i++) {
|
||||
sprintf((char *) output + 2*i, "%02x", digest[i]);
|
||||
}
|
||||
|
||||
printf("H: %s\n", output);
|
||||
if (strcmp((char *) vector, (char *) output)) {
|
||||
fprintf(stderr, "Test failed.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
static unsigned char *vectors[] =
|
||||
{
|
||||
/* HMAC-SHA-224 */
|
||||
"896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22",
|
||||
"a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44",
|
||||
"7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea",
|
||||
"6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a",
|
||||
"0e2aea68a90c8d37c988bcdb9fca6fa8",
|
||||
"95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e",
|
||||
"3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1",
|
||||
/* HMAC-SHA-256 */
|
||||
"b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7",
|
||||
"5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843",
|
||||
"773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe",
|
||||
"82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b",
|
||||
"a3b6167473100ee06e0c796c2955552b",
|
||||
"60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54",
|
||||
"9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2",
|
||||
/* HMAC-SHA-384 */
|
||||
"afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59c"
|
||||
"faea9ea9076ede7f4af152e8b2fa9cb6",
|
||||
"af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e"
|
||||
"8e2240ca5e69e2c78b3239ecfab21649",
|
||||
"88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b"
|
||||
"2a5ab39dc13814b94e3ab6e101a34f27",
|
||||
"3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e"
|
||||
"6801dd23c4a7d679ccf8a386c674cffb",
|
||||
"3abf34c3503b2a23a46efc619baef897",
|
||||
"4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c6"
|
||||
"0c2ef6ab4030fe8296248df163f44952",
|
||||
"6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5"
|
||||
"a678cc31e799176d3860e6110c46523e",
|
||||
/* HMAC-SHA-512 */
|
||||
"87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cde"
|
||||
"daa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854",
|
||||
"164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea250554"
|
||||
"9758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737",
|
||||
"fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39"
|
||||
"bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb",
|
||||
"b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3db"
|
||||
"a91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd",
|
||||
"415fad6271580a531d4179bc891d87a6",
|
||||
"80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f352"
|
||||
"6b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598",
|
||||
"e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944"
|
||||
"b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58"
|
||||
};
|
||||
|
||||
static unsigned char *messages[] =
|
||||
{
|
||||
"Hi There",
|
||||
"what do ya want for nothing?",
|
||||
NULL,
|
||||
NULL,
|
||||
"Test With Truncation",
|
||||
"Test Using Larger Than Block-Size Key - Hash Key First",
|
||||
"This is a test using a larger than block-size key "
|
||||
"and a larger than block-size data. The key needs"
|
||||
" to be hashed before being used by the HMAC algorithm."
|
||||
};
|
||||
|
||||
unsigned char mac[SHA512_DIGEST_SIZE];
|
||||
unsigned char *keys[7];
|
||||
unsigned int keys_len[7] = {20, 4, 20, 25, 20, 131, 131};
|
||||
unsigned int messages2and3_len = 50;
|
||||
unsigned int mac_224_size, mac_256_size, mac_384_size, mac_512_size;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 7; i++) {
|
||||
keys[i] = malloc(keys_len[i]);
|
||||
if (keys[i] == NULL) {
|
||||
fprintf(stderr, "Can't allocate memory\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
memset(keys[0], 0x0b, keys_len[0]);
|
||||
strcpy(keys[1], "Jefe");
|
||||
memset(keys[2], 0xaa, keys_len[2]);
|
||||
for (i = 0; i < keys_len[3]; i++)
|
||||
keys[3][i] = (unsigned char) i + 1;
|
||||
memset(keys[4], 0x0c, keys_len[4]);
|
||||
memset(keys[5], 0xaa, keys_len[5]);
|
||||
memset(keys[6], 0xaa, keys_len[6]);
|
||||
|
||||
messages[2] = malloc(messages2and3_len + 1);
|
||||
messages[3] = malloc(messages2and3_len + 1);
|
||||
|
||||
if (messages[2] == NULL || messages[3] == NULL) {
|
||||
fprintf(stderr, "Can't allocate memory\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
messages[2][messages2and3_len] = '\0';
|
||||
messages[3][messages2and3_len] = '\0';
|
||||
|
||||
memset(messages[2], 0xdd, messages2and3_len);
|
||||
memset(messages[3], 0xcd, messages2and3_len);
|
||||
|
||||
printf("HMAC-SHA-2 IETF Validation tests\n\n");
|
||||
|
||||
for (i = 0; i < 7; i++) {
|
||||
if (i != 4) {
|
||||
mac_224_size = SHA224_DIGEST_SIZE;
|
||||
mac_256_size = SHA256_DIGEST_SIZE;
|
||||
mac_384_size = SHA384_DIGEST_SIZE;
|
||||
mac_512_size = SHA512_DIGEST_SIZE;
|
||||
} else {
|
||||
mac_224_size = 128 / 8; mac_256_size = 128 / 8;
|
||||
mac_384_size = 128 / 8; mac_512_size = 128 / 8;
|
||||
}
|
||||
|
||||
printf("Test %d:\n", i + 1);
|
||||
|
||||
hmac_sha224(keys[i], keys_len[i], messages[i], strlen(messages[i]),
|
||||
mac, mac_224_size);
|
||||
test(vectors[i], mac, mac_224_size );
|
||||
hmac_sha256(keys[i], keys_len[i], messages[i], strlen(messages[i]),
|
||||
mac, mac_256_size);
|
||||
test(vectors[7 + i], mac, mac_256_size);
|
||||
hmac_sha384(keys[i], keys_len[i], messages[i], strlen(messages[i]),
|
||||
mac, mac_384_size);
|
||||
test(vectors[14 + i], mac, mac_384_size);
|
||||
hmac_sha512(keys[i], keys_len[i], messages[i], strlen(messages[i]),
|
||||
mac, mac_512_size);
|
||||
test(vectors[21 + i], mac, mac_512_size);
|
||||
}
|
||||
|
||||
printf("All tests passed.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* TEST_VECTORS */
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
#include "input.h"
|
||||
#include "clog.h"
|
||||
#include "util.h"
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void REQ_STRING( CVars &in, const char * name, int min_len, int max_len, const char *regex ) throw (bad_parameter)
|
||||
{
|
||||
int len = in[name].length();
|
||||
char ret[2048]; ret[0] = 0;
|
||||
|
||||
logfmt( FLOG_MAX, "REQ_STRING(%s)", name );
|
||||
|
||||
bool match = reg_match( in[name].c_str(), regex, ret, sizeof(ret) );
|
||||
len = strlen(ret);
|
||||
if ( !match || len < min_len || len > max_len )
|
||||
{
|
||||
logfmt( FLOG_MAX, "Error in parameter '%s', len= %d <= %d <= %d", name, min_len, match, max_len );
|
||||
in[name].set_valid( false );
|
||||
throw bad_parameter( in, name );
|
||||
}
|
||||
|
||||
in[name] = ret;
|
||||
|
||||
CVars::iterator i = in.find( name );
|
||||
i->second.set_valid();
|
||||
|
||||
//logfmt( FLOG_MAX, "i->second.valid()=%d", i->second.valid() );
|
||||
|
||||
// if not match regexp
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
long REQ_LONG( CVars &in, const char *name, long min, long max )
|
||||
{
|
||||
char *end;
|
||||
long r = strtol( in[name].c_str(), &end, 10 );
|
||||
|
||||
if ( in[name].length() && !*end )
|
||||
{
|
||||
in[name].set_valid();
|
||||
return r;
|
||||
}
|
||||
else
|
||||
{
|
||||
in[name].set_valid( false );
|
||||
throw bad_parameter( in, name );
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
bool OptionalSpecified( CVars &in, const char * name )
|
||||
{
|
||||
if ( in.find(name)==in.end() ) return false; // parameter omitted, not even passed from frontend
|
||||
|
||||
return ! reg_match( in[name].c_str(), "^[[:space:]]*$", NULL, 0 );
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/*
|
||||
vi:ts=2
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "list.h"
|
||||
|
||||
void DestroyList( TList * top )
|
||||
{
|
||||
// LOG( "DestroyList()", LOG_MAX );
|
||||
|
||||
TList * cur = top; unsigned long pos=0;
|
||||
TList * prev;
|
||||
|
||||
while ( cur && cur->text)
|
||||
{
|
||||
free( cur->text );
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
delete prev;
|
||||
}
|
||||
|
||||
// LOG( "/DestroyList()", LOG_MAX );
|
||||
}
|
||||
|
||||
TList * Add( TList * list, char * text, long size )
|
||||
{
|
||||
if (!text)
|
||||
return list;
|
||||
|
||||
list->text = new char[ size+1 ];
|
||||
memcpy( list->text, text, size );
|
||||
list->text[size] = 0;
|
||||
|
||||
// logfmt( FLOG_MAX, "Added: '%s'", list->text );
|
||||
|
||||
list->next = new TList;
|
||||
list->next->next = NULL;
|
||||
list->next->text = NULL;
|
||||
|
||||
return list->next;
|
||||
}
|
||||
|
||||
|
||||
TList * AddF( TList * list, char * format, ... )
|
||||
{
|
||||
if (!format)
|
||||
return list;
|
||||
|
||||
int size;
|
||||
va_list ap;
|
||||
|
||||
va_start( ap, format );
|
||||
size = vsnprintf( NULL, 0, format, ap ) + 1;
|
||||
list->text = new char[ size ];
|
||||
if ( !list->text) return list; // out of mem => do nothing
|
||||
vsnprintf( list->text, size-1, format, ap );
|
||||
va_end( ap );
|
||||
list->text[size] = 0;
|
||||
|
||||
// logfmt( FLOG_MAX, "Added: '%s'", list->text );
|
||||
|
||||
list->next = new TList;
|
||||
list->next->next = NULL;
|
||||
list->next->text = NULL;
|
||||
|
||||
return list->next;
|
||||
}
|
||||
|
||||
|
||||
void PrintList( TList * list )
|
||||
{
|
||||
// LOG( "PrintList()", LOG_MAX );
|
||||
|
||||
TList * cur = list;
|
||||
while (cur && cur->text)
|
||||
{
|
||||
// LOG( cur->text, LOG_MAX );
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
// LOG( "/PrintList()", LOG_MAX );
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
#include "mermsemr.h"
|
||||
#include "clog.h"
|
||||
#include "cfg.h"
|
||||
#include "exceptions.h"
|
||||
#include "input.h"
|
||||
#include "mermsemr_api.h"
|
||||
#include "pgsql.h"
|
||||
|
||||
#include "mermsemr_api_main.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <libpq-fe.h>
|
||||
|
||||
MermsEmr::MermsEmr() {
|
||||
// Open config
|
||||
this->pFile = fopen(MERMSEMR_LOG, "a");
|
||||
Output2FILE::Stream() = pFile;
|
||||
FILE_LOG(logINFO) << "MERMSEMR is starting...";
|
||||
|
||||
CfgReadConfig();
|
||||
logfmt(logINFO, "Version from config: %s", CfgReadChar("version"));
|
||||
|
||||
// Open database
|
||||
FILE_LOG(logDEBUG) << "Connecting to database...";
|
||||
FILE_LOG(logDEBUG) << "host=" << CfgReadChar("database.host") << ", name=" << CfgReadChar("database.name") << ", user=" << CfgReadChar("database.user") << ", pass=***hidden***, port=" << CfgReadLong("database.port");
|
||||
|
||||
this->db = 0;
|
||||
try {
|
||||
this->db = pgsql_db_connect(CfgReadChar("database.host"),
|
||||
CfgReadChar("database.name"),
|
||||
CfgReadChar("database.user"),
|
||||
CfgReadChar("database.pass"),
|
||||
CfgReadLong("database.port") );
|
||||
} catch (...) {
|
||||
logfmt(logDEBUG, "Exception!");
|
||||
}
|
||||
logfmt(logDEBUG, "Database connection %s", this->db>0?"successful":"failed");
|
||||
}
|
||||
|
||||
long MermsEmr::mermsemr_api(CVars in, CVars &out) {
|
||||
long retval = PHP_API_BAD_PARAM;
|
||||
try {
|
||||
retval = mermsemr_api_main(in, out);
|
||||
} catch (bad_parameter) {
|
||||
out["status"] = "Incorrect input parameter";
|
||||
} catch (...) {
|
||||
out["status"] = "Unhandled exception";
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
const char* MermsEmr::cfgReadChar(const char *parameter) {
|
||||
return CfgReadChar(parameter);
|
||||
}
|
||||
|
||||
long MermsEmr::cfgReadLong(const char *parameter) {
|
||||
return CfgReadLong(parameter);
|
||||
}
|
||||
|
||||
void MermsEmr::logMessage(const char *message) {
|
||||
FILE_LOG(logINFO) << message;
|
||||
}
|
||||
|
||||
MermsEmr::~MermsEmr() {
|
||||
FILE_LOG(logINFO) << "MERMSEMR is stopping...";
|
||||
if (db>0) {
|
||||
FILE_LOG(logDEBUG) << "Closing database connection";
|
||||
pgsql_close();
|
||||
}
|
||||
// Do we need it?
|
||||
if (this->pFile) {
|
||||
fclose(this->pFile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
#include "php_mermsemr_api.h"
|
||||
#include "php_mermsemr_api_ns.h"
|
||||
#include "mermsemr.h"
|
||||
#include "cfg.h"
|
||||
#include "clog.h"
|
||||
#include "vars.h"
|
||||
|
||||
#include "safestring.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <map>
|
||||
|
||||
#include <ext/standard/info.h>
|
||||
|
||||
zend_object_handlers mermsemr_object_handlers;
|
||||
|
||||
typedef struct _mermsemr_object {
|
||||
MermsEmr *mermsemr;
|
||||
zend_object std;
|
||||
} mermsemr_object;
|
||||
|
||||
static inline mermsemr_object *php_mermsemr_obj_from_obj(zend_object *obj) {
|
||||
return (mermsemr_object*)((char*)(obj) - XtOffsetOf(mermsemr_object, std));
|
||||
}
|
||||
|
||||
#define Z_TSTOBJ_P(zv) php_mermsemr_obj_from_obj(Z_OBJ_P((zv)))
|
||||
|
||||
zend_class_entry *mermsemr_ce;
|
||||
|
||||
#define SET_ENV( env ) \
|
||||
if (NULL != (token = zend_hash_str_find(_SERVER, env, sizeof(env)-1))) {\
|
||||
setenv( env, Z_STRVAL_P(token), 1 ); \
|
||||
logfmt( logINFO, env " = %s", Z_STRVAL_P(token) ); \
|
||||
} else {\
|
||||
unsetenv( env );\
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
PHP_METHOD(MermsEmr, __construct)
|
||||
{
|
||||
HashTable *_SERVER;
|
||||
zval *token;
|
||||
zval *id = getThis();
|
||||
mermsemr_object *intern;
|
||||
|
||||
intern = Z_TSTOBJ_P(id);
|
||||
if(intern != NULL) {
|
||||
intern->mermsemr = new MermsEmr();
|
||||
// Load some _SERVER data into environment
|
||||
zend_string *_server = zend_string_init("_SERVER", strlen("_SERVER"), 0);
|
||||
zend_is_auto_global(_server);
|
||||
if (Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) == IS_UNDEF) {
|
||||
logfmt( logINFO, "_SERVER not found" );
|
||||
} else {
|
||||
logfmt( logINFO, "_SERVER found" );
|
||||
_SERVER = Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]);
|
||||
SET_ENV( "REMOTE_ADDR" );
|
||||
SET_ENV( "SERVER_NAME" );
|
||||
SET_ENV( "HTTP_COOKIE" );
|
||||
SET_ENV( "QUERY_STRING" );
|
||||
SET_ENV( "HTTP_X_FORWARDED_FOR" );
|
||||
}
|
||||
zend_string_release(_server);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ // ------------------------------------------------------------------
|
||||
PHP_METHOD(MermsEmr, mermsemr_api)
|
||||
{
|
||||
zval *param, *param_out;
|
||||
zval *id = getThis();
|
||||
mermsemr_object *intern;
|
||||
CVars input, output;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", ¶m, ¶m_out) == FAILURE) {
|
||||
// Bad parameters
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
intern = Z_TSTOBJ_P(id);
|
||||
if(intern != NULL) {
|
||||
// Convert input
|
||||
|
||||
HashTable *hash;
|
||||
zend_string *key, val;
|
||||
ulong num_key;
|
||||
uint key_len;
|
||||
zval *value;
|
||||
convert_to_array_ex( param );
|
||||
hash = HASH_OF( param );
|
||||
zend_hash_internal_pointer_reset( hash );
|
||||
ZEND_HASH_FOREACH_KEY_VAL(hash, num_key, key, value) {
|
||||
if (key) { //HASH_KEY_IS_STRING
|
||||
if (Z_TYPE_P(value) == IS_STRING) {
|
||||
input[ ZSTR_VAL(key) ] = Z_STRVAL_P(value);
|
||||
/*
|
||||
} else if (Z_TYPE_P(value) == IS_LONG) {
|
||||
input[ ZSTR_VAL(key) ] = Z_LVAL_P(value);
|
||||
} else if (Z_TYPE_P(value) == IS_DOUBLE) {
|
||||
input[ ZSTR_VAL(key) ] = Z_DVAL_P(value);
|
||||
} else if (Z_TYPE_P(value) == _IS_BOOL) {
|
||||
input[ ZSTR_VAL(key) ] = Z_BVAL(value) ? 1L : 0L;
|
||||
} else if (Z_TYPE_P(value) == IS_NULL) {
|
||||
input[ ZSTR_VAL(key) ] = ""; */
|
||||
} else {
|
||||
//logfmt( logINFO, "Item %s has unsupported value type", ZSTR_VAL(key) );
|
||||
convert_to_string(value);
|
||||
input[ ZSTR_VAL(key) ] = Z_STRVAL_P(value);
|
||||
}
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
long retval = intern->mermsemr->mermsemr_api(input, output);
|
||||
|
||||
// Convert output
|
||||
convert_to_array_ex( param_out );
|
||||
CVars::iterator i;
|
||||
int j = 0;
|
||||
const int out_size = output.size(); // 200
|
||||
const int out_value_size = 200;
|
||||
char out_key[out_value_size], out_value[out_value_size];
|
||||
for ( i=output.begin(); i != output.end() && j<out_size ; i++ ) {
|
||||
bzero(out_key, out_value_size);
|
||||
bzero(out_value, out_value_size);
|
||||
j++;
|
||||
logfmt( logINFO, "RET: %s=%s", i->first.c_str(), i->second.c_str() );
|
||||
strsafecpy( out_key, i->first.c_str(), out_value_size );
|
||||
strsafecpy( out_value, i->second.c_str(), out_value_size );
|
||||
add_assoc_string( param_out, out_key, out_value);
|
||||
}
|
||||
|
||||
RETURN_LONG(retval);
|
||||
}
|
||||
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ // ------------------------------------------------------------------
|
||||
PHP_METHOD(MermsEmr, cfgReadChar)
|
||||
{
|
||||
unsigned char *parameter;
|
||||
zval *id = getThis();
|
||||
mermsemr_object *intern;
|
||||
|
||||
if (zend_parse_parameters(
|
||||
ZEND_NUM_ARGS() TSRMLS_CC, "s", ¶meter) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
intern = Z_TSTOBJ_P(id);
|
||||
if(intern != NULL) {
|
||||
std::string s = intern->mermsemr->cfgReadChar((char*)parameter);
|
||||
RETURN_STRING(s.c_str());
|
||||
}
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ // ------------------------------------------------------------------
|
||||
PHP_METHOD(MermsEmr, cfgReadLong)
|
||||
{
|
||||
unsigned char *parameter;
|
||||
zval *id = getThis();
|
||||
mermsemr_object *intern;
|
||||
|
||||
if (zend_parse_parameters(
|
||||
ZEND_NUM_ARGS() TSRMLS_CC, "s", ¶meter) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
intern = Z_TSTOBJ_P(id);
|
||||
if(intern != NULL) {
|
||||
RETURN_LONG(intern->mermsemr->cfgReadLong((char*)parameter));
|
||||
}
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ // ------------------------------------------------------------------
|
||||
PHP_METHOD(MermsEmr, logMessage)
|
||||
{
|
||||
unsigned char *message;
|
||||
zval *id = getThis();
|
||||
mermsemr_object *intern;
|
||||
|
||||
if (zend_parse_parameters(
|
||||
ZEND_NUM_ARGS() TSRMLS_CC, "s", &message) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
intern = Z_TSTOBJ_P(id);
|
||||
if(intern != NULL) {
|
||||
intern->mermsemr->logMessage((char*)message);
|
||||
RETURN_TRUE;
|
||||
}
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ // ------------------------------------------------------------------
|
||||
const zend_function_entry mermsemr_methods[] = {
|
||||
PHP_ME(MermsEmr, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
|
||||
PHP_ME(MermsEmr, mermsemr_api, NULL, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(MermsEmr, cfgReadChar, NULL, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(MermsEmr, cfgReadLong, NULL, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(MermsEmr, logMessage, NULL, ZEND_ACC_PUBLIC)
|
||||
PHP_FE_END
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------ // ------------------------------------------------------------------
|
||||
zend_object *mermsemr_object_new(zend_class_entry *ce TSRMLS_DC)
|
||||
{
|
||||
mermsemr_object *intern = (mermsemr_object*)ecalloc(1,
|
||||
sizeof(mermsemr_object) +
|
||||
zend_object_properties_size(ce));
|
||||
|
||||
zend_object_std_init(&intern->std, ce TSRMLS_CC);
|
||||
object_properties_init(&intern->std, ce);
|
||||
|
||||
intern->std.handlers = &mermsemr_object_handlers;
|
||||
|
||||
return &intern->std;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ // ------------------------------------------------------------------
|
||||
static void mermsemr_object_destroy(zend_object *object)
|
||||
{
|
||||
mermsemr_object *my_obj;
|
||||
my_obj = (mermsemr_object*)((char *)
|
||||
object - XtOffsetOf(mermsemr_object, std));
|
||||
|
||||
// Call __destruct() from user-land.
|
||||
zend_objects_destroy_object(object);
|
||||
}
|
||||
|
||||
static void mermsemr_object_free(zend_object *object)
|
||||
{
|
||||
mermsemr_object *my_obj;
|
||||
my_obj = (mermsemr_object *)((char *)
|
||||
object - XtOffsetOf(mermsemr_object, std));
|
||||
delete my_obj->mermsemr;
|
||||
// Free the object using Zend macro.
|
||||
zend_object_std_dtor(object);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ // ------------------------------------------------------------------
|
||||
PHP_MINIT_FUNCTION(mermsemr_api_sameye)
|
||||
{
|
||||
zend_class_entry ce;
|
||||
INIT_NS_CLASS_ENTRY(ce, MERMSEMR_API_SAMEYE_NS, "MermsEmr", mermsemr_methods);
|
||||
mermsemr_ce = zend_register_internal_class(&ce TSRMLS_CC);
|
||||
mermsemr_ce->create_object = mermsemr_object_new;
|
||||
|
||||
memcpy(&mermsemr_object_handlers,
|
||||
zend_get_std_object_handlers(),
|
||||
sizeof(mermsemr_object_handlers));
|
||||
|
||||
// Handler for free'ing the object.
|
||||
mermsemr_object_handlers.free_obj = mermsemr_object_free;
|
||||
|
||||
// Handler for the destructor.
|
||||
mermsemr_object_handlers.dtor_obj = mermsemr_object_destroy;
|
||||
|
||||
// Offset into the engine.
|
||||
mermsemr_object_handlers.offset = XtOffsetOf(mermsemr_object, std);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ // ------------------------------------------------------------------
|
||||
PHP_MINFO_FUNCTION(mermsemr_api_sameye)
|
||||
{
|
||||
php_info_print_table_start();
|
||||
php_info_print_table_row(2, "MERMSEMR API support", "enabled");
|
||||
php_info_print_table_row(2, "Log File", MERMSEMR_LOG);
|
||||
php_info_print_table_row(2, "Config File", MERMSEMR_CONFIG"mermsemr_api.conf");
|
||||
php_info_print_table_row(2, "Build Date", __DATE__);
|
||||
php_info_print_table_row(2, "Build Time", __TIME__);
|
||||
php_info_print_table_row(2, "Namespace", MERMSEMR_API_SAMEYE_NS);
|
||||
php_info_print_table_row(2, "Version", PHP_MERMSEMR_API_SAMEYE_EXTVER);
|
||||
php_info_print_table_end();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ // ------------------------------------------------------------------
|
||||
zend_module_entry mermsemr_api_sameye_module_entry = {
|
||||
#if ZEND_MODULE_API_NO >= 20010901
|
||||
STANDARD_MODULE_HEADER,
|
||||
#endif
|
||||
PHP_MERMSEMR_API_SAMEYE_EXTNAME,
|
||||
NULL, /* Functions */
|
||||
PHP_MINIT(mermsemr_api_sameye),
|
||||
NULL, /* MSHUTDOWN */
|
||||
NULL, /* RINIT */
|
||||
NULL, /* RSHUTDOWN */
|
||||
PHP_MINFO(mermsemr_api_sameye), /* MINFO */
|
||||
#if ZEND_MODULE_API_NO >= 20010901
|
||||
PHP_MERMSEMR_API_SAMEYE_EXTVER,
|
||||
#endif
|
||||
STANDARD_MODULE_PROPERTIES
|
||||
};
|
||||
|
||||
//#ifdef COMPILE_DL_MERMSEMR_API_SAMEYE
|
||||
extern "C" {
|
||||
ZEND_GET_MODULE(mermsemr_api_sameye)
|
||||
}
|
||||
//#endif
|
||||
@@ -0,0 +1,216 @@
|
||||
#include "pgsql.h"
|
||||
#include "clog.h"
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
PGconn *conn;
|
||||
|
||||
int pgsql_db_connect(const char*host,const char*name,const char*user,const char*pass,long port)
|
||||
{
|
||||
FILE_LOG(logSQL) << "pgsql_db_connect()";
|
||||
static std::string connection_str;
|
||||
|
||||
if(host) {
|
||||
connection_str+="host=";
|
||||
connection_str+=host;
|
||||
}
|
||||
if(name) {
|
||||
connection_str+=" dbname=";
|
||||
connection_str+=name;
|
||||
}
|
||||
if(user) {
|
||||
connection_str+=" user=";
|
||||
connection_str+=user;
|
||||
}
|
||||
if(pass) {
|
||||
connection_str+=" password=";
|
||||
connection_str+=pass;
|
||||
}
|
||||
if(port>0) {
|
||||
char pdb_port[20];
|
||||
connection_str+=" port=";
|
||||
connection_str+=pgsql_uitoa(port,pdb_port,10);
|
||||
}
|
||||
|
||||
conn = PQconnectdb(connection_str.c_str());
|
||||
if (PQstatus(conn) != CONNECTION_OK) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void pgsql_close()
|
||||
{
|
||||
FILE_LOG(logSQL) << "pgsql_close()";
|
||||
if (PQstatus(conn)==CONNECTION_OK) {
|
||||
PQfinish(conn);
|
||||
}
|
||||
}
|
||||
|
||||
int pgsql_exec(const char * format, ... )
|
||||
{
|
||||
FILE_LOG(logSQL) << "pgsql_exec()";
|
||||
char query[16384];
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
vsprintf (query, format, args);
|
||||
//perror (buffer);
|
||||
va_end (args);
|
||||
|
||||
FILE_LOG(logSQL) << "About to run query: ";
|
||||
FILE_LOG(logSQL) << query;
|
||||
/* Escape any PostgrsSQL-unsafe characters */
|
||||
// user_size = PQescapeStringConn (conn, user_data, username, strlen(username), &pqesc_error);
|
||||
int num = 0;
|
||||
char *cmdTuples = NULL;
|
||||
PGresult *res = PQexec(conn, query);
|
||||
if(!res) {
|
||||
/* Error */
|
||||
FILE_LOG(logSQL) << "Error: NULL result";
|
||||
num = -1;
|
||||
} else {
|
||||
switch (PQresultStatus(res)) {
|
||||
case PGRES_TUPLES_OK:
|
||||
case PGRES_COMMAND_OK:
|
||||
cmdTuples = PQcmdTuples(res);
|
||||
FILE_LOG(logSQL) << "PQcmdTuples: " << cmdTuples;
|
||||
num = atoi(cmdTuples);
|
||||
break;
|
||||
case PGRES_EMPTY_QUERY:
|
||||
case PGRES_BAD_RESPONSE:
|
||||
case PGRES_NONFATAL_ERROR:
|
||||
case PGRES_FATAL_ERROR:
|
||||
case PGRES_COPY_OUT:
|
||||
case PGRES_COPY_IN:
|
||||
num = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (num<0) {
|
||||
FILE_LOG(logSQL) << "Affected rows: ERROR";
|
||||
} else {
|
||||
FILE_LOG(logSQL) << "Affected rows: " << num;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
const PGresult* pgsql_query(const char * format, ... )
|
||||
{
|
||||
FILE_LOG(logSQL) << "pgsql_query()";
|
||||
char query[16384];
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
vsprintf (query, format, args);
|
||||
//perror (buffer);
|
||||
va_end (args);
|
||||
|
||||
FILE_LOG(logSQL) << "About to run query: ";
|
||||
FILE_LOG(logSQL) << query;
|
||||
/* Escape any PostgrsSQL-unsafe characters */
|
||||
// user_size = PQescapeStringConn (conn, user_data, username, strlen(username), &pqesc_error);
|
||||
int num = 0;
|
||||
const PGresult *res = PQexec(conn, query);
|
||||
if(!res) {
|
||||
/* Error */
|
||||
num = -1;
|
||||
FILE_LOG(logSQL) << "Error: NULL result";
|
||||
} else {
|
||||
switch (PQresultStatus(res)) {
|
||||
case PGRES_TUPLES_OK:
|
||||
case PGRES_COMMAND_OK:
|
||||
num = PQntuples(res);
|
||||
FILE_LOG(logSQL) << "Found rows: " << num;
|
||||
break;
|
||||
case PGRES_EMPTY_QUERY:
|
||||
case PGRES_BAD_RESPONSE:
|
||||
case PGRES_NONFATAL_ERROR:
|
||||
case PGRES_FATAL_ERROR:
|
||||
case PGRES_COPY_OUT:
|
||||
case PGRES_COPY_IN:
|
||||
num = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (num>0) {
|
||||
return res;
|
||||
}
|
||||
FILE_LOG(logSQL) << "Found rows: " << (num<0?"ERROR":"0");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int pgsql_num_rows(const PGresult *res)
|
||||
{
|
||||
if (res) {
|
||||
return PQntuples(res);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pgsql_num_fields(const PGresult *res)
|
||||
{
|
||||
if (res) {
|
||||
return PQnfields(res);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
map<const char*,const char*> pgsql_fetch_assoc(const PGresult *res, int row)
|
||||
{
|
||||
map<const char*, const char*> result;
|
||||
if (res) {
|
||||
const int rows = PQntuples(res);
|
||||
if (rows>0 && row<rows) {
|
||||
const int num = PQnfields(res);
|
||||
if (num>0) {
|
||||
for (int i=0; i<num; i++) {
|
||||
result[PQfname(res,i)] = PQgetvalue(res,row,i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
vector<const char*> pgsql_fetch_row(const PGresult *res, int row)
|
||||
{
|
||||
vector<const char*> result;
|
||||
if (res) {
|
||||
const int rows = PQntuples(res);
|
||||
if (rows>0 && row<rows) {
|
||||
const int num = PQnfields(res);
|
||||
if (num>0) {
|
||||
for (int i=0; i<num; i++) {
|
||||
result.push_back(PQgetvalue(res,row,i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
char * pgsql_uitoa(unsigned n, char *s, int radix)
|
||||
{
|
||||
static const char tab[] =
|
||||
"0123456789abcdef";
|
||||
char *p = s;
|
||||
char *q = s;
|
||||
/* generate digits in reverse order */
|
||||
do {
|
||||
*p++ = tab[n % radix];
|
||||
n /= radix;
|
||||
} while (n != 0);
|
||||
*p-- = '\0';
|
||||
/* reverse digits */
|
||||
while (q < p) {
|
||||
int temp = *p;
|
||||
*p-- = *q;
|
||||
*q++ = temp;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
vi:ts=2
|
||||
*/
|
||||
@@ -0,0 +1,362 @@
|
||||
#include "pgsql.h"
|
||||
#include "pgsql_wrapper.h"
|
||||
#include "clog.h"
|
||||
#include <safestring.h>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
void map_to_cvars(map<const char *,const char *>f, CVars &rec)
|
||||
{
|
||||
map<const char *,const char *>::iterator it;
|
||||
for(it = f.begin(); it != f.end(); it++) {
|
||||
logfmt( logINFO, "f[%s] = %s", it->first, it->second );
|
||||
rec[it->first] = it->second;
|
||||
}
|
||||
}
|
||||
|
||||
void load_db_record( const char * table, CVars &rec, const char * where, ... )
|
||||
{
|
||||
logfmt( FLOG_MAX, "void load_db_record( const char * table, CVars &rec, const char * where, ... )");
|
||||
|
||||
size_t buf_size = 512;
|
||||
char *buffer = new char[buf_size];
|
||||
|
||||
va_list argPtr;
|
||||
size_t length;
|
||||
std::string cmd;
|
||||
|
||||
while (true) {
|
||||
if (!buffer) {
|
||||
assert(buffer); // to stop when debugging
|
||||
cmd = std::string("<alloc problem>", 16);
|
||||
break;
|
||||
}
|
||||
va_start(argPtr, where);
|
||||
length = vsnprintf(buffer, buf_size, where, argPtr);
|
||||
va_end(argPtr);
|
||||
|
||||
if (length >= 0 && length < buf_size - 1) {
|
||||
// string fits into current buffer
|
||||
cmd = std::string(buffer, length);
|
||||
break;
|
||||
}
|
||||
// otherwise resize buffer :
|
||||
buf_size *= 2;
|
||||
// fprintf(stderr, "Reallocating vstrf-buffer to size=%u\n", buf_size);
|
||||
delete [] buffer;
|
||||
buffer = new char[buf_size];
|
||||
}
|
||||
|
||||
const PGresult* res = pgsql_query("SELECT * FROM %s WHERE %s", table, cmd.c_str() );
|
||||
|
||||
if( buffer ) delete [] buffer;
|
||||
|
||||
if (!res || pgsql_num_rows(res)!=1) return;
|
||||
|
||||
map<const char*,const char*>f = pgsql_fetch_assoc(res, 0);
|
||||
logfmt( FLOG_MAX, "load_db_record(%s) num_cols=%d", table, f.size() );
|
||||
if (f.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
map<const char *,const char *>::iterator it;
|
||||
for(it = f.begin(); it != f.end(); it++) {
|
||||
rec[ it->first ] = it->second;
|
||||
}
|
||||
}
|
||||
|
||||
// This function now supports binary data
|
||||
long load_db_record( CVars &rec, const char * query, ... )
|
||||
{
|
||||
logfmt( FLOG_MAX, "long load_db_record( CVars &rec, const char * query, ... )");
|
||||
|
||||
size_t buf_size = 512;
|
||||
char *buffer = new char[buf_size];
|
||||
|
||||
va_list argPtr;
|
||||
size_t length;
|
||||
std::string cmd;
|
||||
|
||||
while (true) {
|
||||
if (!buffer) {
|
||||
assert(buffer); // to stop when debugging
|
||||
cmd = std::string("<alloc problem>", 16);
|
||||
break;
|
||||
}
|
||||
va_start(argPtr, query);
|
||||
length = vsnprintf(buffer, buf_size, query, argPtr);
|
||||
va_end(argPtr);
|
||||
|
||||
if (length >= 0 && length < buf_size - 1) {
|
||||
// string fits into current buffer
|
||||
cmd = std::string(buffer, length);
|
||||
break;
|
||||
}
|
||||
// otherwise resize buffer :
|
||||
buf_size *= 2;
|
||||
// fprintf(stderr, "Reallocating vstrf-buffer to size=%u\n", buf_size);
|
||||
delete [] buffer;
|
||||
buffer = new char[buf_size];
|
||||
}
|
||||
|
||||
const PGresult* res = pgsql_query("%s", cmd.c_str() );
|
||||
|
||||
if( buffer ) delete [] buffer;
|
||||
|
||||
if (!res || pgsql_num_rows(res)!=1) return -1l;
|
||||
|
||||
map<const char*,const char*>f = pgsql_fetch_assoc(res, 0);
|
||||
logfmt( FLOG_MAX, "load_db_record(%s) num_cols=%d", cmd.c_str(), f.size() );
|
||||
if (f.empty()) {
|
||||
return 0l;
|
||||
}
|
||||
|
||||
map<const char *,const char *>::iterator it;
|
||||
for(it = f.begin(); it != f.end(); it++) {
|
||||
rec[ it->first ] = it->second;
|
||||
}
|
||||
return 1l;
|
||||
}
|
||||
|
||||
|
||||
#define MAX_BINARY_PARS 20
|
||||
|
||||
long insert_db_record( int mode, const char *table, const char *seq, CVars &rec )
|
||||
{
|
||||
CVars::const_iterator i;
|
||||
char cmd[128]; /*cols[1024], vals[1024]; cols[0] = 0; vals[0] = 0;*/
|
||||
bool first = true;
|
||||
string cols, vals;
|
||||
int bind_i = 0;
|
||||
long int sz[MAX_BINARY_PARS]; bzero( sz, sizeof(sz) ); // provides binding for all binary columns simultaneously
|
||||
int binary_i = 0;
|
||||
|
||||
logfmt( FLOG_MAX, "insert_db_record()" );
|
||||
|
||||
snprintf( cmd, sizeof(cmd), "INSERT INTO %s (%%s) VALUES (%%s)", table );
|
||||
|
||||
for ( i=rec.begin(); i != rec.end(); i++ )
|
||||
{
|
||||
NEED_ESC;
|
||||
// logfmt( FLOG_MAX, "'%s': i->second.valid()=%d, db()=%d", i->first.c_str(), i->second.valid(), i->second.db() );
|
||||
|
||||
if ( (DBS_VALID & mode) && !i->second.valid() ) continue;
|
||||
if ( (DBS_STREAM & mode ) && !i->second.db() ) continue;
|
||||
//logfmt( FLOG_MAX, "insert_db_record(): %s = %s", i->first.c_str(), i->second.c_str() );
|
||||
|
||||
cols += string(first?"":",") + i->first;
|
||||
if ( !first ) vals += ",";
|
||||
|
||||
if ( i->second.binary() )
|
||||
{
|
||||
/*
|
||||
vals += '?';
|
||||
sz[binary_i] = i->second.size();
|
||||
char *data = (char*)i->second.data();
|
||||
|
||||
//logfmt( FLOG_MAX, "saving binary parameter '%s', len = %d", i->first.c_str(), i->second.size() );
|
||||
|
||||
SQLBindParameter( st.hstmt, ++bind_i, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_VARBINARY, sz[binary_i], 0, data, sz[binary_i], &sz[binary_i] );
|
||||
|
||||
if ( binary_i++ == MAX_BINARY_PARS )
|
||||
{
|
||||
logfmt( FLOG_MAX, "Exceeded maximum allowed binary parameters" );
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
throw err("Binary parameters are not supported");
|
||||
}
|
||||
else
|
||||
vals += string("E'") + esc(i->second.c_str()) + "'";
|
||||
|
||||
/*strcatf( cols, sizeof(cols), "%s%s", first?"":",", i->first.c_str() );
|
||||
strcatf( vals, sizeof(vals), "%s'%s'", first?"":",", i->second.c_str() );*/
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
int res = pgsql_exec( cmd, cols.c_str(), vals.c_str() );
|
||||
|
||||
return curr_val( seq );
|
||||
}
|
||||
|
||||
|
||||
void update_db_record( int mode, const char * table, CVars &rec, long id, const char * where, ... ) throw ( bad_parameter )
|
||||
{
|
||||
va_list ap;
|
||||
va_start( ap, where );
|
||||
v_update_db_record( mode, table, rec, "id", id, where, ap );
|
||||
va_end( ap );
|
||||
}
|
||||
|
||||
|
||||
void update_db_record( int mode, const char * table, CVars &rec, const char *index, long id, const char * where, ... ) throw ( bad_parameter )
|
||||
{
|
||||
va_list ap;
|
||||
va_start( ap, where );
|
||||
v_update_db_record( mode, table, rec, index, id, where, ap );
|
||||
va_end( ap );
|
||||
}
|
||||
|
||||
void v_update_db_record( int mode, const char * table, CVars &rec, const char *index, long id, const char * where, va_list ap ) throw ( bad_parameter )
|
||||
{
|
||||
logfmt( FLOG_MAX, "update_db_record()" );
|
||||
int bind_i = 0;
|
||||
|
||||
if ( !id ) throw bad_parameter( rec, "id" );
|
||||
|
||||
CVars::const_iterator i;
|
||||
char cmd[128];
|
||||
bool first = true;
|
||||
string cols;
|
||||
char * wherestr;
|
||||
|
||||
snprintf( cmd, sizeof(cmd), "UPDATE %s SET %%s WHERE %s=%lu AND %%s", table, index, id );
|
||||
|
||||
for ( i=rec.begin(); i != rec.end(); i++ )
|
||||
{
|
||||
NEED_ESC;
|
||||
if ( !i->second.valid() ) continue;
|
||||
if ( (DBS_STREAM & mode) && !i->second.db() ) continue;
|
||||
|
||||
cols += string(first?"":",") + i->first + "=";
|
||||
|
||||
if ( ! i->second.binary() )
|
||||
cols += string("E'") + esc(i->second.c_str()) + "'";
|
||||
else
|
||||
{
|
||||
/*
|
||||
cols += "?";
|
||||
long int sz = i->second.size();
|
||||
char *data = (char*)i->second.data();
|
||||
|
||||
SQLBindParameter( st.hstmt, ++bind_i, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_VARBINARY, sz, 0, data, sz, &sz );
|
||||
*/
|
||||
throw err("Binary data is not supported");
|
||||
}
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
if ( where )
|
||||
{
|
||||
int size = vsnprintf( NULL, 0, where, ap ) + 1;
|
||||
wherestr = (char*)malloc( size );
|
||||
if ( !wherestr ) throw err("malloc() error");
|
||||
vsnprintf( wherestr, size, where, ap );
|
||||
}
|
||||
|
||||
int rows = pgsql_exec( cmd, cols.c_str(), where?wherestr:"true" );
|
||||
if ( where )
|
||||
free( wherestr );
|
||||
|
||||
if ( rows!=1 ) throw bad_parameter( rec, "id" );
|
||||
}
|
||||
|
||||
long curr_val( const char *seq )
|
||||
{
|
||||
long size = 20+strlen(seq);
|
||||
char cmd[size];
|
||||
snprintf( cmd, size, "SELECT currval('%s')", seq );
|
||||
logfmt( FLOG_MAX, "%s", cmd);
|
||||
const PGresult* res = pgsql_query( cmd );
|
||||
if (res && pgsql_num_rows(res)>0) {
|
||||
vector<const char *>f = pgsql_fetch_row(res,0);
|
||||
if (!f.empty() && f.size()>0) {
|
||||
return atol(f[0]);
|
||||
}
|
||||
}
|
||||
logfmt( FLOG_MAX, "SQL error" );
|
||||
return -1l;
|
||||
}
|
||||
|
||||
//---------------------------- class CEscape ----------------
|
||||
|
||||
char * CEscape::New( int sz )
|
||||
{
|
||||
if ( ESCAPE_MAX_VARS==n )
|
||||
{
|
||||
logfmt( FLOG_MAX, "CEscape::New() Maximum number of variables reached" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vars[n] = new char[sz];
|
||||
n++;
|
||||
|
||||
return vars[n-1];
|
||||
}
|
||||
|
||||
CEscape::CEscape( char * st )
|
||||
{
|
||||
n = 0;
|
||||
this->st = st;
|
||||
}
|
||||
|
||||
CEscape::~CEscape()
|
||||
{
|
||||
for ( int i=0; i<n; i++ )
|
||||
delete vars[i];
|
||||
n = 0;
|
||||
}
|
||||
|
||||
char * CEscape::Escape( const char * param )
|
||||
{
|
||||
if ( !param ) return NULL;
|
||||
int len = this->EscapeLength(param);
|
||||
return this->EscapeReal( param, New(len), len );
|
||||
}
|
||||
|
||||
int CEscape::EscapeLength( const char * par )
|
||||
{
|
||||
if ( !par ) return 0;
|
||||
|
||||
int i, len = strlen(par), extra = 0;
|
||||
|
||||
for ( i=0; i<len; i++ )
|
||||
if ( par[i]=='\'' || par[i]=='\\' )
|
||||
extra++;
|
||||
|
||||
return len+extra+1;
|
||||
}
|
||||
|
||||
char * CEscape::EscapeReal( const char * cmd, char * _esc, int sz )
|
||||
{
|
||||
char * c, * c1, * d, *dend;
|
||||
char * esc = _esc?_esc:this->esc;
|
||||
|
||||
if (!sz) sz = sizeof(this->esc);
|
||||
|
||||
c = (char*)cmd; esc[0] = 0; d = esc; dend = d+sz;
|
||||
|
||||
if ( !cmd ) return esc;
|
||||
|
||||
// LOG( cmd, LOG_MAX );
|
||||
|
||||
while ( c<cmd+strlen(cmd) )
|
||||
{
|
||||
c1 = c + strcspn( c, "'\\" ); // apostrophe and backslash
|
||||
|
||||
if ( !*c1 )
|
||||
{
|
||||
strsafecpy( d, c, dend-d );
|
||||
break;
|
||||
}
|
||||
|
||||
strnsafecpy( d, c, c1-c, dend-d );
|
||||
d += strlen(d);
|
||||
//if (*(c1+0)=='\'') strcatf( d, dend-d, "'%c", *c1 );
|
||||
strcatf( d, dend-d, "\\%c", *c1 );
|
||||
d += strlen(d);
|
||||
c = c1+1;
|
||||
}
|
||||
|
||||
// LOG( esc, LOG_MAX );
|
||||
|
||||
return esc;
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
#include "safestring.h"
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
char * strsafecpy( char * dest, const char * src, int size )
|
||||
{
|
||||
if ( src==dest ) return dest;
|
||||
if ( size<=0 ) return dest;
|
||||
dest[0] = 0;
|
||||
if ( !src ) return dest;
|
||||
|
||||
int len = strlen( src );
|
||||
|
||||
if ( len>=size )
|
||||
len = size-1; // to be safe
|
||||
|
||||
strncpy( dest, src, len );
|
||||
dest[ len ] = 0;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
char * strnsafecpy( char * dest, const char * src, int n, int size )
|
||||
{
|
||||
if ( size<=0 ) return dest;
|
||||
dest[0] = 0;
|
||||
if ( !src ) return dest;
|
||||
|
||||
if ( n>=size )
|
||||
n = size-1;
|
||||
|
||||
strncpy( dest, src, n );
|
||||
dest[ n ] = 0;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
char * strsafecat( char * dest, const char * src, int size )
|
||||
{
|
||||
int len = strlen( src );
|
||||
int start = strlen(dest);
|
||||
size -= start;
|
||||
|
||||
if ( len>=size )
|
||||
len = size-1; // to be safe
|
||||
|
||||
strncat( dest, src, len );
|
||||
dest[ start+len ] = 0;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
char * strnsafecat( char * dest, const char * src, int n, int size )
|
||||
{
|
||||
int len = strlen( src );
|
||||
if ( n<len ) len = n;
|
||||
|
||||
int start = strlen(dest);
|
||||
size -= start;
|
||||
|
||||
if ( len>=size )
|
||||
len = size-1; // to be safe
|
||||
|
||||
strncat( dest, src, len );
|
||||
dest[ start+len ] = 0;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
char * strcatf( char * dest, int size, const char * fmt, ... )
|
||||
{
|
||||
va_list ap;
|
||||
va_start( ap, fmt );
|
||||
|
||||
int len = strlen( dest );
|
||||
|
||||
if ( size-len > 0 )
|
||||
vsnprintf( &dest[len], size-len, fmt, ap );
|
||||
|
||||
dest[ size-1 ] = 0;
|
||||
|
||||
va_end( ap );
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
char * toupper( char * s, char * dest/*=NULL*/, int sz/*=0*/ )
|
||||
{
|
||||
if (!s) return NULL;
|
||||
char *c = s;
|
||||
char *d = dest?dest:s;
|
||||
|
||||
while (*c) {
|
||||
if (d-dest>=sz-1) break;
|
||||
*d = toupper(*c);
|
||||
c++; d++;
|
||||
}
|
||||
|
||||
*d = 0;
|
||||
|
||||
return dest?dest:s;
|
||||
}
|
||||
|
||||
char * tolower( char * s, char * dest/*=NULL*/, int sz/*=0*/ )
|
||||
{
|
||||
if (!s) return NULL;
|
||||
char *c = s;
|
||||
char *d = dest?dest:s;
|
||||
|
||||
while (*c) {
|
||||
if ( dest && (d-dest>=sz-1) ) break;
|
||||
*d = tolower(*c);
|
||||
c++; d++;
|
||||
}
|
||||
|
||||
*d = 0;
|
||||
|
||||
return dest?dest:s;
|
||||
}
|
||||
|
||||
|
||||
char * toupper( const char * s, char * dest, int sz )
|
||||
{
|
||||
return toupper( (char*)s, dest, sz );
|
||||
}
|
||||
|
||||
|
||||
char * tolower( const char * s, char * dest, int sz )
|
||||
{
|
||||
return tolower( (char*)s, dest, sz );
|
||||
}
|
||||
|
||||
|
||||
char * last_line( char * buf ) // find the last line and return the pointer to its beginning
|
||||
{
|
||||
char * line = buf, *bufend = buf + strlen(buf);
|
||||
|
||||
while ( char * c = strpbrk( line, "\r\n" ) )
|
||||
{
|
||||
c += strspn( c, "\r\n" );
|
||||
|
||||
if ( c==bufend )
|
||||
return line;
|
||||
|
||||
line = c;
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
|
||||
char * safestrdup( const char *s )
|
||||
{
|
||||
return s ? strdup( s ) : NULL;
|
||||
}
|
||||
|
||||
|
||||
char * strreverse( char *s )
|
||||
{
|
||||
int len = strlen(s);
|
||||
int end = len/2;
|
||||
unsigned char c;
|
||||
|
||||
for ( int i=0; i<end; i++ )
|
||||
{
|
||||
c = s[i];
|
||||
s[i] = s[len-i-1];
|
||||
s[len-i-1] = c;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,950 @@
|
||||
/*
|
||||
* FIPS 180-2 SHA-224/256/384/512 implementation
|
||||
* Last update: 02/02/2007
|
||||
* Issue date: 04/30/2005
|
||||
*
|
||||
* Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#define UNROLL_LOOPS /* Enable loops unrolling */
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "sha2.h"
|
||||
|
||||
#define SHFR(x, n) (x >> n)
|
||||
#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
|
||||
#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
|
||||
#define CH(x, y, z) ((x & y) ^ (~x & z))
|
||||
#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
|
||||
|
||||
#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
|
||||
#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
|
||||
#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))
|
||||
#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
|
||||
|
||||
#define SHA512_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
|
||||
#define SHA512_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
|
||||
#define SHA512_F3(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHFR(x, 7))
|
||||
#define SHA512_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x, 6))
|
||||
|
||||
#define UNPACK32(x, str) \
|
||||
{ \
|
||||
*((str) + 3) = (uint8) ((x) ); \
|
||||
*((str) + 2) = (uint8) ((x) >> 8); \
|
||||
*((str) + 1) = (uint8) ((x) >> 16); \
|
||||
*((str) + 0) = (uint8) ((x) >> 24); \
|
||||
}
|
||||
|
||||
#define PACK32(str, x) \
|
||||
{ \
|
||||
*(x) = ((uint32) *((str) + 3) ) \
|
||||
| ((uint32) *((str) + 2) << 8) \
|
||||
| ((uint32) *((str) + 1) << 16) \
|
||||
| ((uint32) *((str) + 0) << 24); \
|
||||
}
|
||||
|
||||
#define UNPACK64(x, str) \
|
||||
{ \
|
||||
*((str) + 7) = (uint8) ((x) ); \
|
||||
*((str) + 6) = (uint8) ((x) >> 8); \
|
||||
*((str) + 5) = (uint8) ((x) >> 16); \
|
||||
*((str) + 4) = (uint8) ((x) >> 24); \
|
||||
*((str) + 3) = (uint8) ((x) >> 32); \
|
||||
*((str) + 2) = (uint8) ((x) >> 40); \
|
||||
*((str) + 1) = (uint8) ((x) >> 48); \
|
||||
*((str) + 0) = (uint8) ((x) >> 56); \
|
||||
}
|
||||
|
||||
#define PACK64(str, x) \
|
||||
{ \
|
||||
*(x) = ((uint64) *((str) + 7) ) \
|
||||
| ((uint64) *((str) + 6) << 8) \
|
||||
| ((uint64) *((str) + 5) << 16) \
|
||||
| ((uint64) *((str) + 4) << 24) \
|
||||
| ((uint64) *((str) + 3) << 32) \
|
||||
| ((uint64) *((str) + 2) << 40) \
|
||||
| ((uint64) *((str) + 1) << 48) \
|
||||
| ((uint64) *((str) + 0) << 56); \
|
||||
}
|
||||
|
||||
/* Macros used for loops unrolling */
|
||||
|
||||
#define SHA256_SCR(i) \
|
||||
{ \
|
||||
w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \
|
||||
+ SHA256_F3(w[i - 15]) + w[i - 16]; \
|
||||
}
|
||||
|
||||
#define SHA512_SCR(i) \
|
||||
{ \
|
||||
w[i] = SHA512_F4(w[i - 2]) + w[i - 7] \
|
||||
+ SHA512_F3(w[i - 15]) + w[i - 16]; \
|
||||
}
|
||||
|
||||
#define SHA256_EXP(a, b, c, d, e, f, g, h, j) \
|
||||
{ \
|
||||
t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
|
||||
+ sha256_k[j] + w[j]; \
|
||||
t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
|
||||
wv[d] += t1; \
|
||||
wv[h] = t1 + t2; \
|
||||
}
|
||||
|
||||
#define SHA512_EXP(a, b, c, d, e, f, g ,h, j) \
|
||||
{ \
|
||||
t1 = wv[h] + SHA512_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
|
||||
+ sha512_k[j] + w[j]; \
|
||||
t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
|
||||
wv[d] += t1; \
|
||||
wv[h] = t1 + t2; \
|
||||
}
|
||||
|
||||
uint32 sha224_h0[8] =
|
||||
{0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
|
||||
0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4};
|
||||
|
||||
uint32 sha256_h0[8] =
|
||||
{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
||||
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
|
||||
|
||||
uint64 sha384_h0[8] =
|
||||
{0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL,
|
||||
0x9159015a3070dd17ULL, 0x152fecd8f70e5939ULL,
|
||||
0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL,
|
||||
0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL};
|
||||
|
||||
uint64 sha512_h0[8] =
|
||||
{0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
|
||||
0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
|
||||
0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
|
||||
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL};
|
||||
|
||||
uint32 sha256_k[64] =
|
||||
{0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
|
||||
|
||||
uint64 sha512_k[80] =
|
||||
{0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
|
||||
0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
|
||||
0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
|
||||
0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
|
||||
0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
|
||||
0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
|
||||
0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
|
||||
0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
|
||||
0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
|
||||
0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
|
||||
0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
|
||||
0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
|
||||
0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
|
||||
0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
|
||||
0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
|
||||
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
|
||||
0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
|
||||
0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
|
||||
0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
|
||||
0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
|
||||
0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
|
||||
0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
|
||||
0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
|
||||
0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
|
||||
0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
|
||||
0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
|
||||
0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
|
||||
0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
|
||||
0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
|
||||
0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
|
||||
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
|
||||
0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
|
||||
0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
|
||||
0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
|
||||
0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
|
||||
0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
|
||||
0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
|
||||
0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
|
||||
0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
|
||||
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
|
||||
|
||||
/* SHA-256 functions */
|
||||
|
||||
void sha256_transf(sha256_ctx *ctx, const unsigned char *message,
|
||||
unsigned int block_nb)
|
||||
{
|
||||
uint32 w[64];
|
||||
uint32 wv[8];
|
||||
uint32 t1, t2;
|
||||
const unsigned char *sub_block;
|
||||
int i;
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
int j;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < (int) block_nb; i++) {
|
||||
sub_block = message + (i << 6);
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
for (j = 0; j < 16; j++) {
|
||||
PACK32(&sub_block[j << 2], &w[j]);
|
||||
}
|
||||
|
||||
for (j = 16; j < 64; j++) {
|
||||
SHA256_SCR(j);
|
||||
}
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
wv[j] = ctx->h[j];
|
||||
}
|
||||
|
||||
for (j = 0; j < 64; j++) {
|
||||
t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
|
||||
+ sha256_k[j] + w[j];
|
||||
t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
|
||||
wv[7] = wv[6];
|
||||
wv[6] = wv[5];
|
||||
wv[5] = wv[4];
|
||||
wv[4] = wv[3] + t1;
|
||||
wv[3] = wv[2];
|
||||
wv[2] = wv[1];
|
||||
wv[1] = wv[0];
|
||||
wv[0] = t1 + t2;
|
||||
}
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
ctx->h[j] += wv[j];
|
||||
}
|
||||
#else
|
||||
PACK32(&sub_block[ 0], &w[ 0]); PACK32(&sub_block[ 4], &w[ 1]);
|
||||
PACK32(&sub_block[ 8], &w[ 2]); PACK32(&sub_block[12], &w[ 3]);
|
||||
PACK32(&sub_block[16], &w[ 4]); PACK32(&sub_block[20], &w[ 5]);
|
||||
PACK32(&sub_block[24], &w[ 6]); PACK32(&sub_block[28], &w[ 7]);
|
||||
PACK32(&sub_block[32], &w[ 8]); PACK32(&sub_block[36], &w[ 9]);
|
||||
PACK32(&sub_block[40], &w[10]); PACK32(&sub_block[44], &w[11]);
|
||||
PACK32(&sub_block[48], &w[12]); PACK32(&sub_block[52], &w[13]);
|
||||
PACK32(&sub_block[56], &w[14]); PACK32(&sub_block[60], &w[15]);
|
||||
|
||||
SHA256_SCR(16); SHA256_SCR(17); SHA256_SCR(18); SHA256_SCR(19);
|
||||
SHA256_SCR(20); SHA256_SCR(21); SHA256_SCR(22); SHA256_SCR(23);
|
||||
SHA256_SCR(24); SHA256_SCR(25); SHA256_SCR(26); SHA256_SCR(27);
|
||||
SHA256_SCR(28); SHA256_SCR(29); SHA256_SCR(30); SHA256_SCR(31);
|
||||
SHA256_SCR(32); SHA256_SCR(33); SHA256_SCR(34); SHA256_SCR(35);
|
||||
SHA256_SCR(36); SHA256_SCR(37); SHA256_SCR(38); SHA256_SCR(39);
|
||||
SHA256_SCR(40); SHA256_SCR(41); SHA256_SCR(42); SHA256_SCR(43);
|
||||
SHA256_SCR(44); SHA256_SCR(45); SHA256_SCR(46); SHA256_SCR(47);
|
||||
SHA256_SCR(48); SHA256_SCR(49); SHA256_SCR(50); SHA256_SCR(51);
|
||||
SHA256_SCR(52); SHA256_SCR(53); SHA256_SCR(54); SHA256_SCR(55);
|
||||
SHA256_SCR(56); SHA256_SCR(57); SHA256_SCR(58); SHA256_SCR(59);
|
||||
SHA256_SCR(60); SHA256_SCR(61); SHA256_SCR(62); SHA256_SCR(63);
|
||||
|
||||
wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
|
||||
wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
|
||||
wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
|
||||
wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
|
||||
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7, 0); SHA256_EXP(7,0,1,2,3,4,5,6, 1);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5, 2); SHA256_EXP(5,6,7,0,1,2,3,4, 3);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3, 4); SHA256_EXP(3,4,5,6,7,0,1,2, 5);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1, 6); SHA256_EXP(1,2,3,4,5,6,7,0, 7);
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7, 8); SHA256_EXP(7,0,1,2,3,4,5,6, 9);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5,10); SHA256_EXP(5,6,7,0,1,2,3,4,11);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3,12); SHA256_EXP(3,4,5,6,7,0,1,2,13);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1,14); SHA256_EXP(1,2,3,4,5,6,7,0,15);
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7,16); SHA256_EXP(7,0,1,2,3,4,5,6,17);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5,18); SHA256_EXP(5,6,7,0,1,2,3,4,19);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3,20); SHA256_EXP(3,4,5,6,7,0,1,2,21);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1,22); SHA256_EXP(1,2,3,4,5,6,7,0,23);
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7,24); SHA256_EXP(7,0,1,2,3,4,5,6,25);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5,26); SHA256_EXP(5,6,7,0,1,2,3,4,27);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3,28); SHA256_EXP(3,4,5,6,7,0,1,2,29);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1,30); SHA256_EXP(1,2,3,4,5,6,7,0,31);
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7,32); SHA256_EXP(7,0,1,2,3,4,5,6,33);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5,34); SHA256_EXP(5,6,7,0,1,2,3,4,35);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3,36); SHA256_EXP(3,4,5,6,7,0,1,2,37);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1,38); SHA256_EXP(1,2,3,4,5,6,7,0,39);
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7,40); SHA256_EXP(7,0,1,2,3,4,5,6,41);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5,42); SHA256_EXP(5,6,7,0,1,2,3,4,43);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3,44); SHA256_EXP(3,4,5,6,7,0,1,2,45);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1,46); SHA256_EXP(1,2,3,4,5,6,7,0,47);
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7,48); SHA256_EXP(7,0,1,2,3,4,5,6,49);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5,50); SHA256_EXP(5,6,7,0,1,2,3,4,51);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3,52); SHA256_EXP(3,4,5,6,7,0,1,2,53);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1,54); SHA256_EXP(1,2,3,4,5,6,7,0,55);
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7,56); SHA256_EXP(7,0,1,2,3,4,5,6,57);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5,58); SHA256_EXP(5,6,7,0,1,2,3,4,59);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3,60); SHA256_EXP(3,4,5,6,7,0,1,2,61);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1,62); SHA256_EXP(1,2,3,4,5,6,7,0,63);
|
||||
|
||||
ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
|
||||
ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
|
||||
ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
|
||||
ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
}
|
||||
}
|
||||
|
||||
void sha256(const unsigned char *message, unsigned int len, unsigned char *digest)
|
||||
{
|
||||
sha256_ctx ctx;
|
||||
|
||||
sha256_init(&ctx);
|
||||
sha256_update(&ctx, message, len);
|
||||
sha256_final(&ctx, digest);
|
||||
}
|
||||
|
||||
void sha256_init(sha256_ctx *ctx)
|
||||
{
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
ctx->h[i] = sha256_h0[i];
|
||||
}
|
||||
#else
|
||||
ctx->h[0] = sha256_h0[0]; ctx->h[1] = sha256_h0[1];
|
||||
ctx->h[2] = sha256_h0[2]; ctx->h[3] = sha256_h0[3];
|
||||
ctx->h[4] = sha256_h0[4]; ctx->h[5] = sha256_h0[5];
|
||||
ctx->h[6] = sha256_h0[6]; ctx->h[7] = sha256_h0[7];
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
|
||||
ctx->len = 0;
|
||||
ctx->tot_len = 0;
|
||||
}
|
||||
|
||||
void sha256_update(sha256_ctx *ctx, const unsigned char *message,
|
||||
unsigned int len)
|
||||
{
|
||||
unsigned int block_nb;
|
||||
unsigned int new_len, rem_len, tmp_len;
|
||||
const unsigned char *shifted_message;
|
||||
|
||||
tmp_len = SHA256_BLOCK_SIZE - ctx->len;
|
||||
rem_len = len < tmp_len ? len : tmp_len;
|
||||
|
||||
memcpy(&ctx->block[ctx->len], message, rem_len);
|
||||
|
||||
if (ctx->len + len < SHA256_BLOCK_SIZE) {
|
||||
ctx->len += len;
|
||||
return;
|
||||
}
|
||||
|
||||
new_len = len - rem_len;
|
||||
block_nb = new_len / SHA256_BLOCK_SIZE;
|
||||
|
||||
shifted_message = message + rem_len;
|
||||
|
||||
sha256_transf(ctx, ctx->block, 1);
|
||||
sha256_transf(ctx, shifted_message, block_nb);
|
||||
|
||||
rem_len = new_len % SHA256_BLOCK_SIZE;
|
||||
|
||||
memcpy(ctx->block, &shifted_message[block_nb << 6],
|
||||
rem_len);
|
||||
|
||||
ctx->len = rem_len;
|
||||
ctx->tot_len += (block_nb + 1) << 6;
|
||||
}
|
||||
|
||||
void sha256_final(sha256_ctx *ctx, unsigned char *digest)
|
||||
{
|
||||
unsigned int block_nb;
|
||||
unsigned int pm_len;
|
||||
unsigned int len_b;
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
#endif
|
||||
|
||||
block_nb = (1 + ((SHA256_BLOCK_SIZE - 9)
|
||||
< (ctx->len % SHA256_BLOCK_SIZE)));
|
||||
|
||||
len_b = (ctx->tot_len + ctx->len) << 3;
|
||||
pm_len = block_nb << 6;
|
||||
|
||||
memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
|
||||
ctx->block[ctx->len] = 0x80;
|
||||
UNPACK32(len_b, ctx->block + pm_len - 4);
|
||||
|
||||
sha256_transf(ctx, ctx->block, block_nb);
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
for (i = 0 ; i < 8; i++) {
|
||||
UNPACK32(ctx->h[i], &digest[i << 2]);
|
||||
}
|
||||
#else
|
||||
UNPACK32(ctx->h[0], &digest[ 0]);
|
||||
UNPACK32(ctx->h[1], &digest[ 4]);
|
||||
UNPACK32(ctx->h[2], &digest[ 8]);
|
||||
UNPACK32(ctx->h[3], &digest[12]);
|
||||
UNPACK32(ctx->h[4], &digest[16]);
|
||||
UNPACK32(ctx->h[5], &digest[20]);
|
||||
UNPACK32(ctx->h[6], &digest[24]);
|
||||
UNPACK32(ctx->h[7], &digest[28]);
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
}
|
||||
|
||||
/* SHA-512 functions */
|
||||
|
||||
void sha512_transf(sha512_ctx *ctx, const unsigned char *message,
|
||||
unsigned int block_nb)
|
||||
{
|
||||
uint64 w[80];
|
||||
uint64 wv[8];
|
||||
uint64 t1, t2;
|
||||
const unsigned char *sub_block;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < (int) block_nb; i++) {
|
||||
sub_block = message + (i << 7);
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
for (j = 0; j < 16; j++) {
|
||||
PACK64(&sub_block[j << 3], &w[j]);
|
||||
}
|
||||
|
||||
for (j = 16; j < 80; j++) {
|
||||
SHA512_SCR(j);
|
||||
}
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
wv[j] = ctx->h[j];
|
||||
}
|
||||
|
||||
for (j = 0; j < 80; j++) {
|
||||
t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
|
||||
+ sha512_k[j] + w[j];
|
||||
t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
|
||||
wv[7] = wv[6];
|
||||
wv[6] = wv[5];
|
||||
wv[5] = wv[4];
|
||||
wv[4] = wv[3] + t1;
|
||||
wv[3] = wv[2];
|
||||
wv[2] = wv[1];
|
||||
wv[1] = wv[0];
|
||||
wv[0] = t1 + t2;
|
||||
}
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
ctx->h[j] += wv[j];
|
||||
}
|
||||
#else
|
||||
PACK64(&sub_block[ 0], &w[ 0]); PACK64(&sub_block[ 8], &w[ 1]);
|
||||
PACK64(&sub_block[ 16], &w[ 2]); PACK64(&sub_block[ 24], &w[ 3]);
|
||||
PACK64(&sub_block[ 32], &w[ 4]); PACK64(&sub_block[ 40], &w[ 5]);
|
||||
PACK64(&sub_block[ 48], &w[ 6]); PACK64(&sub_block[ 56], &w[ 7]);
|
||||
PACK64(&sub_block[ 64], &w[ 8]); PACK64(&sub_block[ 72], &w[ 9]);
|
||||
PACK64(&sub_block[ 80], &w[10]); PACK64(&sub_block[ 88], &w[11]);
|
||||
PACK64(&sub_block[ 96], &w[12]); PACK64(&sub_block[104], &w[13]);
|
||||
PACK64(&sub_block[112], &w[14]); PACK64(&sub_block[120], &w[15]);
|
||||
|
||||
SHA512_SCR(16); SHA512_SCR(17); SHA512_SCR(18); SHA512_SCR(19);
|
||||
SHA512_SCR(20); SHA512_SCR(21); SHA512_SCR(22); SHA512_SCR(23);
|
||||
SHA512_SCR(24); SHA512_SCR(25); SHA512_SCR(26); SHA512_SCR(27);
|
||||
SHA512_SCR(28); SHA512_SCR(29); SHA512_SCR(30); SHA512_SCR(31);
|
||||
SHA512_SCR(32); SHA512_SCR(33); SHA512_SCR(34); SHA512_SCR(35);
|
||||
SHA512_SCR(36); SHA512_SCR(37); SHA512_SCR(38); SHA512_SCR(39);
|
||||
SHA512_SCR(40); SHA512_SCR(41); SHA512_SCR(42); SHA512_SCR(43);
|
||||
SHA512_SCR(44); SHA512_SCR(45); SHA512_SCR(46); SHA512_SCR(47);
|
||||
SHA512_SCR(48); SHA512_SCR(49); SHA512_SCR(50); SHA512_SCR(51);
|
||||
SHA512_SCR(52); SHA512_SCR(53); SHA512_SCR(54); SHA512_SCR(55);
|
||||
SHA512_SCR(56); SHA512_SCR(57); SHA512_SCR(58); SHA512_SCR(59);
|
||||
SHA512_SCR(60); SHA512_SCR(61); SHA512_SCR(62); SHA512_SCR(63);
|
||||
SHA512_SCR(64); SHA512_SCR(65); SHA512_SCR(66); SHA512_SCR(67);
|
||||
SHA512_SCR(68); SHA512_SCR(69); SHA512_SCR(70); SHA512_SCR(71);
|
||||
SHA512_SCR(72); SHA512_SCR(73); SHA512_SCR(74); SHA512_SCR(75);
|
||||
SHA512_SCR(76); SHA512_SCR(77); SHA512_SCR(78); SHA512_SCR(79);
|
||||
|
||||
wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
|
||||
wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
|
||||
wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
|
||||
wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
|
||||
|
||||
j = 0;
|
||||
|
||||
do {
|
||||
SHA512_EXP(0,1,2,3,4,5,6,7,j); j++;
|
||||
SHA512_EXP(7,0,1,2,3,4,5,6,j); j++;
|
||||
SHA512_EXP(6,7,0,1,2,3,4,5,j); j++;
|
||||
SHA512_EXP(5,6,7,0,1,2,3,4,j); j++;
|
||||
SHA512_EXP(4,5,6,7,0,1,2,3,j); j++;
|
||||
SHA512_EXP(3,4,5,6,7,0,1,2,j); j++;
|
||||
SHA512_EXP(2,3,4,5,6,7,0,1,j); j++;
|
||||
SHA512_EXP(1,2,3,4,5,6,7,0,j); j++;
|
||||
} while (j < 80);
|
||||
|
||||
ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
|
||||
ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
|
||||
ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
|
||||
ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
}
|
||||
}
|
||||
|
||||
void sha512(const unsigned char *message, unsigned int len,
|
||||
unsigned char *digest)
|
||||
{
|
||||
sha512_ctx ctx;
|
||||
|
||||
sha512_init(&ctx);
|
||||
sha512_update(&ctx, message, len);
|
||||
sha512_final(&ctx, digest);
|
||||
}
|
||||
|
||||
void sha512_init(sha512_ctx *ctx)
|
||||
{
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
ctx->h[i] = sha512_h0[i];
|
||||
}
|
||||
#else
|
||||
ctx->h[0] = sha512_h0[0]; ctx->h[1] = sha512_h0[1];
|
||||
ctx->h[2] = sha512_h0[2]; ctx->h[3] = sha512_h0[3];
|
||||
ctx->h[4] = sha512_h0[4]; ctx->h[5] = sha512_h0[5];
|
||||
ctx->h[6] = sha512_h0[6]; ctx->h[7] = sha512_h0[7];
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
|
||||
ctx->len = 0;
|
||||
ctx->tot_len = 0;
|
||||
}
|
||||
|
||||
void sha512_update(sha512_ctx *ctx, const unsigned char *message,
|
||||
unsigned int len)
|
||||
{
|
||||
unsigned int block_nb;
|
||||
unsigned int new_len, rem_len, tmp_len;
|
||||
const unsigned char *shifted_message;
|
||||
|
||||
tmp_len = SHA512_BLOCK_SIZE - ctx->len;
|
||||
rem_len = len < tmp_len ? len : tmp_len;
|
||||
|
||||
memcpy(&ctx->block[ctx->len], message, rem_len);
|
||||
|
||||
if (ctx->len + len < SHA512_BLOCK_SIZE) {
|
||||
ctx->len += len;
|
||||
return;
|
||||
}
|
||||
|
||||
new_len = len - rem_len;
|
||||
block_nb = new_len / SHA512_BLOCK_SIZE;
|
||||
|
||||
shifted_message = message + rem_len;
|
||||
|
||||
sha512_transf(ctx, ctx->block, 1);
|
||||
sha512_transf(ctx, shifted_message, block_nb);
|
||||
|
||||
rem_len = new_len % SHA512_BLOCK_SIZE;
|
||||
|
||||
memcpy(ctx->block, &shifted_message[block_nb << 7],
|
||||
rem_len);
|
||||
|
||||
ctx->len = rem_len;
|
||||
ctx->tot_len += (block_nb + 1) << 7;
|
||||
}
|
||||
|
||||
void sha512_final(sha512_ctx *ctx, unsigned char *digest)
|
||||
{
|
||||
unsigned int block_nb;
|
||||
unsigned int pm_len;
|
||||
unsigned int len_b;
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
#endif
|
||||
|
||||
block_nb = 1 + ((SHA512_BLOCK_SIZE - 17)
|
||||
< (ctx->len % SHA512_BLOCK_SIZE));
|
||||
|
||||
len_b = (ctx->tot_len + ctx->len) << 3;
|
||||
pm_len = block_nb << 7;
|
||||
|
||||
memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
|
||||
ctx->block[ctx->len] = 0x80;
|
||||
UNPACK32(len_b, ctx->block + pm_len - 4);
|
||||
|
||||
sha512_transf(ctx, ctx->block, block_nb);
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
for (i = 0 ; i < 8; i++) {
|
||||
UNPACK64(ctx->h[i], &digest[i << 3]);
|
||||
}
|
||||
#else
|
||||
UNPACK64(ctx->h[0], &digest[ 0]);
|
||||
UNPACK64(ctx->h[1], &digest[ 8]);
|
||||
UNPACK64(ctx->h[2], &digest[16]);
|
||||
UNPACK64(ctx->h[3], &digest[24]);
|
||||
UNPACK64(ctx->h[4], &digest[32]);
|
||||
UNPACK64(ctx->h[5], &digest[40]);
|
||||
UNPACK64(ctx->h[6], &digest[48]);
|
||||
UNPACK64(ctx->h[7], &digest[56]);
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
}
|
||||
|
||||
/* SHA-384 functions */
|
||||
|
||||
void sha384(const unsigned char *message, unsigned int len,
|
||||
unsigned char *digest)
|
||||
{
|
||||
sha384_ctx ctx;
|
||||
|
||||
sha384_init(&ctx);
|
||||
sha384_update(&ctx, message, len);
|
||||
sha384_final(&ctx, digest);
|
||||
}
|
||||
|
||||
void sha384_init(sha384_ctx *ctx)
|
||||
{
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
ctx->h[i] = sha384_h0[i];
|
||||
}
|
||||
#else
|
||||
ctx->h[0] = sha384_h0[0]; ctx->h[1] = sha384_h0[1];
|
||||
ctx->h[2] = sha384_h0[2]; ctx->h[3] = sha384_h0[3];
|
||||
ctx->h[4] = sha384_h0[4]; ctx->h[5] = sha384_h0[5];
|
||||
ctx->h[6] = sha384_h0[6]; ctx->h[7] = sha384_h0[7];
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
|
||||
ctx->len = 0;
|
||||
ctx->tot_len = 0;
|
||||
}
|
||||
|
||||
void sha384_update(sha384_ctx *ctx, const unsigned char *message,
|
||||
unsigned int len)
|
||||
{
|
||||
unsigned int block_nb;
|
||||
unsigned int new_len, rem_len, tmp_len;
|
||||
const unsigned char *shifted_message;
|
||||
|
||||
tmp_len = SHA384_BLOCK_SIZE - ctx->len;
|
||||
rem_len = len < tmp_len ? len : tmp_len;
|
||||
|
||||
memcpy(&ctx->block[ctx->len], message, rem_len);
|
||||
|
||||
if (ctx->len + len < SHA384_BLOCK_SIZE) {
|
||||
ctx->len += len;
|
||||
return;
|
||||
}
|
||||
|
||||
new_len = len - rem_len;
|
||||
block_nb = new_len / SHA384_BLOCK_SIZE;
|
||||
|
||||
shifted_message = message + rem_len;
|
||||
|
||||
sha512_transf(ctx, ctx->block, 1);
|
||||
sha512_transf(ctx, shifted_message, block_nb);
|
||||
|
||||
rem_len = new_len % SHA384_BLOCK_SIZE;
|
||||
|
||||
memcpy(ctx->block, &shifted_message[block_nb << 7],
|
||||
rem_len);
|
||||
|
||||
ctx->len = rem_len;
|
||||
ctx->tot_len += (block_nb + 1) << 7;
|
||||
}
|
||||
|
||||
void sha384_final(sha384_ctx *ctx, unsigned char *digest)
|
||||
{
|
||||
unsigned int block_nb;
|
||||
unsigned int pm_len;
|
||||
unsigned int len_b;
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
#endif
|
||||
|
||||
block_nb = (1 + ((SHA384_BLOCK_SIZE - 17)
|
||||
< (ctx->len % SHA384_BLOCK_SIZE)));
|
||||
|
||||
len_b = (ctx->tot_len + ctx->len) << 3;
|
||||
pm_len = block_nb << 7;
|
||||
|
||||
memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
|
||||
ctx->block[ctx->len] = 0x80;
|
||||
UNPACK32(len_b, ctx->block + pm_len - 4);
|
||||
|
||||
sha512_transf(ctx, ctx->block, block_nb);
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
for (i = 0 ; i < 6; i++) {
|
||||
UNPACK64(ctx->h[i], &digest[i << 3]);
|
||||
}
|
||||
#else
|
||||
UNPACK64(ctx->h[0], &digest[ 0]);
|
||||
UNPACK64(ctx->h[1], &digest[ 8]);
|
||||
UNPACK64(ctx->h[2], &digest[16]);
|
||||
UNPACK64(ctx->h[3], &digest[24]);
|
||||
UNPACK64(ctx->h[4], &digest[32]);
|
||||
UNPACK64(ctx->h[5], &digest[40]);
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
}
|
||||
|
||||
/* SHA-224 functions */
|
||||
|
||||
void sha224(const unsigned char *message, unsigned int len,
|
||||
unsigned char *digest)
|
||||
{
|
||||
sha224_ctx ctx;
|
||||
|
||||
sha224_init(&ctx);
|
||||
sha224_update(&ctx, message, len);
|
||||
sha224_final(&ctx, digest);
|
||||
}
|
||||
|
||||
void sha224_init(sha224_ctx *ctx)
|
||||
{
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
ctx->h[i] = sha224_h0[i];
|
||||
}
|
||||
#else
|
||||
ctx->h[0] = sha224_h0[0]; ctx->h[1] = sha224_h0[1];
|
||||
ctx->h[2] = sha224_h0[2]; ctx->h[3] = sha224_h0[3];
|
||||
ctx->h[4] = sha224_h0[4]; ctx->h[5] = sha224_h0[5];
|
||||
ctx->h[6] = sha224_h0[6]; ctx->h[7] = sha224_h0[7];
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
|
||||
ctx->len = 0;
|
||||
ctx->tot_len = 0;
|
||||
}
|
||||
|
||||
void sha224_update(sha224_ctx *ctx, const unsigned char *message,
|
||||
unsigned int len)
|
||||
{
|
||||
unsigned int block_nb;
|
||||
unsigned int new_len, rem_len, tmp_len;
|
||||
const unsigned char *shifted_message;
|
||||
|
||||
tmp_len = SHA224_BLOCK_SIZE - ctx->len;
|
||||
rem_len = len < tmp_len ? len : tmp_len;
|
||||
|
||||
memcpy(&ctx->block[ctx->len], message, rem_len);
|
||||
|
||||
if (ctx->len + len < SHA224_BLOCK_SIZE) {
|
||||
ctx->len += len;
|
||||
return;
|
||||
}
|
||||
|
||||
new_len = len - rem_len;
|
||||
block_nb = new_len / SHA224_BLOCK_SIZE;
|
||||
|
||||
shifted_message = message + rem_len;
|
||||
|
||||
sha256_transf(ctx, ctx->block, 1);
|
||||
sha256_transf(ctx, shifted_message, block_nb);
|
||||
|
||||
rem_len = new_len % SHA224_BLOCK_SIZE;
|
||||
|
||||
memcpy(ctx->block, &shifted_message[block_nb << 6],
|
||||
rem_len);
|
||||
|
||||
ctx->len = rem_len;
|
||||
ctx->tot_len += (block_nb + 1) << 6;
|
||||
}
|
||||
|
||||
void sha224_final(sha224_ctx *ctx, unsigned char *digest)
|
||||
{
|
||||
unsigned int block_nb;
|
||||
unsigned int pm_len;
|
||||
unsigned int len_b;
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
#endif
|
||||
|
||||
block_nb = (1 + ((SHA224_BLOCK_SIZE - 9)
|
||||
< (ctx->len % SHA224_BLOCK_SIZE)));
|
||||
|
||||
len_b = (ctx->tot_len + ctx->len) << 3;
|
||||
pm_len = block_nb << 6;
|
||||
|
||||
memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
|
||||
ctx->block[ctx->len] = 0x80;
|
||||
UNPACK32(len_b, ctx->block + pm_len - 4);
|
||||
|
||||
sha256_transf(ctx, ctx->block, block_nb);
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
for (i = 0 ; i < 7; i++) {
|
||||
UNPACK32(ctx->h[i], &digest[i << 2]);
|
||||
}
|
||||
#else
|
||||
UNPACK32(ctx->h[0], &digest[ 0]);
|
||||
UNPACK32(ctx->h[1], &digest[ 4]);
|
||||
UNPACK32(ctx->h[2], &digest[ 8]);
|
||||
UNPACK32(ctx->h[3], &digest[12]);
|
||||
UNPACK32(ctx->h[4], &digest[16]);
|
||||
UNPACK32(ctx->h[5], &digest[20]);
|
||||
UNPACK32(ctx->h[6], &digest[24]);
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
}
|
||||
|
||||
#ifdef TEST_VECTORS
|
||||
|
||||
/* FIPS 180-2 Validation tests */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void test(const unsigned char *vector, unsigned char *digest,
|
||||
unsigned int digest_size)
|
||||
{
|
||||
unsigned char output[2 * SHA512_DIGEST_SIZE + 1];
|
||||
int i;
|
||||
|
||||
output[2 * digest_size] = '\0';
|
||||
|
||||
for (i = 0; i < (int) digest_size ; i++) {
|
||||
sprintf((char *) output + 2 * i, "%02x", digest[i]);
|
||||
}
|
||||
|
||||
printf("H: %s\n", output);
|
||||
if (strcmp((char *) vector, (char *) output)) {
|
||||
fprintf(stderr, "Test failed.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
static const unsigned char *vectors[4][3] =
|
||||
{ /* SHA-224 */
|
||||
{
|
||||
"23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7",
|
||||
"75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525",
|
||||
"20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67",
|
||||
},
|
||||
/* SHA-256 */
|
||||
{
|
||||
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
|
||||
"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1",
|
||||
"cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0",
|
||||
},
|
||||
/* SHA-384 */
|
||||
{
|
||||
"cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"
|
||||
"8086072ba1e7cc2358baeca134c825a7",
|
||||
"09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712"
|
||||
"fcc7c71a557e2db966c3e9fa91746039",
|
||||
"9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b"
|
||||
"07b8b3dc38ecc4ebae97ddd87f3d8985",
|
||||
},
|
||||
/* SHA-512 */
|
||||
{
|
||||
"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"
|
||||
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
|
||||
"8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
|
||||
"501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909",
|
||||
"e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb"
|
||||
"de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"
|
||||
}
|
||||
};
|
||||
|
||||
static const unsigned char message1[] = "abc";
|
||||
static const unsigned char message2a[] = "abcdbcdecdefdefgefghfghighijhi"
|
||||
"jkijkljklmklmnlmnomnopnopq";
|
||||
static const unsigned char message2b[] =
|
||||
"abcdefghbcdefghicdefghijdefghijkefghij"
|
||||
"klfghijklmghijklmnhijklmnoijklmnopjklm"
|
||||
"nopqklmnopqrlmnopqrsmnopqrstnopqrstu";
|
||||
unsigned char *message3;
|
||||
unsigned int message3_len = 1000000;
|
||||
unsigned char digest[SHA512_DIGEST_SIZE];
|
||||
|
||||
message3 = malloc(message3_len);
|
||||
if (message3 == NULL) {
|
||||
fprintf(stderr, "Can't allocate memory\n");
|
||||
return -1;
|
||||
}
|
||||
memset(message3, 'a', message3_len);
|
||||
|
||||
printf("SHA-2 FIPS 180-2 Validation tests\n\n");
|
||||
printf("SHA-224 Test vectors\n");
|
||||
|
||||
sha224(message1, strlen((char *) message1), digest);
|
||||
test(vectors[0][0], digest, SHA224_DIGEST_SIZE);
|
||||
sha224(message2a, strlen((char *) message2a), digest);
|
||||
test(vectors[0][1], digest, SHA224_DIGEST_SIZE);
|
||||
sha224(message3, message3_len, digest);
|
||||
test(vectors[0][2], digest, SHA224_DIGEST_SIZE);
|
||||
printf("\n");
|
||||
|
||||
printf("SHA-256 Test vectors\n");
|
||||
|
||||
sha256(message1, strlen((char *) message1), digest);
|
||||
test(vectors[1][0], digest, SHA256_DIGEST_SIZE);
|
||||
sha256(message2a, strlen((char *) message2a), digest);
|
||||
test(vectors[1][1], digest, SHA256_DIGEST_SIZE);
|
||||
sha256(message3, message3_len, digest);
|
||||
test(vectors[1][2], digest, SHA256_DIGEST_SIZE);
|
||||
printf("\n");
|
||||
|
||||
printf("SHA-384 Test vectors\n");
|
||||
|
||||
sha384(message1, strlen((char *) message1), digest);
|
||||
test(vectors[2][0], digest, SHA384_DIGEST_SIZE);
|
||||
sha384(message2b, strlen((char *) message2b), digest);
|
||||
test(vectors[2][1], digest, SHA384_DIGEST_SIZE);
|
||||
sha384(message3, message3_len, digest);
|
||||
test(vectors[2][2], digest, SHA384_DIGEST_SIZE);
|
||||
printf("\n");
|
||||
|
||||
printf("SHA-512 Test vectors\n");
|
||||
|
||||
sha512(message1, strlen((char *) message1), digest);
|
||||
test(vectors[3][0], digest, SHA512_DIGEST_SIZE);
|
||||
sha512(message2b, strlen((char *) message2b), digest);
|
||||
test(vectors[3][1], digest, SHA512_DIGEST_SIZE);
|
||||
sha512(message3, message3_len, digest);
|
||||
test(vectors[3][2], digest, SHA512_DIGEST_SIZE);
|
||||
printf("\n");
|
||||
|
||||
printf("All tests passed.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* TEST_VECTORS */
|
||||
|
||||
@@ -0,0 +1,262 @@
|
||||
//jagatsastry.nitk@gmail.com 9th April 09
|
||||
//Implementation of SHA 512
|
||||
#include<iostream>
|
||||
#include<vector>
|
||||
#include<fstream>
|
||||
#include<string>
|
||||
using namespace std;
|
||||
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned long long ullint;
|
||||
|
||||
string fromDecimal(ullint n, ullint b)
|
||||
{
|
||||
string chars="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
string result="";
|
||||
while(n>0)
|
||||
{
|
||||
result=chars.at(n%b)+result;
|
||||
n/=b;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ullint K[80] = {
|
||||
0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
|
||||
0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
|
||||
0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
|
||||
0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
|
||||
0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
|
||||
0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
|
||||
0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
|
||||
0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
|
||||
0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
|
||||
0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
|
||||
0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
|
||||
0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
|
||||
0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
|
||||
0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
|
||||
0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
|
||||
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
|
||||
0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
|
||||
0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
|
||||
0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
|
||||
0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
|
||||
0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
|
||||
0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
|
||||
0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
|
||||
0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
|
||||
0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
|
||||
0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
|
||||
0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
|
||||
0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
|
||||
0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
|
||||
0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
|
||||
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
|
||||
0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
|
||||
0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
|
||||
0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
|
||||
0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
|
||||
0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
|
||||
0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
|
||||
0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
|
||||
0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
|
||||
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
|
||||
};
|
||||
|
||||
void makeblock(vector<ullint>& ret, string p_msg)
|
||||
{
|
||||
ullint cur=0;
|
||||
int ind=0;
|
||||
for(uint i=0; i<p_msg.size(); i++)
|
||||
{
|
||||
cur = (cur<<8) | (unsigned char)p_msg[i];
|
||||
if(i%8==7)
|
||||
{
|
||||
|
||||
ret.at(ind++)=cur;
|
||||
cur=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Block
|
||||
{
|
||||
public:
|
||||
vector<ullint> msg;
|
||||
|
||||
Block():msg(16, 0) { }
|
||||
|
||||
Block(string p_msg):msg(16, 0)
|
||||
{
|
||||
makeblock(msg, p_msg);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
void split(vector<Block>& blks, string& msg)
|
||||
{
|
||||
cout<<endl<<msg.size()<<endl;;
|
||||
cout<<blks.size()<<endl;
|
||||
cout<<"Splitting into blocks: "<<endl;
|
||||
cout<<endl<<"msgsize: "<<msg.size()*8<<endl;
|
||||
for(uint i=0; i<msg.size(); i+=128)
|
||||
{
|
||||
|
||||
makeblock(blks[i/128].msg, msg.substr(i, 128));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
string mynum(ullint x)
|
||||
{
|
||||
string ret;
|
||||
for(uint i=0; i<8; i++)
|
||||
ret+=char(0);
|
||||
|
||||
for(uint i=8; i>=1; i--) //big endian machine assumed
|
||||
{
|
||||
ret += ((char*)(&x))[i-1];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define shr(x,n) ((x & 0xFFFFFFFFFFFFFFFFULL) >> n)
|
||||
#define rotr(x,n) (shr(x,n) | (x << (64 - n)))
|
||||
|
||||
ullint ch(ullint x, ullint y, ullint z)
|
||||
{
|
||||
return (x&y) ^ (~x&z);
|
||||
}
|
||||
|
||||
ullint maj(ullint x, ullint y, ullint z)
|
||||
{
|
||||
return (x&y) ^ (y&z) ^ (z&x);
|
||||
}
|
||||
|
||||
ullint fn0(ullint x)
|
||||
{
|
||||
return rotr(x, 28) ^ rotr(x, 34) ^ rotr(x, 39);
|
||||
}
|
||||
|
||||
ullint fn1(ullint x)
|
||||
{
|
||||
return rotr(x, 14) ^ rotr(x, 18) ^ rotr(x, 41);
|
||||
}
|
||||
|
||||
ullint sigma0(ullint x)
|
||||
{
|
||||
return rotr(x, 1) ^ rotr(x, 8) ^ shr(x, 7);
|
||||
}
|
||||
|
||||
ullint sigma1(ullint x)
|
||||
{
|
||||
return rotr(x, 19) ^ rotr(x, 61) ^ shr(x, 6);
|
||||
}
|
||||
|
||||
string hash_sha512_cpp(string msg_arr)
|
||||
{
|
||||
cout<<char(1<<7)<<endl;
|
||||
|
||||
string msg_out, msg;
|
||||
// cout<<"Enter message"<<endl;
|
||||
// ifstream fin("input.txt");
|
||||
// fin>>msg_arr;
|
||||
// cin>>msg_arr;
|
||||
msg=msg_arr;
|
||||
msg_arr += (char)(1<<7);
|
||||
uint cur_len = msg.size()*8 + 8;
|
||||
uint reqd_len = ((msg.size()*8)/1024+1) *1024;
|
||||
uint pad_len = reqd_len - cur_len - 128;
|
||||
|
||||
string pad(pad_len/8, char(0));
|
||||
msg_arr += pad;
|
||||
|
||||
string len_str(mynum(msg.size()*8));
|
||||
cout<<"mynum: "<<mynum(msg.size()*8)<<endl;
|
||||
msg_arr = msg_arr + len_str;
|
||||
|
||||
uint num_blk = msg_arr.size()*8/1024;
|
||||
vector<Block> M(num_blk, Block());
|
||||
split(M, msg_arr);
|
||||
|
||||
ullint H[]={
|
||||
0x6a09e667f3bcc908ULL,
|
||||
0xbb67ae8584caa73bULL,
|
||||
0x3c6ef372fe94f82bULL,
|
||||
0xa54ff53a5f1d36f1ULL,
|
||||
0x510e527fade682d1ULL,
|
||||
0x9b05688c2b3e6c1fULL,
|
||||
0x1f83d9abfb41bd6bULL,
|
||||
0x5be0cd19137e2179ULL
|
||||
};
|
||||
|
||||
for(uint i=0; i<num_blk; i++)
|
||||
{
|
||||
cout<<"Blk no: "<<i<<endl;
|
||||
vector<ullint> W(80, 0);
|
||||
for(uint t=0; t<16; t++)
|
||||
{
|
||||
W[t] = M[i].msg[t];
|
||||
}
|
||||
|
||||
|
||||
for(uint t=16; t<80; t++)
|
||||
{
|
||||
W[t] = sigma1(W[t-2]) + W[t-7] + sigma0(W[t-15]) + W[t-16];
|
||||
}
|
||||
|
||||
ullint work[8];
|
||||
for(uint i=0; i<8; i++)
|
||||
work[i] = H[i];
|
||||
|
||||
for(uint t=0; t<80; t++)
|
||||
{
|
||||
|
||||
ullint t1, t2;
|
||||
t1 = work[7] + fn1(work[4]) + ch(work[4], work[5], work[6]) + K[t] + W[t];
|
||||
t2 = fn0(work[0]) + maj(work[0], work[1], work[2]);
|
||||
work[7] = work[6];
|
||||
work[6] = work[5];
|
||||
work[5] = work[4];
|
||||
work[4] = work[3] + t1;
|
||||
work[3] = work[2];
|
||||
work[2] = work[1];
|
||||
work[1] = work[0];
|
||||
work[0] = t1 + t2;
|
||||
|
||||
}
|
||||
|
||||
for(uint i=0; i<8; i++)
|
||||
{
|
||||
H[i] = work[i] + H[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cout<<"Output: "<<endl;
|
||||
cout<<"SHA 512 HASH"<<endl;
|
||||
for(uint i=0; i<8; i++)
|
||||
cout<<H[i]<<" ";
|
||||
cout<<endl;
|
||||
|
||||
cout<<endl<<endl<<endl<<"****************SHA 512 MESSAGE DIGEST IN HEX****************"<<endl<<endl;
|
||||
for(uint i=0; i<8; i++) {
|
||||
cout<<fromDecimal(H[i], 16)<<" ";
|
||||
string msg_tmp = fromDecimal(H[i], 16);
|
||||
// Fix padding
|
||||
while (msg_tmp.length()<16) {
|
||||
msg_tmp = "0"+msg_tmp;
|
||||
}
|
||||
msg_out += msg_tmp;
|
||||
}
|
||||
cout<<endl;
|
||||
|
||||
// system("pause");
|
||||
return msg_out;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "safestring.h"
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
|
||||
//#include "general_types.h"
|
||||
#include "clog.h"
|
||||
//#include "mx.h"
|
||||
#include "smtp.h"
|
||||
#include "timer.h"
|
||||
//#include "socket.h"
|
||||
|
||||
int SMTP2( const char * _server, const char * _from, char * _to, char * _body, const char * _domain, const char * _user, const char * _pass, const char * _name)
|
||||
{
|
||||
// SAF 1/24/03: first copy all data to local structures to avoid race conditions, which is currently causing crashes !
|
||||
// Actually, it wasn't the race condition, it was the fact that '_to' was NULL due to a bug in profile.cpp: "email" was not set
|
||||
|
||||
logfmt( FLOG_MAX, "ESMTP( %s, %s, %s )", _server, _from, _to );
|
||||
|
||||
if ( !_server || !_from || !_to || !_body )
|
||||
{
|
||||
logfmt( FLOG_MAX, "Input parameters server, from, to & body are requied" );
|
||||
return 0;
|
||||
}
|
||||
if ( !_to[0])
|
||||
{
|
||||
logfmt( FLOG_MAX, "Empty recipient list" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BUF_SIZE = 512+strlen(_server)+strlen(_from)+strlen(_to)+strlen(_domain)+strlen(_user)+strlen(_pass)+strlen(_name)+2*strlen(_body);
|
||||
|
||||
char *subject = NULL, *body = NULL;
|
||||
char *name = new char[BUF_SIZE+1];
|
||||
|
||||
// Prepare body & subject
|
||||
logfmt( FLOG_MAX, "Prepare body" );
|
||||
int lines = 0;
|
||||
int len = strlen( _body );
|
||||
for ( int i=0; i<len; i++ )
|
||||
{
|
||||
int c = _body[i];
|
||||
// Replace ' with "
|
||||
if (c == 39)
|
||||
{
|
||||
_body[i] = '"';
|
||||
}
|
||||
// count LFs
|
||||
if (c == 10)
|
||||
{
|
||||
lines++;
|
||||
}
|
||||
// remove CRs (replace with whitespaces)
|
||||
if (c == 13)
|
||||
{
|
||||
_body[i] = 32;
|
||||
}
|
||||
}
|
||||
// Locate & extract subject
|
||||
logfmt( FLOG_MAX, "Locate & extract subject" );
|
||||
char *subj = strstr ( _body, "Subject: " );
|
||||
if (subj != NULL)
|
||||
{
|
||||
int k = 0;
|
||||
int n = strlen(subj);
|
||||
for (int i=0; i<n; i++)
|
||||
{
|
||||
int c = subj[i];
|
||||
if (subject != NULL)
|
||||
{
|
||||
name[k++] = c;
|
||||
}
|
||||
if (subject == NULL && c == 10)
|
||||
{
|
||||
if (i > 9)
|
||||
{
|
||||
subject = new char[i+1];
|
||||
memset( subject, 0, i );
|
||||
int j = 9;
|
||||
for (; j<i; j++)
|
||||
{
|
||||
//logfmt( FLOG_MAX, "c=%ld", subj[j] );
|
||||
subject[j-9] = subj[j];
|
||||
//subj[j] = 32;
|
||||
}
|
||||
subject[j] = '\0';
|
||||
logfmt( FLOG_MAX, "Found subject: %s", subject);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (subject != NULL)
|
||||
{
|
||||
name[k++] = '\0';
|
||||
body = new char[k];
|
||||
//logfmt( FLOG_MAX, "New body(%ld): %s (%ld)", k, name, strlen(_body) );
|
||||
snprintf( body, k, "%s", name);
|
||||
}
|
||||
}
|
||||
if (subject == NULL)
|
||||
{
|
||||
subject = new char[15];
|
||||
strcpy(subject,"Wrenchboard Support");
|
||||
logfmt( FLOG_MAX, "Subject is not found - defaulting to: %s", subject );
|
||||
}
|
||||
|
||||
// Google
|
||||
/*
|
||||
snprintf( name, BUF_SIZE, EMAIL_PREFIX"/../src/modules/mailsend -smtp %s -f %s -t %s -d %s -name '%s' +cc +bcc -v -starttls -auth-plain -user %s -pass %s -sub '%s' -M '%s'",
|
||||
_server, _from, _to, _domain, _name, _user, _pass, subject, body != NULL ? body : _body );
|
||||
*//*
|
||||
// Virtualmail
|
||||
snprintf( name, BUF_SIZE, EMAIL_PREFIX"/../src/modules/mailsend -smtp %s -f %s -t %s -d %s -name '%s' +cc +bcc -v -port 25 -auth-plain -user %s -pass %s -sub '%s' -M '%s'",
|
||||
_server, _from, _to, _domain, _name, _user, _pass, subject, body != NULL ? body : _body );
|
||||
*/
|
||||
// GoDaddy
|
||||
snprintf( name, BUF_SIZE, EMAIL_PREFIX"/../src/modules/mailsend -smtp %s -f %s -t %s -d %s -name '%s' +cc +bcc -v -port 80 -auth-plain -user %s -pass %s -sub '%s' -M '%s'",
|
||||
_server, _from, _to, _domain, _name, _user, _pass, subject, body != NULL ? body : _body );
|
||||
|
||||
logfmt( FLOG_MAX, "Calling MAILSEND: %s", name);
|
||||
|
||||
FILE * p = popen( name, "r" );
|
||||
|
||||
int c = 0;
|
||||
do
|
||||
{
|
||||
c = fread( name, 1, BUF_SIZE, p );
|
||||
if (c > 0)
|
||||
{
|
||||
logfmt( FLOG_MAX, "%s", name );
|
||||
}
|
||||
else
|
||||
{
|
||||
logfmt( FLOG_MAX, "\n\nEND OF PIPE OUTPUT\n\n" );
|
||||
}
|
||||
}
|
||||
while (c > 0);
|
||||
|
||||
pclose( p );
|
||||
|
||||
if (name != NULL)
|
||||
{
|
||||
delete name;
|
||||
}
|
||||
if (subject != NULL)
|
||||
{
|
||||
delete subject;
|
||||
}
|
||||
if (body != NULL)
|
||||
{
|
||||
delete body;
|
||||
}
|
||||
logfmt( FLOG_MAX, "/ESMTP()" );
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include "timer.h"
|
||||
|
||||
|
||||
unsigned long stamp()
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday( &tv, NULL );
|
||||
|
||||
return tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
}
|
||||
|
||||
|
||||
CTimer::CTimer( )
|
||||
{
|
||||
prev = stamp();
|
||||
}
|
||||
|
||||
|
||||
void CTimer::init( )
|
||||
{
|
||||
prev = stamp();
|
||||
}
|
||||
|
||||
|
||||
void CTimer::wake( unsigned long usec )
|
||||
{
|
||||
long sleep_time = usec-(stamp()-prev);
|
||||
|
||||
if ( sleep_time>0 )
|
||||
usleep( sleep_time );
|
||||
|
||||
prev = stamp();
|
||||
}
|
||||
|
||||
|
||||
bool CTimer::timeout( unsigned long usec )
|
||||
{
|
||||
return stamp()-prev > usec;
|
||||
}
|
||||
|
||||
|
||||
unsigned long CTimer::elapsed( )
|
||||
{
|
||||
return stamp()-prev;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <regex.h>
|
||||
|
||||
#include "safestring.h"
|
||||
#include "util.h"
|
||||
#include "clog.h"
|
||||
|
||||
bool reg_match( const char * input, const char * regexp, char * ret, int sz, int * pos /*= NULL*/ )
|
||||
{
|
||||
regex_t compiled;
|
||||
regmatch_t match[2];
|
||||
|
||||
bool satisfied = false;
|
||||
if ( ret ) ret[0] = 0;
|
||||
|
||||
// logfmt( FLOG_MAX, "Matching '%s' against '%s'", input, regexp );
|
||||
|
||||
if ( regcomp( &compiled, regexp, REG_EXTENDED ) != 0 )
|
||||
{
|
||||
logfmt( logWARNING, "regcomp returned non-0, assuming a match" );
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t r = regexec( &compiled, input, 2, match, 0 );
|
||||
|
||||
if ( r==0 ) // match
|
||||
{
|
||||
if ( pos )
|
||||
*pos = match[1].rm_so;
|
||||
|
||||
int len = match[1].rm_eo-match[1].rm_so;
|
||||
|
||||
if ( ret )
|
||||
strnsafecpy( ret, &input[ match[1].rm_so ], len, sz );
|
||||
|
||||
satisfied = true;
|
||||
}
|
||||
else
|
||||
satisfied = false;
|
||||
|
||||
regfree( &compiled );
|
||||
}
|
||||
return satisfied;
|
||||
}
|
||||
|
||||
|
||||
char * urlencode( const char * buf, char * text, int sz )
|
||||
{
|
||||
// old char url[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ^_\\-0123456789."; // . ???
|
||||
char url[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789$-_.!*'(),"; // $-_.+!*'(), took '+' out
|
||||
int len = strlen(buf);
|
||||
// fprintf(flog, "buf: '%s', len: %d\n", buf, len); fflush(flog);
|
||||
text[0] = 0;
|
||||
for (int i=0; i<len; i++)
|
||||
{
|
||||
int len = strlen(text);
|
||||
|
||||
if (strchr(url, buf[i]))
|
||||
snprintf(&text[len], sz-len, "%c", buf[i]);
|
||||
else
|
||||
snprintf(&text[len], sz-len, "%%%02x", (unsigned char)buf[i]);
|
||||
// fprintf(flog, "%d\n", i); fflush(flog);
|
||||
}
|
||||
// strcpy(buf, text);
|
||||
// Log(text, "Returning:");
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
char * urlencode(const char * buf)
|
||||
{
|
||||
return urlencode( buf, text, sizeof(text) );
|
||||
}
|
||||
*/
|
||||
|
||||
char * urldecode( char * buf, char * text, int sz)
|
||||
{
|
||||
// Log(buf, "urldecode()");
|
||||
unsigned int c3;
|
||||
char * c2; c2 = buf;
|
||||
unsigned int ch;
|
||||
char * value=text;
|
||||
// int valuelen = sz;
|
||||
|
||||
value[0] = 0;
|
||||
//bool EOS = false;
|
||||
|
||||
while (c2)
|
||||
{
|
||||
c3 = strcspn(c2, "%+"); // "%+"
|
||||
if (c3==strlen(c2))
|
||||
{
|
||||
// strncpy_(&value[strlen(value)], c2, Min0(c3, valuelen-strlen(value)-1, EOS) );
|
||||
strsafecat( value, c2, sz );
|
||||
break; //over
|
||||
}
|
||||
|
||||
// strncpy_(&value[strlen(value)], c2, Min0(c3, valuelen-strlen(value)-1, EOS) );
|
||||
strnsafecat( value, c2, c3, sz );
|
||||
|
||||
// Log(value);
|
||||
// if (EOS) break;
|
||||
|
||||
|
||||
// '+' is actually an allowed symbol per http://www.rfc-editor.org/rfc/rfc1738.txt
|
||||
// but browser rules say space is encoded as '+'
|
||||
// http://www.speakeasy.org/~cgires/readdata/
|
||||
|
||||
if (*(c2+c3)=='+')
|
||||
{
|
||||
// strncpy_(&value[strlen(value)], " ", Min0(1, valuelen-strlen(value)-1, EOS) );
|
||||
strsafecat( value, " ", sz );
|
||||
// if (EOS) break;
|
||||
c2+=c3+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sscanf(c2+c3+1, "%2x", &ch);
|
||||
strcatf( value, sz, "%c", ch);
|
||||
|
||||
// if (strlen(value)>=valuelen-1)
|
||||
// { EOS = TRUE; break; }
|
||||
|
||||
c2+=c3+3;
|
||||
}
|
||||
}
|
||||
|
||||
value[sz-1] = 0;
|
||||
|
||||
// Log(text, "urldecode returning");
|
||||
return text;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,372 @@
|
||||
#include <stdio.h>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include "safestring.h"
|
||||
|
||||
|
||||
#pragma implementation "vars.h"
|
||||
#include "vars.h"
|
||||
|
||||
//#include <stl_hashtable.h>
|
||||
//#include <stl_tree.h>
|
||||
|
||||
|
||||
//template _Rb_tree< string const, pair<string const, varstring>, _Select1st<pair<string const, varstring> >, less<string const>, allocator<varstring> >;
|
||||
//template _Rb_tree<long, pair<long const, long>, _Select1st<pair<long const, long> >, less<long>, allocator<long> >;
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
//template class std::_Rb_tree<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, varstring>, std::_Select1st<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, varstring> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const>, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, varstring> > >;
|
||||
|
||||
|
||||
// template class _Rb_tree<string const, pair<string const, varstring>, _Select1st<pair<basic_string<char, char_traits<char>, allocator<char> > const, varstring> >, less<basic_string<char, char_traits<char>, allocator<char> > const>, allocator<pair<basic_string<char, char_traits<char>, allocator<char> > const, varstring> > >;
|
||||
|
||||
template class _Rb_tree< string const, pair<string const, varstring>, _Select1st<pair<string const, varstring> >, less<string const>, allocator<pair<string const,varstring> > >;
|
||||
|
||||
|
||||
|
||||
//::operator=(std::_Rb_tree<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, varstring>, std::_Select1st<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, varstring> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const>, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, varstring> > > const&);
|
||||
|
||||
|
||||
|
||||
|
||||
// default constructor
|
||||
|
||||
varstring::varstring() : string()
|
||||
{
|
||||
validated = false;
|
||||
db_var = false;
|
||||
binary_var = false;
|
||||
}
|
||||
|
||||
varstring::varstring( const char *c ) : string( c )
|
||||
{
|
||||
this->validated = false;
|
||||
db_var = false;
|
||||
binary_var = false;
|
||||
}
|
||||
|
||||
varstring::varstring(const char* c, int len) : string( c, len )
|
||||
{
|
||||
// logfmt( FLOG_MAX, "varstring constructor( c='%s', len=%d )", c, len );
|
||||
validated = false;
|
||||
db_var = false;
|
||||
binary_var = false;
|
||||
}
|
||||
|
||||
// copy constructor
|
||||
|
||||
varstring::varstring( const varstring &c ) : string( c )
|
||||
{
|
||||
// logfmt( FLOG_MAX, "varstring copy constructor, c.validated=%d, value=%s", c.validated, c.c_str() );
|
||||
this->validated = c.validated;
|
||||
this->db_var = c.db_var;
|
||||
this->binary_var = c.binary_var;
|
||||
}
|
||||
|
||||
varstring::varstring( const string &c ) : string( c )
|
||||
{
|
||||
// logfmt( FLOG_MAX, "string->varstring copy constructor, value=%s", c.c_str() );
|
||||
validated = false;
|
||||
db_var = false;
|
||||
binary_var = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
long varstring::Long() const
|
||||
{
|
||||
return atol( c_str() );
|
||||
}
|
||||
|
||||
double varstring::Double()
|
||||
{
|
||||
return atof( c_str() );
|
||||
}
|
||||
|
||||
varstring& varstring::operator=( const char* c )
|
||||
{
|
||||
set_valid( false );
|
||||
string::operator=( c );
|
||||
return *this;
|
||||
};
|
||||
|
||||
|
||||
void varstring::operator=( long l )
|
||||
{
|
||||
set_valid( false );
|
||||
char s[20];
|
||||
snprintf( s, sizeof(s), "%ld", l );
|
||||
string::operator=( s );
|
||||
};
|
||||
|
||||
|
||||
varstring& varstring::operator=( const varstring &c )
|
||||
{
|
||||
//set_valid( false );
|
||||
this->validated = c.validated;
|
||||
this->binary_var = c.binary_var;
|
||||
string::operator=( c );
|
||||
|
||||
return *this;
|
||||
};
|
||||
|
||||
|
||||
void varstring::operator=( const string c )
|
||||
{
|
||||
set_valid( false );
|
||||
binary_var = false;
|
||||
string::operator=( c );
|
||||
}
|
||||
|
||||
varstring::operator long()
|
||||
{
|
||||
return this->Long();
|
||||
}
|
||||
|
||||
varstring::operator const char*() // type conversion
|
||||
{
|
||||
return this->c_str();
|
||||
}
|
||||
|
||||
|
||||
bool varstring::valid() const
|
||||
{
|
||||
return validated;
|
||||
}
|
||||
|
||||
void varstring::set_valid( bool validated /*= true*/ )
|
||||
{
|
||||
this->validated = validated;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool varstring::db() const
|
||||
{
|
||||
return db_var;
|
||||
}
|
||||
|
||||
void varstring::set_db( bool db /*= true*/ )
|
||||
{
|
||||
this->db_var = db;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool varstring::binary() const
|
||||
{
|
||||
return this->binary_var;
|
||||
}
|
||||
|
||||
void varstring::set_binary( bool binary_var /*= true*/ )
|
||||
{
|
||||
this->binary_var = binary_var;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ---------------- string_key --------
|
||||
/*
|
||||
string_key& string_key::operator=( const char* c )
|
||||
{
|
||||
// set_valid( false );
|
||||
string::operator=( c );
|
||||
|
||||
return *this;
|
||||
};
|
||||
|
||||
|
||||
void string_key::operator=( long l )
|
||||
{
|
||||
// set_valid( false );
|
||||
char s[20];
|
||||
snprintf( s, sizeof(s), "%ld", l );
|
||||
string::operator=( s );
|
||||
};
|
||||
|
||||
|
||||
void string_key::operator=( const string c )
|
||||
{
|
||||
// set_valid( false );
|
||||
string::operator=( c );
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// ---------------- CVars -------------
|
||||
|
||||
|
||||
CVars& CVars::operator<<( char const *name )
|
||||
{
|
||||
//logfmt( FLOG_MAX, "CVars << %s", name );
|
||||
|
||||
CVars::iterator i = find( name );
|
||||
if ( i != end() )
|
||||
{
|
||||
i->second.set_db();
|
||||
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
CVars& CVars::operator>>( char const *name )
|
||||
{
|
||||
//logfmt( FLOG_MAX, "CVars >> %s", name );
|
||||
|
||||
CVars::iterator i = find( name );
|
||||
if ( i != end() )
|
||||
{
|
||||
i->second.set_db( false );
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void CVars::ClearDB()
|
||||
{
|
||||
CVars::iterator i;
|
||||
|
||||
for ( i=begin(); i!=end(); i++ )
|
||||
i->second.set_db( false );
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
FORMAT:
|
||||
int count;
|
||||
|
||||
|
||||
{
|
||||
name,value,
|
||||
bitmap{
|
||||
bool validated;
|
||||
bool db_var; // is this variable to be used in DB updates
|
||||
bool binary_var;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//implement << operator??
|
||||
|
||||
long CVars::serialize( unsigned char *&buf ) // this will serialize the data into buf and return the resulting size
|
||||
// it is the responsibility of the caller to free the buffer with free()
|
||||
{
|
||||
long len;
|
||||
CVars::iterator i;
|
||||
int count = 0; // do NOT change this datatype as this will affect data structure below!!!
|
||||
unsigned char *c = buf + sizeof(count);
|
||||
|
||||
|
||||
// Calculate the length
|
||||
|
||||
for ( i=begin(); i!=end(); i++ )
|
||||
{
|
||||
count++;
|
||||
|
||||
int size = i->first.size();
|
||||
c += sizeof(unsigned char); // name should be no longer than 255
|
||||
c += size;
|
||||
|
||||
size = i->second.size();
|
||||
c += sizeof(int);
|
||||
c += size;
|
||||
|
||||
// record bits
|
||||
c++;
|
||||
}
|
||||
|
||||
len = c-buf;
|
||||
|
||||
buf = (unsigned char*)malloc( len );
|
||||
|
||||
if ( !buf ) return 0;
|
||||
|
||||
|
||||
// Populate buf
|
||||
|
||||
// first store the number of elements
|
||||
|
||||
*(int*)buf = count;
|
||||
c = buf + sizeof(count);
|
||||
|
||||
for ( i=begin(); i!=end(); i++ )
|
||||
{
|
||||
int size = *(int*)c = i->first.size();
|
||||
c += sizeof(unsigned char);
|
||||
memcpy( c, i->first.data(), size );
|
||||
c += size;
|
||||
|
||||
size = *(int*)c = i->second.size();
|
||||
c += sizeof(int);
|
||||
memcpy( c, i->second.data(), size );
|
||||
c += size;
|
||||
|
||||
// record bits
|
||||
*c = i->second.validated | i->second.db_var << 1 | i->second.binary_var << 2;
|
||||
|
||||
c++;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
int CVars::deserialize( unsigned char *buf, long buf_sz ) // this will initialize the current instance by de-serializing the data from buf
|
||||
{
|
||||
// clear out the underlying map / erase any previous data
|
||||
|
||||
erase( begin(), end() );
|
||||
|
||||
if ( buf_sz < (long)sizeof(int) ) return 0;
|
||||
|
||||
unsigned char *c = buf;
|
||||
int count = *(int*)buf;
|
||||
c += sizeof( count );
|
||||
int i = 0;
|
||||
|
||||
for ( i=0; i<count; i++ )
|
||||
{
|
||||
if ( c-buf >= buf_sz ) return 0;
|
||||
|
||||
char name[256];
|
||||
|
||||
int size = *(unsigned char*)c;
|
||||
c += sizeof(unsigned char);
|
||||
|
||||
if ( c-buf+size >= buf_sz ) break; // boundary check
|
||||
|
||||
strnsafecpy( name, (char*)c, size, sizeof(name) );
|
||||
c += size;
|
||||
|
||||
if ( c-buf+(long)sizeof(int) >= buf_sz ) break; // boundary check
|
||||
|
||||
size = *(int*)c;
|
||||
c += sizeof(int);
|
||||
|
||||
if ( c-buf+size+1 > buf_sz ) break; // boundary check
|
||||
|
||||
(*this)[name].assign( (char*)c, size );
|
||||
c += size;
|
||||
|
||||
(*this)[name].validated = *c & 1;
|
||||
(*this)[name].db_var = (*c >> 1) & 1;
|
||||
(*this)[name].binary_var = (*c >> 2) & 1;
|
||||
|
||||
c++;
|
||||
|
||||
//printf( "i=%d\n", i );
|
||||
}
|
||||
|
||||
return i; //>0 ? i-1 : 0;
|
||||
}
|
||||
Reference in New Issue
Block a user