diff options
Diffstat (limited to '')
-rw-r--r-- | src/api.c | 110 |
1 files changed, 96 insertions, 14 deletions
@@ -25,6 +25,25 @@ void dc_api_stack (struct dc_api_io i) { /* stack output struct to be delivered *(i.program->api_ios[i.program->api_ios_length++]) = i; return; } +unsigned long long int dc_calculate_permissions (struct dc_user * u, struct dc_channel * c) { + unsigned long long int p = 0; /* note: this is NOT according to server's implementation of */ + struct dc_role ** role = &c->guild->role; /* permission parsing, but should suffice for most */ + while (*role) { /* cases. */ + if ((*role)->status & DC_EVERYONE || dc_find_user((*role)->users, (*role)->users_length, u->id)) + p |= (*role)->permissions; + role = &(*role)->next; + } + if (p & DC_ADMIN) + return DC_ALL_PERMISSIONS; + for (size_t i = 0; i < c->permissions_length; i++) + if (c->permissions[i]->user == u || dc_find_user(c->permissions[i]->role->users, c->permissions[i]->role->users_length, u->id) || c->permissions[i]->role->status & DC_EVERYONE) { + p &= ~c->permissions[i]->deny; + p |= c->permissions[i]->allow; + if ((*role)->permissions & DC_ADMIN) + return DC_ALL_PERMISSIONS; + } + return p; +} signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warnings of incompatible pointer times, we create a new type with enum later on */ enum dc_json_paths path = ctx->path_match-1; /* we assume that the order of incoming data is */ struct dc_lws_pass * pass = ctx->user; /* correct. op and t should come first, etc. */ @@ -32,7 +51,6 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn struct dc_program * program = pass->api_io.program; pass->json_reason = reason; if (reason == LEJPCB_FAILED || reason == LEJPCB_START || (reason == LEJPCB_COMPLETE && pass->packet != DC_MESSAGE_CREATE /* hack for lejp bug with wrong path on OBJECT_END */)) { - if (reason == LEJPCB_COMPLETE) DC_API_IO_GC(pass->api_io); pass->packet = DC_NONE; return '\0'; @@ -74,6 +92,7 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn DC_MR(program->users); /* don't need DC_IN_PROGRESS, we have ref in cl */ program->users[program->users_length++] = client->user = dc_user_init(); client->user->status |= DC_INCOMPLETE; /* when ->disc is set, it's complete */ + client->user->program = program; } /* we do not check on the object end */ switch (path) { /* email is already set from login */ case DC_JSON_ME_USERNAME: @@ -96,6 +115,7 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn 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->program = program; 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 || path == DC_JSON_MEMBER) && reason == LEJPCB_OBJECT_END) { @@ -158,7 +178,7 @@ 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); + dc_transfer_channel(pass->api_io.channel, ch); 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); @@ -182,18 +202,15 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn channel = &(*channel)->next; 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); + dc_transfer_channel(pass->api_io.channel, ch); 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(gu->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; - pe = &(*pe)->next; - } + for (size_t i = 0; i < pass->api_io.channel->permissions_length; i++) + pass->api_io.channel->permissions[i]->channel = pass->api_io.channel; switch (path) { case DC_JSON_MESSAGE_MENTION_CHANNEL: if (pass->api_io.message) @@ -268,13 +285,14 @@ 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; - if (pass->packet == DC_MESSAGE_CREATE && reason == LEJPCB_COMPLETE) { + if (pass->packet == DC_MESSAGE_CREATE && path == DC_JSON_MESSAGE && reason == LEJPCB_OBJECT_START) { pass->api_io.message = dc_message_init(); pass->api_io.message->reply = dc_message_init(); pass->api_io.message->reply->status |= DC_IN_PROGRESS; pass->api_io.message->status |= DC_IN_PROGRESS; } - if (pass->packet == DC_MESSAGE_CREATE && pass->api_io.message && path == DC_JSON_MESSAGE && reason == LEJPCB_COMPLETE /* hack for lejp bug with wrong path on OBJECT_END */ ) { + if (pass->packet == DC_MESSAGE_CREATE && pass->api_io.message && reason == LEJPCB_COMPLETE) { + int ismessage = 0; struct dc_message * me; if (!pass->api_io.message->id || !pass->api_io.message->channel || !DC_MESSAGE_SUPPORTED(pass->api_io.message->type)) { dc_message_free(pass->api_io.message, DC_UNSET); @@ -285,6 +303,7 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn if (!pass->api_io.message->reply->id || !pass->api_io.message->reply->channel || !DC_MESSAGE_SUPPORTED(pass->api_io.message->reply->type)) { dc_message_free(pass->api_io.message->reply, DC_UNSET); pass->api_io.message->reply = NULL; + goto no_reply; } pass->api_io.message->reply->status &= ~DC_IN_PROGRESS; pass->api_io.message->reply->time = DC_ID2TIME(pass->api_io.message->reply->id); @@ -299,6 +318,7 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn } if (!dc_find_ll_message(pass->api_io.message->reply->channel->message, pass->api_io.message->reply->id)) { fprintf(stderr, "new message reply id=%llu (:\n", pass->api_io.message->reply->id); + ismessage++; if (*message) { pass->api_io.message->reply->next = (*message)->next; (*message)->next = pass->api_io.message->reply; @@ -308,6 +328,7 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn } } } +no_reply: pass->api_io.message->status &= ~DC_IN_PROGRESS; pass->api_io.message->time = DC_ID2TIME(pass->api_io.message->id); if ((me = dc_find_message(program->messages, program->messages_length, pass->api_io.message->id))) @@ -321,6 +342,7 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn } if (!dc_find_ll_message(pass->api_io.message->channel->message, pass->api_io.message->id)) { fprintf(stderr, "new message id=%llu (:\n", pass->api_io.message->id); + ismessage++; if (*message) { pass->api_io.message->next = (*message)->next; /* based linked lists */ (*message)->next = pass->api_io.message; @@ -329,7 +351,34 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn *message = pass->api_io.message; } } + struct dc_api_io tostack = { + .type = DC_API_MESSAGE, + .status = DC_OK, + .message = pass->api_io.message, + .program = program + }; + if (ismessage) + dc_api_stack(tostack); pass->api_io.message = NULL; + pass->packet = DC_NONE; /* we do this because this is triggered on LEJPCB_COMPLETE */ + DC_API_IO_GC(pass->api_io); /* only as a hack due to a lejp bug */ + return '\0'; + } + if (path == DC_JSON_GUILD_CHANNEL_PERMISSION && reason == LEJPCB_OBJECT_START) { + pass->api_io.permission = dc_permission_init(); + pass->api_io.permission->channel = pass->api_io.channel; + pass->api_io.permission->status = DC_IN_PROGRESS; + } + if (path == DC_JSON_GUILD_CHANNEL_PERMISSION && reason == LEJPCB_OBJECT_END) { + if (!pass->api_io.permission || (!pass->api_io.permission->user && !pass->api_io.permission->role) || (!pass->api_io.permission->user && !pass->api_io.permission->role)) { + dc_permission_free(pass->api_io.permission, DC_UNSET); + pass->api_io.permission = NULL; + return '\0'; + } + pass->api_io.permission->status &= ~DC_IN_PROGRESS; + DC_MR(pass->api_io.channel->permissions); + pass->api_io.channel->permissions[pass->api_io.channel->permissions_length++] = pass->api_io.permission; + pass->api_io.permission = NULL; } if (reason & LEJP_FLAG_CB_IS_VALUE) { struct dc_user * user; /* this is just a var for you use */ @@ -436,6 +485,7 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn if (!(user = dc_find_user(program->users, program->users_length, pass->api_io.id))) { št |= 1; user = dc_user_init(); + user->program = program; user->id = pass->api_io.id; } if (!(role = dc_find_role(program->roles, program->roles_length, id))) { @@ -467,7 +517,7 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn case DC_JSON_MESSAGE_CONTENT: if (pass->api_io.message) { /* lejp parses in chunks of 256, msg is 2k */ if (!pass->api_io.message->message) /* so we don't have garbag */ - pass->api_io.message->message = strdup(""); + pass->api_io.message->message = strdup(ctx->buf); pass->api_io.message->message = realloc(pass->api_io.message->message, strlen(pass->api_io.message->message)+strlen(ctx->buf)+1); strcat(pass->api_io.message->message, ctx->buf); } @@ -501,10 +551,43 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn case DC_JSON_MESSAGE_REFOBJ_CONTENT: if (pass->api_io.message && pass->api_io.message->reply) { if (!pass->api_io.message->reply->message) - pass->api_io.message->reply->message = strdup(""); + pass->api_io.message->reply->message = strdup(ctx->buf); pass->api_io.message->reply->message = realloc(pass->api_io.message->reply->message, strlen(pass->api_io.message->reply->message)+strlen(ctx->buf)+1); strcat(pass->api_io.message->reply->message, ctx->buf); } + break; + case DC_JSON_GUILD_CHANNEL_PERMISSION_TYPE: + if (pass->api_io.permission) + pass->api_io.permission->type = atoi(ctx->buf); + break; + case DC_JSON_GUILD_CHANNEL_PERMISSION_ID: /* we assume we get user before perm */ + if (pass->api_io.permission) { + pass->api_io.permission->user = dc_find_user(program->users, program->users_length, strtoull(ctx->buf, NULL, 10)); + pass->api_io.permission->role = dc_find_role(program->roles, program->roles_length, strtoull(ctx->buf, NULL, 10)); + if (!pass->api_io.permission->role || !pass->api_io.permission->user) + switch (pass->api_io.permission->type) { + case DC_USER: + pass->api_io.permission->user = dc_user_init(); + pass->api_io.permission->user->program = program; + pass->api_io.permission->user->id = strtoull(ctx->buf, NULL, 10); + dc_addr_user(program, DC_ISAE(program->users), pass->api_io.permission->user, DC_UNSET); + break; + case DC_ROLE: + pass->api_io.permission->role = dc_role_init(); + pass->api_io.permission->role->id = strtoull(ctx->buf, NULL, 10); + dc_addr_role(program, DC_ISAE(program->roles), pass->api_io.permission->role, DC_UNSET); + break; + } + } + break; + case DC_JSON_GUILD_CHANNEL_PERMISSION_DENY: + if (pass->api_io.permission) + pass->api_io.permission->deny = strtoull(ctx->buf, NULL, 10); + break; + case DC_JSON_GUILD_CHANNEL_PERMISSION_ALLOW: + if (pass->api_io.permission) + pass->api_io.permission->allow = strtoull(ctx->buf, NULL, 10); + break; default: break; } @@ -689,8 +772,7 @@ static int dc_lws_cb (struct lws * wsi, enum lws_callback_reasons rs, void * us, void dc_api_i (struct dc_api_io i) { /* this function does not call attached functions, only output does that */ struct lws_client_connect_info info; struct dc_lws_pass * pass; - if (!i.program) - return; + assert(i.program); if (i.program->lws_context && !(i.status & DC_FROM_LWS)) lws_service(i.program->lws_context, 0); /* DO NOT CALL THIS FROM _cb! */ switch (i.type) { |