/**
* example C code using libcurl and json-c
* to post and return a payload using
* http://jsonplaceholder.typicode.com
*
* Requirements:
*
* json-c - https://github.com/json-c/json-c
* libcurl - http://curl.haxx.se/libcurl/c
*
* Build:
*
* gcc test.c -lcrypto -lcurl -ljson-c -o test
*
* DESCRIPTION
- 특정사이트에 접속해서 데이타를 불러오는역할은 curl lib가 담당한다.
- 데이타 입력및 출력의 인터페이스에 필요한 데이타의 암호화는 lcrypto lib가 담당한다.
- 출력데이타를 복호화 했을때에, JSON형식의 데이타를 파싱하는데에는 ljson-c lib가 필요하다.
*
*/
/* standard includes */
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <curl/curl.h>
#include <iconv.h>
#include <locale.h>
#include <langinfo.h>
#include <openssl/aes.h>
#include <time.h>
#include <sys/time.h>
#include <json-c/json.h>
#define MAX_AES_BUFF_SIZE 2048
#define MAX_FSS_STRING_SIZE 100
int __debug;
const unsigned char fw_aes_key[16+1] = {0X45, 0X72, 0X23, 0X33, 0X77, 0XAB, 0X6C, 0X6C, 0XFD, 0X59, 0X6C, 0X75, 0X74, 0X69, 0X6F, 0X6E, 0x00};
/* holder for curl fetch */
struct curl_fetch_st {
char *payload;
size_t size;
};
/*
* Function prototype
*/
json_object *sbo634_wascall(char *MSGCODE, char *ACCNO, char *PAGE);
size_t curl_callback (void *contents, size_t size, size_t nmemb, void *userp);
CURLcode curl_fetch_url(CURL *ch, const char *url, struct curl_fetch_st *fetch);
static void e_hex_convert(const void* pv, size_t len, char *outBuff) {
const unsigned char * p = (const unsigned char*)pv;
if (NULL == pv) {
return;
}
else
{
size_t i = 0;
int hexLen = 0;
char editb[8];
memset (editb, 0x00, sizeof(editb));
for (; i<len;++i) {
sprintf(editb, "%02X", *p++);
memcpy(outBuff+hexLen, editb, 2);
hexLen += 2;
}
}
return;
}
static void d_hex_convert(unsigned char *pv, size_t len, char *outBuff) {
const unsigned char * p = (const unsigned char*)pv;
int ii, kk, jj;
kk=0;
ii=0;
while(1)
{
if(ii >= len) break;
jj=0;
if(pv[ii] == 'F') pv[ii] = 15;
else if(pv[ii] == 'E') pv[ii] = 14;
else if(pv[ii] == 'D') pv[ii] = 13;
else if(pv[ii] == 'C') pv[ii] = 12;
else if(pv[ii] == 'B') pv[ii] = 11;
else if(pv[ii] == 'A') pv[ii] = 10;
else if(pv[ii] == '9') pv[ii] = 9;
else if(pv[ii] == '8') pv[ii] = 8;
else if(pv[ii] == '7') pv[ii] = 7;
else if(pv[ii] == '6') pv[ii] = 6;
else if(pv[ii] == '5') pv[ii] = 5;
else if(pv[ii] == '4') pv[ii] = 4;
else if(pv[ii] == '3') pv[ii] = 3;
else if(pv[ii] == '2') pv[ii] = 2;
else if(pv[ii] == '1') pv[ii] = 1;
else if(pv[ii] == '0') pv[ii] = 0;
if((pv[ii] & 0x08) > 0) jj = jj + 128;
if((pv[ii] & 0x04) > 0) jj = jj + 64;
if((pv[ii] & 0x02) > 0) jj = jj + 32;
if((pv[ii] & 0x01) > 0) jj = jj + 16;
if(pv[ii+1] == 'F') pv[ii+1] = 15;
else if(pv[ii+1] == 'E') pv[ii+1] = 14;
else if(pv[ii+1] == 'D') pv[ii+1] = 13;
else if(pv[ii+1] == 'C') pv[ii+1] = 12;
else if(pv[ii+1] == 'B') pv[ii+1] = 11;
else if(pv[ii+1] == 'A') pv[ii+1] = 10;
else if(pv[ii+1] == '9') pv[ii+1] = 9;
else if(pv[ii+1] == '8') pv[ii+1] = 8;
else if(pv[ii+1] == '7') pv[ii+1] = 7;
else if(pv[ii+1] == '6') pv[ii+1] = 6;
else if(pv[ii+1] == '5') pv[ii+1] = 5;
else if(pv[ii+1] == '4') pv[ii+1] = 4;
else if(pv[ii+1] == '3') pv[ii+1] = 3;
else if(pv[ii+1] == '2') pv[ii+1] = 2;
else if(pv[ii+1] == '1') pv[ii+1] = 1;
else if(pv[ii+1] == '0') pv[ii+1] = 0;
if((pv[ii+1] & 0x08) > 0) jj = jj + 8;
if((pv[ii+1] & 0x04) > 0) jj = jj + 4;
if((pv[ii+1] & 0x02) > 0) jj = jj + 2;
if((pv[ii+1] & 0x01) > 0) jj = jj + 1;
outBuff[kk] = jj;
kk = kk + 1;
ii = ii + 2;
}
return;
}
static int e_makeAesPacket(unsigned char *EncryptText, int EncryptTextLen, unsigned char *DecryptText) {
AES_KEY enc_key;
long idx=0;
unsigned char padBuff[MAX_AES_BUFF_SIZE];
unsigned char encBuff[MAX_AES_BUFF_SIZE];
int ii;
size_t encPadLen = ((EncryptTextLen + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
memset(padBuff, 0x00, MAX_AES_BUFF_SIZE);
memset(encBuff, 0x00, MAX_AES_BUFF_SIZE);
AES_set_encrypt_key(fw_aes_key, 128, &enc_key);
memcpy(padBuff, EncryptText, EncryptTextLen);
for (ii = EncryptTextLen; ii < encPadLen; ii++) {
padBuff[ii] = (encPadLen - EncryptTextLen);
}
while(idx < encPadLen) {
AES_ecb_encrypt(padBuff+idx, encBuff+idx, &enc_key, AES_ENCRYPT);
idx += AES_BLOCK_SIZE;
}
printf("e_makeAesPacket[%d]", strlen(encBuff));
e_hex_convert(encBuff, encPadLen, DecryptText);
return(strlen(DecryptText));
}
static int d_makeAesPacket(unsigned char *DecryptText, int DecryptTextLen, unsigned char *PlainText) {
AES_KEY dec_key;
long idx=0;
unsigned char outBuff[MAX_AES_BUFF_SIZE];
int ii, kk, jj;
memset(outBuff, 0x00, MAX_AES_BUFF_SIZE);
AES_set_decrypt_key(fw_aes_key, 128, &dec_key);
size_t encPadLen = strlen(DecryptText) / 2;
d_hex_convert(DecryptText, DecryptTextLen, outBuff);
printf("d_makeAesPacket[%d]", strlen(outBuff));
while(idx < encPadLen) {
AES_ecb_encrypt(outBuff+idx, PlainText+idx, &dec_key, AES_DECRYPT);
idx += AES_BLOCK_SIZE;
}
if(__debug) printf(">>%s\n", PlainText);
jj=PlainText[encPadLen-1];
ii=0;
for(kk=encPadLen-2; kk>0; kk--)
{
if(PlainText[kk] == jj)
{
PlainText[kk]=0x00;
}
else break;
}
return(strlen(PlainText));
}
/* callback for curl fetch */
size_t curl_callback (void *contents, size_t size, size_t nmemb, void *userp) {
size_t realsize = size * nmemb; /* calculate buffer size */
struct curl_fetch_st *p = (struct curl_fetch_st *) userp; /* cast pointer to fetch struct */
/* expand buffer */
p->payload = (char *) realloc(p->payload, p->size + realsize + 1);
/* check buffer */
if (p->payload == NULL) {
/* this isn't good */
fprintf(stderr, "ERROR: Failed to expand buffer in curl_callback");
/* free buffer */
free(p->payload);
/* return */
return -1;
}
/* copy contents to buffer */
memcpy(&(p->payload[p->size]), contents, realsize);
/* set new buffer size */
p->size += realsize;
/* ensure null termination */
p->payload[p->size] = 0;
/* return size */
return realsize;
}
/* fetch and return url body via curl */
CURLcode curl_fetch_url(CURL *ch, const char *url, struct curl_fetch_st *fetch) {
CURLcode rcode; /* curl result code */
/* init payload */
fetch->payload = (char *) calloc(1, sizeof(fetch->payload));
/* check payload */
if (fetch->payload == NULL) {
/* log error */
fprintf(stderr, "ERROR: Failed to allocate payload in curl_fetch_url");
/* return error */
return CURLE_FAILED_INIT;
}
/* init size */
fetch->size = 0;
/* set url to fetch */
curl_easy_setopt(ch, CURLOPT_URL, url);
/* set calback function */
curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, curl_callback);
/* pass fetch struct pointer */
curl_easy_setopt(ch, CURLOPT_WRITEDATA, (void *) fetch);
/* set default user agent */
curl_easy_setopt(ch, CURLOPT_USERAGENT, "libcurl-agent/1.0");
/* set timeout */
curl_easy_setopt(ch, CURLOPT_TIMEOUT, 30);
/* enable location redirects */
curl_easy_setopt(ch, CURLOPT_FOLLOWLOCATION, 1);
/* set maximum allowed redirects */
curl_easy_setopt(ch, CURLOPT_MAXREDIRS, 1);
/* fetch the url */
rcode = curl_easy_perform(ch);
/* return */
return rcode;
}
json_object *sbo634_wascall(char *MSGCODE, char *ACCNO, char *PAGE)
{
CURL *ch; /* curl handle */
CURLcode rcode; /* curl result code */
json_object *json; /* json post body */
enum json_tokener_error jerr = json_tokener_success; /* json parse error */
struct curl_fetch_st curl_fetch; /* curl fetch struct */
struct curl_fetch_st *cf = &curl_fetch; /* pointer to fetch struct */
struct curl_slist *headers = NULL; /* http headers to send with request */
char post_data [1024*32] = {0x00,};
unsigned char TextPlain [1204L * 128L] = {0x00,};
unsigned char inBuff[MAX_AES_BUFF_SIZE];
unsigned char txParam[MAX_AES_BUFF_SIZE];
unsigned char txRemark[MAX_AES_BUFF_SIZE];
int rlen;
/* url to test site */
char *url = "http://cyper-01:44444/GW/rest/service.do";
printf("[URL]%s\n", url);
/* init curl handle */
if ((ch = curl_easy_init()) == NULL) {
/* log error */
fprintf(stderr, "ERROR: Failed to create curl handle in fetch_session");
/* return error */
return NULL;
}
/* set content type */
//headers = curl_slist_append(headers, "Accept: application/json");
//headers = curl_slist_append(headers, "Content-Type: application/json");
/* create json object for post */
json = json_object_new_object();
/* build post data */
json_object_object_add(json, "MSGCODE", json_object_new_string(MSGCODE));
json_object_object_add(json, "ACCNO", json_object_new_string(ACCNO));
json_object_object_add(json, "PAGE", json_object_new_string(PAGE));
memset(inBuff, 0x00, sizeof(inBuff));
sprintf(inBuff, "%s", json_object_to_json_string(json));
printf(">>BEFORE ENCRYPT:::msg=%s\n", json_object_to_json_string(json));
rlen = e_makeAesPacket(inBuff, strlen(inBuff), txRemark);
if (rlen < 0) {
printf("AesPacket make failed(%s)", inBuff);
return NULL;
}
sprintf(post_data, "msg=%s", txRemark);
printf(">>AFTER ENCRYPT:::%s", post_data);
printf("\n\n\n\n");
/* set curl options */
curl_easy_setopt(ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(ch, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(ch, CURLOPT_POSTFIELDS, post_data);
curl_easy_setopt(ch, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(ch, CURLOPT_POST, 1L);
/* fetch page and capture return code */
rcode = curl_fetch_url(ch, url, cf);
//FREE
curl_easy_cleanup(ch);
curl_slist_free_all(headers);
json_object_put(json);
/* check return code */
if (rcode != CURLE_OK || cf->size < 1) {
/* log error */
fprintf(stderr, "ERROR: Failed to fetch url (%s) - curl said: %s",
url, curl_easy_strerror(rcode));
/* return error */
return NULL;
}
/* check payload */
if (cf->payload != NULL)
{
/* print result */
printf("CURL Returned: \n%s\n", cf->payload);
rlen = d_makeAesPacket((unsigned char *)cf->payload, strlen(cf->payload), TextPlain);
if (rlen < 0) {
printf("d_makeAesPacket make failed(%s)", inBuff);
return NULL;
}
/* parse return */
json = json_tokener_parse_verbose(TextPlain, &jerr);
/* free payload */
free(cf->payload);
}
else
{
/* error */
fprintf(stderr, "ERROR: Failed to populate payload");
/* free payload */
free(cf->payload);
/* return */
return NULL;
}
/* check error */
if (jerr != json_tokener_success) {
/* error */
fprintf(stderr, "ERROR: Failed to parse json string");
/* free json object */
json_object_put(json);
/* return */
return NULL;
}
return json;
}
char CreditBalanceDefineName[44][100] = {"MSGCODE",
"RESULT","REASON","ACCNO","AO","LIMIT","CREDIT-AVAI","ASSETS","LIABILITIES",
"EQUITY","CASHBAL","LMV","COLLATERAL","DEBT","SMV","MR","BUYMR",
"SELLMR","EE","PP","CALLMARGIN","SHORTCALL","CALLFORCESELL","CALL_LMV","CALL_SMV",
"FORCE_LMV","FORCE_SMV","MARGINRATIO","WITHDRAWAL","ACTION","ACCEE","BUYCR50",
"BUYCR60","BUYCR70","MTMEE","MTMBUYCR50","MTMBUYCR60","MTMBUYCR70","MTMMRATIO",
"MTMCALLM35","TOTALBUY","TOTALSELL","PAGE","NEXTPAGE"};
char CreditPortDefineName[9][100] = {"MSGCODE",
"RESULT","REASON","ACCNO","TAMOUNT","TMKTVALUE","PAGE",
"NEXTPAGE","COUNT"};
int main(int argc, char *argv[])
{
json_object *json = NULL;
json_object *array = NULL;
json_object *pdata = NULL;
json_object *jvalue = NULL;
char MSGCODE[MAX_FSS_STRING_SIZE];
char ACCNO[MAX_FSS_STRING_SIZE];
char PAGE[MAX_FSS_STRING_SIZE];
int kk;
if(argc < 2)
{
printf("[1]:MSGCODE>ACR, ACCNO>, PAGE>1 + DEBUG(D)\n");
printf("[2]:MSGCODE>ACP, ACCNO>, PAGE>1 + DEBUG(D)\n");
return(-1);
}
if(argc == 3)
{
if(argv[2][0] == 'D') __debug = 1;
else __debug = 0;
}
memset(MSGCODE,0x00,sizeof(MSGCODE));
memset(ACCNO,0x00,sizeof(ACCNO));
memset(PAGE,0x00,sizeof(PAGE));
if(argv[1][0] =='1')
{
strcpy(MSGCODE, "ACR");
strcpy(ACCNO, "987654321");
strcpy(PAGE, "1");
}
else if(argv[1][0] =='2')
{
strcpy(MSGCODE, "ACP");
strcpy(ACCNO, "987654321");
strcpy(PAGE, "1");
}
else
{
printf("Argument IS 1 or 2 !!!!!!!\n");
return(-1);
}
json = sbo634_wascall(MSGCODE, ACCNO, PAGE);
if(json == NULL) {
return(-1);
}
/* debugging */
printf("Parsed JSON: %s\n", json_object_to_json_string(json));
char *creditvalue = NULL;
printf("\n\n\n\n\n>>>>>>>>\n");
if(argv[1][0]=='2')
for(kk=0; kk<9; kk++)
{
if (json_object_object_get_ex(json, CreditPortDefineName[kk], &pdata)) {
creditvalue = (char *)json_object_get_string(pdata);
printf("[%.3d]%20s:[%s]\n", kk+1, CreditPortDefineName[kk], creditvalue);
}
}
if(argv[1][0]=='1')
for(kk=0; kk<44; kk++)
{
if (json_object_object_get_ex(json, CreditBalanceDefineName[kk], &pdata)) {
creditvalue = (char *)json_object_get_string(pdata);
printf("[%.3d]%20s:[%s]\n", kk+1, CreditBalanceDefineName[kk], creditvalue);
}
}
json_object_put(json);
return(0);
}
/*----복호화한 출력 JSON포맷 ----------------------------------------------------------------------------------------------
{ "PP": "3890427.94", "BUYMR": "0.00", "COLLATERAL": "0.00", "MTMEE": "1945213.97", "BUYCR70": "2778877.10", "CASHBAL": "1945213.97", "SHORTCALL": "1945213.97", "CREDIT-AVAI": "3890427.94", "TOTALB": "0.00", "LIMIT": "12000000.00", "LIABILITIES": "0.00", "DEBT": "0.00", "MARGINRATIO": "1.0000", "SHORTFORCE": "1945213.97", "MTMCALLM35": "0.35", "ACCNO": "0058866", "MTMBUYCR50": "3890427.94", "MTMBUYCR70": "2778877.10", "REASON": "complete", "BUYCR50": "3890427.94", "EQUITY": "1945213.97", "ASSETS": "1945213.97", "EE": "1945213.97", "BUYCR60": "3242023.28", "MSGCODE": "RCR", "MR": "0.00", "SELLMR": "0.00", "CALLMARGIN": "0.00", "CALLFORCESELL": "0.00", "AO": "9233", "ACCEE": "1945213.97", "LMV": "0.00", "CALL_SMV": "40.00", "ACTION": "", "FORCE_SMV": "30.00", "TOTALS": "0.00", "MTMBUYCR60": "3242023.28", "CALL_LMV": "35.00", "MTMMRATIO": "0.00", "SMV": "0.00", "WITHDRAWAL": "1945213.97", "RESULT": "0", "FORCE_LMV": "25.00" }
-----------------------------------------------------------------------------------------------------------------------*/
/*----복호화한 출력 JSON포맷 ----------------------------------------------------------------------------------------------
{ "STOCKLISTS": [ ], "ACCNO": "0058866", "MSGCODE": "RCP", "TAMOUNT": "0.00", "PAGE": "1", "COUNT": "0", "NEXTPAGE": "0", "TMKTVALUE": "0.00", "REASON": "complete", "RESULT": "0" }
-----------------------------------------------------------------------------------------------------------------------*/
'c 언어 > 고급과정' 카테고리의 다른 글
Firebase : Send notification with REST API(common.c) (0) | 2019.10.30 |
---|---|
Firebase : Send notification with REST API(sample.c) (0) | 2019.10.30 |
WINDOWS,LINUX,Firebase Cloud Messaging (0) | 2019.10.30 |
LINUX,C-ISAM FILE(UPDATE) SAMPLE PROGRAM (0) | 2019.10.30 |
마우스위치 저장및 재생(WIN32-API) (0) | 2019.10.29 |