static bool module_check_wrong_binary_dependency(const struct module_dir_load_settings *set, struct module *module, const char **error_r) { const char *symbol_name, *binary_dep, *const *names; string_t *errstr; if (set->binary_name == NULL) return TRUE; symbol_name = t_strconcat(module->name, "_binary_dependency", NULL); binary_dep = dlsym(module->handle, symbol_name); if (binary_dep == NULL) return TRUE; names = t_strsplit(binary_dep, " "); if (str_array_find(names, set->binary_name)) return TRUE; errstr = t_str_new(128); str_printfa(errstr, "Can't load plugin %s: " "Plugin is intended to be used only by ", module->name); if (names[1] == NULL) str_printfa(errstr, "%s binary", binary_dep); else str_printfa(errstr, "binaries: %s", binary_dep); str_printfa(errstr, " (we're %s)", set->binary_name); *error_r = str_c(errstr); return FALSE; }
static bool want_kick_alt_username(struct client *client, const char *const *args, unsigned int key_idx) { unsigned int i; if (client->alt_usernames == NULL) return FALSE; for (i = 0; i < key_idx; i++) { if (client->alt_usernames[i] == NULL) return FALSE; } return str_array_find(args, client->alt_usernames[i]); }
static bool client_exec_script(struct master_service_connection *conn) { ARRAY_TYPE(const_string) envs; const char *const *args; string_t *input; void *buf; size_t prev_size, scanpos; bool header_complete = FALSE, noreply = FALSE; ssize_t ret; int status; pid_t pid; net_set_nonblock(conn->fd, FALSE); input = t_buffer_create(IO_BLOCK_SIZE); /* Input contains: VERSION .. <lf> [alarm=<secs> <lf>] "noreply" | "-" (or anything really) <lf> arg 1 <lf> arg 2 <lf> ... <lf> DATA This is quite a horrible protocol. If alarm is specified, it MUST be before "noreply". If "noreply" isn't given, something other string (typically "-") must be given which is eaten away. */ alarm(SCRIPT_READ_TIMEOUT_SECS); scanpos = 1; while (!header_complete) { const unsigned char *pos, *end; prev_size = input->used; buf = buffer_append_space_unsafe(input, IO_BLOCK_SIZE); /* peek in socket input buffer */ ret = recv(conn->fd, buf, IO_BLOCK_SIZE, MSG_PEEK); if (ret <= 0) { buffer_set_used_size(input, prev_size); if (strchr(str_c(input), '\n') != NULL) script_verify_version(t_strcut(str_c(input), '\n')); if (ret < 0) i_fatal("recv(MSG_PEEK) failed: %m"); i_fatal("recv(MSG_PEEK) failed: disconnected"); } /* scan for final \n\n */ pos = CONST_PTR_OFFSET(input->data, scanpos); end = CONST_PTR_OFFSET(input->data, prev_size + ret); for (; pos < end; pos++) { if (pos[-1] == '\n' && pos[0] == '\n') { header_complete = TRUE; pos++; break; } } scanpos = pos - (const unsigned char *)input->data; /* read data for real (up to and including \n\n) */ ret = recv(conn->fd, buf, scanpos-prev_size, 0); if (prev_size+ret != scanpos) { if (ret < 0) i_fatal("recv() failed: %m"); if (ret == 0) i_fatal("recv() failed: disconnected"); i_fatal("recv() failed: size of definitive recv() differs from peek"); } buffer_set_used_size(input, scanpos); } alarm(0); /* drop the last two LFs */ buffer_set_used_size(input, scanpos-2); args = t_strsplit(str_c(input), "\n"); script_verify_version(*args); args++; t_array_init(&envs, 16); if (*args != NULL) { const char *p; if (str_begins(*args, "alarm=")) { unsigned int seconds; if (str_to_uint(*args + 6, &seconds) < 0) i_fatal("invalid alarm option"); alarm(seconds); args++; } while (str_begins(*args, "env_")) { const char *envname, *env; env = t_str_tabunescape(*args+4); p = strchr(env, '='); if (p == NULL) i_fatal("invalid environment variable"); envname = t_strdup_until(*args+4, p); if (str_array_find(accepted_envs, envname)) array_append(&envs, &env, 1); args++; } if (strcmp(*args, "noreply") == 0) { noreply = TRUE; } if (**args == '\0') i_fatal("empty options"); args++; } array_append_zero(&envs); if (noreply) { /* no need to fork and check exit status */ exec_child(conn, args, array_idx(&envs, 0)); i_unreached(); } if ((pid = fork()) == (pid_t)-1) { i_error("fork() failed: %m"); return FALSE; } if (pid == 0) { /* child */ exec_child(conn, args, array_idx(&envs, 0)); i_unreached(); } /* parent */ /* check script exit status */ if (waitpid(pid, &status, 0) < 0) { i_error("waitpid() failed: %m"); return FALSE; } else if (WIFEXITED(status)) { ret = WEXITSTATUS(status); if (ret != 0) { i_error("Script terminated abnormally, exit status %d", (int)ret); return FALSE; } } else if (WIFSIGNALED(status)) { i_error("Script terminated abnormally, signal %d", WTERMSIG(status)); return FALSE; } else if (WIFSTOPPED(status)) { i_fatal("Script stopped, signal %d", WSTOPSIG(status)); return FALSE; } else { i_fatal("Script terminated abnormally, return status %d", status); return FALSE; } return TRUE; }
static void waprpl_process_incoming_events(PurpleConnection * gc) { whatsapp_connection *wconn = purple_connection_get_protocol_data(gc); PurpleAccount *acc = purple_connection_get_account(gc); switch (waAPI_loginstatus(wconn->waAPI)) { case 0: purple_connection_update_progress(gc, "Connecting", 0, 4); break; case 1: purple_connection_update_progress(gc, "Sending authorization", 1, 4); break; case 2: purple_connection_update_progress(gc, "Awaiting response", 2, 4); break; case 3: purple_connection_update_progress(gc, "Connection established", 3, 4); purple_connection_set_state(gc, PURPLE_CONNECTED); if (!wconn->connected) waprpl_insert_contacts(gc); wconn->connected = 1; PurpleAccount *account = purple_connection_get_account(gc); PurpleStatus *status = purple_account_get_active_status(account); waprpl_set_status(account, status); break; default: break; }; /* Groups update */ if (waAPI_getgroupsupdated(wconn->waAPI)) { /* Delete/update the chats that are in our list */ PurpleBlistNode *node; for (node = purple_blist_get_root(); node; node = purple_blist_node_next(node, FALSE)) { if (!PURPLE_BLIST_NODE_IS_CHAT(node)) continue; PurpleChat *ch = PURPLE_CHAT(node); if (purple_chat_get_account(ch) != acc) continue; GHashTable *hasht = purple_chat_get_components(ch); char *grid = g_hash_table_lookup(hasht, "id"); char *glist = waAPI_getgroups(wconn->waAPI); gchar **gplist = g_strsplit(glist, ",", 0); if (str_array_find(gplist, grid) >= 0) { /* The group is in the system, update the fields */ char *sub, *own; waAPI_getgroupinfo(wconn->waAPI, grid, &sub, &own, 0); g_hash_table_replace(hasht, g_strdup("subject"), g_strdup(sub)); g_hash_table_replace(hasht, g_strdup("owner"), g_strdup(own)); purple_blist_alias_chat(ch, g_strdup(sub)); } else { /* The group was deleted */ PurpleChat *del = (PurpleChat *) node; node = purple_blist_node_next(node, FALSE); purple_blist_remove_chat(del); } g_strfreev(gplist); } /* Add new groups */ char *glist = waAPI_getgroups(wconn->waAPI); gchar **gplist = g_strsplit(glist, ",", 0); gchar **p; for (p = gplist; *p; p++) { gchar *gpid = *p; PurpleChat *ch = blist_find_chat_by_id(gc, gpid); if (!ch) { char *sub, *own; waAPI_getgroupinfo(wconn->waAPI, gpid, &sub, &own, 0); purple_debug_info("waprpl", "New group found %s %s\n", gpid, sub); GHashTable *htable = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); g_hash_table_insert(htable, g_strdup("subject"), g_strdup(sub)); g_hash_table_insert(htable, g_strdup("id"), g_strdup(gpid)); g_hash_table_insert(htable, g_strdup("owner"), g_strdup(own)); ch = purple_chat_new(acc, sub, htable); purple_blist_add_chat(ch, NULL, NULL); } /* Now update the open conversation that may exist */ char *id = g_hash_table_lookup(purple_chat_get_components(ch), "id"); int prplid = chatid_to_convo(id); PurpleConversation *conv = purple_find_chat(gc, prplid); char *subject, *owner, *part; if (conv && waAPI_getgroupinfo(wconn->waAPI, id, &subject, &owner, &part)) conv_add_participants(conv, part, owner); } g_strfreev(gplist); } /* Incoming messages. */ for (;;) { int r = waAPI_querynext(wconn->waAPI); if (r < 0) break; switch (r) { case 0: query_chat_message(gc); break; case 1: query_chat_image(gc); break; case 2: query_chat_location(gc); break; case 3: query_chat_sound(gc); break; case 4: query_chat_video(gc); break; default: /* Unsupported message type. */ break; }; } /* Status changes, typing notices and profile pictures. */ query_status(gc); query_typing(gc); query_icon(gc); }
static bool want_kick_virtual_user(struct client *client, const char *const *args, unsigned int key_idx ATTR_UNUSED) { return str_array_find(args, client->virtual_user); }
static void waprpl_process_incoming_events(PurpleConnection * gc) { whatsapp_connection *wconn = purple_connection_get_protocol_data(gc); PurpleAccount *acc = purple_connection_get_account(gc); switch (waAPI_loginstatus(wconn->waAPI)) { case 0: purple_connection_update_progress(gc, "Connecting", 0, 4); break; case 1: purple_connection_update_progress(gc, "Sending authorization", 1, 4); break; case 2: purple_connection_update_progress(gc, "Awaiting response", 2, 4); break; case 3: purple_connection_update_progress(gc, "Connection established", 3, 4); purple_connection_set_state(gc, PURPLE_CONNECTED); if (!wconn->connected) waprpl_insert_contacts(gc); wconn->connected = 1; PurpleAccount *account = purple_connection_get_account(gc); PurpleStatus *status = purple_account_get_active_status(account); waprpl_set_status(account, status); break; default: break; }; char *msg, *who, *prev, *url, *author; int status; int size; double lat, lng; unsigned long timestamp; /* Incoming messages */ while (1) { int r = waAPI_querynext(wconn->waAPI); switch (r) { case 0: if (waAPI_querychat(wconn->waAPI, &who, &msg, &author, ×tamp)) { purple_debug_info(WHATSAPP_ID, "Got chat message from %s: %s\n", who, msg); conv_add_message(gc, who, msg, author, timestamp); } break; case 1: if (waAPI_querychatimage(wconn->waAPI, &who, &prev, &size, &url, &author, ×tamp)) { purple_debug_info(WHATSAPP_ID, "Got image from %s: %s\n", who, url); int imgid = purple_imgstore_add_with_id(g_memdup(prev, size), size, NULL); char *msg = g_strdup_printf("<a href=\"%s\"><img id=\"%u\"></a><br/><a href=\"%s\">%s</a>", url, imgid, url, url); conv_add_message(gc, who, msg, author, timestamp); g_free(msg); } break; case 2: if (waAPI_querychatlocation(wconn->waAPI, &who, &prev, &size, &lat, &lng, &author, ×tamp)) { purple_debug_info(WHATSAPP_ID, "Got geomessage from: %s Coordinates (%f %f)\n", who, (float)lat, (float)lng); int imgid = purple_imgstore_add_with_id(g_memdup(prev, size), size, NULL); char *msg = g_strdup_printf("<a href=\"http://openstreetmap.org/?lat=%f&lon=%f&zoom=16\"><img src=\"%u\"></a>", lat, lng, imgid); conv_add_message(gc, who, msg, author, timestamp); g_free(msg); } break; case 3: if (waAPI_querychatsound(wconn->waAPI, &who, &url, &author, ×tamp)) { purple_debug_info(WHATSAPP_ID, "Got chat sound from %s: %s\n", who, url); char *msg = g_strdup_printf("<a href=\"%s\">%s</a>", url, url); conv_add_message(gc, who, msg, author, timestamp); g_free(msg); } break; default: break; }; if (r < 0) break; } /* User status change */ while (waAPI_querystatus(wconn->waAPI, &who, &status)) { if (status == 1) { purple_prpl_got_user_status(acc, who, "available", "message", "", NULL); } else { purple_prpl_got_user_status(acc, who, "unavailable", "message", "", NULL); } } /* User typing info notify */ while (waAPI_querytyping(wconn->waAPI, &who, &status)) { if (status == 1) { purple_debug_info(WHATSAPP_ID, "%s is typing\n", who); serv_got_typing(gc, who, 0, PURPLE_TYPING); } else { purple_debug_info(WHATSAPP_ID, "%s is not typing\n", who); serv_got_typing(gc, who, 0, PURPLE_NOT_TYPING); serv_got_typing_stopped(gc, who); } } /* User profile picture */ char *icon, *hash; int len; while (waAPI_queryicon(wconn->waAPI, &who, &icon, &len, &hash)) { purple_buddy_icons_set_for_user(acc, who, g_memdup(icon, len), len, hash); } /* Groups update */ if (waAPI_getgroupsupdated(wconn->waAPI)) { /* Delete/update the chats that are in our list */ PurpleBlistNode *node; for (node = purple_blist_get_root(); node; node = purple_blist_node_next(node, FALSE)) { if (!PURPLE_BLIST_NODE_IS_CHAT(node)) continue; PurpleChat *ch = PURPLE_CHAT(node); if (purple_chat_get_account(ch) != acc) continue; GHashTable *hasht = purple_chat_get_components(ch); char *grid = g_hash_table_lookup(hasht, "id"); char *glist = waAPI_getgroups(wconn->waAPI); gchar **gplist = g_strsplit(glist, ",", 0); if (str_array_find(gplist, grid) >= 0) { /* The group is in the system, update the fields */ char *sub, *own; waAPI_getgroupinfo(wconn->waAPI, grid, &sub, &own, 0); g_hash_table_insert(hasht, g_strdup("subject"), g_strdup(sub)); g_hash_table_insert(hasht, g_strdup("owner"), g_strdup(own)); } else { /* The group was deleted */ PurpleChat *del = (PurpleChat *) node; node = purple_blist_node_next(node, FALSE); purple_blist_remove_chat(del); } g_strfreev(gplist); } /* Add new groups */ char *glist = waAPI_getgroups(wconn->waAPI); gchar **gplist = g_strsplit(glist, ",", 0); gchar **p; for (p = gplist; *p; p++) { gchar *gpid = *p; PurpleChat *ch = blist_find_chat_by_id(gc, gpid); if (!ch) { char *sub, *own; waAPI_getgroupinfo(wconn->waAPI, gpid, &sub, &own, 0); purple_debug_info("waprpl", "New group found %s %s\n", gpid, sub); GHashTable *htable = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); g_hash_table_insert(htable, g_strdup("subject"), g_strdup(sub)); g_hash_table_insert(htable, g_strdup("id"), g_strdup(gpid)); g_hash_table_insert(htable, g_strdup("owner"), g_strdup(own)); ch = purple_chat_new(acc, sub, htable); purple_blist_add_chat(ch, NULL, NULL); } /* Now update the open conversation that may exist */ char *id = g_hash_table_lookup(purple_chat_get_components(ch), "id"); int prplid = chatid_to_convo(id); PurpleConversation *conv = purple_find_chat(gc, prplid); char *subject, *owner, *part; if (conv && waAPI_getgroupinfo(wconn->waAPI, id, &subject, &owner, &part)) conv_add_participants(conv, part, owner); } g_strfreev(gplist); } }
static void waprpl_process_incoming_events(PurpleConnection * gc) { whatsapp_connection *wconn = purple_connection_get_protocol_data(gc); PurpleAccount *acc = purple_connection_get_account(gc); int err; do { char * reason; err = waAPI_geterror(wconn->waAPI, &reason); if (err != 0) { PurpleConnectionError errcode = PURPLE_CONNECTION_ERROR_OTHER_ERROR; if (err == 1) errcode = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; purple_connection_error_reason(gc, errcode, reason); g_free(reason); } } while (err != 0); switch (waAPI_loginstatus(wconn->waAPI)) { case 0: purple_connection_update_progress(gc, "Connecting", 0, 4); break; case 1: purple_connection_update_progress(gc, "Sending authorization", 1, 4); break; case 2: purple_connection_update_progress(gc, "Awaiting response", 2, 4); break; case 3: if (!wconn->connected) { purple_connection_update_progress(gc, "Connection established", 3, 4); purple_connection_set_state(gc, PURPLE_CONNECTED); PurpleAccount *account = purple_connection_get_account(gc); PurpleStatus *status = purple_account_get_active_status(account); waprpl_insert_contacts(gc); waprpl_set_status(account, status); wconn->connected = 1; } break; default: break; }; /* Groups update */ if (waAPI_getgroupsupdated(wconn->waAPI)) { purple_debug_info(WHATSAPP_ID, "Receiving update information from my groups\n"); /* Delete/update the chats that are in our list */ PurpleBlistNode *node; for (node = purple_blist_get_root(); node; node = purple_blist_node_next(node, FALSE)) { if (!PURPLE_BLIST_NODE_IS_CHAT(node)) continue; PurpleChat *ch = PURPLE_CHAT(node); if (purple_chat_get_account(ch) != acc) continue; GHashTable *hasht = purple_chat_get_components(ch); char *grid = g_hash_table_lookup(hasht, "id"); char *glist = waAPI_getgroups(wconn->waAPI); gchar **gplist = g_strsplit(glist, ",", 0); if (str_array_find(gplist, grid) >= 0) { /* The group is in the system, update the fields */ char *sub, *own; waAPI_getgroupinfo(wconn->waAPI, grid, &sub, &own, 0); g_hash_table_replace(hasht, g_strdup("subject"), sub); g_hash_table_replace(hasht, g_strdup("owner"), own); purple_blist_alias_chat(ch, sub); } else { /* The group was deleted */ PurpleChat *del = (PurpleChat *) node; node = purple_blist_node_next(node, FALSE); purple_blist_remove_chat(del); } g_strfreev(gplist); g_free(glist); } /* Add new groups */ char *glist = waAPI_getgroups(wconn->waAPI); gchar **gplist = g_strsplit(glist, ",", 0); gchar **p; for (p = gplist; *p; p++) { gchar *gpid = *p; PurpleChat *ch = blist_find_chat_by_id(gc, gpid); if (!ch) ch = create_chat_group(gpid, wconn, acc); /* Now update the open conversation that may exist */ char *id = g_hash_table_lookup(purple_chat_get_components(ch), "id"); int prplid = chatid_to_convo(id); PurpleConversation *conv = purple_find_chat(gc, prplid); char *subject, *owner, *part; if (conv && waAPI_getgroupinfo(wconn->waAPI, id, &subject, &owner, &part)) { conv_add_participants(conv, part, owner); } } g_strfreev(gplist); g_free(glist); } t_message m; while (waAPI_querymsg(wconn->waAPI, &m)) { switch (m.type) { case 0: purple_debug_info(WHATSAPP_ID, "Got chat message from %s: %s\n", m.who, m.message); conv_add_message(gc, m.who, m.message, m.author, m.t); break; case 1: { purple_debug_info(WHATSAPP_ID, "Got image from %s: %s\n", m.who, m.message); int imgid = purple_imgstore_add_with_id(g_memdup(m.image, m.imagelen), m.imagelen, NULL); char *msg = g_strdup_printf("<a href=\"%s\"><img id=\"%u\"></a><br/><a href=\"%s\">%s</a>", m.url, imgid, m.url, m.url); conv_add_message(gc, m.who, msg, m.author, m.t); g_free(msg); } break; case 2: { purple_debug_info(WHATSAPP_ID, "Got geomessage from: %s Coordinates (%f %f)\n", m.who, (float)m.lat, (float)m.lng); char * lat = dbl2str(m.lat); char * lng = dbl2str(m.lng); char *msg = g_strdup_printf("<a href=\"http://openstreetmap.org/?lat=%s&lon=%s&zoom=20\">" "http://openstreetmap.org/?lat=%s&lon=%s&zoom=20</a>", lat, lng, lat, lng); conv_add_message(gc, m.who, msg, m.author, m.t); g_free(msg); g_free(lng); g_free(lat); } break; case 3: { purple_debug_info(WHATSAPP_ID, "Got chat sound from %s: %s\n", m.who, m.url); char *msg = g_strdup_printf("<a href=\"%s\">%s</a>", m.url, m.url); conv_add_message(gc, m.who, msg, m.author, m.t); g_free(msg); } break; case 4: { purple_debug_info(WHATSAPP_ID, "Got chat video from %s: %s\n", m.who, m.url); char *msg = g_strdup_printf("<a href=\"%s\">%s</a>", m.url, m.url); conv_add_message(gc, m.who, msg, m.author, m.t); g_free(msg); } break; case 5: { purple_debug_info(WHATSAPP_ID, "Got phone call from %s\n", m.who); conv_add_message(gc, m.who, "[Trying to voice-call you]", m.author, m.t); } break; default: purple_debug_info(WHATSAPP_ID, "Got an unrecognized message!\n"); break; }; g_free(m.who); g_free(m.author); g_free(m.message); } while (1) { int typer; char msgid[128]; if (!waAPI_queryreceivedmsg(wconn->waAPI, msgid, &typer)) break; purple_debug_info(WHATSAPP_ID, "Received message %s type: %d\n", msgid, typer); purple_signal_emit(purple_connection_get_prpl(gc), "whatsapp-message-received", gc, msgid, typer); } /* Status changes, typing notices and profile pictures. */ query_status(gc); query_typing(gc); query_icon(gc); }