Created
August 16, 2023 05:29
-
-
Save ashraf267/40a1ce10b0967ade23a406faca6418bf to your computer and use it in GitHub Desktop.
This works enough for the proof of concept. created at 6:29am on Wednesday, 16th of AUG, 2023
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Ui.h" | |
#include "Common.h" | |
#include "Communication.h" | |
#include "net_if.h" | |
#include "jsmn.h" | |
// string replace function | |
char *replace( | |
char const *const original, | |
char const *const pattern, | |
char const *const replacement) | |
{ | |
size_t const replen = strlen(replacement); | |
size_t const patlen = strlen(pattern); | |
size_t const orilen = strlen(original); | |
size_t patcnt = 0; | |
const char *oriptr; | |
const char *patloc; | |
// find how many times the pattern occurs in the original string | |
for (oriptr = original; (patloc = strstr(oriptr, pattern)); oriptr = patloc + patlen) | |
{ | |
patcnt++; | |
} | |
{ | |
// allocate memory for the new string | |
size_t const retlen = orilen + patcnt * (replen - patlen); | |
char *const returned = (char *)malloc(sizeof(char) * (retlen + 1)); | |
if (returned != NULL) | |
{ | |
// copy the original string, | |
// replacing all the instances of the pattern | |
char *retptr = returned; | |
for (oriptr = original; (patloc = strstr(oriptr, pattern)); oriptr = patloc + patlen) | |
{ | |
size_t const skplen = patloc - oriptr; | |
// copy the section until the occurence of the pattern | |
strncpy(retptr, oriptr, skplen); | |
retptr += skplen; | |
// copy the replacement | |
strncpy(retptr, replacement, replen); | |
retptr += replen; | |
} | |
// copy the rest of the string. | |
strcpy(retptr, oriptr); | |
} | |
return returned; | |
} | |
} | |
static int jsoneq(const char *json, jsmntok_t *tok, const char *s) | |
{ | |
if (tok->type == JSMN_STRING && (int)strlen(s) == tok->end - tok->start && | |
strncmp(json + tok->start, s, tok->end - tok->start) == 0) | |
{ | |
return 0; | |
} | |
return -1; | |
} | |
// custom FetchWallet func that returns a string:- reqHash | |
const char *FetchWallet(unsigned char *pcOut) | |
{ | |
char *pBuf = "{\"walletId\": \"5149\"}"; | |
// I have pcOut; | |
// some hack to add "pcOut" into the json | |
// say the user inputs 5150 as wallet id, the below pads it with \" at the front and back so we can then replace it in the pBuf | |
char x[50] = "\\\""; | |
strcat(x, (char *)pcOut); | |
char y[50] = "\\\""; | |
strcat(x, y); | |
strcpy((char *)pcOut, x); | |
// I can now replace | |
pBuf = replace(pBuf, "\"5149\"", (const char *)pcOut); // replaces 5149 with the user wallet id | |
uint16_t uLen = strlen(pBuf); | |
char *pExtHeadr = "Content-Type: application/json\r\n"; | |
short mySh = UIWireHttpSend("https://devapi.ucard.store/identity/Agent/login/wallet/initate", (uint8_t *)pBuf, uLen, pExtHeadr); | |
// if (mySh != 0) | |
// { | |
// return TY_ERR; | |
// } | |
if (!(mySh == 0)) | |
{ | |
return TY_ERR; | |
} | |
int u_len = 250; | |
// char *response[u_len]; | |
const char response[u_len]; | |
mySh = UIWireHttpRecv((uint8_t *)response, (uint16_t *)u_len); | |
// jsmn | |
int i, j; | |
int r; | |
jsmn_parser p; | |
jsmntok_t t[128]; /* We expect no more than 128 tokens */ | |
jsmn_init(&p); | |
r = jsmn_parse(&p, /* response */ response, /* mySh */strlen(response), t, | |
sizeof(t) / sizeof(t[0])); | |
if (r < 0) | |
{ | |
printf("Failed to parse JSON: %d\n", r); | |
return 1; | |
} | |
// code | |
if (r < 1 || t[0].type != JSMN_OBJECT) | |
{ | |
printf("Object expected\n"); | |
return 1; | |
} | |
char isSuccessfulValue[10] = ""; | |
// char requestHashValue[64] = ""; | |
char *requestHashValue = ""; | |
char emailAddressValue[128] = ""; | |
char messageValue[256] = ""; | |
char statusCodeValue[10] = ""; | |
/* Loop over all keys of the root object */ | |
for (i = 1; i < r; i++) | |
{ | |
if (jsoneq(response, &t[i], "isSuccessful") == 0) | |
{ | |
snprintf(isSuccessfulValue, sizeof(isSuccessfulValue), "%.*s", t[i + 1].end - t[i + 1].start, response + t[i + 1].start); | |
i++; | |
} | |
else if (jsoneq(response, &t[i], "responseModel") == 0) | |
{ | |
if (t[i + 1].type != JSMN_OBJECT) | |
{ | |
continue; /* We expect responseModel to be an object */ | |
} | |
for (j = 0; j < t[i + 1].size; j++) | |
{ | |
jsmntok_t *response_key = &t[i + j + 2]; | |
jsmntok_t *response_value = &t[i + j + 3]; | |
if (jsoneq(response, response_key, "requestHash") == 0) | |
{ | |
snprintf(requestHashValue, /* sizeof(requestHashValue)*/ 64, "%.*s", response_value->end - response_value->start, response + response_value->start); | |
} | |
else if (jsoneq(response, response_key, "emailAddress") == 0) | |
{ | |
snprintf(emailAddressValue, sizeof(emailAddressValue), "%.*s", response_value->end - response_value->start, response + response_value->start); | |
} | |
j++; // Skip the value token | |
} | |
i += t[i + 1].size + 1; | |
} | |
else if (jsoneq(response, &t[i], "message") == 0) | |
{ | |
snprintf(messageValue, sizeof(messageValue), "%.*s", t[i + 1].end - t[i + 1].start, response + t[i + 1].start); | |
i++; | |
} | |
else if (jsoneq(response, &t[i], "statusCode") == 0) | |
{ | |
snprintf(statusCodeValue, sizeof(statusCodeValue), "%.*s", t[i + 1].end - t[i + 1].start, response + t[i + 1].start); | |
i++; | |
} | |
} | |
// return "hfhfhffhfjhffhf67838xxdscddv"; | |
return requestHashValue; | |
} | |
// custom VerifyOTP func | |
short VerifyOTP(unsigned char *pcOut) | |
{ | |
char *pBuf = "{\"requestHash\": \"363P9e2062c63b574fd090adfad5db78fa5b\", \"otp\": \"7777\"}"; // json body | |
char x[50] = "\\\""; | |
strcat(x, (char *)pcOut); | |
char y[50] = "\\\""; | |
strcat(x, y); | |
strcpy((char *)pcOut, x); // input padded | |
pBuf = replace(pBuf, "\"7777\"", (const char *)pcOut); // 7777 replaced with user entered otp | |
uint16_t uLen = strlen(pBuf); | |
char *pExtHeadr = "Content-Type: application/json\r\n"; | |
short mySh = UIWireHttpSend("https://devapi.ucard.store/identity/Agent/login/wallet/complete", (uint8_t *)pBuf, uLen, pExtHeadr); | |
if (!(mySh == 0)) | |
{ | |
return TY_ERR; | |
} | |
int u_len = 250; | |
// char *response[u_len]; | |
const char response[u_len]; | |
mySh = UIWireHttpRecv((uint8_t *)response, (uint16_t *)u_len); | |
// jsmn code here | |
int i; | |
int r; | |
jsmn_parser p; | |
jsmntok_t t[128]; /* We expect no more than 128 tokens */ | |
jsmn_init(&p); | |
r = jsmn_parse(&p, response, strlen(response), t, | |
sizeof(t) / sizeof(t[0])); | |
if (r < 0) | |
{ | |
printf("Failed to parse JSON: %d\n", r); | |
return 1; | |
} | |
/* Assume the top-level element is an object */ | |
if (r < 1 || t[0].type != JSMN_OBJECT) | |
{ | |
printf("Object expected\n"); | |
return 1; | |
} | |
// if needed, declare vars here | |
for (i = 1; i < r; i++) | |
{ | |
if (jsoneq(response, &t[i], "message") == 0) | |
{ | |
/* We may use strndup() to fetch string value */ | |
printf("- User: %.*s\n", t[i + 1].end - t[i + 1].start, | |
response + t[i + 1].start); | |
i++; | |
} | |
else if (jsoneq(response, &t[i], "statusCode") == 0) | |
{ | |
printf("- Admin: %.*s\n", t[i + 1].end - t[i + 1].start, | |
response + t[i + 1].start); | |
i++; | |
} | |
else if (jsoneq(response, &t[i], "isSuccessful") == 0) | |
{ | |
printf("- Admin: %.*s\n", t[i + 1].end - t[i + 1].start, | |
response + t[i + 1].start); | |
i++; | |
} | |
else | |
{ | |
printf("Unexpected key: %.*s\n", t[i].end - t[i].start, | |
response + t[i].start); | |
} | |
} | |
// return | |
return TY_OK; | |
} | |
// custom UIInputOTP func that accepts the reqHash | |
short UIInputOTP(unsigned char ucOutXmode, unsigned char *pcOut, unsigned char *pucOutLen, int iTimeout, const char *requestHash) | |
{ | |
unsigned char ucInputLenMax; /* ������볤�� */ | |
unsigned char ucInputCnt; /* ������� */ | |
// unsigned char ucKey; | |
unsigned char ucDisplayLen; | |
char acCodeBuff[64]; | |
short sRC; | |
// ucInputLenMax = 12; // max no of characters, I believe | |
ucInputLenMax = 4; | |
ucInputCnt = 0; | |
// Lib_LcdDrowArea(DEFAULT_FORG_COLOR, 0, 30, 320, 140); | |
Lib_LcdDrowArea(RGB565_WHITE, 0, 30, 320, 210); | |
// Lib_LcdDrowArea(DEFAULT_BACK_COLOR, 0, 170, 320, 70); | |
pcOut[0] = 0; | |
while (1) | |
{ | |
// DRAW_TITLE(TIP_ENTER_AMOUNT); | |
DRAW_TITLE_X("Verify Number"); | |
UILabelMyText("Enter digit sent to your", ALIGN_L, RGB565_BLACK, RGB565_WHITE, 0, 50 + 10); | |
UILabelShopName("Press O to continue, X to cancel!"); | |
memset(acCodeBuff, 0, sizeof(acCodeBuff)); // fills the whole acCodeBuff (64 bytes) with 0 | |
ucDisplayLen = (unsigned char)strlen((char *)pcOut); | |
if (ucDisplayLen < 1) | |
{ | |
memcpy(acCodeBuff, "0000", 4); // copies n (4) chars from src ("0.00") to dest (acCodeBuff), in this case | |
// if the below causes any error, remove it | |
memcpy(acCodeBuff + 10 - ucDisplayLen, pcOut, ucDisplayLen); | |
ucDisplayLen = 10; | |
} | |
else | |
{ | |
// memcpy(acCodeBuff, pcOut, ucDisplayLen-2); | |
memcpy(acCodeBuff, pcOut, ucDisplayLen); | |
// acCodeBuff[ucDisplayLen-2] = '.'; | |
// memcpy(acCodeBuff+ucDisplayLen-1, pcOut+ucDisplayLen-2, 2); | |
// ucDisplayLen = ucDisplayLen+1; | |
} | |
// ShowAmount(acCodeBuff, 90, DEFAULT_BACK_COLOR, DEFAULT_FORG_COLOR); | |
ShowAmount(acCodeBuff, 90, RGB565_BLACK, RGB565_WHITE); | |
// ��ȡ�������� | |
sRC = UIWaitKey(iTimeout, 1); | |
// �ȴ�ʱ���ѳ�ʱ | |
if (UI_INPUT_TIMEOUT == sRC) | |
{ | |
return UI_INPUT_TIMEOUT; | |
} | |
if ((sRC >= '0') && (sRC <= '9')) | |
{ | |
// �����ʼ����0��Ч | |
if ((0 == ucInputCnt) && ('0' == sRC)) | |
{ | |
continue; | |
} | |
if (ucInputCnt < ucInputLenMax) | |
{ | |
// ���水��ֵ��pcOut | |
pcOut[ucInputCnt++] = sRC; | |
pcOut[ucInputCnt] = 0; // �ַ��������� | |
// TRACEBUF(pcOut,ucInputCnt); | |
} | |
} | |
else if (UI_INPUT_CLEAR == sRC) | |
{ | |
if (ucInputCnt > 0) | |
{ | |
pcOut[--ucInputCnt] = 0; | |
// UIClearRect(0, 3, LCD_MAX_SEG, 1); | |
} | |
} | |
else if (UI_INPUT_ENTER == sRC) | |
{ | |
pcOut[ucInputCnt] = 0; /* �ַ��������� */ | |
*pucOutLen = ucInputCnt; | |
TRACE("ucInputCnt==%d \r\n", ucInputCnt); | |
TRACEBUF(pcOut, ucInputCnt); | |
// return UI_INPUT_ENTER; | |
if (!(pcOut == NULL)) { | |
VerifyOTP(pcOut); | |
// then set sRC to go to custom Main menu | |
return UI_INPUT_ENTER; | |
} else { | |
return UI_INPUT_ENTER_NULL; | |
} | |
} | |
else if (UI_INPUT_CANCEL == sRC) | |
{ | |
memset(pcOut, 0, ucInputCnt); | |
*pucOutLen = 0; | |
ucInputCnt = 0; | |
return UI_INPUT_CANCEL; | |
} | |
else if (UI_INPUT_MENU == sRC) | |
{ | |
*pucOutLen = 0; | |
return UI_INPUT_MENU; | |
} | |
else | |
{ | |
} | |
} | |
} | |
// custom UIInputWallet func | |
short UIInputWallet(unsigned char ucOutXmode, unsigned char *pcOut, unsigned char *pucOutLen, int iTimeout) | |
{ | |
unsigned char ucInputLenMax; /* ������볤�� */ | |
unsigned char ucInputCnt; /* ������� */ | |
// unsigned char ucKey; | |
unsigned char ucDisplayLen; | |
char acCodeBuff[64]; | |
short sRC; | |
ucInputLenMax = 10; // max no of characters, I believe | |
ucInputCnt = 0; | |
// Lib_LcdDrowArea(DEFAULT_FORG_COLOR, 0, 30, 320, 140); | |
Lib_LcdDrowArea(RGB565_WHITE, 0, 30, 320, 210); | |
// Lib_LcdDrowArea(DEFAULT_BACK_COLOR, 0, 170, 320, 70); | |
pcOut[0] = 0; | |
// my vars | |
const char *reqHash; | |
unsigned char ucCashLen, ucSumArray[12]; | |
while (1) | |
{ | |
// DRAW_TITLE(TIP_ENTER_AMOUNT); | |
DRAW_TITLE_X("Welcome"); | |
UILabelMyText("Enter Wallet ID", ALIGN_L, RGB565_BLACK, RGB565_WHITE, 0, 50 + 10); | |
UILabelShopName("Press O to send OTP, X to cancel!"); | |
memset(acCodeBuff, 0, sizeof(acCodeBuff)); | |
ucDisplayLen = (unsigned char)strlen((char *)pcOut); | |
if (ucDisplayLen < 1) | |
{ | |
memcpy(acCodeBuff, "0000000000", 10); // copies n (4) chars from src ("0.00") to dest (acCodeBuff), in this case | |
// if the below causes any error, remove it | |
memcpy(acCodeBuff + 10 - ucDisplayLen, pcOut, ucDisplayLen); | |
ucDisplayLen = 10; | |
} | |
else | |
{ | |
// memcpy(acCodeBuff, pcOut, ucDisplayLen-2); | |
memcpy(acCodeBuff, pcOut, ucDisplayLen); | |
// acCodeBuff[ucDisplayLen-2] = '.'; | |
// memcpy(acCodeBuff+ucDisplayLen-1, pcOut+ucDisplayLen-2, 2); | |
// ucDisplayLen = ucDisplayLen+1; | |
} | |
// ShowAmount(acCodeBuff, 90, DEFAULT_BACK_COLOR, DEFAULT_FORG_COLOR); | |
ShowAmount(acCodeBuff, 90, RGB565_BLACK, RGB565_WHITE); | |
// ��ȡ�������� | |
sRC = UIWaitKey(iTimeout, 1); | |
// �ȴ�ʱ���ѳ�ʱ | |
if (UI_INPUT_TIMEOUT == sRC) | |
{ | |
return UI_INPUT_TIMEOUT; | |
} | |
if ((sRC >= '0') && (sRC <= '9')) | |
{ | |
// �����ʼ����0��Ч | |
if ((0 == ucInputCnt) && ('0' == sRC)) | |
{ | |
continue; | |
} | |
if (ucInputCnt < ucInputLenMax) | |
{ | |
// ���水��ֵ��pcOut | |
pcOut[ucInputCnt++] = sRC; | |
pcOut[ucInputCnt] = 0; // �ַ��������� | |
// TRACEBUF(pcOut,ucInputCnt); | |
} | |
} | |
else if (UI_INPUT_CLEAR == sRC) | |
{ | |
if (ucInputCnt > 0) | |
{ | |
pcOut[--ucInputCnt] = 0; | |
// UIClearRect(0, 3, LCD_MAX_SEG, 1); | |
} | |
} | |
else if (UI_INPUT_ENTER == sRC) | |
{ | |
pcOut[ucInputCnt] = 0; /* �ַ��������� */ | |
*pucOutLen = ucInputCnt; | |
TRACE("ucInputCnt==%d \r\n", ucInputCnt); | |
TRACEBUF(pcOut, ucInputCnt); | |
if (pcOut != NULL) | |
{ | |
// TODO: this code needs a rewrite | |
reqHash = FetchWallet(pcOut); | |
sRC = UIInputOTP(ALIGN_L, ucSumArray, &ucCashLen, iTimeout, reqHash); | |
return UI_INPUT_ENTER; | |
} | |
else | |
{ | |
} | |
// return UI_INPUT_ENTER | |
} | |
else if (UI_INPUT_CANCEL == sRC) | |
{ | |
memset(pcOut, 0, ucInputCnt); | |
*pucOutLen = 0; | |
ucInputCnt = 0; | |
return UI_INPUT_CANCEL; | |
} | |
else if (UI_INPUT_MENU == sRC) | |
{ | |
*pucOutLen = 0; | |
return UI_INPUT_MENU; | |
} | |
else | |
{ | |
} | |
} | |
} | |
short UISplashScreen(char *pcAmt, unsigned short usY, unsigned short usForeCl, unsigned short usBlackCl) | |
{ | |
uint16_t *pBuf; | |
int iRes; | |
unsigned int Bufsize; | |
uint16_t height = 64; | |
Bufsize = 320 * height * 2; | |
pBuf = (uint16_t *)Lib_malloc(Bufsize); | |
if (pBuf == NULL) | |
{ | |
return -1; | |
} | |
WIDGET_TEXT Text; | |
Text.ForegroundColorText = usForeCl; | |
Text.BackgroundColorText = usBlackCl; | |
Text.h = height; | |
Text.FontTextEn = FONT_28X56; | |
Text.FontTextCn = FONT_56X56; | |
Text.pText = (uint8_t *)pcAmt; | |
Text.TextLen = strlen((const char *)Text.pText); | |
Text.Align = ALIGN_M; | |
Text.w = 320; | |
iRes = Lib_LcdCreatText(&Text, pBuf, Bufsize); | |
if (0 > iRes) | |
{ | |
Lib_free(pBuf); | |
return -1; | |
} | |
Lib_LcdDispMemcpy(pBuf, 0, usY, Text.w, Text.h); | |
UILabelMyText("Welcome to UCARD", ALIGN_M, RGB565_WHITE, BGBACK_PURPLE, 0, (170 + 10)); | |
Lib_LcdRefresh(); | |
Lib_free(pBuf); | |
return TY_OK; // 0 | |
} | |
// to be called in main.c | |
// ucOutXmode:- sets the align | |
short UIShow(unsigned char ucOutXmode, int iTimeout) | |
{ | |
short sRC; | |
Lib_LcdDrowArea(BGBACK_PURPLE, 0, 30, 320, 210); | |
while (1) | |
{ | |
// call UISplashScreen func | |
UISplashScreen("UCARD", 90, DEFAULT_BACK_COLOR, BGBACK_PURPLE); | |
sRC = UIWaitKey(iTimeout, 1); | |
if (UI_INPUT_TIMEOUT == sRC) | |
{ | |
return UI_INPUT_TIMEOUT; | |
} | |
if (UI_INPUT_ENTER == sRC) | |
{ | |
return UI_INPUT_ENTER; | |
} | |
else if (UI_INPUT_CANCEL == sRC) | |
{ | |
return UI_INPUT_CANCEL; | |
} | |
else if (UI_INPUT_MENU == sRC) | |
{ | |
return UI_INPUT_MENU; | |
} | |
else | |
{ | |
// an empty return gives a warning | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment