From 605cb0ca371517c7a5cff79b4ef2dfdfe22ab4fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anton=20Luka=20=C5=A0ijanec?= Date: Fri, 24 Sep 2021 22:53:01 +0200 Subject: i hope it's fixed now (magic?), though there's still a memory leak --- src/api.c | 47 ++++++++++++++++++++++++++++++++++------------- src/h.c | 43 +++++++++++++++++++++++++------------------ src/ui.c | 4 +++- 3 files changed, 62 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/api.c b/src/api.c index 43aca84..c405cff 100644 --- a/src/api.c +++ b/src/api.c @@ -107,10 +107,27 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn } pass->api_io.user->status &= ~DC_IN_PROGRESS; pass->api_io.user = dc_addr_user(program, DC_ISAE(program->users), pass->api_io.user, DC_MAY_FREE); - if (path != DC_JSON_MESSAGE_AUTHOR && path != DC_JSON_MESSAGE_REFOBJ_AUTHOR && path != DC_JSON_MESSAGE_MENTION_USER && path != DC_JSON_MESSAGE_REFOBJ_MENTION_USER && getenv("DC_0") /* override if those are disabled */) /* those expect a user parsed */ - pass->api_io.user = NULL; /* when implementing parser: handle OBJECT_END */ - else /* if something goes wrong - if those handlers do not null user, IO_MEMB_GC will */ - pass->api_io.user->status |= DC_EXPLICIT_NULL; /* but will not free. */ + switch (path) { + case DC_JSON_MESSAGE_AUTHOR: + if (pass->api_io.message) + pass->api_io.message->user = pass->api_io.user; + break; + case DC_JSON_MESSAGE_REFOBJ_AUTHOR: + if (pass->api_io.message && pass->api_io.message->reply) + pass->api_io.message->reply->user = pass->api_io.user; + break; + case DC_JSON_MESSAGE_MENTION_USER: + if (pass->api_io.message) + dc_add_user(DC_ISAE(pass->api_io.message->users), pass->api_io.user, DC_UNSET); + break; + case DC_JSON_MESSAGE_REFOBJ_MENTION_USER: + if (pass->api_io.message && pass->api_io.message->reply) + dc_add_user(DC_ISAE(pass->api_io.message->reply->users), pass->api_io.user, DC_UNSET); + break; + default: + break; + } + pass->api_io.user = NULL; } if ((path == DC_JSON_DM || path == DC_JSON_GUILD_CHANNEL) && reason == LEJPCB_OBJECT_START) { pass->api_io.channel = dc_channel_init(); @@ -140,9 +157,10 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn struct dc_channel * ch; if ((ch = dc_find_channel(program->channels, program->channels_length, pass->api_io.channel->id))) DC_TRANSFER_CHANNEL(pass->api_io.channel, ch); - pass->api_io.channel = dc_addr_channel(program, DC_ISAN, pass->api_io.channel, DC_MAY_FREE | DC_REPLACE); + pass->api_io.channel = dc_addr_channel(program, DC_ISAE(program->channels), pass->api_io.channel, DC_MAY_FREE | DC_REPLACE); if (!dc_find_ll_channel(client->guilds[0]->channel, pass->api_io.channel->id)) { fprintf(stderr, "new DM id=%llu (:\n", pass->api_io.channel->id); + pass->api_io.channel->next = NULL; *channel = pass->api_io.channel; } pass->api_io.channel->guild = client->guilds[0]; @@ -160,7 +178,12 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn struct dc_channel * ch; if ((ch = dc_find_channel(program->channels, program->channels_length, pass->api_io.channel->id))) DC_TRANSFER_CHANNEL(pass->api_io.channel, ch); - pass->api_io.channel = *channel = dc_addr_channel(program, DC_ISAN, pass->api_io.channel, DC_MAY_FREE | DC_REPLACE); + pass->api_io.channel = dc_addr_channel(program, DC_ISAE(program->channels), pass->api_io.channel, DC_MAY_FREE | DC_REPLACE); + if (!dc_find_ll_channel(pass->api_io.guild->channel, pass->api_io.channel->id)) { + fprintf(stderr, "new channel id=%llu (:\n", pass->api_io.channel->id); + pass->api_io.channel->next = NULL; + *channel = pass->api_io.channel; + } struct dc_permission ** pe = &pass->api_io.channel->permission; while (*pe) { /* fix all permission pointers to channel to this new channel */ (*pe)->channel = pass->api_io.channel; @@ -196,7 +219,6 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn dc_add_guild(DC_ISAE(client->guilds), pass->api_io.guild, DC_UNSET); pass->api_io.guild = NULL; /* we're done, NULL it or PROBLEMS WILL APPEAR!!! */ } -#if 0 if (path == DC_JSON_GUILD_ROLE && reason == LEJPCB_OBJECT_START) { pass->api_io.role = dc_role_init(); pass->api_io.role->status |= DC_IN_PROGRESS; @@ -211,7 +233,7 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn struct dc_role * ro; if ((ro = dc_find_role(program->roles, program->roles_length, pass->api_io.role->id))) dc_transfer_role(pass->api_io.role, ro); - pass->api_io.role = dc_addr_role(program, DC_ISAE(program->roles), pass->api_io.role, DC_MAY_FREE | DC_REPLACE); + pass->api_io.role = dc_add_role(DC_ISAE(program->roles), pass->api_io.role, DC_MAY_FREE | DC_REPLACE); struct dc_role ** role; role = &pass->api_io.guild->role; while (*role) @@ -224,7 +246,6 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn } if (path == DC_JSON_MEMBERSHIP && (reason == LEJPCB_OBJECT_END || reason == LEJPCB_OBJECT_START)) pass->api_io.id = 0; -#endif if (reason & LEJP_FLAG_CB_IS_VALUE) { struct dc_user * user; /* this is just a var for you use */ struct dc_role * role; /* now we rely on -Wuninitialized to detect weird stuff */ @@ -286,7 +307,6 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn if (pass->api_io.channel && !pass->api_io.channel->topic) pass->api_io.channel->topic = strdup(ctx->buf); break; -#if 0 case DC_JSON_GUILD_ROLE_ID: if (pass->api_io.role) pass->api_io.role->id = strtoull(ctx->buf, NULL, 10); @@ -297,10 +317,10 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn break; case DC_JSON_GUILD_ROLE_PERMISSION: if (pass->api_io.role) { - if (atoi(ctx->buf) & DC_ADMIN) + if (strtoull(ctx->buf, NULL, 10) & DC_ADMIN) pass->api_io.role->permissions = DC_ALL_PERMISSIONS; else - pass->api_io.role->permissions = atoi(ctx->buf); + pass->api_io.role->permissions = strtoull(ctx->buf, NULL, 10); } break; case DC_JSON_MEMBERSHIP_USER: @@ -331,7 +351,6 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn fprintf(stderr, "new role membership user %s#%d (usr=%llu role=%llu)\n", user->username ? user->username : "", user->discriminator, user->id, role->id); pass->api_io.id = 0; break; -#endif default: break; } @@ -439,6 +458,8 @@ static int dc_lws_cb (struct lws * wsi, enum lws_callback_reasons rs, void * us, dc_api_i(pass->api_io); pass->api_io.status &= ~DC_FROM_LWS; } + DC_API_IO_GC(pass->api_io); /* frees all unfinished parsing objects */ + pass->packet = DC_NONE; pass->api_io.client->pass = NULL; dc_lws_pass_free(pass, DC_UNSET); /* called the last time us ptr & wsi r still */ break; /* accessible - we can free the struct that was passed in as a heap ptr */ diff --git a/src/h.c b/src/h.c index 499885b..bd20bf8 100644 --- a/src/h.c +++ b/src/h.c @@ -53,15 +53,13 @@ enum dc_status { /* theese are flags and should be and-checked */ DC_EVERYONE = 1 << 25, /* role applies to all guild users */ DC_INTERNAL = DC_FROM_LWS | DC_FROM_API, /* call originates from an internal function */ }; /* note: when checking status, first check for DC_OK, if it's set then disregard errors! */ -enum dc_permissions { /* other permissions exist, but are not implemented/understood */ - DC_ADMIN = 1 << 3, /* this is incredibly retarded, why is this SEPARATE?!? - admins */ - DC_CHANNEL_VIEW = 1 << 10, /* all enum fields here have values same as the server values */ - DC_MESSAGE_SEND = 1 << 11, - DC_MESSAGE_READ = 1 << 16, /* na tistem vegova serverju sem lahko pošiljal ne pa bral sporočil */ - DC_VOICE_LISTEN = 1 << 20, - DC_VOICE_SPEAK = 1 << 21, - DC_ALL_PERMISSIONS = DC_ADMIN | DC_CHANNEL_VIEW | DC_MESSAGE_SEND | DC_MESSAGE_READ | DC_VOICE_LISTEN | DC_VOICE_SPEAK /* admins get this@parsing, UI need not check admin separatly */ -}; /* all enum fields here have values same as the values that the server sends */ +#define DC_ADMIN (1 << 3) /* not all enum fields are implemented/understood */ +#define DC_CHANNEL_VIEW (1 << 10) /* all enum fields here have values same as the server values */ +#define DC_MESSAGE_SEND (1 << 11) /* this is not an enum as there are over 40 permissions */ +#define DC_MESSAGE_READ (1 << 16) /* na tistem vegova serverju sem lahko pošiljal ne pa bral sporočil */ +#define DC_VOICE_LISTEN (1 << 20) /* ISO C enums are at most int-wide */ +#define DC_VOICE_SPEAK (1 << 21) +#define DC_ALL_PERMISSIONS (DC_ADMIN | DC_CHANNEL_VIEW | DC_MESSAGE_SEND | DC_MESSAGE_READ | DC_VOICE_LISTEN | DC_VOICE_SPEAK) /* admins get this@parsing, UI need not check admin separatly */ enum dc_channel_type { /* other types exist, but are not implemented/understood */ DC_GC = 0, /* guild channel */ DC_DM = 1, /* direct messages channel */ @@ -515,9 +513,15 @@ struct dc_message { struct dc_message * next; /* next message (linked list of all messages of dc_channel) */ struct dc_message * reply; /* nofree - this message replies to another message or NULL */ enum dc_status status; + DC_ISASQ(user); /* yesfree pointer array only - mentions */ + DC_ISASQ(role); /* yesfree pointer array only - mentions */ + DC_ISASQ(channel); /* yesfree pointer array only - mentions */ }; struct dc_message * dc_message_init () { struct dc_message * s = calloc(1, sizeof(*s)); + DC_ISASIQ(user); + DC_ISASIQ(role); + DC_ISASIQ(channel); return s; } void dc_message_free (struct dc_message * s, enum dc_status t) { @@ -525,6 +529,9 @@ void dc_message_free (struct dc_message * s, enum dc_status t) { return; free(s->message); free(s->attachment); + free(s->users); + free(s->roles); + free(s->channel); if (!(t & DC_REPLACE)) free(s); } @@ -532,7 +539,7 @@ struct dc_role { DC_STRUCT_PREFIX char * name; /* yesfree */ unsigned long long int id; - enum dc_permissions permissions; /* this are guild permission */ + unsigned long long int permissions; /* this are guild permission */ struct dc_guild * guild; /* nofree - owner of the role */ struct dc_role * next; /* nofree - next role (linked list of all roles of dc_guild) */ DC_ISASQ(user); /* yesfree pointer array only - users with this role */ @@ -571,8 +578,8 @@ void dc_user_free (struct dc_user * s, enum dc_status t) { } struct dc_permission { /* permissions can be individual on a per-channel basis */ DC_STRUCT_PREFIX /* assume all permissions */ - enum dc_permissions allow; - enum dc_permissions deny; + unsigned long long int allow; + unsigned long long int deny; struct dc_channel * channel; /* nofree - on which channel does it apply */ struct dc_user * user; /* nofree - non-null if permission applies to a user */ struct dc_role * role; /* nofree - non-null if it applies to a role */ @@ -753,12 +760,12 @@ void dc_api_stack (struct dc_api_io); } #define DC_ADDR_X(x, y) struct dc_##x * dc_addr_##x (struct dc_program * p, struct dc_##x *** a, size_t * so, size_t * l, struct dc_##x * u, enum dc_status s) { \ struct dc_##x * us; \ - if (!a) { \ - if (u != (us = dc_add_##x(&p->x##s, &p->x##s_sizeof, &p->x##s_length, u, s))) \ - return us; \ - } else \ - if (u != (us = dc_add_##x(a, so, l, u, s))) \ - return us; \ + if (!a) \ + us = dc_add_##x(&p->x##s, &p->x##s_sizeof, &p->x##s_length, u, s); \ + else \ + us = dc_add_##x(a, so, l, u, s); \ + if (us != u) \ + return us; \ struct dc_api_io io; \ memset(&io, 0, sizeof(io)); \ io.type = DC_API_##y; \ diff --git a/src/ui.c b/src/ui.c index f2dbe7a..279ef4f 100644 --- a/src/ui.c +++ b/src/ui.c @@ -29,7 +29,7 @@ void dc_ui_spawn_message (struct dc_message * m, struct dc_ui_data * d) { /* !m GtkWidget * w, * w2; #define DC_USMTL 32 char t[DC_USMTL]; - g_autoptr(gchar) c = g_key_file_get_string(d->k, "discord.c", "strftime", NULL); + char * c; GtkGrid * g = GTK_GRID(gtk_builder_get_object(d->b, "dc_main_messages")); if (!m) { while (gtk_grid_get_child_at(g, 0, 0)) @@ -60,7 +60,9 @@ void dc_ui_spawn_message (struct dc_message * m, struct dc_ui_data * d) { /* !m snprintf(t, DC_USMTL, "%s#%04d", m->user->username, m->user->discriminator); gtk_container_add(GTK_CONTAINER(b), gtk_label_new(t)); /* TODO: implement parsing markup here: bold, italic, underline; REMOVE < character; implement tags, timestamps, channels and spoilers with GTK ahrefs */ + c = g_key_file_get_string(d->k, "discord.c", "strftime", NULL); strftime(t, DC_USMTL, c ? strcmp(c, "") ? c : "%c" : "%c", localtime(&m->time)); /* singlethreaded only */ + free(c); gtk_container_add(GTK_CONTAINER(b), gtk_label_new(t)); g_object_set_data(G_OBJECT(b), "message", m); gtk_grid_attach(g /* grid */, b /* widget to insert */, 0 /* left */, i /* top */, 1 /* width */, 1 /* height */); -- cgit v1.2.3