summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Luka Šijanec <anton@sijanec.eu>2021-09-23 22:23:05 +0200
committerAnton Luka Šijanec <anton@sijanec.eu>2021-09-23 22:23:05 +0200
commitdacbcc8ff2ee9fd788c946b01335bd94eedbff6e (patch)
tree215438d472c62b59991062895ac06fce2daaeab7
parentgrem spat. se ne kompajla. bom popravil ju3. zrihtal DM (diff)
downloaddiscord.c-dacbcc8ff2ee9fd788c946b01335bd94eedbff6e.tar
discord.c-dacbcc8ff2ee9fd788c946b01335bd94eedbff6e.tar.gz
discord.c-dacbcc8ff2ee9fd788c946b01335bd94eedbff6e.tar.bz2
discord.c-dacbcc8ff2ee9fd788c946b01335bd94eedbff6e.tar.lz
discord.c-dacbcc8ff2ee9fd788c946b01335bd94eedbff6e.tar.xz
discord.c-dacbcc8ff2ee9fd788c946b01335bd94eedbff6e.tar.zst
discord.c-dacbcc8ff2ee9fd788c946b01335bd94eedbff6e.zip
-rw-r--r--Makefile3
-rw-r--r--src/api.c167
-rw-r--r--src/h.c86
3 files changed, 194 insertions, 62 deletions
diff --git a/Makefile b/Makefile
index 9eae4b4..86a4621 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/src/api.c b/src/api.c
index 3e70684..43aca84 100644
--- a/src/api.c
+++ b/src/api.c
@@ -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));
diff --git a/src/h.c b/src/h.c
index fd0d40a..499885b 100644
--- a/src/h.c
+++ b/src/h.c
@@ -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;
+ }
+}