[ADD/WIP] Actually make the login screen "usable"

It now actually does a login request, and notifies you of the status.
I'll still need to make sure that it stores the user somewhere...
This commit is contained in:
lda 2024-02-07 18:08:43 +01:00
parent dad4a844a6
commit 3612d306af
9 changed files with 227 additions and 75 deletions

View File

@ -5,7 +5,10 @@
#include <stddef.h>
#include <string.h>
#define INITIAL_CAPACITY 10
#include <gint/keyboard.h>
#include <gint/display.h>
#define INITIAL_CAPACITY 11
typedef struct hm_bucket {
bool used;
@ -26,12 +29,12 @@ struct hashmap {
static size_t string_hash(char *str)
{
size_t length = strlen(str);
size_t hash = 0;
size_t hash = 5381;
size_t i;
for (i = 0; i < strlen(str); i++)
{
hash = (5 * (hash + str[i])) ^ i; /* shitty hashing algo */
hash = (hash << 5) + hash + str[i];
}
return hash;
@ -61,6 +64,8 @@ void utils_hashmap_add(hashmap_t *hm, char *key, void *val)
bool found = false;
size_t i;
if (!hm || !key || !val)
{
return;
@ -84,11 +89,17 @@ void utils_hashmap_add(hashmap_t *hm, char *key, void *val)
if (found) return;
hm->buckets = reallocarray(
hm->buckets, ++hm->capacity, sizeof(hm_bucket_t)
hm->buckets, hm->capacity + INITIAL_CAPACITY, sizeof(hm_bucket_t)
);
hm->buckets[hm->capacity - 1].used = true;
hm->buckets[hm->capacity - 1].string = utils_strcpy(key);
hm->buckets[hm->capacity - 1].value = val;
for (i = 0; i < INITIAL_CAPACITY; i++)
{
hm->buckets[i + hm->capacity].used = false;
}
hm->buckets[hm->capacity].used = true;
hm->buckets[hm->capacity].string = utils_strcpy(key);
hm->buckets[hm->capacity].value = val;
hm->capacity += INITIAL_CAPACITY;
}
void * utils_hashmap_get(hashmap_t *hm, char *key)
@ -105,6 +116,13 @@ void * utils_hashmap_get(hashmap_t *hm, char *key)
hash = string_hash(key);
lhsh = hash % hm->capacity;
if (!strcmp(key, "login"))
{
dclear(C_RED);
dprint(1, 1, C_WHITE, "Hash: %d", lhsh);
dupdate();
getkey();
}
for (probing = 0; probing < (lhsh); probing++)
{
size_t idx = (lhsh + probing) % hm->capacity;
@ -117,6 +135,62 @@ void * utils_hashmap_get(hashmap_t *hm, char *key)
return NULL;
}
void * utils_hashmap_set(hashmap_t *hm, char *key, void *value)
{
size_t hash, probing;
size_t lhsh;
bool found = false;
void *prev = NULL;
size_t i;
if (!hm || !key || !value)
{
return NULL;
}
hash = string_hash(key);
lhsh = hash % hm->capacity;
if (!strcmp(key, "login"))
{
dclear(C_RED);
dprint(1, 1, C_WHITE, "Hash: %d", lhsh);
dupdate();
getkey();
}
for (probing = 0; probing < (lhsh); probing++)
{
size_t idx = (lhsh + probing) % hm->capacity;
if (hm->buckets[idx].used && !strcmp(key, hm->buckets[idx].string))
{
free(hm->buckets[idx].string);
prev = hm->buckets[idx].value;
found = true;
hm->buckets[idx].string = utils_strcpy(key);
hm->buckets[idx].value = value;
break;
}
}
if (found) return prev;
hm->buckets = reallocarray(
hm->buckets, hm->capacity + INITIAL_CAPACITY, sizeof(hm_bucket_t)
);
for (i = 0; i < INITIAL_CAPACITY; i++)
{
hm->buckets[i + hm->capacity].used = false;
}
hm->buckets[hm->capacity].used = true;
hm->buckets[hm->capacity].string = utils_strcpy(key);
hm->buckets[hm->capacity].value = value;
hm->capacity += INITIAL_CAPACITY;
return NULL;
}
void * utils_hashmap_del(hashmap_t *hm, char *key)
{

View File

@ -90,6 +90,7 @@ void http_transfer_set_data(http_transfer_t *t, void *data, size_t len)
}
t->request = malloc(len);
t->req_length = len;
memcpy(t->request, data, len);
}
@ -145,6 +146,13 @@ void http_transfer_send(http_transfer_t *t)
add_header("\r\n");
free(line);
if (t->request)
{
len_line = snprintf(NULL, 0, "%ld", t->req_length);
line = malloc(len_line + 1);
snprintf(line, len_line + 1, "%ld", t->req_length);
utils_hashmap_add(t->req_header, "Content-Length", line);
}
while (utils_hashmap_list(t->req_header, &key, (void **) &val))
{
@ -157,7 +165,6 @@ void http_transfer_send(http_transfer_t *t)
}
add_header("\r\n");
len = strlen(header);
if (t->request)
{

View File

@ -32,13 +32,13 @@ typedef struct ui_session {
struct ui_screen;
typedef void * (*screen_setup_t)(struct ui_screen *that);
typedef void (*screen_focus_t)(struct ui_screen *that);
typedef void (*screen_event_t)(struct ui_screen *that, jevent event);
typedef void * (*screen_focus_t)(struct ui_screen *that);
typedef void * (*screen_event_t)(struct ui_screen *that, jevent event);
typedef struct ui_screen {
ui_session_t *owner;
void *widget;
hashmap_t *data; /* Personal data within screen */
void *data;
screen_setup_t init;
screen_focus_t on_focus;

View File

@ -8,6 +8,6 @@
extern void * ui_infos_init(ui_screen_t *that);
extern void * ui_login_init(ui_screen_t *that);
extern void ui_login_focus(ui_screen_t *that);
extern void ui_login_event(ui_screen_t *that, jevent e);
extern void * ui_login_focus(ui_screen_t *that);
extern void * ui_login_event(ui_screen_t *that, jevent e);
#endif

View File

@ -14,6 +14,7 @@ typedef struct hashmap hashmap_t;
extern hashmap_t * utils_new_hashmap(void);
extern void utils_hashmap_add(hashmap_t *, char *, void *);
extern void * utils_hashmap_get(hashmap_t *, char *);
extern void * utils_hashmap_set(hashmap_t *, char *, void *);
extern void * utils_hashmap_del(hashmap_t *, char *);
extern bool utils_hashmap_list(hashmap_t *, char **, void **);
extern void utils_free_hashmap(hashmap_t *);

View File

@ -1,5 +1,8 @@
#include <matrix.h>
#include <gint/display.h>
#include <gint/keyboard.h>
#include <stdlib.h>
#include <string.h>
@ -86,6 +89,10 @@ m_user_t *matrix_login(char *server, char *user, char *password)
request,
"type", utils_string_as_json(utils_strcpy("m.login.password"))
);
utils_hashmap_add(
request,
"password", utils_string_as_json(utils_strcpy(password))
);
utils_hashmap_add(
request,
"initial_device_display_name",
@ -110,18 +117,27 @@ m_user_t *matrix_login(char *server, char *user, char *password)
data = utils_json_write(request, &data_len);
utils_free_json(request);
data_len = strlen(data);
trans = http_transfer_create(
HTTP_POST, server, "/_matrix/client/v3/login"
);
http_transfer_add_header(trans, "User-Agent", "Mastrix/1.0 (fx-CG50)");
http_transfer_set_data(trans, data, data_len);
http_transfer_set_data(trans, data, strlen(data));
http_transfer_send(trans);
free(data);
if (http_transfer_code(trans) != 200)
{
char *msg = http_get_reply_data(trans, &data_len);
ret = NULL;
dclear(C_RED);
dprint(1, 1, C_WHITE, "Code %d", http_transfer_code(trans));
dprint(1, 11, C_WHITE, "%.*s", data_len, msg);
dupdate();
getkey();
goto end;
}

View File

@ -28,8 +28,7 @@ int main(void)
int in, out;
usb_fxlink_header_t reply;
/*easter_goda();
getkey();*/
getkey();
dclear(C_WHITE);
dtext(1, 1, C_BLACK, "Waiting for USB link...");

View File

@ -37,17 +37,18 @@ ui_session_t *ui_create_session(void)
}
size_t ui_add_screen(ui_session_t *ui, ui_screen_t *screen)
{
size_t ret;
if (!ui || !screen)
{
return 0;
}
screen->owner = ui;
screen->data = utils_new_hashmap();
screen->widget = screen->init(screen);
ui_set_screen(ui, utils_array_add(ui->screens, screen));
ui_set_screen(ui, (ret = utils_array_add(ui->screens, screen)));
return ret;
}
ui_screen_t * ui_set_screen(ui_session_t *ui, size_t idx)
{
@ -68,30 +69,41 @@ ui_screen_t * ui_set_screen(ui_session_t *ui, size_t idx)
jscene_show_and_focus(ui->justui_screen, indexed->widget);
if (indexed->on_focus)
{
indexed->on_focus(indexed);
void *widget = indexed->on_focus(indexed);
if (widget)
{
jscene_set_focused_widget(ui->justui_screen, widget);
}
}
return indexed;
}
static void ui_manage_event(ui_session_t *ui, jevent e)
static bool ui_manage_event(ui_session_t *ui, jevent e)
{
ui_screen_t *screen;
void *widget;
if (!ui)
{
return;
return false;
}
if (ui->current_screen == -1)
{
return;
return false;
}
screen = utils_array_get(ui->screens, ui->current_screen);
if (!screen || !screen->on_event)
{
return;
return false;
}
screen->on_event(screen, e);
widget = screen->on_event(screen, e);
if (widget)
{
jscene_set_focused_widget(ui->justui_screen, widget);
return true;
}
return false;
}
void ui_session_loop(ui_session_t *ui)
{
@ -107,7 +119,12 @@ void ui_session_loop(ui_session_t *ui)
dupdate();
continue;
}
ui_manage_event(ui, e);
if (ui_manage_event(ui, e))
{
dclear(C_WHITE);
jscene_render(ui->justui_screen);
dupdate();
}
key = e.key.key;
}
}

View File

@ -15,6 +15,14 @@
extern const bopti_image_t mastrix;
typedef struct login_data {
jinput *server, *login, *password;
void *focusing;
jlabel *error;
char *delegated;
} login_data_t;
void draw_mastrix(int x, int y)
{
dimage(x, y, &mastrix);
@ -29,9 +37,13 @@ void * ui_login_init(ui_screen_t *that)
jlabel *login_to_mastrix = jlabel_create(
"Login to Matrix", login_widget
);
login_data_t *data;
jlabel *error;
jpainted *logo;
login_content = jwidget_create(login_widget);
that->data = malloc(sizeof(login_data_t));
data = that->data;
data->delegated = NULL;
jlayout_set_vbox(login_widget)->spacing = 3;
jwidget_set_padding(login_widget, 0, 0, 0, 0);
@ -75,45 +87,34 @@ void * ui_login_init(ui_screen_t *that)
jwidget_set_stretch(password, 1, 0, true);
/* Store those so that they can be referenced later */
utils_hashmap_add(that->data, "server", server);
utils_hashmap_add(that->data, "login", login);
utils_hashmap_add(that->data, "password", password);
utils_hashmap_add(that->data, "error", error);
utils_hashmap_add(that->data, "focusing", "server");
data->server = server;
data->login = login;
data->password = password;
data->focusing = server;
data->error = error;
return login_widget;
}
void ui_login_focus(ui_screen_t *that)
void * ui_login_focus(ui_screen_t *that)
{
char *focus_to = utils_hashmap_get(that->data, "focusing");
if (!strcmp(focus_to, "server"))
{
void *server = utils_hashmap_get(that->data, "server");
jscene_show_and_focus(that->owner->justui_screen, server);
}
else if (!strcmp(focus_to, "login"))
{
void *login = utils_hashmap_get(that->data, "login");
jscene_show_and_focus(that->owner->justui_screen, login);
}
else if (!strcmp(focus_to, "password"))
{
void *password = utils_hashmap_get(that->data, "password");
jscene_show_and_focus(that->owner->justui_screen, password);
}
login_data_t *data = that->data;
return data->focusing;
}
void ui_login_event(ui_screen_t *that, jevent e)
void * ui_login_event(ui_screen_t *that, jevent e)
{
char *focus_to = utils_hashmap_get(that->data, "focusing");
login_data_t *data = that->data;
if (e.type == JINPUT_VALIDATED)
{
if (!strcmp(focus_to, "server"))
jinput *server, *login, *password;
jlabel *error = data->error;
server = data->server;
login = data->login;
password = data->password;
if (data->focusing == data->server)
{
jinput *server = utils_hashmap_get(that->data, "server");
char *delegated = NULL;
char *serv_name = (char *) jinput_value(server);
m_delegation_t status;
@ -129,52 +130,89 @@ void ui_login_event(ui_screen_t *that, jevent e)
{
case DELEG_FAIL_ERROR:
jlabel_asprintf(
utils_hashmap_get(that->data, "error"),
error,
"Couldn't find a correct servname for '%s'.",
serv_name
);
jlabel_set_text_color(
utils_hashmap_get(that->data, "error"),
C_RED
);
jlabel_set_text_color(error, C_RED);
break;
case DELEG_IGNORE:
delegated = utils_strcpy(serv_name);
break;
case DELEG_SUCCESS:
jlabel_asprintf(
utils_hashmap_get(that->data, "error"),
error,
"'%s' => '%s'",
serv_name, delegated
);
jlabel_set_text_color(
utils_hashmap_get(that->data, "error"),
C_GREEN
);
jlabel_set_text_color(error, C_GREEN);
break;
case DELEG_FAIL_PROMPT:
jlabel_set_text_color(error, C_RED);
case DELEG_PROMPT:
jlabel_asprintf(
utils_hashmap_get(that->data, "error"),
error,
"Please enter the delegation for '%s'.",
serv_name
);
jlabel_set_text_color(
utils_hashmap_get(that->data, "error"),
C_BLACK
);
break;
}
if (delegated)
{
char *copy = utils_hashmap_get(that->data, "delegated");
if (copy)
{
free(copy);
}
utils_hashmap_add(that->data, "delegated", delegated);
if (data->delegated) free(data->delegated);
data->delegated = delegated;
data->focusing = data->login;
return ui_login_focus(that);
}
return NULL;
}
else if (data->focusing == data->login)
{
char *username = (char *) jinput_value(data->login);
if (!strcmp(username, ""))
{
jlabel_set_text_color(error, C_RED);
jlabel_asprintf(error, "Empty usernames are not allowed.");
return NULL;
}
data->focusing = data->password;
return ui_login_focus(that);
}
else if (data->focusing == data->password)
{
char *username = (char *) jinput_value(data->login);
char *password = (char *) jinput_value(data->password);
m_user_t *user;
if (!strcmp(password, ""))
{
jlabel_set_text_color(error, C_RED);
jlabel_asprintf(error, "Empty password are not allowed.");
return NULL;
}
return;
/* Submit the login process out... */
jlabel_set_text_color(error, C_BLACK);
jlabel_asprintf(error, "Logging in...");
user = matrix_login(data->delegated, username, password);
if (user)
{
jlabel_set_text_color(error, C_GREEN);
jlabel_asprintf(error, "Logged in (DID: %s)!", user->device_id);
/* TODO: Store user data *somewhere* */
return NULL; /* TODO: Change screen, since we're logged in */
}
else
{
jlabel_set_text_color(error, C_RED);
jlabel_asprintf(error, "Couldn't login as '%s'", username);
}
return NULL;
}
}
return NULL;
}