diff options
Diffstat (limited to '')
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | src/api.c | 167 | ||||
-rw-r--r-- | src/h.c | 86 |
3 files changed, 194 insertions, 62 deletions
@@ -46,3 +46,6 @@ gensupp: cc misc/valgrind-supp-extractor.c -otmp/vse G_SLICE=always-malloc G_DEBUG=gc-friendly valgrind $(VGARGS) --gen-suppressions=all ./discord.c tmp/vse < valgrind-out.txt > tmp/gend.supp + +echo: + echo $$DC_E @@ -30,14 +30,10 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn struct dc_lws_pass * pass = ctx->user; /* correct. op and t should come first, etc. */ struct dc_client * client = pass->api_io.client; struct dc_program * program = pass->api_io.program; - struct dc_user * user; /* don't confuse this with client->user, this is just a var for you use */ pass->json_reason = reason; if (reason == LEJPCB_FAILED || reason == LEJPCB_COMPLETE || reason == LEJPCB_START) { - if (pass->parsing_status) - *pass->parsing_status &= ~DC_IN_PROGRESS; DC_API_IO_GC(pass->api_io); pass->packet = DC_NONE; - pass->parsing_status = NULL; return '\0'; } if (getenv("DC_J")) /* print json to standard error */ @@ -89,8 +85,6 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn if (client->user->status & DC_INCOMPLETE) { /* we can't just check if */ client->user->discriminator = atoi(ctx->buf); /* !discriminat, */ client->user->status &= ~DC_INCOMPLETE; /* because 0 is allowd */ - if (getenv("DC_C")) - dc_interrupted++; } break; default: @@ -98,19 +92,26 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn } return '\0'; /* because we use same checks for parsing other users GUILD_MEMBER_UPDATE */ } - if ((path == DC_JSON_ME || path == DC_JSON_USER || path == DC_JSON_MESSAGE_AUTHOR || path == DC_JSON_MESSAGE_REFOBJ_AUTHOR || path == DC_JSON_MESSAGE_MENTION_USER || path == DC_JSON_MESSAGE_REFOBJ_MENTION_USER) && reason == LEJPCB_OBJECT_START) { /* user parsing start */ + if ((path == DC_JSON_ME || path == DC_JSON_USER || path == DC_JSON_MESSAGE_AUTHOR || path == DC_JSON_MESSAGE_REFOBJ_AUTHOR || path == DC_JSON_MESSAGE_MENTION_USER || path == DC_JSON_MESSAGE_REFOBJ_MENTION_USER || path == DC_JSON_MEMBER) && reason == LEJPCB_OBJECT_START) { /* dc_user_free(pass->api_io.user); */ /* parser branches MUST ALWAYS set to 0 */ pass->api_io.user = dc_user_init(); /* and possibly free api_io members after! */ pass->api_io.user->status |= DC_IN_PROGRESS; /* if we never get here again */ } - if ((path == DC_JSON_ME || path == DC_JSON_USER || path == DC_JSON_MESSAGE_AUTHOR || path == DC_JSON_MESSAGE_REFOBJ_AUTHOR || path == DC_JSON_MESSAGE_MENTION_USER || path == DC_JSON_MESSAGE_REFOBJ_MENTION_USER) && reason == LEJPCB_OBJECT_END) { /* if it was just a user */ + if ((path == DC_JSON_ME || path == DC_JSON_USER || path == DC_JSON_MESSAGE_AUTHOR || path == DC_JSON_MESSAGE_REFOBJ_AUTHOR || path == DC_JSON_MESSAGE_MENTION_USER || path == DC_JSON_MESSAGE_REFOBJ_MENTION_USER || path == DC_JSON_MEMBER) && reason == LEJPCB_OBJECT_END) { + if (getenv("DC_R")) + assert(pass->api_io.user->id); + if (!pass->api_io.user->id) { + dc_user_free(pass->api_io.user, DC_UNSET); + pass->api_io.user = NULL; + return '\0'; + } 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 */ + 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. */ - } /* user parsing end */ + } if ((path == DC_JSON_DM || path == DC_JSON_GUILD_CHANNEL) && reason == LEJPCB_OBJECT_START) { pass->api_io.channel = dc_channel_init(); pass->api_io.channel->status |= DC_IN_PROGRESS; @@ -119,6 +120,12 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn struct dc_channel ** channel = &client->guilds[0]->channel; /* 1. guild = DMs */ while (*channel) channel = &(*channel)->next; + if (!pass->api_io.channel->id) { + dc_channel_free(pass->api_io.channel, DC_UNSET); + pass->api_io.channel = NULL; + return '\0'; + } + pass->api_io.channel->next = NULL; pass->api_io.channel->guild = client->guilds[0]; /* client->guilds[0] always exists */ pass->api_io.channel->status &= ~DC_IN_PROGRESS; free(pass->api_io.channel->topic); @@ -130,8 +137,9 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn strcat(pass->api_io.channel->topic, pass->api_io.channel->users[i]->username); strcat(pass->api_io.channel->topic, buf); } - if ((struct dc_channel * ch = dc_find_channel(program->channels, program->channels_length, pass->api_io.channel->id))) - DC_TRANSFER_CHANNEL(pass->api_io.channel->id, ch); + 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); 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); @@ -141,28 +149,87 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn pass->api_io.channel = NULL; /* we're done, NULL it or PROBLEMS WILL APPEAR!!! */ } if (path == DC_JSON_GUILD_CHANNEL && reason == LEJPCB_OBJECT_END) { + if (!pass->api_io.channel->id || !DC_CHANNEL_SUPPORTED(pass->api_io.channel->type)) { + dc_channel_free(pass->api_io.channel, DC_UNSET); + pass->api_io.channel = NULL; + return '\0'; + } struct dc_channel ** channel = &pass->api_io.guild->channel; while (*channel) channel = &(*channel)->next; - pass->api_io.channel = dc_addr_channel(program, DC_ISAN, pass->api_io.channel, DC_MAY_FREE | DC_REPLACE); - pass->api_io.channel = NULL; + 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); + 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; + pe = &(*pe)->next; + } + pass->api_io.channel = NULL; /* we're done, NULL it or */ } - if (path == DC_JSON_GUILD && reason == LEJPCB_OBJECT_START) { /* guild parsing start */ + if (path == DC_JSON_GUILD && reason == LEJPCB_OBJECT_START) { pass->api_io.guild = dc_guild_init(); pass->api_io.guild->status |= DC_IN_PROGRESS; } if (path == DC_JSON_GUILD && reason == LEJPCB_OBJECT_END) { + if (!pass->api_io.guild->id) { + dc_guild_free(pass->api_io.guild, DC_UNSET); + pass->api_io.guild = NULL; + return '\0'; + } pass->api_io.guild->status &= ~DC_IN_PROGRESS; - pass->api_io.guild = dc_addr_guild(program, DC_ISAE(program->guilds), pass->api_io.guild, DC_MAY_FREE | DC_REPLACE); /* when we replace, the new guild's channels' ptrs */ + pass->api_io.guild = dc_addr_guild(program, DC_ISAE(program->guilds), pass->api_io.guild, DC_MAY_FREE | DC_REPLACE); /* when we replace, new guild's chs' & roles' ptrs */ struct dc_channel ** channel = &pass->api_io.guild->channel; /* to guild will be inv. */ + struct dc_role ** role = &pass->api_io.guild->role; while (*channel) { - *(channel)->guild = pass->api_io.guild; + (*channel)->guild = pass->api_io.guild; channel = &(*channel)->next; } - dc_add_guild(program, DC_ISAE(client->guilds), pass->api_io.guild, DC_UNSET); + while (*role) { + (*role)->guild = pass->api_io.guild; + role = &(*role)->next; + } + struct dc_guild * gu; + if ((gu = dc_find_guild(program->guilds, program->guilds_length, pass->api_io.guild->id))) + DC_TRANSFER_GUILD(pass->api_io.guild, gu); + 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!!! */ - } /* guild parsing end */ - if (reason & LEJP_FLAG_CB_IS_VALUE) + } +#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; + } + if (path == DC_JSON_GUILD_ROLE && reason == LEJPCB_OBJECT_END) { + if (!pass->api_io.role->id) { + dc_role_free(pass->api_io.role, DC_UNSET); + pass->api_io.role = NULL; + return '\0'; + } + pass->api_io.role->status &= ~DC_IN_PROGRESS; + 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); + struct dc_role ** role; + role = &pass->api_io.guild->role; + while (*role) + role = &(*role)->next; + *role = pass->api_io.guild->role; + pass->api_io.role->guild = pass->api_io.guild; + if (pass->api_io.role->name && !strncmp(pass->api_io.role->name, "@everyone", strlen(pass->api_io.role->name))) + pass->api_io.role->status |= DC_EVERYONE; + pass->api_io.role = NULL; /* we're done, NULL it or PROBLEMS WILL APPEAR!!! */ + } + 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 */ + unsigned long long int id; /* so don't initialize them here, that'd be wrong */ + int št; switch (path) { case DC_JSON_FRIEND: /* we assume we get users[] before relationships[] */ user = dc_find_user(program->users, program->users_length, strtoull(ctx->buf, NULL, 10)); @@ -176,16 +243,19 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn break; case DC_JSON_ME_USERNAME: /* we are always checking for user because evil srv */ case DC_JSON_USER_NAME: /* might insert dots in keys and prevent OBJECT_CREATE */ + case DC_JSON_MEMBER_USERNAME: if (pass->api_io.user && !pass->api_io.user->username) /* no trust srv */ pass->api_io.user->username = strdup(ctx->buf); break; case DC_JSON_ME_ID: case DC_JSON_USER_ID: + case DC_JSON_MEMBER_ID: if (pass->api_io.user) pass->api_io.user->id = strtoll(ctx->buf, NULL, 10); break; case DC_JSON_ME_DISCRIMINATOR: case DC_JSON_USER_DISCRIMINATOR: + case DC_JSON_MEMBER_DISCRIMINATOR: if (pass->api_io.user) pass->api_io.user->discriminator = atoi(ctx->buf); break; /* yeah, we don't care about nicknames */ @@ -201,11 +271,11 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn break; case DC_JSON_DM_NAME: case DC_JSON_GUILD_CHANNEL_NAME: - if (pass->api_io.channel) + if (pass->api_io.channel && !pass->api_io.channel->name) pass->api_io.channel->name = strdup(ctx->buf); break; case DC_JSON_GUILD_NAME: - if (pass->api_io.guild) + if (pass->api_io.guild && !pass->api_io.guild->name) pass->api_io.guild->name = strdup(ctx->buf); break; case DC_JSON_GUILD_ID: @@ -213,15 +283,62 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn pass->api_io.guild->id = strtoull(ctx->buf, NULL, 10); break; case DC_JSON_GUILD_CHANNEL_TOPIC: - if (pass->api_io.channel) + 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); + break; + case DC_JSON_GUILD_ROLE_NAME: + if (pass->api_io.role && !pass->api_io.role->name) + pass->api_io.role->name = strdup(ctx->buf); + break; + case DC_JSON_GUILD_ROLE_PERMISSION: + if (pass->api_io.role) { + if (atoi(ctx->buf) & DC_ADMIN) + pass->api_io.role->permissions = DC_ALL_PERMISSIONS; + else + pass->api_io.role->permissions = atoi(ctx->buf); + } + break; + case DC_JSON_MEMBERSHIP_USER: + pass->api_io.id = strtoull(ctx->buf, NULL, 10); + break; + case DC_JSON_MEMBERSHIP_ROLE: + case DC_JSON_MEMBER_ROLE: + if (!pass->api_io.id) /* we assume we get ID first */ + if (!pass->api_io.user || !(pass->api_io.id = pass->api_io.user->id)) + break; + if (!(id = strtoull(ctx->buf, NULL, 10))) + break; + št = 0; + if (!(user = dc_find_user(program->users, program->users_length, pass->api_io.id))) { + št |= 1; + user = dc_user_init(); + } + if (!(role = dc_find_role(program->roles, program->roles_length, id))) { + št |= 2; + role = dc_role_init(); + role->id = id; + } + dc_add_user(DC_ISAE(role->users), user, DC_UNSET); + if (št & 1) + dc_addr_user(program, DC_ISAE(program->users), user, DC_UNSET); + if (št & 2) + dc_addr_role(program, DC_ISAE(program->roles), role, DC_UNSET); + 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; } + } if (pass->packet == DC_NONE) /* useless to do anything BELOW if we haven't recvd packet type */ return '\0'; - switch (pass->packet) { /* we fill in structs, set DC_INCOMPLETE and pass->parsing_status */ + switch (pass->packet) { case DC_MESSAGE_CREATE: break; default: @@ -476,8 +593,6 @@ void dc_api_i (struct dc_api_io i) { /* this function does not call attached fun goto ws; /* we could call dc_api_i but that just fills stack */ break; case DC_API_WS: - if (getenv("DC_R")) /* detect _WS calls */ - raise(SIGINT); fprintf(stderr, "DC_API_WS called\n"); ws: memset(&info, 0, sizeof(info)); @@ -50,6 +50,7 @@ enum dc_status { /* theese are flags and should be and-checked */ DC_SET_WS_ACTIVE = 1 << 22, /* whether _CREATE _cb shall set client->status =| DC_WS_ACTIVE */ DC_REPLACE = 1 << 23, /* dc_add_x replace old with new on found, _free: only free members */ DC_EXPLICIT_NULL = 1 << 24, /* MEMB_GC will NULL this member (PROGRES?aftr free) (& clear bit) */ + 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 */ @@ -135,6 +136,7 @@ struct dc_api_io { /* output struct does NOT contain void * data (user pointer) struct dc_permission * permission; struct dc_attached_function * attached_function; /* ptr2 heap alloc struct when DC_API_ATTAH */ struct dc_lws_pass * pass; + unsigned long long int id; }; #define DC_API_IO_MEMB_GC(m, t) if (m && m->status & DC_IN_PROGRESS) { \ t##_free(m, DC_UNSET); \ @@ -212,6 +214,14 @@ enum dc_json_paths { /* lws reduces the following char array to uint8_t, so we c DC_JSON_GUILD_CHANNEL_PERMISSION_ID, DC_JSON_GUILD_CHANNEL_PERMISSION_DENY, DC_JSON_GUILD_CHANNEL_PERMISSION_ALLOW, + DC_JSON_MEMBERSHIP, /* this object unfortionately only tells us our roles, */ + DC_JSON_MEMBERSHIP_USER, /* id */ /* though this is enough to calculate permissions */ + DC_JSON_MEMBERSHIP_ROLE, /* id */ + DC_JSON_MEMBER, /* guild member object */ + DC_JSON_MEMBER_USERNAME, + DC_JSON_MEMBER_ID, + DC_JSON_MEMBER_DISCRIMINATOR, + DC_JSON_MEMBER_ROLE, /* id, array */ DC_JSON_MESSAGE, DC_JSON_MESSAGE_ATTACHMENTS, DC_JSON_MESSAGE_ID, @@ -222,7 +232,6 @@ enum dc_json_paths { /* lws reduces the following char array to uint8_t, so we c DC_JSON_MESSAGE_AUTHOR_USERNAME, DC_JSON_MESSAGE_AUTHOR_DISCRIMINATOR, DC_JSON_MESSAGE_AUTHOR_ID, - DC_JSON_MESSAGE_AUTHOR_ROLES, DC_JSON_MESSAGE_REFERENCE, /* id */ DC_JSON_MESSAGE_MENTION_CHANNEL, /* TODO: implement role and user mentions fetching */ DC_JSON_MESSAGE_MENTION_CHANNEL_ID, @@ -294,6 +303,14 @@ char * dc_json_paths[] = { /* array of paths we are interested in */ "d.guilds[].channels[].permission_overwrites.id", "d.guilds[].channels[].permission_overwrites.deny", "d.guilds[].channels[].permission_overwrites.allow", + "d.merged_members", + "d.merged_members[][].user_id", + "d.merged_members[][].roles", + "d.member", + "d.member.user.username", + "d.member.user.id", + "d.member.user.discriminator", + "d.member.roles", "d", "d.attachments[]", "d.id", @@ -304,7 +321,6 @@ char * dc_json_paths[] = { /* array of paths we are interested in */ "d.author.username", "d.author.discriminator", "d.author.id", - "d.member.roles[]", "d.message_reference", /* this is ID */ "d.mention_channels[]", "d.mention_channels[].id", @@ -350,7 +366,6 @@ struct dc_lws_pass { /* struct that is allocated for in dc_lws_cb unique per con enum lejp_callbacks json_reason; /* holds last reason sent to json callback */ struct lws * wsi; /* set on ESTABLISHED and NULLed on CLOSED or ERROR */ enum dc_ws_packet packet; /* what type of packet are we currently handling in lejp */ - enum dc_status * parsing_status; /* to remove DC_IN_PROGRESS & signal if call api on COMPL */ uint16_t reason; /* reason for closing connection */ /* temporary debug things */ char * cp; @@ -378,7 +393,7 @@ void dc_payload_free (struct dc_payload * s, enum dc_status t) { #define DC_ISAS_INIT(type/* w/o struct */, name) do { name##_sizeof = DC_ALLOC_CHUNK; /* structs ISA */ \ name = calloc(name##_sizeof, sizeof(struct type *)); } while (0) /* prep arr, NO INIT membrs */ #define DC_ISASIQ(shortname) DC_ISAS_INIT(dc_##shortname, s->shortname##s) /* ISAS init quick */ -#define DC_ISAF(shortname) for (size_t i = 0; i < s->shortname##s_sizeof; i++) /* hmm, I used to fre */ \ +#define DC_ISAF(shortname) for (size_t i = 0; i < s->shortname##s_length; i++) /* hmm, I used to fre */ \ dc_##shortname##_free(s->shortname##s[i], DC_UNSET); /* till _sizeof, but now I fixd */ \ free(s->shortname##s); /* to only free till _length. is this problematic in any ways? */ struct dc_client { @@ -520,34 +535,19 @@ struct dc_role { enum dc_permissions 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) */ - struct dc_role_membership * role_membership; /* nofree - first role membership ll) */ + DC_ISASQ(user); /* yesfree pointer array only - users with this role */ enum dc_status status; }; struct dc_role * dc_role_init () { struct dc_role * s = calloc(1, sizeof(*s)); + DC_ISASIQ(user); return s; } void dc_role_free (struct dc_role * s, enum dc_status t) { if (!s) return; free(s->name); - if (!(t & DC_REPLACE)) - free(s); -} -struct dc_role_membership { - DC_STRUCT_PREFIX - struct dc_channel * channel; /* nofree */ - struct dc_user * user; /* nofree */ - struct dc_role * role; /* nofree */ - struct dc_role_membership * next; /* nofree - next role membership (lili in role) */ -}; -struct dc_role_membership * dc_role_membership_init () { - struct dc_role_membership * s = calloc(1, sizeof(*s)); - return s; -} -void dc_role_membership_free (struct dc_role_membership * s, enum dc_status t) { - if (!s) - return; + free(s->users); if (!(t & DC_REPLACE)) free(s); } @@ -573,7 +573,6 @@ 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 id; /* to whom does this permission apply */ 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 */ @@ -628,7 +627,6 @@ struct dc_program { /* data storage and token used for communication with the li DC_ISASQ(channel); /* yesfree */ DC_ISASQ(message); /* yesfree */ DC_ISASQ(role); /* yesfree */ - DC_ISASQ(role_membership); /* yesfree */ DC_ISASQ(user); /* yesfree */ DC_ISASQ(permission); /* yesfree */ DC_ISASQ(attached_function); /* yesfree */ @@ -665,7 +663,6 @@ struct dc_program * dc_program_init () { DC_ISASIQ(channel); DC_ISASIQ(message); DC_ISASIQ(role); - DC_ISASIQ(role_membership); DC_ISASIQ(user); DC_ISASIQ(permission); DC_ISASIQ(attached_function); @@ -701,7 +698,6 @@ void dc_program_free (struct dc_program * s, enum dc_status t) { DC_ISAF(channel); DC_ISAF(message); DC_ISAF(role); - DC_ISAF(role_membership); DC_ISAF(user); DC_ISAF(permission); DC_ISAF(attached_function); @@ -713,7 +709,7 @@ void dc_api_stack (struct dc_api_io); #define DC_FIND_X(x) struct dc_##x * dc_find_##x(struct dc_##x ** p, size_t l, unsigned long long int id) { \ for (size_t i = 0; i < l; i++) \ if (p[i]->id == id) { \ - fprintf(stderr, "id %llu was found!\n", id); \ + /* fprintf(stderr, "id %llu was found!\n", id); */ /* too much */ \ return p[i]; \ } \ return NULL; \ @@ -732,7 +728,7 @@ void dc_api_stack (struct dc_api_io); #define DC_ADD_X(x) struct dc_##x * dc_add_##x (struct dc_##x *** p, size_t * so, size_t * l, struct dc_##x * u, enum dc_status s) { \ struct dc_##x * us; \ if ((us = dc_find_##x(*p, *l, u->id))) { \ - fprintf(stderr, "debug: %s found already existing member\n", __func__); \ + /* fprintf(stderr, "debug: %s found already existing member\n", __func__); */ \ if (us == u) \ return us; \ if (s & DC_REPLACE) { \ @@ -751,17 +747,17 @@ void dc_api_stack (struct dc_api_io); *so = ceil(*so*DC_REALLOC_K); \ *p = realloc(*p, sizeof(**p) * *so); \ } \ - fprintf(stderr, "debug: %s inserted into ISA\n", __func__); \ + /* fprintf(stderr, "debug: %s inserted into ISA\n", __func__); */ /* too much */ \ (*p)[(*l)++] = u; \ return u; \ } #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))) \ + 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))) \ + if (u != (us = dc_add_##x(a, so, l, u, s))) \ return us; \ struct dc_api_io io; \ memset(&io, 0, sizeof(io)); \ @@ -776,13 +772,31 @@ DC_GEN_X(user, USER) DC_GEN_X(channel, CHANNEL) DC_FIND_LL_X(channel) DC_GEN_X(guild, GUILD) -#define DC_ISAE(a) &a, &a##_sizeof, &a##_length /* ISA Expand */ +DC_GEN_X(role, ROLE) +#define DC_ISAE(a) &(a), &(a##_sizeof), &(a##_length) /* ISA Expand */ #define DC_ISAN NULL, NULL, NULL /* ISA NULL */ #define DC_TRANSFER_CHANNEL(n, o) do { /* n is going to DC_REPLACE o, transfer important data */ \ - n->message = o->message; \ - n->next = o->next; \ + (n)->message = (o)->message; /* don't transfer perms because we get them in the new */ \ + (n)->next = o->next; /* new channel object */ \ DC_IF_UI_GTK( \ - memcpy(pass->api_io.channel->iter, ch->iter, sizeof(GtkTreeIter)); \ - pass->api_io.channel->is_iter = ch->is_iter; \ + memmove(&(n)->iter, &(o)->iter, sizeof(GtkTreeIter)); \ + (n)->is_iter = (o)->is_iter; \ ) \ } while(0) +#define DC_TRANSFER_GUILD(n, o) do { \ + DC_IF_UI_GTK( \ + memmove(&(n)->iter, &(o)->iter, sizeof(GtkTreeIter)); \ + (n)->is_iter = (o)->is_iter; \ + ) \ + } while (0) +void dc_transfer_role (struct dc_role * n, struct dc_role * o) { + n->next = o->next; + if (!n->users_length) { /* if we didn't update users array in the new role object */ + n->users = o->users; + n->users_sizeof = o->users_sizeof; + n->users_length = o->users_sizeof; + o->users = NULL; /* so that free does not free array of pointers */ + o->users_sizeof = 0; + o->users_length = 0; + } +} |