Exemple #1
0
/**
 * Called when a channel message or private message is received.
 */
static int handle_incoming(char *word[], char *word_eol[], void *userdata) {
    const char *prefix;
    const char *command;
    const char *recipient;
    const char *encrypted;
    const char *peice;
    char *sender_nick;
    char *decrypted;
    char *message;
    size_t w;
    size_t ew;
    size_t uw;
    size_t length;

    if (!irc_parse_message((const char **)word, &prefix, &command, &w))
        return HEXCHAT_EAT_NONE;
    
    // Topic (command 332) has an extra parameter
    if (!strcmp(command, "332")) w++;
    
    // Look for encrypted data
    for (ew = w+1; ew < HEXCHAT_MAX_WORDS-1; ew++) {
        const char *s = (ew == w+1 ? word[ew]+1 : word[ew]);
        if (strcmp(s, "+OK") == 0 || strcmp(s, "mcps") == 0) goto has_encrypted_data;
    }
    return HEXCHAT_EAT_NONE;
  has_encrypted_data: ;
    // Extract sender nick and recipient nick/channel
    sender_nick = irc_prefix_get_nick(prefix);
    recipient = word[w];
    
    // Try to decrypt with these (the keys are searched for in the key store)
    encrypted = word[ew+1];
    decrypted = fish_decrypt_from_nick(recipient, encrypted);
    if (!decrypted) decrypted = fish_decrypt_from_nick(sender_nick, encrypted);
    
    // Check for error
    if (!decrypted) goto decrypt_error;
    
    // Build unecrypted message
    message = NULL;
    length = 0;
    if (!append(&message, &length, "RECV")) goto decrypt_error;
    
    for (uw = 1; uw < HEXCHAT_MAX_WORDS; uw++) {
        if (word[uw][0] != '\0' && !append(&message, &length, " ")) goto decrypt_error;
        
        if (uw == ew) {
            // Add the encrypted data
            peice = decrypted;
            uw++; // Skip "OK+"
            
            if (ew == w+1) {
                // Prefix with colon, which gets stripped out otherwise
                if (!append(&message, &length, ":")) goto decrypt_error;
            }
            
        } else {
            // Add unencrypted data (for example, a prefix from a bouncer or bot)
            peice = word[uw];
        }
        
        if (!append(&message, &length, peice)) goto decrypt_error;
    }
    free(decrypted);
    
    // Simulate unencrypted message
    //hexchat_printf(ph, "simulating: %s\n", message);
    hexchat_command(ph, message);
    
    free(message);
    free(sender_nick);
    return HEXCHAT_EAT_HEXCHAT;
  
  decrypt_error:
    free(decrypted);
    free(sender_nick);
    return HEXCHAT_EAT_NONE;
}
/**
 * Called when a channel message or private message is received.
 */
static int handle_incoming(char *word[], char *word_eol[], hexchat_event_attrs *attrs, void *userdata) {
    const char *prefix;
    const char *command;
    const char *recipient;
    const char *encrypted;
    const char *peice;
    char *sender_nick;
    char *decrypted;
    size_t w;
    size_t ew;
    size_t uw;
    char prefix_char = 0;
    GString *message;

    if (!irc_parse_message((const char **)word, &prefix, &command, &w))
        return HEXCHAT_EAT_NONE;
    
    /* Topic (command 332) has an extra parameter */
    if (!strcmp(command, "332")) w++;
    
    /* Look for encrypted data */
    for (ew = w+1; ew < HEXCHAT_MAX_WORDS-1; ew++) {
        const char *s = (ew == w+1 ? word[ew]+1 : word[ew]);
        if (*s && (s[1] == '+' || s[1] == 'm')) { prefix_char = *(s++); }
        else { prefix_char = 0; }
        if (strcmp(s, "+OK") == 0 || strcmp(s, "mcps") == 0) goto has_encrypted_data;
    }
    return HEXCHAT_EAT_NONE;
  has_encrypted_data: ;
    /* Extract sender nick and recipient nick/channel */
    sender_nick = irc_prefix_get_nick(prefix);
    recipient = word[w];
    
    /* Try to decrypt with these (the keys are searched for in the key store) */
    encrypted = word[ew+1];
    decrypted = fish_decrypt_from_nick(recipient, encrypted);
    if (!decrypted) decrypted = fish_decrypt_from_nick(sender_nick, encrypted);
    
    /* Check for error */
    if (!decrypted) goto decrypt_error;
    
    /* Build unecrypted message */
    message = g_string_sized_new (100); /* TODO: more accurate estimation of size */
    g_string_append (message, "RECV");

    if (attrs->server_time_utc)
    {
        GTimeVal tv = { (glong)attrs->server_time_utc, 0 };
        char *timestamp = g_time_val_to_iso8601 (&tv);

       g_string_append (message, " @time=");
       g_string_append (message, timestamp);
       g_free (timestamp);
    }

    for (uw = 1; uw < HEXCHAT_MAX_WORDS; uw++) {
        if (word[uw][0] != '\0')
            g_string_append_c (message, ' ');
        
        if (uw == ew) {
            /* Add the encrypted data */
            peice = decrypted;
            uw++; /* Skip "OK+" */
            
            if (ew == w+1) {
                /* Prefix with colon, which gets stripped out otherwise */
                g_string_append_c (message, ':');
            }
            
            if (prefix_char) {
                g_string_append_c (message, prefix_char);
            }
            
        } else {
            /* Add unencrypted data (for example, a prefix from a bouncer or bot) */
            peice = word[uw];
        }

        g_string_append (message, peice);
    }
    g_free(decrypted);
    
    /* Simulate unencrypted message */
    /* hexchat_printf(ph, "simulating: %s\n", message->str); */
    hexchat_command(ph, message->str);

    g_string_free (message, TRUE);
    g_free(sender_nick);
    return HEXCHAT_EAT_HEXCHAT;
  
  decrypt_error:
    g_free(decrypted);
    g_free(sender_nick);
    return HEXCHAT_EAT_NONE;
}