summaryrefslogtreecommitdiffstats
path: root/src/api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/api.c')
-rw-r--r--src/api.c110
1 files changed, 96 insertions, 14 deletions
diff --git a/src/api.c b/src/api.c
index afbdfd8..cc91eff 100644
--- a/src/api.c
+++ b/src/api.c
@@ -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) {