struct t_relay_server * relay_server_new (const char *protocol_string, enum t_relay_protocol protocol, const char *protocol_args, int port, int ipv4, int ipv6, int ssl) { struct t_relay_server *new_server; if (!protocol_string) return NULL; if (relay_server_search_port (port)) { dogechat_printf (NULL, _("%s%s: error: port \"%d\" is already used"), dogechat_prefix ("error"), RELAY_PLUGIN_NAME, port); return NULL; } new_server = malloc (sizeof (*new_server)); if (new_server) { new_server->protocol_string = strdup (protocol_string); new_server->protocol = protocol; new_server->protocol_args = (protocol_args) ? strdup (protocol_args) : NULL; new_server->port = port; new_server->ipv4 = ipv4; new_server->ipv6 = ipv6; new_server->ssl = ssl; new_server->sock = -1; new_server->hook_fd = NULL; new_server->start_time = 0; new_server->last_client_disconnect = 0; relay_server_create_socket (new_server); new_server->prev_server = NULL; new_server->next_server = relay_servers; if (relay_servers) relay_servers->prev_server = new_server; else last_relay_server = new_server; relay_servers = new_server; } else { dogechat_printf (NULL, _("%s%s: not enough memory for listening on new port"), dogechat_prefix ("error"), RELAY_PLUGIN_NAME); } return new_server; }
void fifo_exec (const char *text) { char *text2, *pos_msg; struct t_gui_buffer *ptr_buffer; text2 = strdup (text); if (!text2) return; pos_msg = NULL; ptr_buffer = NULL; /* * look for plugin + buffer name at beginning of text * text may be: "plugin.buffer *text" or "*text" */ if (text2[0] == '*') { pos_msg = text2 + 1; ptr_buffer = dogechat_current_buffer (); } else { pos_msg = strstr (text2, " *"); if (!pos_msg) { dogechat_printf (NULL, _("%s%s: invalid text received in pipe"), dogechat_prefix ("error"), FIFO_PLUGIN_NAME); free (text2); return; } pos_msg[0] = '\0'; pos_msg += 2; ptr_buffer = dogechat_buffer_search ("==", text2); if (!ptr_buffer) { dogechat_printf (NULL, _("%s%s: buffer \"%s\" not found"), dogechat_prefix ("error"), FIFO_PLUGIN_NAME, text2); free (text2); return; } } dogechat_command (ptr_buffer, pos_msg); free (text2); }
void dogechat_js_reload_name (const char *name) { struct t_plugin_script *ptr_script; char *filename; ptr_script = plugin_script_search (dogechat_js_plugin, js_scripts, name); if (ptr_script) { filename = strdup (ptr_script->filename); if (filename) { dogechat_js_unload (ptr_script); if (!js_quiet) { dogechat_printf (NULL, dogechat_gettext ("%s: script \"%s\" unloaded"), JS_PLUGIN_NAME, name); } dogechat_js_load (filename); free (filename); } } else { dogechat_printf (NULL, dogechat_gettext ("%s%s: script \"%s\" not loaded"), dogechat_prefix ("error"), JS_PLUGIN_NAME, name); } }
void xfer_network_send_file_fork (struct t_xfer *xfer) { pid_t pid; int rc; if (!xfer_network_create_pipe (xfer)) return; xfer->file = open (xfer->local_filename, O_RDONLY | O_NONBLOCK, 0644); switch (pid = fork ()) { case -1: /* fork failed */ dogechat_printf (NULL, _("%s%s: unable to fork"), dogechat_prefix ("error"), XFER_PLUGIN_NAME); xfer_close (xfer, XFER_STATUS_FAILED); xfer_buffer_refresh (DOGECHAT_HOTLIST_MESSAGE); return; case 0: /* child process */ rc = setuid (getuid ()); (void) rc; close (xfer->child_read); switch (xfer->protocol) { case XFER_NO_PROTOCOL: _exit (EXIT_SUCCESS); break; case XFER_PROTOCOL_DCC: xfer_dcc_send_file_child (xfer); break; case XFER_NUM_PROTOCOLS: break; } _exit (EXIT_SUCCESS); } dogechat_printf (NULL, _("%s: sending file to %s (%s, %s.%s), " "name: %s (local filename: %s), %llu bytes (protocol: %s)"), XFER_PLUGIN_NAME, xfer->remote_nick, xfer->remote_address_str, xfer->plugin_name, xfer->plugin_id, xfer->filename, xfer->local_filename, xfer->size, xfer_protocol_string[xfer->protocol]); /* parent process */ xfer->child_pid = pid; close (xfer->child_write); xfer->child_write = -1; xfer->hook_fd = dogechat_hook_fd (xfer->child_read, 1, 0, 0, &xfer_network_child_read_cb, xfer); }
int irc_input_data (struct t_gui_buffer *buffer, const char *input_data, int flags) { const char *ptr_data; char *data_with_colors, *msg; IRC_BUFFER_GET_SERVER_CHANNEL(buffer); if (buffer == irc_raw_buffer) { if (dogechat_strcasecmp (input_data, "q") == 0) dogechat_buffer_close (buffer); } else { /* * if send unknown commands is enabled and that input data is a * command, then send this command to IRC server */ if (dogechat_config_boolean (irc_config_network_send_unknown_commands) && !dogechat_string_input_for_buffer (input_data)) { if (ptr_server) { irc_server_sendf (ptr_server, flags, NULL, "%s", dogechat_utf8_next_char (input_data)); } return DOGECHAT_RC_OK; } if (ptr_channel) { ptr_data = dogechat_string_input_for_buffer (input_data); if (!ptr_data) ptr_data = input_data; data_with_colors = irc_color_encode ( ptr_data, dogechat_config_boolean (irc_config_network_colors_send)); msg = strdup ((data_with_colors) ? data_with_colors : ptr_data); if (msg) { irc_input_send_user_message (buffer, flags, NULL, msg); free (msg); } if (data_with_colors) free (data_with_colors); } else { dogechat_printf (buffer, _("%s%s: this buffer is not a channel!"), dogechat_prefix ("error"), IRC_PLUGIN_NAME); } } return DOGECHAT_RC_OK; }
void xfer_network_recv_file_fork (struct t_xfer *xfer) { pid_t pid; int rc; if (!xfer_network_create_pipe (xfer)) return; if (xfer->start_resume > 0) xfer->file = open (xfer->local_filename, O_APPEND | O_WRONLY | O_NONBLOCK); else xfer->file = open (xfer->local_filename, O_CREAT | O_TRUNC | O_WRONLY | O_NONBLOCK, 0644); switch (pid = fork ()) { case -1: /* fork failed */ dogechat_printf (NULL, _("%s%s: unable to fork"), dogechat_prefix ("error"), XFER_PLUGIN_NAME); xfer_close (xfer, XFER_STATUS_FAILED); xfer_buffer_refresh (DOGECHAT_HOTLIST_MESSAGE); return; case 0: /* child process */ rc = setuid (getuid ()); (void) rc; close (xfer->child_read); switch (xfer->protocol) { case XFER_NO_PROTOCOL: _exit (EXIT_SUCCESS); break; case XFER_PROTOCOL_DCC: xfer_dcc_recv_file_child (xfer); break; case XFER_NUM_PROTOCOLS: break; } _exit (EXIT_SUCCESS); } /* parent process */ xfer->child_pid = pid; close (xfer->child_write); xfer->child_write = -1; xfer->hook_fd = dogechat_hook_fd (xfer->child_read, 1, 0, 0, &xfer_network_child_read_cb, xfer); }
int xfer_command_me (void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { struct t_xfer *ptr_xfer; /* make C compiler happy */ (void) data; (void) argc; (void) argv; ptr_xfer = xfer_search_by_buffer (buffer); if (!ptr_xfer) { dogechat_printf (NULL, _("%s%s: can't find xfer for buffer \"%s\""), dogechat_prefix ("error"), XFER_PLUGIN_NAME, dogechat_buffer_get_string (buffer, "name")); return DOGECHAT_RC_OK; } if (!XFER_HAS_ENDED(ptr_xfer->status)) { xfer_chat_sendf (ptr_xfer, "\01ACTION %s\01\r\n", (argv_eol[1]) ? argv_eol[1] : ""); dogechat_printf_tags (buffer, "no_highlight", "%s%s%s %s%s", dogechat_prefix ("action"), dogechat_color ("chat_nick_self"), ptr_xfer->local_nick, dogechat_color ("chat"), (argv_eol[1]) ? argv_eol[1] : ""); } return DOGECHAT_RC_OK; }
struct t_exec_cmd * exec_command_search_running_id (const char *id) { struct t_exec_cmd *ptr_exec_cmd; ptr_exec_cmd = exec_search_by_id (id); if (!ptr_exec_cmd) { dogechat_printf (NULL, _("%s%s: command id \"%s\" not found"), dogechat_prefix ("error"), EXEC_PLUGIN_NAME, id); return NULL; } if (!ptr_exec_cmd->hook) { dogechat_printf (NULL, _("%s%s: command with id \"%s\" is not running any " "more"), dogechat_prefix ("error"), EXEC_PLUGIN_NAME, id); return NULL; } return ptr_exec_cmd; }
void irc_input_send_user_message (struct t_gui_buffer *buffer, int flags, const char *tags, char *message) { int number, action; char hash_key[32], *str_args; struct t_hashtable *hashtable; IRC_BUFFER_GET_SERVER_CHANNEL(buffer); if (!ptr_server || !ptr_channel || !message || !message[0]) return; if (!ptr_server->is_connected) { dogechat_printf (buffer, _("%s%s: you are not connected to server"), dogechat_prefix ("error"), IRC_PLUGIN_NAME); return; } hashtable = irc_server_sendf (ptr_server, flags | IRC_SERVER_SEND_RETURN_HASHTABLE, tags, "PRIVMSG %s :%s", ptr_channel->name, message); if (hashtable) { action = (strncmp (message, "\01ACTION ", 8) == 0); number = 1; while (1) { snprintf (hash_key, sizeof (hash_key), "args%d", number); str_args = dogechat_hashtable_get (hashtable, hash_key); if (!str_args) break; irc_input_user_message_display (buffer, action, str_args); number++; } dogechat_hashtable_free (hashtable); } }
int xfer_network_create_pipe (struct t_xfer *xfer) { int child_pipe[2]; if (pipe (child_pipe) < 0) { dogechat_printf (NULL, _("%s%s: unable to create pipe: error %d %s"), dogechat_prefix ("error"), XFER_PLUGIN_NAME, errno, strerror (errno)); xfer_close (xfer, XFER_STATUS_FAILED); xfer_buffer_refresh (DOGECHAT_HOTLIST_MESSAGE); return 0; } xfer->child_read = child_pipe[0]; xfer->child_write = child_pipe[1]; return 1; }
int xfer_network_timer_cb (void *arg_xfer, int remaining_calls) { struct t_xfer *xfer; /* make C compiler happy */ (void) remaining_calls; xfer = (struct t_xfer *)arg_xfer; if ((xfer->status == XFER_STATUS_WAITING) || (xfer->status == XFER_STATUS_CONNECTING)) { dogechat_printf (NULL, _("%s%s: timeout for \"%s\" with %s"), dogechat_prefix ("error"), XFER_PLUGIN_NAME, xfer->filename, xfer->remote_nick); xfer_close (xfer, XFER_STATUS_FAILED); xfer_buffer_refresh (DOGECHAT_HOTLIST_MESSAGE); } return DOGECHAT_RC_OK; }
char * irc_sasl_get_key_content (struct t_irc_server *server, const char *sasl_key) { const char *dogechat_dir; char *key_path1, *key_path2, *content; if (!sasl_key) return NULL; content = NULL; dogechat_dir = dogechat_info_get ("dogechat_dir", ""); key_path1 = dogechat_string_replace (sasl_key, "%h", dogechat_dir); key_path2 = (key_path1) ? dogechat_string_expand_home (key_path1) : NULL; if (key_path2) content = dogechat_file_get_content (key_path2); if (!content) { dogechat_printf ( server->buffer, _("%s%s: unable to read private key in file \"%s\""), dogechat_prefix ("error"), IRC_PLUGIN_NAME, (key_path2) ? key_path2 : ((key_path1) ? key_path1 : sasl_key)); } if (key_path1) free (key_path1); if (key_path2) free (key_path2); return content; }
int script_action_show_source_process_cb (void *data, const char *command, int return_code, const char *out, const char *err) { char *pos, *filename, *filename_loaded, line[4096], *ptr_line; char *diff_command; const char *ptr_diff_command; struct t_script_repo *ptr_script; FILE *file; int length, diff_made; /* make C compiler happy */ (void) data; (void) out; if (return_code >= 0) { pos = strrchr (command, '/'); if (err && err[0]) { dogechat_printf (NULL, _("%s%s: error downloading script \"%s\": %s"), dogechat_prefix ("error"), SCRIPT_PLUGIN_NAME, (pos) ? pos + 1 : "?", err); return DOGECHAT_RC_OK; } if (pos) { ptr_script = script_repo_search_by_name_ext (pos + 1); if (ptr_script) { filename = script_config_get_script_download_filename (ptr_script, ".repository"); if (filename) { /* * read file and display content on script buffer * (only if script buffer is still displaying detail of * this script) */ if (script_buffer && script_buffer_detail_script && (script_buffer_detail_script == ptr_script)) { file = fopen (filename, "r"); if (file) { while (!feof (file)) { ptr_line = fgets (line, sizeof (line) - 1, file); if (ptr_line) { dogechat_printf_y (script_buffer, script_buffer_detail_script_last_line++, "%s", ptr_line); } } fclose (file); } else { dogechat_printf_y (script_buffer, script_buffer_detail_script_last_line++, _("Error: file not found")); } dogechat_printf_y (script_buffer, script_buffer_detail_script_last_line++, "%s----------------------------------------" "----------------------------------------", dogechat_color ("lightcyan")); } diff_made = 0; ptr_diff_command = script_config_get_diff_command (); if (ptr_diff_command && ptr_diff_command[0] && (ptr_script->status & SCRIPT_STATUS_NEW_VERSION)) { /* * diff command set => get the diff with a new process, * file will be deleted later (in callback of this new * process) */ filename_loaded = script_repo_get_filename_loaded (ptr_script); if (filename_loaded) { length = strlen (ptr_diff_command) + 1 + strlen (filename_loaded) + 1 + strlen (filename) + 1; diff_command = malloc (length); if (diff_command) { snprintf (diff_command, length, "%s %s %s", ptr_diff_command, filename_loaded, filename); script_buffer_detail_script_last_line++; script_buffer_detail_script_line_diff = script_buffer_detail_script_last_line; dogechat_printf_y (script_buffer, script_buffer_detail_script_last_line++, "%s", diff_command); dogechat_printf_y (script_buffer, script_buffer_detail_script_last_line++, "%s----------------------------------------" "----------------------------------------", dogechat_color ("magenta")); dogechat_hook_process (diff_command, 10000, &script_action_show_diff_process_cb, filename); diff_made = 1; free (diff_command); } free (filename_loaded); } } if (!diff_made) { /* no diff made: delete temporary file now */ unlink (filename); free (filename); } } } } } return DOGECHAT_RC_OK; }
int xfer_network_connect_chat_recv_cb (void *data, int status, int gnutls_rc, int sock, const char *error, const char *ip_address) { struct t_xfer *xfer; int flags; /* make C compiler happy */ (void) gnutls_rc; (void) ip_address; xfer = (struct t_xfer*)data; dogechat_unhook (xfer->hook_connect); xfer->hook_connect = NULL; /* connection OK? */ if (status == DOGECHAT_HOOK_CONNECT_OK) { xfer->sock = sock; flags = fcntl (xfer->sock, F_GETFL); if (flags == -1) flags = 0; if (fcntl (xfer->sock, F_SETFL, flags | O_NONBLOCK) == -1) { dogechat_printf (NULL, _("%s%s: unable to set option \"nonblock\" " "for socket: error %d %s"), dogechat_prefix ("error"), XFER_PLUGIN_NAME, errno, strerror (errno)); close (xfer->sock); xfer->sock = -1; xfer_close (xfer, XFER_STATUS_FAILED); xfer_buffer_refresh (DOGECHAT_HOTLIST_MESSAGE); return DOGECHAT_RC_OK; } xfer->hook_fd = dogechat_hook_fd (xfer->sock, 1, 0, 0, &xfer_chat_recv_cb, xfer); xfer_chat_open_buffer (xfer); xfer->status = XFER_STATUS_ACTIVE; xfer_buffer_refresh (DOGECHAT_HOTLIST_MESSAGE); return DOGECHAT_RC_OK; } /* connection error */ switch (status) { case DOGECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND: dogechat_printf (NULL, (xfer->proxy && xfer->proxy[0]) ? _("%s%s: proxy address \"%s\" not found") : _("%s%s: address \"%s\" not found"), dogechat_prefix ("error"), XFER_PLUGIN_NAME, xfer->remote_address_str); break; case DOGECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND: dogechat_printf (NULL, (xfer->proxy && xfer->proxy[0]) ? _("%s%s: proxy IP address not found") : _("%s%s: IP address not found"), dogechat_prefix ("error"), XFER_PLUGIN_NAME); break; case DOGECHAT_HOOK_CONNECT_CONNECTION_REFUSED: dogechat_printf (NULL, (xfer->proxy && xfer->proxy[0]) ? _("%s%s: proxy connection refused") : _("%s%s: connection refused"), dogechat_prefix ("error"), XFER_PLUGIN_NAME); break; case DOGECHAT_HOOK_CONNECT_PROXY_ERROR: dogechat_printf (NULL, _("%s%s: proxy fails to establish connection to " "server (check username/password if used and if " "server address/port is allowed by proxy)"), dogechat_prefix ("error"), XFER_PLUGIN_NAME); break; case DOGECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR: dogechat_printf (NULL, _("%s%s: unable to set local hostname/IP"), dogechat_prefix ("error"), XFER_PLUGIN_NAME); break; case DOGECHAT_HOOK_CONNECT_MEMORY_ERROR: dogechat_printf (NULL, _("%s%s: not enough memory"), dogechat_prefix ("error"), XFER_PLUGIN_NAME); break; case DOGECHAT_HOOK_CONNECT_TIMEOUT: dogechat_printf (NULL, _("%s%s: timeout"), dogechat_prefix ("error"), XFER_PLUGIN_NAME); break; case DOGECHAT_HOOK_CONNECT_SOCKET_ERROR: dogechat_printf (NULL, _("%s%s: unable to create socket"), dogechat_prefix ("error"), XFER_PLUGIN_NAME); break; default: dogechat_printf (NULL, _("%s%s: unable to connect: unexpected error (%d)"), dogechat_prefix ("error"), XFER_PLUGIN_NAME, status); break; } if (error && error[0]) { dogechat_printf (NULL, _("%s%s: error: %s"), dogechat_prefix ("error"), XFER_PLUGIN_NAME, error); } xfer_close (xfer, XFER_STATUS_FAILED); xfer_buffer_refresh (DOGECHAT_HOTLIST_MESSAGE); return DOGECHAT_RC_OK; }
int script_action_install_process_cb (void *data, const char *command, int return_code, const char *out, const char *err) { char *pos, *filename, *filename2, str_signal[256]; int quiet, length; struct t_script_repo *ptr_script; /* make C compiler happy */ (void) out; quiet = (data) ? 1 : 0; if (return_code >= 0) { pos = strrchr (command, '/'); if (err && err[0]) { dogechat_printf (NULL, _("%s%s: error downloading script \"%s\": %s"), dogechat_prefix ("error"), SCRIPT_PLUGIN_NAME, (pos) ? pos + 1 : "?", err); return DOGECHAT_RC_OK; } if (pos) { ptr_script = script_repo_search_by_name_ext (pos + 1); if (ptr_script) { filename = script_config_get_script_download_filename (ptr_script, NULL); if (filename) { length = 16 + strlen (filename) + 1; filename2 = malloc (length); if (filename2) { snprintf (filename2, length, "%s%s%s", (quiet && dogechat_config_boolean (script_config_look_quiet_actions)) ? "-q " : "", (dogechat_config_boolean (script_config_scripts_autoload)) ? "-a " : "", filename); snprintf (str_signal, sizeof (str_signal), "%s_script_install", script_language[ptr_script->language]); (void) dogechat_hook_signal_send (str_signal, DOGECHAT_HOOK_SIGNAL_STRING, filename2); free (filename2); } free (filename); } /* schedule install of next script */ dogechat_hook_timer (10, 0, 1, &script_action_installnext_timer_cb, (quiet) ? (void *)1 : (void *)0); } } } return DOGECHAT_RC_OK; }
int relay_server_sock_cb (void *data, int fd) { struct t_relay_server *server; struct sockaddr_in client_addr; struct sockaddr_in6 client_addr6; socklen_t client_addr_size; void *ptr_addr; int client_fd, flags, set; char ipv4_address[INET_ADDRSTRLEN + 1], ipv6_address[INET6_ADDRSTRLEN + 1]; char *ptr_ip_address; /* make C compiler happy */ (void) fd; server = (struct t_relay_server *)data; if (server->ipv6) { ptr_addr = &client_addr6; client_addr_size = sizeof (struct sockaddr_in6); } else { ptr_addr = &client_addr; client_addr_size = sizeof (struct sockaddr_in); } memset (ptr_addr, 0, client_addr_size); client_fd = accept (server->sock, (struct sockaddr *)ptr_addr, &client_addr_size); if (client_fd < 0) { dogechat_printf (NULL, _("%s%s: cannot accept client on port %d (%s): error %d %s"), dogechat_prefix ("error"), RELAY_PLUGIN_NAME, server->port, server->protocol_string, errno, strerror (errno)); return DOGECHAT_RC_OK; } ptr_ip_address = NULL; if (server->ipv6) { if (inet_ntop (AF_INET6, &(client_addr6.sin6_addr), ipv6_address, INET6_ADDRSTRLEN)) { ptr_ip_address = ipv6_address; if (strncmp (ptr_ip_address, "::ffff:", 7) == 0) { /* actually an IPv4-mapped IPv6 address, so skip "::ffff:" */ ptr_ip_address += 7; } } } else { if (inet_ntop (AF_INET, &(client_addr.sin_addr), ipv4_address, INET_ADDRSTRLEN)) { ptr_ip_address = ipv4_address; } } /* check if IP is allowed, if not, just close socket */ if (relay_config_regex_allowed_ips && (regexec (relay_config_regex_allowed_ips, ptr_ip_address, 0, NULL, 0) != 0)) { if (dogechat_relay_plugin->debug >= 1) { dogechat_printf (NULL, _("%s%s: IP address \"%s\" not allowed for relay"), dogechat_prefix ("error"), RELAY_PLUGIN_NAME, ptr_ip_address); } close (client_fd); return DOGECHAT_RC_OK; } /* set non-blocking mode for socket */ flags = fcntl (client_fd, F_GETFL); if (flags == -1) flags = 0; fcntl (client_fd, F_SETFL, flags | O_NONBLOCK); /* set socket option SO_REUSEADDR */ set = 1; if (setsockopt (client_fd, SOL_SOCKET, SO_REUSEADDR, (void *) &set, sizeof (set)) < 0) { dogechat_printf (NULL, _("%s%s: cannot set socket option \"%s\" to %d: " "error %d %s"), dogechat_prefix ("error"), RELAY_PLUGIN_NAME, "SO_REUSEADDR", set, errno, strerror (errno)); close (client_fd); return DOGECHAT_RC_OK; } /* add the client */ relay_client_new (client_fd, ptr_ip_address, server); return DOGECHAT_RC_OK; }
int relay_server_create_socket (struct t_relay_server *server) { int domain, set, max_clients, addr_size; struct sockaddr_in server_addr; struct sockaddr_in6 server_addr6; const char *bind_address; void *ptr_addr; bind_address = dogechat_config_string (relay_config_network_bind_address); if (server->ipv6) { domain = AF_INET6; memset (&server_addr6, 0, sizeof (struct sockaddr_in6)); server_addr6.sin6_family = domain; server_addr6.sin6_port = htons (server->port); server_addr6.sin6_addr = in6addr_any; if (bind_address && bind_address[0]) { if (!inet_pton (domain, bind_address, &server_addr6.sin6_addr)) { dogechat_printf (NULL, /* TRANSLATORS: second "%s" is "IPv4" or "IPv6" */ _("%s%s: invalid bind address \"%s\" for %s"), dogechat_prefix ("error"), RELAY_PLUGIN_NAME, bind_address, "IPv6"); return 0; } } ptr_addr = &server_addr6; addr_size = sizeof (struct sockaddr_in6); } else { domain = AF_INET; memset (&server_addr, 0, sizeof (struct sockaddr_in)); server_addr.sin_family = domain; server_addr.sin_port = htons (server->port); server_addr.sin_addr.s_addr = INADDR_ANY; if (bind_address && bind_address[0]) { if (!inet_pton (domain, bind_address, &server_addr.sin_addr)) { dogechat_printf (NULL, /* TRANSLATORS: second "%s" is "IPv4" or "IPv6" */ _("%s%s: invalid bind address \"%s\" for %s"), dogechat_prefix ("error"), RELAY_PLUGIN_NAME, bind_address, "IPv4"); return 0; } } ptr_addr = &server_addr; addr_size = sizeof (struct sockaddr_in); } /* create socket */ server->sock = socket (domain, SOCK_STREAM, 0); if (server->sock < 0) { dogechat_printf (NULL, _("%s%s: cannot create socket: error %d %s"), dogechat_prefix ("error"), RELAY_PLUGIN_NAME, errno, strerror (errno)); if (errno == EAFNOSUPPORT) { dogechat_printf (NULL, _("%s%s: try /set relay.network.ipv6 off"), dogechat_prefix ("error"), RELAY_PLUGIN_NAME); } return 0; } #ifdef IPV6_V6ONLY /* set option IPV6_V6ONLY to 0 or 1 */ if (server->ipv6) { set = (server->ipv4) ? 0 : 1; if (setsockopt (server->sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *) &set, sizeof (set)) < 0) { dogechat_printf (NULL, _("%s%s: cannot set socket option \"%s\" " "to %d: error %d %s"), dogechat_prefix ("error"), RELAY_PLUGIN_NAME, "IPV6_V6ONLY", set, errno, strerror (errno)); close (server->sock); server->sock = -1; return 0; } } #endif /* IPV6_V6ONLY */ /* set option SO_REUSEADDR to 1 */ set = 1; if (setsockopt (server->sock, SOL_SOCKET, SO_REUSEADDR, (void *) &set, sizeof (set)) < 0) { dogechat_printf (NULL, _("%s%s: cannot set socket option \"%s\" to %d: " "error %d %s"), dogechat_prefix ("error"), RELAY_PLUGIN_NAME, "SO_REUSEADDR", set, errno, strerror (errno)); close (server->sock); server->sock = -1; return 0; } /* set option SO_KEEPALIVE to 1 */ set = 1; if (setsockopt (server->sock, SOL_SOCKET, SO_KEEPALIVE, (void *) &set, sizeof (set)) < 0) { dogechat_printf (NULL, _("%s%s: cannot set socket option \"%s\" to %d: " "error %d %s"), dogechat_prefix ("error"), RELAY_PLUGIN_NAME, "SO_KEEPALIVE", set, errno, strerror (errno)); close (server->sock); server->sock = -1; return 0; } /* bind */ if (bind (server->sock, (struct sockaddr *)ptr_addr, addr_size) < 0) { dogechat_printf (NULL, _("%s%s: cannot \"bind\" on port %d (%s): error %d %s"), dogechat_prefix ("error"), RELAY_PLUGIN_NAME, server->port, server->protocol_string, errno, strerror (errno)); close (server->sock); server->sock = -1; return 0; } max_clients = dogechat_config_integer (relay_config_network_max_clients); if (listen (server->sock, max_clients) != 0) { dogechat_printf (NULL, _("%s%s: cannot \"listen\" on port %d (%s): error %d %s"), dogechat_prefix ("error"), RELAY_PLUGIN_NAME, server->port, server->protocol_string, errno, strerror (errno)); close (server->sock); server->sock = -1; return 0; } dogechat_printf (NULL, _("%s: listening on port %d (relay: %s, %s, max %d clients)"), RELAY_PLUGIN_NAME, server->port, server->protocol_string, ((server->ipv4 && server->ipv6) ? "IPv4+6" : ((server->ipv6) ? "IPv6" : "IPv4")), max_clients); server->hook_fd = dogechat_hook_fd (server->sock, 1, 0, 0, &relay_server_sock_cb, server); server->start_time = time (NULL); return 1; }
void * dogechat_js_exec (struct t_plugin_script *script, int ret_type, const char *function, const char *format, void **argv) { struct t_plugin_script *old_js_current_script; DogechatJsV8 *js_v8; void *ret_value; v8::Handle<v8::Value> argv2[16], ret_js; int i, argc, *ret_int; ret_value = NULL; old_js_current_script = js_current_script; js_current_script = script; js_v8 = (DogechatJsV8 *)(script->interpreter); if (!js_v8->functionExists(function)) { dogechat_printf (NULL, dogechat_gettext ("%s%s: unable to run function \"%s\""), dogechat_prefix ("error"), JS_PLUGIN_NAME, function); goto end; } argc = 0; if (format && format[0]) { argc = strlen (format); for (i = 0; i < argc; i++) { switch (format[i]) { case 's': /* string */ argv2[i] = v8::String::New((const char *)argv[i]); break; case 'i': /* integer */ argv2[i] = v8::Integer::New(*((int *)argv[i])); break; case 'h': /* hash */ argv2[i] = dogechat_js_hashtable_to_object ( (struct t_hashtable *)argv[i]); break; } } } ret_js = js_v8->execFunction(function, argc, (argc > 0) ? argv2 : NULL); if (!ret_js.IsEmpty()) { if ((ret_type == DOGECHAT_SCRIPT_EXEC_STRING) && (ret_js->IsString())) { v8::String::Utf8Value temp_str(ret_js); ret_value = *temp_str; } else if ((ret_type == DOGECHAT_SCRIPT_EXEC_INT) && (ret_js->IsInt32())) { ret_int = (int *)malloc (sizeof (*ret_int)); if (ret_int) *ret_int = (int)(ret_js->IntegerValue()); ret_value = ret_int; } else if ((ret_type == DOGECHAT_SCRIPT_EXEC_HASHTABLE) && (ret_js->IsObject())) { ret_value = (struct t_hashtable *)dogechat_js_object_to_hashtable ( ret_js->ToObject(), DOGECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE, DOGECHAT_HASHTABLE_STRING, DOGECHAT_HASHTABLE_STRING); } else { dogechat_printf (NULL, dogechat_gettext ("%s%s: function \"%s\" must " "return a valid value"), dogechat_prefix ("error"), JS_PLUGIN_NAME, function); } } if (!ret_value) { dogechat_printf (NULL, dogechat_gettext ("%s%s: error in function \"%s\""), dogechat_prefix ("error"), JS_PLUGIN_NAME, function); } end: js_current_script = old_js_current_script; return ret_value; }
int xfer_network_child_read_cb (void *arg_xfer, int fd) { struct t_xfer *xfer; char bufpipe[1 + 1 + 32 + 1]; int num_read; /* make C compiler happy */ (void) fd; xfer = (struct t_xfer *)arg_xfer; num_read = read (xfer->child_read, bufpipe, sizeof (bufpipe)); if (num_read > 0) { sscanf (bufpipe + 2, "%llu", &xfer->pos); xfer->last_activity = time (NULL); xfer_file_calculate_speed (xfer, 0); /* read error code */ switch (bufpipe[1] - '0') { /* errors for sender */ case XFER_ERROR_READ_LOCAL: dogechat_printf (NULL, _("%s%s: unable to read local file"), dogechat_prefix ("error"), XFER_PLUGIN_NAME); break; case XFER_ERROR_SEND_BLOCK: dogechat_printf (NULL, _("%s%s: unable to send block to receiver"), dogechat_prefix ("error"), XFER_PLUGIN_NAME); break; case XFER_ERROR_READ_ACK: dogechat_printf (NULL, _("%s%s: unable to read ACK from receiver"), dogechat_prefix ("error"), XFER_PLUGIN_NAME); break; /* errors for receiver */ case XFER_ERROR_CONNECT_SENDER: dogechat_printf (NULL, _("%s%s: unable to connect to sender"), dogechat_prefix ("error"), XFER_PLUGIN_NAME); break; case XFER_ERROR_RECV_BLOCK: dogechat_printf (NULL, _("%s%s: unable to receive block from sender"), dogechat_prefix ("error"), XFER_PLUGIN_NAME); break; case XFER_ERROR_WRITE_LOCAL: dogechat_printf (NULL, _("%s%s: unable to write local file"), dogechat_prefix ("error"), XFER_PLUGIN_NAME); break; case XFER_ERROR_SEND_ACK: dogechat_printf (NULL, _("%s%s: unable to send ACK to sender"), dogechat_prefix ("error"), XFER_PLUGIN_NAME); break; case XFER_ERROR_HASH_MISMATCH: dogechat_printf (NULL, _("%s%s: wrong CRC32 for file %s"), dogechat_prefix ("error"), XFER_PLUGIN_NAME, xfer->filename); xfer->hash_status = XFER_HASH_STATUS_MISMATCH; break; case XFER_ERROR_HASH_RESUME_ERROR: dogechat_printf (NULL, _("%s%s: CRC32 error while resuming"), dogechat_prefix ("error"), XFER_PLUGIN_NAME); xfer->hash_status = XFER_HASH_STATUS_RESUME_ERROR; break; } /* read new DCC status */ switch (bufpipe[0] - '0') { case XFER_STATUS_CONNECTING: xfer->status = XFER_STATUS_CONNECTING; xfer_buffer_refresh (DOGECHAT_HOTLIST_MESSAGE); break; case XFER_STATUS_ACTIVE: if (xfer->status == XFER_STATUS_CONNECTING) { /* connection was successful by child, init transfer times */ xfer->status = XFER_STATUS_ACTIVE; xfer->start_transfer = time (NULL); xfer->last_check_time = time (NULL); xfer_buffer_refresh (DOGECHAT_HOTLIST_MESSAGE); } else xfer_buffer_refresh (DOGECHAT_HOTLIST_LOW); break; case XFER_STATUS_DONE: xfer_close (xfer, XFER_STATUS_DONE); xfer_buffer_refresh (DOGECHAT_HOTLIST_MESSAGE); break; case XFER_STATUS_FAILED: xfer_close (xfer, XFER_STATUS_FAILED); xfer_buffer_refresh (DOGECHAT_HOTLIST_MESSAGE); break; case XFER_STATUS_HASHING: xfer->status = XFER_STATUS_HASHING; xfer_buffer_refresh (DOGECHAT_HOTLIST_MESSAGE); break; case XFER_STATUS_HASHED: if (bufpipe[1] - '0' == XFER_NO_ERROR) xfer->hash_status = XFER_HASH_STATUS_MATCH; xfer_buffer_refresh (DOGECHAT_HOTLIST_MESSAGE); break; } } return DOGECHAT_RC_OK; }
void fifo_create () { int filename_length; const char *fifo_option, *dogechat_home; fifo_option = dogechat_config_get_plugin ("fifo"); if (!fifo_option) { dogechat_config_set_plugin ("fifo", "on"); fifo_option = dogechat_config_get_plugin ("fifo"); } dogechat_home = dogechat_info_get ("dogechat_dir", ""); if (fifo_option && dogechat_home) { fifo_remove_old_pipes (); if (dogechat_strcasecmp (fifo_option, "on") == 0) { /* * build FIFO filename: * "<dogechat_home>/dogechat_fifo_" + process PID */ if (!fifo_filename) { filename_length = strlen (dogechat_home) + 64; fifo_filename = malloc (filename_length); snprintf (fifo_filename, filename_length, "%s/%s%d", dogechat_home, FIFO_FILENAME_PREFIX, (int) getpid()); } fifo_fd = -1; /* create FIFO pipe, writable for user only */ if (mkfifo (fifo_filename, 0600) == 0) { /* open FIFO pipe in read-only, non-blocking mode */ if ((fifo_fd = open (fifo_filename, O_RDONLY | O_NONBLOCK)) != -1) { if ((dogechat_fifo_plugin->debug >= 1) || !fifo_quiet) { dogechat_printf (NULL, _("%s: pipe opened (file: %s)"), FIFO_PLUGIN_NAME, fifo_filename); } fifo_fd_hook = dogechat_hook_fd (fifo_fd, 1, 0, 0, &fifo_read, NULL); } else dogechat_printf (NULL, _("%s%s: unable to open pipe (%s) for " "reading"), dogechat_prefix ("error"), FIFO_PLUGIN_NAME, fifo_filename); } else { dogechat_printf (NULL, _("%s%s: unable to create pipe for remote " "control (%s): error %d %s"), dogechat_prefix ("error"), FIFO_PLUGIN_NAME, fifo_filename, errno, strerror (errno)); } } } }
int alias_cb (void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { struct t_alias *ptr_alias; char **commands, **ptr_cmd, **ptr_next_cmd; char *args_replaced, *alias_command; int some_args_replaced, length1, length2; /* make C compiler happy */ (void) argv; ptr_alias = (struct t_alias *)data; if (ptr_alias->running) { dogechat_printf (NULL, _("%s%s: error, circular reference when calling " "alias \"%s\""), dogechat_prefix ("error"), ALIAS_PLUGIN_NAME, ptr_alias->name); return DOGECHAT_RC_OK; } else { /* an alias can contain many commands separated by ';' */ commands = dogechat_string_split_command (ptr_alias->command, ';'); if (commands) { some_args_replaced = 0; ptr_alias->running = 1; for (ptr_cmd = commands; *ptr_cmd; ptr_cmd++) { ptr_next_cmd = ptr_cmd; ptr_next_cmd++; args_replaced = alias_replace_args (*ptr_cmd, (argc > 1) ? argv_eol[1] : ""); if (args_replaced && (strcmp (args_replaced, *ptr_cmd) != 0)) some_args_replaced = 1; /* * if alias has arguments, they are now * arguments of the last command in the list (if no $1,$2,..$*) * was found */ if ((*ptr_next_cmd == NULL) && argv_eol[1] && (!some_args_replaced)) { length1 = strlen (*ptr_cmd); length2 = strlen (argv_eol[1]); alias_command = malloc (1 + length1 + 1 + length2 + 1); if (alias_command) { if (!dogechat_string_is_command_char (*ptr_cmd)) strcpy (alias_command, "/"); else alias_command[0] = '\0'; strcat (alias_command, *ptr_cmd); strcat (alias_command, " "); strcat (alias_command, argv_eol[1]); alias_run_command (&buffer, alias_command); free (alias_command); } } else { if (dogechat_string_is_command_char (*ptr_cmd)) { alias_run_command (&buffer, (args_replaced) ? args_replaced : *ptr_cmd); } else { alias_command = malloc (1 + strlen((args_replaced) ? args_replaced : *ptr_cmd) + 1); if (alias_command) { strcpy (alias_command, "/"); strcat (alias_command, (args_replaced) ? args_replaced : *ptr_cmd); alias_run_command (&buffer, alias_command); free (alias_command); } } } if (args_replaced) free (args_replaced); } ptr_alias->running = 0; dogechat_string_free_split_command (commands); } } return DOGECHAT_RC_OK; }
int dogechat_plugin_init (struct t_dogechat_plugin *plugin, int argc, char *argv[]) { int i, auto_connect, upgrading; dogechat_plugin = plugin; if (!irc_config_init ()) return DOGECHAT_RC_ERROR; irc_config_read (); irc_command_init (); irc_info_init (); irc_redirect_init (); irc_notify_init (); /* hook some signals */ irc_debug_init (); dogechat_hook_signal ("quit", &irc_signal_quit_cb, NULL); dogechat_hook_signal ("upgrade", &irc_signal_upgrade_cb, NULL); dogechat_hook_signal ("xfer_send_ready", &irc_server_xfer_send_ready_cb, NULL); dogechat_hook_signal ("xfer_resume_ready", &irc_server_xfer_resume_ready_cb, NULL); dogechat_hook_signal ("xfer_send_accept_resume", &irc_server_xfer_send_accept_resume_cb, NULL); dogechat_hook_signal ("irc_input_send", &irc_input_send_cb, NULL); /* hook hsignals for redirection */ dogechat_hook_hsignal ("irc_redirect_pattern", &irc_redirect_pattern_hsignal_cb, NULL); dogechat_hook_hsignal ("irc_redirect_command", &irc_redirect_command_hsignal_cb, NULL); /* modifiers */ dogechat_hook_modifier ("irc_color_decode", &irc_color_modifier_cb, NULL); dogechat_hook_modifier ("irc_color_encode", &irc_color_modifier_cb, NULL); dogechat_hook_modifier ("irc_color_decode_ansi", &irc_color_modifier_cb, NULL); /* hook completions */ irc_completion_init (); irc_bar_item_init (); /* look at arguments */ auto_connect = 1; upgrading = 0; for (i = 0; i < argc; i++) { if ((dogechat_strcasecmp (argv[i], "-a") == 0) || (dogechat_strcasecmp (argv[i], "--no-connect") == 0)) { auto_connect = 0; } else if ((dogechat_strncasecmp (argv[i], IRC_PLUGIN_NAME, 3) == 0)) { if (!irc_server_alloc_with_url (argv[i])) { dogechat_printf ( NULL, _("%s%s: unable to add temporary server \"%s\" (check " "if there is already a server with this name)"), dogechat_prefix ("error"), IRC_PLUGIN_NAME, argv[i]); } } else if (dogechat_strcasecmp (argv[i], "--upgrade") == 0) { upgrading = 1; } } if (upgrading) { if (!irc_upgrade_load ()) { dogechat_printf ( NULL, _("%s%s: WARNING: some network connections may still be " "opened and not visible, you should restart DogeChat now " "(with /quit)."), dogechat_prefix ("error"), IRC_PLUGIN_NAME); } } else { irc_server_auto_connect (auto_connect); } irc_hook_timer = dogechat_hook_timer (1 * 1000, 0, 0, &irc_server_timer_cb, NULL); return DOGECHAT_RC_OK; }
int irc_signal_upgrade_cb (void *data, const char *signal, const char *type_data, void *signal_data) { struct t_irc_server *ptr_server; int quit, ssl_disconnected; /* make C compiler happy */ (void) data; (void) signal; (void) type_data; irc_signal_upgrade_received = 1; quit = (signal_data && (strcmp (signal_data, "quit") == 0)); ssl_disconnected = 0; for (ptr_server = irc_servers; ptr_server; ptr_server = ptr_server->next_server) { /* * FIXME: it's not possible to upgrade with SSL servers connected * (GnuTLS library can't reload data after upgrade), so we close * connection for all SSL servers currently connected */ if (ptr_server->is_connected && (ptr_server->ssl_connected || quit)) { if (!quit) { ssl_disconnected++; dogechat_printf ( ptr_server->buffer, _("%s%s: disconnecting from server because upgrade can't " "work for servers connected via SSL"), dogechat_prefix ("error"), IRC_PLUGIN_NAME); } irc_server_disconnect (ptr_server, 0, 0); /* * schedule reconnection: DogeChat will reconnect to this server * after restart */ ptr_server->index_current_address = 0; ptr_server->reconnect_delay = IRC_SERVER_OPTION_INTEGER(ptr_server, IRC_SERVER_OPTION_AUTORECONNECT_DELAY); ptr_server->reconnect_start = time (NULL) - ptr_server->reconnect_delay - 1; } } if (ssl_disconnected > 0) { dogechat_printf ( NULL, /* TRANSLATORS: "%s" after "%d" is "server" or "servers" */ _("%s%s: disconnected from %d %s (SSL connection not supported " "with upgrade)"), dogechat_prefix ("error"), IRC_PLUGIN_NAME, ssl_disconnected, NG_("server", "servers", ssl_disconnected)); } return DOGECHAT_RC_OK; }
int exec_command_exec (void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { int i, length, count; char *text; struct t_exec_cmd *ptr_exec_cmd, *ptr_next_exec_cmd; /* make C compiler happy */ (void) data; (void) buffer; /* list running commands */ if ((argc == 1) || ((argc == 2) && (dogechat_strcasecmp (argv[1], "-list") == 0))) { exec_command_list (); return DOGECHAT_RC_OK; } /* send text to a running process */ if (dogechat_strcasecmp (argv[1], "-in") == 0) { DOGECHAT_COMMAND_MIN_ARGS(4, "-in"); ptr_exec_cmd = exec_command_search_running_id (argv[2]); if (ptr_exec_cmd && ptr_exec_cmd->hook) { length = strlen (argv_eol[3]) + 1 + 1; text = malloc (length); if (text) { snprintf (text, length, "%s\n", argv_eol[3]); dogechat_hook_set (ptr_exec_cmd->hook, "stdin", text); free (text); } } return DOGECHAT_RC_OK; } /* send text to a running process (if given), then close stdin */ if (dogechat_strcasecmp (argv[1], "-inclose") == 0) { DOGECHAT_COMMAND_MIN_ARGS(3, "-inclose"); ptr_exec_cmd = exec_command_search_running_id (argv[2]); if (ptr_exec_cmd && ptr_exec_cmd->hook) { if (argc > 3) { length = strlen (argv_eol[3]) + 1 + 1; text = malloc (length); if (text) { snprintf (text, length, "%s\n", argv_eol[3]); dogechat_hook_set (ptr_exec_cmd->hook, "stdin", text); free (text); } } dogechat_hook_set (ptr_exec_cmd->hook, "stdin_close", "1"); } return DOGECHAT_RC_OK; } /* send a signal to a running process */ if (dogechat_strcasecmp (argv[1], "-signal") == 0) { DOGECHAT_COMMAND_MIN_ARGS(4, "-signal"); ptr_exec_cmd = exec_command_search_running_id (argv[2]); if (ptr_exec_cmd) dogechat_hook_set (ptr_exec_cmd->hook, "signal", argv[3]); return DOGECHAT_RC_OK; } /* send a KILL signal to a running process */ if (dogechat_strcasecmp (argv[1], "-kill") == 0) { DOGECHAT_COMMAND_MIN_ARGS(3, "-kill"); ptr_exec_cmd = exec_command_search_running_id (argv[2]); if (ptr_exec_cmd) dogechat_hook_set (ptr_exec_cmd->hook, "signal", "kill"); return DOGECHAT_RC_OK; } /* send a KILL signal to all running processes */ if (dogechat_strcasecmp (argv[1], "-killall") == 0) { for (ptr_exec_cmd = exec_cmds; ptr_exec_cmd; ptr_exec_cmd = ptr_exec_cmd->next_cmd) { if (ptr_exec_cmd->hook) { dogechat_hook_set (ptr_exec_cmd->hook, "signal", "kill"); } } return DOGECHAT_RC_OK; } /* set a hook property */ if (dogechat_strcasecmp (argv[1], "-set") == 0) { DOGECHAT_COMMAND_MIN_ARGS(5, "-set"); ptr_exec_cmd = exec_command_search_running_id (argv[2]); if (ptr_exec_cmd) dogechat_hook_set (ptr_exec_cmd->hook, argv[3], argv_eol[4]); return DOGECHAT_RC_OK; } /* delete terminated command(s) */ if (dogechat_strcasecmp (argv[1], "-del") == 0) { DOGECHAT_COMMAND_MIN_ARGS(3, "-del"); if (dogechat_strcasecmp (argv[2], "-all") == 0) { count = 0; ptr_exec_cmd = exec_cmds; while (ptr_exec_cmd) { ptr_next_exec_cmd = ptr_exec_cmd->next_cmd; if (!ptr_exec_cmd->hook) { exec_free (ptr_exec_cmd); count++; } ptr_exec_cmd = ptr_next_exec_cmd; } dogechat_printf (NULL, _("%d commands removed"), count); } else { for (i = 2; i < argc; i++) { ptr_exec_cmd = exec_search_by_id (argv[i]); if (ptr_exec_cmd) { if (ptr_exec_cmd->hook) { dogechat_printf (NULL, _("%s%s: command with id \"%s\" is still " "running"), dogechat_prefix ("error"), EXEC_PLUGIN_NAME, argv[i]); } else { exec_free (ptr_exec_cmd); dogechat_printf (NULL, _("Command \"%s\" removed"), argv[i]); } } else { dogechat_printf (NULL, _("%s%s: command id \"%s\" not found"), dogechat_prefix ("error"), EXEC_PLUGIN_NAME, argv[i]); } } } return DOGECHAT_RC_OK; } return exec_command_run (buffer, argc, argv, argv_eol, 1); }
struct t_alias * alias_new (const char *name, const char *command, const char *completion) { struct t_alias *new_alias, *ptr_alias, *pos_alias; if (!alias_name_valid (name)) { dogechat_printf (NULL, _("%s%s: invalid alias name: \"%s\""), dogechat_prefix ("error"), ALIAS_PLUGIN_NAME, name); return NULL; } if (!command || !command[0]) return NULL; while (dogechat_string_is_command_char (name)) { name = dogechat_utf8_next_char (name); } ptr_alias = alias_search (name); if (ptr_alias) alias_free (ptr_alias); new_alias = malloc (sizeof (*new_alias)); if (new_alias) { new_alias->hook = NULL; new_alias->name = strdup (name); new_alias->command = strdup (command); new_alias->completion = (completion) ? strdup (completion) : NULL; new_alias->running = 0; alias_hook_command (new_alias); if (alias_list) { pos_alias = alias_find_pos (name); if (pos_alias) { /* insert alias into the list (before alias found) */ new_alias->prev_alias = pos_alias->prev_alias; new_alias->next_alias = pos_alias; if (pos_alias->prev_alias) (pos_alias->prev_alias)->next_alias = new_alias; else alias_list = new_alias; pos_alias->prev_alias = new_alias; } else { /* add alias to end of list */ new_alias->prev_alias = last_alias; new_alias->next_alias = NULL; last_alias->next_alias = new_alias; last_alias = new_alias; } } else { new_alias->prev_alias = NULL; new_alias->next_alias = NULL; alias_list = new_alias; last_alias = new_alias; } } return new_alias; }
void irc_input_user_message_display (struct t_gui_buffer *buffer, int action, const char *text) { struct t_irc_nick *ptr_nick; char *pos, *text2, *text_decoded, str_tags[256], *str_color; const char *ptr_text; /* if message is an action, force "action" to 1 and extract message */ if (strncmp (text, "\01ACTION ", 8) == 0) { action = 1; pos = strrchr (text + 8, '\01'); if (pos) text2 = dogechat_strndup (text + 8, pos - text - 8); else text2 = strdup (text + 8); } else text2 = strdup (text); text_decoded = irc_color_decode ( (text2) ? text2 : text, dogechat_config_boolean (irc_config_network_colors_send)); IRC_BUFFER_GET_SERVER_CHANNEL(buffer); if (ptr_channel) { ptr_nick = NULL; if (ptr_channel->type == IRC_CHANNEL_TYPE_CHANNEL) { ptr_nick = irc_nick_search (ptr_server, ptr_channel, ptr_server->nick); } if (action) { snprintf (str_tags, sizeof (str_tags), "irc_action,notify_none,no_highlight"); } else { str_color = irc_color_for_tags ( dogechat_config_color ( dogechat_config_get ("dogechat.color.chat_nick_self"))); snprintf (str_tags, sizeof (str_tags), "notify_none,no_highlight,prefix_nick_%s", (str_color) ? str_color : "default"); if (str_color) free (str_color); } ptr_text = (text_decoded) ? text_decoded : ((text2) ? text2 : text); if (action) { dogechat_printf_tags ( buffer, irc_protocol_tags ( "privmsg", str_tags, (ptr_nick) ? ptr_nick->name : ptr_server->nick, NULL), "%s%s%s%s%s %s", dogechat_prefix ("action"), irc_nick_mode_for_display (ptr_server, ptr_nick, 0), IRC_COLOR_CHAT_NICK_SELF, ptr_server->nick, IRC_COLOR_RESET, ptr_text); } else { dogechat_printf_tags ( buffer, irc_protocol_tags ( "privmsg", str_tags, (ptr_nick) ? ptr_nick->name : ptr_server->nick, NULL), "%s%s", irc_nick_as_prefix ( ptr_server, (ptr_nick) ? ptr_nick : NULL, (ptr_nick) ? NULL : ptr_server->nick, IRC_COLOR_CHAT_NICK_SELF), ptr_text); } } if (text2) free (text2); if (text_decoded) free (text_decoded); }
char * irc_sasl_mechanism_ecdsa_nist256p_challenge (struct t_irc_server *server, const char *data_base64, const char *sasl_username, const char *sasl_key) { #if defined(HAVE_GNUTLS) && (LIBGNUTLS_VERSION_NUMBER >= 0x030015) /* 3.0.21 */ char *data, *string, *answer_base64; int length_data, length_username, length, ret; char *str_privkey; gnutls_x509_privkey_t x509_privkey; gnutls_privkey_t privkey; gnutls_datum_t filedatum, decoded_data, signature; #if LIBGNUTLS_VERSION_NUMBER >= 0x030300 /* 3.3.0 */ gnutls_ecc_curve_t curve; gnutls_datum_t x, y, k; char *pubkey, *pubkey_base64; #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x030300 */ answer_base64 = NULL; string = NULL; length = 0; if (strcmp (data_base64, "+") == 0) { /* send "username" + '\0' + "username" */ answer_base64 = NULL; length_username = strlen (sasl_username); length = length_username + 1 + length_username; string = malloc (length + 1); if (string) { snprintf (string, length + 1, "%s|%s", sasl_username, sasl_username); string[length_username] = '\0'; } } else { /* sign the challenge with the private key and return the result */ /* decode the challenge */ data = malloc (strlen (data_base64) + 1); if (!data) return NULL; length_data = dogechat_string_decode_base64 (data_base64, data); /* read file with private key */ str_privkey = irc_sasl_get_key_content (server, sasl_key); if (!str_privkey) { free (data); return NULL; } /* import key */ gnutls_x509_privkey_init (&x509_privkey); gnutls_privkey_init (&privkey); filedatum.data = (unsigned char *)str_privkey; filedatum.size = strlen (str_privkey); ret = gnutls_x509_privkey_import (x509_privkey, &filedatum, GNUTLS_X509_FMT_PEM); free (str_privkey); if (ret != GNUTLS_E_SUCCESS) { dogechat_printf ( server->buffer, _("%sgnutls: invalid private key file: error %d %s"), dogechat_prefix ("error"), ret, gnutls_strerror (ret)); gnutls_x509_privkey_deinit (x509_privkey); gnutls_privkey_deinit (privkey); free (data); return NULL; } #if LIBGNUTLS_VERSION_NUMBER >= 0x030300 /* 3.3.0 */ /* read raw values in key, to display public key */ ret = gnutls_x509_privkey_export_ecc_raw (x509_privkey, &curve, &x, &y, &k); if (ret == GNUTLS_E_SUCCESS) { pubkey = malloc (x.size + 1); if (pubkey) { pubkey[0] = (y.data[y.size - 1] & 1) ? 0x03 : 0x02; memcpy (pubkey + 1, x.data, x.size); pubkey_base64 = malloc ((x.size + 1 + 1) * 4); if (pubkey_base64) { dogechat_string_encode_base64 (pubkey, x.size + 1, pubkey_base64); dogechat_printf ( server->buffer, _("%s%s: signing the challenge with ECC public key: " "%s"), dogechat_prefix ("network"), IRC_PLUGIN_NAME, pubkey_base64); free (pubkey_base64); } free (pubkey); } gnutls_free (x.data); gnutls_free (y.data); gnutls_free (k.data); } #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x030300 */ /* import private key in an abstract key structure */ ret = gnutls_privkey_import_x509 (privkey, x509_privkey, 0); /* gnutls >= 2.11.0 */ if (ret != GNUTLS_E_SUCCESS) { dogechat_printf ( server->buffer, _("%sgnutls: unable to import the private key: error %d %s"), dogechat_prefix ("error"), ret, gnutls_strerror (ret)); gnutls_x509_privkey_deinit (x509_privkey); gnutls_privkey_deinit (privkey); free (data); return NULL; } decoded_data.data = (unsigned char *)data; decoded_data.size = length_data; ret = gnutls_privkey_sign_hash (privkey, GNUTLS_DIG_SHA256, 0, /* gnutls >= 2.11.0 */ &decoded_data, &signature); if (ret != GNUTLS_E_SUCCESS) { dogechat_printf ( server->buffer, _("%sgnutls: unable to sign the hashed data: error %d %s"), dogechat_prefix ("error"), ret, gnutls_strerror (ret)); gnutls_x509_privkey_deinit (x509_privkey); gnutls_privkey_deinit (privkey); free (data); return NULL; } gnutls_x509_privkey_deinit (x509_privkey); gnutls_privkey_deinit (privkey); string = malloc (signature.size); if (string) memcpy (string, signature.data, signature.size); length = signature.size; gnutls_free (signature.data); free (data); } if (string && (length > 0)) { answer_base64 = malloc ((length + 1) * 4); if (answer_base64) dogechat_string_encode_base64 (string, length, answer_base64); free (string); } return answer_base64; #else /* no gnutls or gnutls < 3.0.21 */ /* make C compiler happy */ (void) data_base64; (void) sasl_username; (void) sasl_key; dogechat_printf (server->buffer, _("%sgnutls: version >= 3.0.21 is required for SASL " "\"ecdsa-nist256p-challenge\""), dogechat_prefix ("error")); return NULL; #endif /* defined(HAVE_GNUTLS) && (LIBGNUTLS_VERSION_NUMBER >= 0x030015) */ }
int fifo_read (void *data, int fd) { static char buffer[4096 + 2]; char *buf2, *pos, *ptr_buf, *next_ptr_buf; int num_read; /* make C compiler happy */ (void) data; (void) fd; num_read = read (fifo_fd, buffer, sizeof (buffer) - 2); if (num_read > 0) { buffer[num_read] = '\0'; buf2 = NULL; ptr_buf = buffer; if (fifo_unterminated) { buf2 = malloc (strlen (fifo_unterminated) + strlen (buffer) + 1); if (buf2) { strcpy (buf2, fifo_unterminated); strcat (buf2, buffer); } ptr_buf = buf2; free (fifo_unterminated); fifo_unterminated = NULL; } while (ptr_buf && ptr_buf[0]) { next_ptr_buf = NULL; pos = strstr (ptr_buf, "\r\n"); if (pos) { pos[0] = '\0'; next_ptr_buf = pos + 2; } else { pos = strstr (ptr_buf, "\n"); if (pos) { pos[0] = '\0'; next_ptr_buf = pos + 1; } else { fifo_unterminated = strdup (ptr_buf); ptr_buf = NULL; next_ptr_buf = NULL; } } if (ptr_buf) fifo_exec (ptr_buf); ptr_buf = next_ptr_buf; } if (buf2) free (buf2); } else { if (num_read < 0) { #ifdef __CYGWIN__ if ((errno == EAGAIN) || (errno == ECOMM)) #else if (errno == EAGAIN) #endif /* __CYGWIN__ */ return DOGECHAT_RC_OK; dogechat_printf (NULL, _("%s%s: error reading pipe (%d %s), closing it"), dogechat_prefix ("error"), FIFO_PLUGIN_NAME, errno, strerror (errno)); fifo_remove (); } else { dogechat_unhook (fifo_fd_hook); fifo_fd_hook = NULL; close (fifo_fd); fifo_fd = open (fifo_filename, O_RDONLY | O_NONBLOCK); if (fifo_fd < 0) { dogechat_printf (NULL, _("%s%s: error opening file, closing it"), dogechat_prefix ("error"), FIFO_PLUGIN_NAME); fifo_remove (); } else fifo_fd_hook = dogechat_hook_fd (fifo_fd, 1, 0, 0, &fifo_read, NULL); } } return DOGECHAT_RC_OK; }
int exec_command_run (struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol, int start_arg) { char str_buffer[512]; struct t_exec_cmd *new_exec_cmd; struct t_exec_cmd_options cmd_options; struct t_hashtable *process_options; struct t_infolist *ptr_infolist; struct t_gui_buffer *ptr_new_buffer; /* parse command options */ cmd_options.command_index = -1; cmd_options.use_shell = 0; cmd_options.detached = 0; cmd_options.pipe_stdin = 0; cmd_options.timeout = 0; cmd_options.ptr_buffer_name = NULL; cmd_options.ptr_buffer = buffer; cmd_options.output_to_buffer = 0; cmd_options.new_buffer = 0; cmd_options.new_buffer_clear = 0; cmd_options.switch_to_buffer = 1; cmd_options.line_numbers = -1; cmd_options.flush = 1; cmd_options.color = EXEC_COLOR_AUTO; cmd_options.display_rc = 1; cmd_options.ptr_command_name = NULL; cmd_options.pipe_command = NULL; cmd_options.hsignal = NULL; /* parse default options */ if (!exec_command_parse_options (&cmd_options, exec_config_cmd_num_options, exec_config_cmd_options, 0, 0)) { dogechat_printf (NULL, _("%s%s: invalid options in option " "exec.command.default_options"), dogechat_prefix ("error"), EXEC_PLUGIN_NAME); return DOGECHAT_RC_ERROR; } if (!exec_command_parse_options (&cmd_options, argc, argv, start_arg, 1)) return DOGECHAT_RC_ERROR; /* options "-bg" and "-o"/"-n" are incompatible */ if (cmd_options.detached && (cmd_options.output_to_buffer || cmd_options.new_buffer)) return DOGECHAT_RC_ERROR; /* options "-pipe" and "-bg"/"-o"/"-n" are incompatible */ if (cmd_options.pipe_command && (cmd_options.detached || cmd_options.output_to_buffer || cmd_options.new_buffer)) return DOGECHAT_RC_ERROR; /* command not found? */ if (cmd_options.command_index < 0) return DOGECHAT_RC_ERROR; new_exec_cmd = exec_add (); if (!new_exec_cmd) return DOGECHAT_RC_ERROR; /* create hashtable for dogechat_hook_process_hashtable() */ process_options = dogechat_hashtable_new (32, DOGECHAT_HASHTABLE_STRING, DOGECHAT_HASHTABLE_STRING, NULL, NULL); if (!process_options) { exec_free (new_exec_cmd); return DOGECHAT_RC_ERROR; } /* automatically disable shell if we are downloading an URL */ if (strncmp (argv_eol[cmd_options.command_index], "url:", 4) == 0) cmd_options.use_shell = 0; if (cmd_options.use_shell) { /* command will be: sh -c "command arguments..." */ dogechat_hashtable_set (process_options, "arg1", "-c"); dogechat_hashtable_set (process_options, "arg2", argv_eol[cmd_options.command_index]); } if (cmd_options.pipe_stdin) dogechat_hashtable_set (process_options, "stdin", "1"); if (cmd_options.detached) dogechat_hashtable_set (process_options, "detached", "1"); if (cmd_options.flush) dogechat_hashtable_set (process_options, "buffer_flush", "1"); /* set variables in new command (before running the command) */ new_exec_cmd->name = (cmd_options.ptr_command_name) ? strdup (cmd_options.ptr_command_name) : NULL; new_exec_cmd->command = strdup (argv_eol[cmd_options.command_index]); new_exec_cmd->detached = cmd_options.detached; if (!cmd_options.detached && !cmd_options.pipe_command && !cmd_options.hsignal) { if (cmd_options.ptr_buffer_name && !cmd_options.ptr_buffer) { /* output in a new buffer using given name */ new_exec_cmd->output_to_buffer = 0; snprintf (str_buffer, sizeof (str_buffer), "exec.%s", cmd_options.ptr_buffer_name); ptr_new_buffer = exec_buffer_new (str_buffer, (cmd_options.new_buffer == 2), cmd_options.new_buffer_clear, cmd_options.switch_to_buffer); if (ptr_new_buffer) { new_exec_cmd->buffer_full_name = strdup (dogechat_buffer_get_string (ptr_new_buffer, "full_name")); } } else if (cmd_options.new_buffer) { /* output in a new buffer using automatic name */ if (new_exec_cmd->name) { snprintf (str_buffer, sizeof (str_buffer), "exec.%s", new_exec_cmd->name); } else { snprintf (str_buffer, sizeof (str_buffer), "exec.%d", new_exec_cmd->number); } ptr_new_buffer = exec_buffer_new (str_buffer, (cmd_options.new_buffer == 2), cmd_options.new_buffer_clear, cmd_options.switch_to_buffer); if (ptr_new_buffer) { new_exec_cmd->buffer_full_name = strdup (dogechat_buffer_get_string (ptr_new_buffer, "full_name")); } } else if (cmd_options.ptr_buffer) { new_exec_cmd->buffer_full_name = strdup (dogechat_buffer_get_string (cmd_options.ptr_buffer, "full_name")); if (cmd_options.switch_to_buffer) dogechat_buffer_set (cmd_options.ptr_buffer, "display", "1"); } if (cmd_options.ptr_buffer && (strcmp (dogechat_buffer_get_string (cmd_options.ptr_buffer, "plugin"), EXEC_PLUGIN_NAME) == 0)) { cmd_options.output_to_buffer = 0; cmd_options.new_buffer = 1; } } new_exec_cmd->output_to_buffer = cmd_options.output_to_buffer; new_exec_cmd->line_numbers = (cmd_options.line_numbers < 0) ? cmd_options.new_buffer : cmd_options.line_numbers; new_exec_cmd->color = cmd_options.color; new_exec_cmd->display_rc = cmd_options.display_rc; new_exec_cmd->pipe_command = cmd_options.pipe_command; new_exec_cmd->hsignal = cmd_options.hsignal; /* execute the command */ if (dogechat_exec_plugin->debug >= 1) { dogechat_printf (NULL, "%s: executing command: \"%s%s%s\"", EXEC_PLUGIN_NAME, (cmd_options.use_shell) ? "" : "sh -c '", argv_eol[cmd_options.command_index], (cmd_options.use_shell) ? "" : "'"); } new_exec_cmd->hook = dogechat_hook_process_hashtable ( (cmd_options.use_shell) ? "sh" : argv_eol[cmd_options.command_index], process_options, cmd_options.timeout * 1000, &exec_process_cb, new_exec_cmd); if (new_exec_cmd->hook) { /* get PID of command */ ptr_infolist = dogechat_infolist_get ("hook", new_exec_cmd->hook, NULL); if (ptr_infolist) { if (dogechat_infolist_next (ptr_infolist)) { new_exec_cmd->pid = dogechat_infolist_integer (ptr_infolist, "child_pid"); } dogechat_infolist_free (ptr_infolist); } } else { exec_free (new_exec_cmd); dogechat_printf (NULL, _("%s%s: failed to run command \"%s\""), dogechat_prefix ("error"), EXEC_PLUGIN_NAME, argv_eol[cmd_options.command_index]); } dogechat_hashtable_free (process_options); return DOGECHAT_RC_OK; }
int dogechat_js_load (const char *filename) { char *source; source = dogechat_file_get_content (filename); if (!source) { dogechat_printf (NULL, dogechat_gettext ("%s%s: script \"%s\" not found"), dogechat_prefix ("error"), JS_PLUGIN_NAME, filename); return 0; } if ((dogechat_js_plugin->debug >= 2) || !js_quiet) { dogechat_printf (NULL, dogechat_gettext ("%s: loading script \"%s\""), JS_PLUGIN_NAME, filename); } js_current_script = NULL; js_registered_script = NULL; js_current_interpreter = new DogechatJsV8(); if (!js_current_interpreter) { dogechat_printf (NULL, dogechat_gettext ("%s%s: unable to create new " "sub-interpreter"), dogechat_prefix ("error"), JS_PLUGIN_NAME); free (source); return 0; } /* load libs */ js_current_interpreter->loadLibs(); js_current_script_filename = filename; if (!js_current_interpreter->load(source)) { dogechat_printf (NULL, dogechat_gettext ("%s%s: unable to load file \"%s\""), dogechat_prefix ("error"), JS_PLUGIN_NAME); delete js_current_interpreter; free (source); /* if script was registered, remove it from list */ if (js_current_script) { plugin_script_remove (dogechat_js_plugin, &js_scripts, &last_js_script, js_current_script); js_current_script = NULL; } return 0; } free (source); if (!js_current_interpreter->execScript()) { dogechat_printf (NULL, dogechat_gettext ("%s%s: unable to execute file " "\"%s\""), dogechat_prefix ("error"), JS_PLUGIN_NAME, filename); delete js_current_interpreter; /* if script was registered, remove it from list */ if (js_current_script) { plugin_script_remove (dogechat_js_plugin, &js_scripts, &last_js_script, js_current_script); js_current_script = NULL; } return 0; } if (!js_registered_script) { dogechat_printf (NULL, dogechat_gettext ("%s%s: function \"register\" not " "found (or failed) in file \"%s\""), dogechat_prefix ("error"), JS_PLUGIN_NAME, filename); delete js_current_interpreter; return 0; } js_current_script = js_registered_script; /* * set input/close callbacks for buffers created by this script * (to restore callbacks after upgrade) */ plugin_script_set_buffer_callbacks (dogechat_js_plugin, js_scripts, js_current_script, &dogechat_js_api_buffer_input_data_cb, &dogechat_js_api_buffer_close_cb); dogechat_hook_signal_send ("javascript_script_loaded", DOGECHAT_HOOK_SIGNAL_STRING, js_current_script->filename); return 1; }