/**
 * 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" }

-----------------------------------------------------------------------------------------------------------------------*/


 

+ Recent posts