Skip to content

Instantly share code, notes, and snippets.

@ashraf267
Created August 16, 2023 05:29
Show Gist options
  • Save ashraf267/40a1ce10b0967ade23a406faca6418bf to your computer and use it in GitHub Desktop.
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
#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