コード例 #1
0
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);
    }
}
コード例 #2
0
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);
}
コード例 #3
0
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;
}
コード例 #4
0
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);
}
コード例 #5
0
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;
}
コード例 #6
0
void
script_action_list ()
{
    int i, scripts_loaded;
    char hdata_name[128];
    const char *ptr_name;
    struct t_hdata *hdata;
    void *ptr_script;

    dogechat_printf (NULL, "");
    dogechat_printf (NULL, _("Scripts loaded:"));

    scripts_loaded = 0;

    for (i = 0; i < SCRIPT_NUM_LANGUAGES; i++)
    {
        snprintf (hdata_name, sizeof (hdata_name),
                  "%s_script", script_language[i]);
        hdata = dogechat_hdata_get (hdata_name);
        ptr_script = dogechat_hdata_get_list (hdata, "scripts");
        while (ptr_script)
        {
            ptr_name = dogechat_hdata_string (hdata, ptr_script, "name");
            dogechat_printf (NULL, " %s %s%s%s.%s %s%s %s(%s%s%s)",
                            script_repo_get_status_for_display (script_repo_search_by_name (ptr_name),
                                                                "*?iaHN", 0),
                            dogechat_color (dogechat_config_string (script_config_color_text_name)),
                            ptr_name,
                            dogechat_color (dogechat_config_string (script_config_color_text_extension)),
                            script_extension[i],
                            dogechat_color (dogechat_config_string (script_config_color_text_version)),
                            dogechat_hdata_string (hdata, ptr_script, "version"),
                            dogechat_color ("chat_delimiters"),
                            dogechat_color (dogechat_config_string (script_config_color_text_description)),
                            dogechat_hdata_string (hdata, ptr_script, "description"),
                            dogechat_color ("chat_delimiters"));
            scripts_loaded++;
            ptr_script = dogechat_hdata_move (hdata, ptr_script, 1);
        }
    }

    if (scripts_loaded == 0)
    {
        dogechat_printf (NULL, _("  (none)"));
    }
}
コード例 #7
0
int
script_action_hold (const char *name, int quiet)
{
    struct t_script_repo *ptr_script;

    ptr_script = script_repo_search_by_name_ext (name);
    if (ptr_script)
    {
        if (ptr_script->status & SCRIPT_STATUS_HELD)
        {
            script_config_unhold (ptr_script->name_with_extension);
            if (!quiet)
            {
                dogechat_printf (NULL,
                                _("%s: script \"%s\" is not "
                                  "held any more"),
                                SCRIPT_PLUGIN_NAME, name);
            }
        }
        else
        {
            script_config_hold (ptr_script->name_with_extension);
            if (!quiet)
            {
                dogechat_printf (NULL,
                                _("%s: script \"%s\" is held"),
                                SCRIPT_PLUGIN_NAME, name);
            }
        }
        script_repo_update_status (ptr_script);
        return 1;
    }
    else
    {
        if (!quiet)
        {
            dogechat_printf (NULL,
                            _("%s: script \"%s\" not found"),
                            SCRIPT_PLUGIN_NAME, name);
        }
    }

    return 0;
}
コード例 #8
0
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);
}
コード例 #9
0
void
script_action_load (const char *name, int quiet)
{
    char *pos, str_command[1024];
    int language;

    language = -1;
    pos = strrchr (name, '.');
    if (pos)
        language = script_language_search_by_extension (pos + 1);
    if (language < 0)
    {
        if (!quiet)
        {
            dogechat_printf (NULL,
                            _("%s: unknown language for script \"%s\""),
                            SCRIPT_PLUGIN_NAME, name);
        }
        return;
    }

    /* check that plugin for this language is loaded */
    if (!script_plugin_loaded[language])
    {
        dogechat_printf (NULL,
                        _("%s: plugin \"%s\" is not loaded"),
                        SCRIPT_PLUGIN_NAME, script_language[language]);
        return;
    }

    /* execute command (for example: "/perl load iset.pl") */
    snprintf (str_command, sizeof (str_command),
              "/%s load %s%s",
              script_language[language],
              (quiet && dogechat_config_boolean (script_config_look_quiet_actions)) ? "-q " : "",
              name);
    dogechat_command (NULL, str_command);
}
コード例 #10
0
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;
}
コード例 #11
0
int
dogechat_js_signal_debug_libs_cb (void *data, const char *signal,
                                 const char *type_data, void *signal_data)
{
    /* make C++ compiler happy */
    (void) data;
    (void) signal;
    (void) type_data;
    (void) signal_data;

    dogechat_printf (NULL, "  %s (v8): %s",
                    JS_PLUGIN_NAME, v8::V8::GetVersion());

    return DOGECHAT_RC_OK;
}
コード例 #12
0
void
fifo_remove_old_pipes ()
{
    char *buf;
    int buf_len, prefix_len;
    const char *dogechat_home, *dir_separator;
    DIR *dp;
    struct dirent *entry;
    struct stat statbuf;

    buf_len = PATH_MAX;
    buf = malloc (buf_len);
    if (!buf)
        return;

    dogechat_home = dogechat_info_get ("dogechat_dir", "");
    dir_separator = dogechat_info_get ("dir_separator", "");

    prefix_len = strlen (FIFO_FILENAME_PREFIX);

    dp = opendir (dogechat_home);
    if (dp != NULL)
    {
        while ((entry = readdir (dp)) != NULL)
        {
            if (strcmp (entry->d_name, ".") == 0 || strcmp (entry->d_name, "..") == 0)
                continue;

            if (strncmp (entry->d_name, FIFO_FILENAME_PREFIX, prefix_len) == 0)
            {
                snprintf (buf, buf_len, "%s%s%s",
                          dogechat_home, dir_separator, entry->d_name);
                if (stat (buf, &statbuf) != -1)
                {
                    dogechat_printf (NULL,
                                    _("%s: removing old fifo pipe \"%s\""),
                                    FIFO_PLUGIN_NAME, buf);
                    unlink (buf);
                }
            }
        }
        closedir (dp);
    }

    free (buf);
}
コード例 #13
0
int
exec_process_cb (void *data, const char *command, int return_code,
                 const char *out, const char *err)
{
    struct t_exec_cmd *ptr_exec_cmd;
    struct t_gui_buffer *ptr_buffer;

    /* make C compiler happy */
    (void) command;

    ptr_exec_cmd = (struct t_exec_cmd *)data;
    if (!ptr_exec_cmd)
        return DOGECHAT_RC_ERROR;

    if (dogechat_exec_plugin->debug >= 2)
    {
        dogechat_printf (NULL,
                        "%s: process_cb: command=\"%s\", rc=%d, "
                        "out: %d bytes, err: %d bytes",
                        EXEC_PLUGIN_NAME,
                        ptr_exec_cmd->command,
                        return_code,
                        (out) ? strlen (out) : 0,
                        (err) ? strlen (err) : 0);
    }

    if (out || err)
    {
        ptr_buffer = dogechat_buffer_search ("==",
                                            ptr_exec_cmd->buffer_full_name);
        if (out)
            exec_concat_output (ptr_exec_cmd, ptr_buffer, EXEC_STDOUT, out);
        if (err)
            exec_concat_output (ptr_exec_cmd, ptr_buffer, EXEC_STDERR, err);
    }

    if (return_code == DOGECHAT_HOOK_PROCESS_ERROR)
        exec_end_command (ptr_exec_cmd, -1);
    else if (return_code >= 0)
        exec_end_command (ptr_exec_cmd, return_code);

    return DOGECHAT_RC_OK;
}
コード例 #14
0
void
dogechat_js_unload (struct t_plugin_script *script)
{
    int *rc;
    char *filename;
    void *interpreter;

    if ((dogechat_js_plugin->debug >= 2) || !js_quiet)
    {
        dogechat_printf (NULL,
                        dogechat_gettext ("%s: unloading script \"%s\""),
                        JS_PLUGIN_NAME, script->name);
    }

    if (script->shutdown_func && script->shutdown_func[0])
    {
        rc = (int *)dogechat_js_exec (script, DOGECHAT_SCRIPT_EXEC_INT,
                                     script->shutdown_func, NULL, NULL);
        if (rc)
            free (rc);
    }

    filename = strdup (script->filename);
    interpreter = script->interpreter;

    if (js_current_script == script)
    {
        js_current_script = (js_current_script->prev_script) ?
            js_current_script->prev_script : js_current_script->next_script;
    }

    plugin_script_remove (dogechat_js_plugin,
                          &js_scripts, &last_js_script, script);

    if (interpreter)
        delete((DogechatJsV8 *)interpreter);

    (void) dogechat_hook_signal_send ("javascript_script_unloaded",
                                     DOGECHAT_HOOK_SIGNAL_STRING, filename);
    if (filename)
        free (filename);
}
コード例 #15
0
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);
    }
}
コード例 #16
0
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;
}
コード例 #17
0
void
fifo_remove ()
{
    /* remove fd hook */
    if (fifo_fd_hook)
    {
        dogechat_unhook (fifo_fd_hook);
        fifo_fd_hook = NULL;
    }

    /* close FIFO pipe */
    if (fifo_fd != -1)
    {
        close (fifo_fd);
        fifo_fd = -1;
    }

    /* remove FIFO from disk */
    if (fifo_filename)
        unlink (fifo_filename);

    /* remove any unterminated message */
    if (fifo_unterminated)
    {
        free (fifo_unterminated);
        fifo_unterminated = NULL;
    }

    /* free filename */
    if (fifo_filename)
    {
        free (fifo_filename);
        fifo_filename = NULL;
    }

    dogechat_printf (NULL,
                    _("%s: pipe closed"),
                    FIFO_PLUGIN_NAME);
}
コード例 #18
0
void
relay_server_close_socket (struct t_relay_server *server)
{
    if (server->hook_fd)
    {
        dogechat_unhook (server->hook_fd);
        server->hook_fd = NULL;
    }
    if (server->sock >= 0)
    {
        close (server->sock);
        server->sock = -1;

        if (!relay_signal_upgrade_received)
        {
            dogechat_printf (NULL,
                            _("%s: socket closed for %s (port %d)"),
                            RELAY_PLUGIN_NAME, server->protocol_string,
                            server->port);
        }
    }
}
コード例 #19
0
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;
}
コード例 #20
0
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;
}
コード例 #21
0
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;
}
コード例 #22
0
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) */
}
コード例 #23
0
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;
}
コード例 #24
0
void
script_action_remove (const char *name, int quiet)
{
    struct t_script_repo *ptr_script;
    char str_signal[256], *filename;
    int length;

    ptr_script = script_repo_search_by_name_ext (name);
    if (!ptr_script)
    {
        if (!quiet)
        {
            dogechat_printf (NULL,
                            _("%s: script \"%s\" not found"),
                            SCRIPT_PLUGIN_NAME, name);
        }
        return;
    }

    /* check that script is installed */
    if (!(ptr_script->status & SCRIPT_STATUS_INSTALLED))
    {
        if (!quiet)
        {
            dogechat_printf (NULL,
                            _("%s: script \"%s\" is not installed"),
                            SCRIPT_PLUGIN_NAME, name);
        }
        return;
    }

    /* check that script is not held */
    if (ptr_script->status & SCRIPT_STATUS_HELD)
    {
        if (!quiet)
        {
            dogechat_printf (NULL,
                            _("%s: script \"%s\" is held"),
                            SCRIPT_PLUGIN_NAME, name);
        }
        return;
    }

    /* check that plugin for this language is loaded */
    if (!script_plugin_loaded[ptr_script->language])
    {
        dogechat_printf (NULL,
                        _("%s: script \"%s\" can not be removed "
                          "because plugin \"%s\" is not loaded"),
                        SCRIPT_PLUGIN_NAME,
                        ptr_script->name_with_extension,
                        script_language[ptr_script->language]);
        return;
    }

    /* ask plugin to remove script */
    length = 3 + strlen (ptr_script->name_with_extension) + 1;
    filename = malloc (length);
    if (filename)
    {
        snprintf (filename, length,
                  "%s%s",
                  (quiet && dogechat_config_boolean (script_config_look_quiet_actions)) ? "-q " : "",
                  ptr_script->name_with_extension);
        snprintf (str_signal, sizeof (str_signal),
                  "%s_script_remove",
                  script_language[ptr_script->language]);
        (void) dogechat_hook_signal_send (str_signal,
                                         DOGECHAT_HOOK_SIGNAL_STRING,
                                         filename);
        free (filename);
    }
}
コード例 #25
0
void
script_action_install (int quiet)
{
    struct t_script_repo *ptr_script_to_install;
    char *filename, *url;
    struct t_hashtable *options;

    while (1)
    {
        ptr_script_to_install = script_action_get_next_script_to_install ();

        /* no more script to install? just exit function */
        if (!ptr_script_to_install)
            return;

        /*
         * script to install and plugin is loaded: exit loop and go on with
         * install
         */
        if (script_plugin_loaded[ptr_script_to_install->language])
            break;

        /* plugin not loaded for language of script: display error */
        dogechat_printf (NULL,
                        _("%s: script \"%s\" can not be installed because "
                          "plugin \"%s\" is not loaded"),
                        SCRIPT_PLUGIN_NAME,
                        ptr_script_to_install->name_with_extension,
                        script_language[ptr_script_to_install->language]);
    }

    filename = script_config_get_script_download_filename (ptr_script_to_install,
                                                           NULL);
    if (filename)
    {
        options = dogechat_hashtable_new (32,
                                         DOGECHAT_HASHTABLE_STRING,
                                         DOGECHAT_HASHTABLE_STRING,
                                         NULL,
                                         NULL);
        if (options)
        {
            url = script_build_download_url (ptr_script_to_install->url);
            if (url)
            {
                if (!dogechat_config_boolean (script_config_look_quiet_actions))
                {
                    dogechat_printf (NULL,
                                    _("%s: downloading script \"%s\"..."),
                                    SCRIPT_PLUGIN_NAME,
                                    ptr_script_to_install->name_with_extension);
                }
                dogechat_hashtable_set (options, "file_out", filename);
                dogechat_hook_process_hashtable (
                    url,
                    options,
                    dogechat_config_integer (script_config_scripts_download_timeout) * 1000,
                    &script_action_install_process_cb,
                    (quiet) ? (void *)1 : (void *)0);
                free (url);
            }
            dogechat_hashtable_free (options);
        }
        free (filename);
    }
}
コード例 #26
0
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;
}
コード例 #27
0
void
script_action_autoload (const char *name, int quiet, int autoload)
{
    struct t_script_repo *ptr_script;
    char str_signal[256], *filename;
    int length;

    ptr_script = script_repo_search_by_name_ext (name);
    if (!ptr_script)
    {
        if (!quiet)
        {
            dogechat_printf (NULL,
                            _("%s: script \"%s\" not found"),
                            SCRIPT_PLUGIN_NAME, name);
        }
        return;
    }

    /* check that script is installed */
    if (!(ptr_script->status & SCRIPT_STATUS_INSTALLED))
    {
        if (!quiet)
        {
            dogechat_printf (NULL,
                            _("%s: script \"%s\" is not installed"),
                            SCRIPT_PLUGIN_NAME, name);
        }
        return;
    }

    /* toggle autoload if value is -1 */
    if (autoload < 0)
        autoload = (ptr_script->status & SCRIPT_STATUS_AUTOLOADED) ? 0 : 1;

    /* ask plugin to autoload (or not) script */
    length = 16 + strlen (ptr_script->name_with_extension) + 1;
    filename = malloc (length);
    if (filename)
    {
        snprintf (filename, length,
                  "%s%s%s",
                  (quiet && dogechat_config_boolean (script_config_look_quiet_actions)) ? "-q " : "",
                  (autoload) ? "-a " : "",
                  ptr_script->name_with_extension);
        snprintf (str_signal, sizeof (str_signal),
                  "%s_script_autoload",
                  script_language[ptr_script->language]);
        (void) dogechat_hook_signal_send (str_signal,
                                         DOGECHAT_HOOK_SIGNAL_STRING,
                                         filename);
        free (filename);
    }
    if (!quiet)
    {
        dogechat_printf (NULL,
                        (autoload) ?
                        _("%s: autoload enabled for script \"%s\"") :
                        _("%s: autoload disabled for script \"%s\""),
                        SCRIPT_PLUGIN_NAME, name);
    }
    script_repo_update_status (ptr_script);
}
コード例 #28
0
void
script_action_reload (const char *name, int quiet)
{
    char *pos, hdata_name[128], *filename, *ptr_base_name, str_command[1024];
    const char *ptr_filename, *ptr_registered_name;
    int language, found, i;
    struct t_hdata *hdata;
    void *ptr_script;

    pos = strrchr (name, '.');
    if (pos)
    {
        /* reload script by using name + extension (example: "iset.pl") */
        language = script_language_search_by_extension (pos + 1);
        if (language < 0)
        {
            if (!quiet)
            {
                dogechat_printf (NULL,
                                _("%s: unknown language for script \"%s\""),
                                SCRIPT_PLUGIN_NAME, name);
            }
            return;
        }
        /*
         * search registered name of script using name with extension,
         * for example with "iset.pl" we should find "iset"
         */
        snprintf (hdata_name, sizeof (hdata_name),
                  "%s_script", script_language[language]);
        hdata = dogechat_hdata_get (hdata_name);
        ptr_script = dogechat_hdata_get_list (hdata, "scripts");
        while (ptr_script)
        {
            found = 0;
            ptr_filename = dogechat_hdata_string (hdata, ptr_script, "filename");
            if (ptr_filename)
            {
                filename = strdup (ptr_filename);
                if (filename)
                {
                    ptr_base_name = basename (filename);
                    if (strcmp (ptr_base_name, name) == 0)
                        found = 1;
                    free (filename);
                }
            }
            if (found)
            {
                ptr_registered_name = dogechat_hdata_string (hdata, ptr_script,
                                                            "name");
                if (ptr_registered_name)
                {
                    snprintf (str_command, sizeof (str_command),
                              "/%s reload %s%s",
                              script_language[language],
                              (quiet && dogechat_config_boolean (script_config_look_quiet_actions)) ? "-q " : "",
                              ptr_registered_name);
                    dogechat_command (NULL, str_command);
                }
                return;
            }
            ptr_script = dogechat_hdata_move (hdata, ptr_script, 1);
        }
    }
    else
    {
        /* reload script by using name (example: "iset") */
        for (i = 0; i < SCRIPT_NUM_LANGUAGES; i++)
        {
            snprintf (hdata_name, sizeof (hdata_name),
                      "%s_script", script_language[i]);
            hdata = dogechat_hdata_get (hdata_name);
            ptr_script = dogechat_hdata_get_list (hdata, "scripts");
            while (ptr_script)
            {
                ptr_registered_name = dogechat_hdata_string (hdata, ptr_script,
                                                            "name");
                if (strcmp (ptr_registered_name, name) == 0)
                {
                    snprintf (str_command, sizeof (str_command),
                              "/%s reload %s%s",
                              script_language[i],
                              (quiet && dogechat_config_boolean (script_config_look_quiet_actions)) ? "-q " : "",
                              name);
                    dogechat_command (NULL, str_command);
                    return;
                }
                ptr_script = dogechat_hdata_move (hdata, ptr_script, 1);
            }
        }
    }

    if (!quiet)
    {
        dogechat_printf (NULL,
                        _("%s: script \"%s\" is not loaded"),
                        SCRIPT_PLUGIN_NAME, name);
    }
}
コード例 #29
0
void
script_action_show (const char *name, int quiet)
{
    struct t_script_repo *ptr_script;
    char *filename, *url;
    struct t_hashtable *options;

    if (name)
    {
        ptr_script = script_repo_search_by_name_ext (name);
        if (ptr_script)
        {
            script_buffer_show_detail_script (ptr_script);
            if (dogechat_config_boolean (script_config_look_display_source))
            {
                dogechat_printf_y (script_buffer,
                                  script_buffer_detail_script_last_line++,
                                  _("Source code:"));
                dogechat_printf_y (script_buffer,
                                  script_buffer_detail_script_last_line++,
                                  "%s----------------------------------------"
                                  "----------------------------------------",
                                  dogechat_color ("lightcyan"));
                dogechat_printf_y (script_buffer,
                                  script_buffer_detail_script_last_line,
                                  _("Downloading script..."));
                dogechat_printf_y (script_buffer,
                                  script_buffer_detail_script_last_line + 1,
                                  "%s----------------------------------------"
                                  "----------------------------------------",
                                  dogechat_color ("lightcyan"));
                filename = script_config_get_script_download_filename (ptr_script,
                                                                       ".repository");
                if (filename)
                {
                    options = dogechat_hashtable_new (32,
                                                     DOGECHAT_HASHTABLE_STRING,
                                                     DOGECHAT_HASHTABLE_STRING,
                                                     NULL,
                                                     NULL);
                    if (options)
                    {
                        url = script_build_download_url (ptr_script->url);
                        if (url)
                        {
                            dogechat_hashtable_set (options, "file_out", filename);
                            dogechat_hook_process_hashtable (
                                url,
                                options,
                                dogechat_config_integer (script_config_scripts_download_timeout) * 1000,
                                &script_action_show_source_process_cb,
                                NULL);
                            free (url);
                        }
                        dogechat_hashtable_free (options);
                    }
                    free (filename);
                }
            }
        }
        else
        {
            if (!quiet)
            {
                dogechat_printf (NULL,
                                _("%s: script \"%s\" not found"),
                                SCRIPT_PLUGIN_NAME, name);
            }
        }
    }
    else
        script_buffer_show_detail_script (NULL);
}
コード例 #30
0
int
script_action_run ()
{
    char **actions, **argv, **argv_eol, *ptr_action;
    int num_actions, argc, i, j, quiet, script_found;
    struct t_script_repo *ptr_script;

    if (!script_actions)
        return 0;

    script_get_loaded_plugins ();

    actions = dogechat_string_split (script_actions, "\n", 0, 0, &num_actions);
    if (actions)
    {
        for (i = 0; i < num_actions; i++)
        {
            quiet = 0;
            ptr_action = actions[i];
            if (ptr_action[0] == '-')
            {
                /*
                 * if action starts with options (like "-q"),
                 * read and skip them
                 */
                ptr_action++;
                while (ptr_action[0] && (ptr_action[0] != ' '))
                {
                    switch (ptr_action[0])
                    {
                        case 'q': /* quiet */
                            quiet = 1;
                            break;
                    }
                    ptr_action++;
                }
                while (ptr_action[0] == ' ')
                {
                    ptr_action++;
                }
            }
            argv = dogechat_string_split (ptr_action, " ", 0, 0, &argc);
            argv_eol = dogechat_string_split (ptr_action, " ", 1, 0, &argc);
            if (argv && argv_eol)
            {
                if (dogechat_strcasecmp (argv[0], "buffer") == 0)
                {
                    /* open buffer with list of scripts */
                    if (!script_buffer)
                    {
                        script_buffer_open ();
                        script_buffer_refresh (1);
                    }
                    dogechat_buffer_set (script_buffer, "display", "1");
                }
                else if (dogechat_strcasecmp (argv[0], "list") == 0)
                {
                    if (argc > 1)
                    {
                        if (dogechat_strcasecmp (argv[1], "-i") == 0)
                            script_action_list_input (0);
                        else if (dogechat_strcasecmp (argv[1], "-o") == 0)
                            script_action_list_input (1);
                        else
                            script_action_list ();
                    }
                    else
                        script_action_list ();
                }
                else if (dogechat_strcasecmp (argv[0], "load") == 0)
                {
                    for (j = 1; j < argc; j++)
                    {
                        script_action_load (argv[j], quiet);
                    }
                }
                else if (dogechat_strcasecmp (argv[0], "unload") == 0)
                {
                    for (j = 1; j < argc; j++)
                    {
                        script_action_unload (argv[j], quiet);
                    }
                }
                else if (dogechat_strcasecmp (argv[0], "reload") == 0)
                {
                    for (j = 1; j < argc; j++)
                    {
                        script_action_reload (argv[j], quiet);
                    }
                }
                else if (dogechat_strcasecmp (argv[0], "autoload") == 0)
                {
                    for (j = 1; j < argc; j++)
                    {
                        script_action_autoload (argv[j], quiet, 1);
                    }
                }
                else if (dogechat_strcasecmp (argv[0], "noautoload") == 0)
                {
                    for (j = 1; j < argc; j++)
                    {
                        script_action_autoload (argv[j], quiet, 0);
                    }
                }
                else if (dogechat_strcasecmp (argv[0], "toggleautoload") == 0)
                {
                    for (j = 1; j < argc; j++)
                    {
                        script_action_autoload (argv[j], quiet, -1);
                    }
                }
                else if (dogechat_strcasecmp (argv[0], "install") == 0)
                {
                    script_found = 0;
                    for (j = 1; j < argc; j++)
                    {
                        ptr_script = script_repo_search_by_name_ext (argv[j]);
                        if (ptr_script)
                        {
                            if (ptr_script->status & SCRIPT_STATUS_HELD)
                            {
                                dogechat_printf (NULL,
                                                _("%s: script \"%s\" is held"),
                                                SCRIPT_PLUGIN_NAME, argv[j]);
                            }
                            else if ((ptr_script->status & SCRIPT_STATUS_INSTALLED)
                                     && !(ptr_script->status & SCRIPT_STATUS_NEW_VERSION))
                            {
                                dogechat_printf (NULL,
                                                _("%s: script \"%s\" is already "
                                                  "installed and up-to-date"),
                                                SCRIPT_PLUGIN_NAME, argv[j]);
                            }
                            else
                            {
                                script_found++;
                                ptr_script->install_order = script_found;
                            }
                        }
                        else
                        {
                            dogechat_printf (NULL,
                                            _("%s: script \"%s\" not found"),
                                            SCRIPT_PLUGIN_NAME, argv[j]);
                        }
                    }
                    if (script_found)
                        script_action_install (quiet);
                }
                else if (dogechat_strcasecmp (argv[0], "remove") == 0)
                {
                    for (j = 1; j < argc; j++)
                    {
                        script_action_remove (argv[j], quiet);
                    }
                }
                else if (dogechat_strcasecmp (argv[0], "installremove") == 0)
                {
                    script_found = 0;
                    for (j = 1; j < argc; j++)
                    {
                        ptr_script = script_repo_search_by_name_ext (argv[j]);
                        if (ptr_script)
                        {
                            if (ptr_script->status & SCRIPT_STATUS_HELD)
                            {
                                dogechat_printf (NULL,
                                                _("%s: script \"%s\" is held"),
                                                SCRIPT_PLUGIN_NAME, argv[j]);
                            }
                            else if (ptr_script->status & SCRIPT_STATUS_INSTALLED)
                            {
                                script_action_remove (argv[j], quiet);
                            }
                            else
                            {
                                script_found++;
                                ptr_script->install_order = script_found;
                            }
                        }
                        else
                        {
                            dogechat_printf (NULL,
                                            _("%s: script \"%s\" not found"),
                                            SCRIPT_PLUGIN_NAME, argv[j]);
                        }
                    }
                    if (script_found)
                        script_action_install (quiet);
                }
                else if (dogechat_strcasecmp (argv[0], "hold") == 0)
                {
                    script_found = 0;
                    for (j = 1; j < argc; j++)
                    {
                        if (script_action_hold (argv[j], quiet))
                            script_found = 1;
                    }
                    if (script_found)
                        script_buffer_refresh (0);
                }
                else if (dogechat_strcasecmp (argv[0], "show") == 0)
                {
                    if (!script_buffer)
                        script_buffer_open ();
                    script_action_show ((argc >= 2) ? argv[1] : NULL,
                                        quiet);
                    dogechat_buffer_set (script_buffer, "display", "1");
                }
                else if (dogechat_strcasecmp (argv[0], "showdiff") == 0)
                {
                    script_action_showdiff ();
                }
                else if (dogechat_strcasecmp (argv[0], "upgrade") == 0)
                {
                    script_found = 0;
                    for (ptr_script = scripts_repo; ptr_script;
                         ptr_script = ptr_script->next_script)
                    {
                        /*
                         * if script is installed, with new version available,
                         * and not held, then upgrade it
                         */
                        if ((ptr_script->status & SCRIPT_STATUS_INSTALLED)
                            && (ptr_script->status & SCRIPT_STATUS_NEW_VERSION)
                            && !(ptr_script->status & SCRIPT_STATUS_HELD))
                        {
                            script_found++;
                            ptr_script->install_order = script_found;
                        }
                    }
                    if (script_found)
                        script_action_install (quiet);
                    else
                    {
                        dogechat_printf (NULL,
                                        _("%s: all scripts are up-to-date"),
                                        SCRIPT_PLUGIN_NAME);
                    }
                }
            }
            if (argv)
                dogechat_string_free_split (argv);
            if (argv_eol)
                dogechat_string_free_split (argv_eol);
        }
        dogechat_string_free_split (actions);
    }

    free (script_actions);
    script_actions = NULL;

    return 1;
}