Ejemplo n.º 1
0
/*
 * Encrypt a message and store in bf_dest (using key for target)
 * @param server
 * @param msg_ptr
 * @param target
 * @param bf_dest
 * @return 1 if everything ok 0 if not
 */
int FiSH_encrypt(const SERVER_REC * serverRec, const char *msgPtr,
		 const char *target, char *bf_dest)
{
	char theKey[KEYBUF_SIZE] = "";
	char contactName[CONTACT_SIZE] = "";

	if (IsNULLorEmpty(msgPtr) || bf_dest == NULL || IsNULLorEmpty(target))
		return 0;

	if (settings_get_bool("process_outgoing") == 0)
		return 0;

	if (getIniSectionForContact(serverRec, target, contactName) == FALSE)
		return 0;

	if (getContactKey(contactName, theKey) == FALSE)
		return 0;

	strcpy(bf_dest, "+OK ");

	encrypt_string(theKey, msgPtr, bf_dest + 4, strlen(msgPtr));

	ZeroMemory(theKey, KEYBUF_SIZE);

	return 1;
}
Ejemplo n.º 2
0
void encrypt_msg(SERVER_REC * server, char *target, char *msg,
		 char *orig_target)
{
	char bf_dest[800] = "", *plainMsg;
	char contactName[CONTACT_SIZE] = "";

	if (IsNULLorEmpty(msg) || IsNULLorEmpty(target))
		return;

	if (getIniSectionForContact(server, target, contactName) == FALSE)
		return;

	if (getContactKey(contactName, NULL) == FALSE)
		return;

	plainMsg = isPlainPrefix(msg);
	if (plainMsg) {
		signal_continue(4, server, target, plainMsg, orig_target);
		return;
	}
	// generally cut a message to a size of 512 byte, as everything above will never arrive complete anyway
	if (strlen(msg) > 512)
		msg[512] = '\0';

	if (FiSH_encrypt(server, msg, target, bf_dest) == 1) {	// message was encrypted
		bf_dest[512] = '\0';
		signal_continue(4, server, target, bf_dest, orig_target);
	}
}
Ejemplo n.º 3
0
/*
 * format outgoing (encrypted) messages (add crypt-mark or remove plain-prefix)
 */
void format_msg(SERVER_REC * server, char *msg, char *target, char *orig_target)
{
	char contactName[CONTACT_SIZE] = "", myMark[20] =
	    "", formattedMsg[800] = "";
	int i, markPos;
	char *plainMsg;

	if (IsNULLorEmpty(msg) || IsNULLorEmpty(target))
		return;

	if (settings_get_bool("process_outgoing") == 0)
		return;

	if (getIniSectionForContact(server, target, contactName) == FALSE)
		return;

	if (getContactKey(contactName, NULL) == FALSE)
		return;

	plainMsg = isPlainPrefix(msg);
	if (plainMsg) {
		signal_continue(4, server, plainMsg, target, orig_target);
		return;
	}
	// generally cut a message to a size of 512 byte, as everything above will never arrive complete anyway
	if (strlen(msg) > 512)
		msg[512] = '\0';

	// append crypt-mark?
	strncpy(myMark, settings_get_str("mark_encrypted"), sizeof(myMark));
	if (*myMark != '\0') {
		strcpy(formattedMsg, msg);
		markPos = settings_get_int("mark_position");
		if (markPos == 0)
			strcat(formattedMsg, myMark);	//append mark at the end
		else {		// prefix mark
			i = strlen(myMark);
			memmove(formattedMsg + i, formattedMsg,
				strlen(formattedMsg) + 1);
			strncpy(formattedMsg, myMark, i);
		}

		signal_continue(4, server, formattedMsg, target, orig_target);

		ZeroMemory(formattedMsg, sizeof(formattedMsg));
	}

	return;
}
Ejemplo n.º 4
0
/*
 * format outgoing (encrypted) messages (add crypt-mark or remove plain-prefix)
 */
void format_msg(SERVER_REC *server, char *msg, char *target, char *orig_target)
{
    char contactName[CONTACT_SIZE]="", myMark[20]="", markPos[20]="", formattedMsg[800]="";
    int i;
    char *plainMsg;


    if (IsNULLorEmpty(msg) || IsNULLorEmpty(target)) return;
    if (GetBlowIniSwitch("FiSH", "process_outgoing", "1") == 0) return;

    if (GetIniSectionForContact(server, target, contactName)==FALSE) return;

    if (LoadKeyForContact(contactName, NULL)==FALSE) return;


    plainMsg = IsPlainPrefix(msg);
    if (plainMsg) {
        signal_continue(4, server, plainMsg, target, orig_target);
        return;
    }


    // generally cut a message to a size of 512 byte, as everything above will never arrive complete anyway
    if (strlen(msg) > 512) msg[512]='\0';


    // append crypt-mark?
    if (GetBlowIniSwitch(contactName, "mark_encrypted", "1") != 0) {
        GetPrivateProfileString("FiSH", "mark_encrypted", "", myMark, sizeof(myMark), iniPath);	// global setting
        if (*myMark != '\0') {
            strcpy(formattedMsg, msg);

            GetPrivateProfileString("FiSH", "mark_position", "0", markPos, sizeof(markPos), iniPath);
            if (*markPos=='0') strcat(formattedMsg, myMark);		//append mark at the end
            else {	// prefix mark
                i=strlen(myMark);
                memmove(formattedMsg+i, formattedMsg, strlen(formattedMsg)+1);
                strncpy(formattedMsg, myMark, i);
            }

            signal_continue(4, server, formattedMsg, target, orig_target);

            ZeroMemory(formattedMsg, sizeof(formattedMsg));
        }
    }

    return;
}
Ejemplo n.º 5
0
void cmd_keyx(const char *target, SERVER_REC * server, WI_ITEM_REC * item)
{
	if (IsNULLorEmpty(target)) {
		if (item != NULL)
			target = window_item_get_target(item);
		else {
			printtext(NULL, NULL, MSGLEVEL_CRAP,
				  "\002FiSH:\002 Please define nick/#channel. Usage: /keyx <nick/#channel>");
			return;
		}
	}

	if (ischannel(*target)) {
		printtext(server, target, MSGLEVEL_CRAP,
			  "\002FiSH:\002 KeyXchange does not work for channels!");
		return;
	}

	DH1080_gen(g_myPrivKey, g_myPubKey);

	irc_send_cmdv((IRC_SERVER_REC *) server, "NOTICE %s :%s %s", target,
		      "DH1080_INIT", g_myPubKey);

	printtext(server, item != NULL ? window_item_get_target(item) : NULL,
		  MSGLEVEL_CRAP,
		  "\002FiSH:\002 Sent my DH1080 public key to %s, waiting for reply ...",
		  target);
}
Ejemplo n.º 6
0
/**
 * Sets the key for a nick / channel in a server
 * @param data command
 * @param server irssi server record
 * @param item irssi window/item
 */
void cmd_setkey(const char *data, SERVER_REC *server, WI_ITEM_REC *item)
{
    GHashTable *optlist;
    char contactName[CONTACT_SIZE]="", encryptedKey[150]="";
    const char *target, *key;
    void *free_arg;

    if (IsNULLorEmpty(data)) {
        printtext(server, item!=NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP,
                  "\002FiSH:\002 No parameters. Usage: /setkey [-<server tag>] [<nick | #channel>] <key>");
        return;
    }

    if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS |
                        PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_GETREST,
                        "setkey", &optlist, &target, &key))
        return;

    if (*target=='\0') {
        printtext(server, item!=NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP,
                  "\002FiSH:\002 No parameters. Usage: /setkey [-<server tag>] [<nick | #channel>] <key>");
        cmd_params_free(free_arg);
        return;
    }

    server = cmd_options_get_server("setkey", optlist, server);
    if (server == NULL || !server->connected)
        cmd_param_error(CMDERR_NOT_CONNECTED);

    if (*key=='\0') {
        // one paramter given - it's the key
        key = target;
        if (item != NULL) target = window_item_get_target(item);
        else {
            printtext(NULL, NULL, MSGLEVEL_CRAP,
                      "\002FiSH:\002 Please define nick/#channel. Usage: /setkey [-<server tag>] [<nick | #channel>] <key>");
            cmd_params_free(free_arg);
            return;
        }
    }

    encrypt_key((char *)key, encryptedKey);

    if (GetIniSectionForContact(server, target, contactName)==FALSE) return;

    if (WritePrivateProfileString(contactName, "key", encryptedKey, iniPath) == -1) {
        ZeroMemory(encryptedKey, sizeof(encryptedKey));
        printtext(server, item!=NULL ? window_item_get_target(item) : NULL,	MSGLEVEL_CRAP,
                  "\002FiSH ERROR:\002 Unable to write to blow.ini, probably out of space or permission denied.");
        cmd_params_free(free_arg);
        return;
    }

    ZeroMemory(encryptedKey, sizeof(encryptedKey));

    printtext(server, item!=NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP,
              "\002FiSH:\002 Key for %s@%s successfully set!", target, server->tag);

    cmd_params_free(free_arg);
}
Ejemplo n.º 7
0
void raw_handler(SERVER_REC *server, char *data)
{
    char channel[CONTACT_SIZE], *ptr, *ptr_bak;
    int len;

    if (IsNULLorEmpty(data)) return;

    ptr=strchr(data, ' ');	// point to command
    if (ptr==NULL) return;
    ptr++;

    if (strncmp(ptr, "332 ", 4)!=0) return;	// 332 = TOPIC

    ptr_bak=ptr;
    ptr=strchr(ptr, '#');	// point to #channel
    if (ptr==NULL) {
        ptr=strchr(ptr_bak, '&');	// point to &channel
        if (ptr==NULL) {
            ptr=strchr(ptr_bak, '!');	// point to !channel
            if (ptr==NULL) return;
        }
    }

    len=strchr(ptr, ' ')-ptr;
    if (len >= CONTACT_SIZE-2) return;	// channel string too long, something went wrong
    strncpy(channel, ptr, len);
    channel[len]='\0';

    ptr=strchr(ptr, ':');	// point to topic msg start
    if (ptr==NULL) return;
    ptr++;

    FiSH_decrypt(server, ptr, ptr, channel);
}
Ejemplo n.º 8
0
void cmd_key(const char *data, SERVER_REC * server, WI_ITEM_REC * item)
{
	GHashTable *optlist;
	char *target;
	char contactName[CONTACT_SIZE] = "", theKey[KEYBUF_SIZE] = "";
	void *free_arg;

	if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
			    PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_GETREST,
			    "key", &optlist, &target))
		return;

	if (item != NULL && IsNULLorEmpty(target))
		target = (char *)window_item_get_target(item);

	if (IsNULLorEmpty(target)) {
		printtext(server,
			  item != NULL ? window_item_get_target(item) : NULL,
			  MSGLEVEL_CRAP,
			  "\002FiSH:\002 Please define nick/#channel. Usage: /key [-<server tag>] [<nick | #channel>]");
		return;
	}

	server = cmd_options_get_server("key", optlist, server);
	if (server == NULL || !server->connected)
		cmd_param_error(CMDERR_NOT_CONNECTED);

	target = (char *)g_strchomp(target);

	if (getIniSectionForContact(server, target, contactName) == FALSE)
		return;

	if (getContactKey(contactName, theKey) == FALSE) {
		ZeroMemory(theKey, KEYBUF_SIZE);
		printtext(server,
			  item != NULL ? window_item_get_target(item) : NULL,
			  MSGLEVEL_CRAP,
			  "\002FiSH:\002 Key for %s@%s not found or invalid!",
			  target, server->tag);
		return;
	}

	printtext(server, target, MSGLEVEL_CRAP,
		  "\002FiSH:\002 Key for %s@%s: %s", target, server->tag,
		  theKey);
	ZeroMemory(theKey, KEYBUF_SIZE);
}
Ejemplo n.º 9
0
/*
 * New command: /notice+ <nick/#channel> <notice message>
 */
void cmd_crypt_notice(const char *data, SERVER_REC * server, WI_ITEM_REC * item)
{
	char bf_dest[1000] = "", *msg;
	const char *target;
	void *free_arg = NULL;

	if (data == NULL || (strlen(data) < 3))
		goto notice_error;
	if (!cmd_get_params(data, &free_arg, 1, &target))
		goto notice_error;

	msg = strchr(data, ' ');
	if (IsNULLorEmpty(target) || IsNULLorEmpty(msg))
		goto notice_error;

	msg++;			// point to the notice message

	// generally refuse a notice size of more than 512 byte, as everything above will never arrive complete anyway
	if (strlen(msg) >= 512) {
		printtext(server, target, MSGLEVEL_CRAP,
			  "\002FiSH:\002 /notice+ \002error\002: message argument exceeds buffer size!");
		return;
	}

	if (FiSH_encrypt(server, msg, target, bf_dest) == 0) {
		printtext(server, target, MSGLEVEL_CRAP,
			  "\002FiSH:\002 /notice+ \002error\002: Encryption disabled or no key found for %s.",
			  target);
		return;
	}

	bf_dest[512] = '\0';
	irc_send_cmdv((IRC_SERVER_REC *) server, "NOTICE %s :%s\n", target,
		      bf_dest);

	signal_emit("message irc own_notice", 3, server, msg, target);
	cmd_params_free(free_arg);
	return;

 notice_error:
	if (free_arg)
		cmd_params_free(free_arg);
	printtext(server, item != NULL ? window_item_get_target(item) : NULL,
		  MSGLEVEL_CRAP,
		  "\002FiSH:\002 Usage: /notice+ <nick/#channel> <notice message>");
}
Ejemplo n.º 10
0
void cmd_delkey(const char *data, SERVER_REC * server, WI_ITEM_REC * item)
{
	GHashTable *optlist;
	char *target;
	char contactName[CONTACT_SIZE] = "";
	void *free_arg;

	if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
			    PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_GETREST,
			    "delkey", &optlist, &target))
		return;

	if (item != NULL && IsNULLorEmpty(target))
		target = (char *)window_item_get_target(item);

	if (IsNULLorEmpty(target)) {
		printtext(server,
			  item != NULL ? window_item_get_target(item) : NULL,
			  MSGLEVEL_CRAP,
			  "\002FiSH:\002 No parameters. Usage: /delkey [-<server tag>] [<nick | #channel>]");
		return;
	}

	server = cmd_options_get_server("delkey", optlist, server);
	if (server == NULL || !server->connected)
		cmd_param_error(CMDERR_NOT_CONNECTED);

	target = (char *)g_strchomp(target);

	if (getIniSectionForContact(server, target, contactName) == FALSE)
		return;

	if (deleteIniValue(contactName, "key", iniPath) == 1) {
		printtext(server, item != NULL ? window_item_get_target(item) : NULL,
			  MSGLEVEL_CRAP,
			  "\002FiSH:\002 Key for %s@%s successfully removed!", target,
			  server->tag);
	} else {
		printtext(server, item != NULL ? window_item_get_target(item) : NULL,
			MSGLEVEL_CRAP,
			"\002FiSH:\002 No key found for %s@%s", target,
			server->tag);
	}
}
Ejemplo n.º 11
0
/*
 * Encrypt a message and store in bf_dest (using key for target)
 * @param server
 * @param msg_ptr
 * @param target
 * @param bf_dest
 * @return 1 if everything ok 0 if not
 */
int FiSH_encrypt(const SERVER_REC *server, const char *msg_ptr, const char *target, char *bf_dest)
{
    char theKey[KEYBUF_SIZE]="";
    char contactName[CONTACT_SIZE]="";

    if (IsNULLorEmpty(msg_ptr) || bf_dest==NULL || IsNULLorEmpty(target)) return 0;

    if (GetBlowIniSwitch("FiSH", "process_outgoing", "1") == 0) return 0;

    if (GetIniSectionForContact(server, target, contactName)==FALSE) return 0;

    if (LoadKeyForContact(contactName, theKey)==FALSE) return 0;

    strcpy(bf_dest, "+OK ");

    encrypt_string(theKey, msg_ptr, bf_dest+4, strlen(msg_ptr));

    ZeroMemory(theKey, KEYBUF_SIZE);
    return 1;
}
Ejemplo n.º 12
0
void raw_handler(SERVER_REC * server, char *data)
{
	GString *decrypted;
	char channel[CONTACT_SIZE], *ptr, *ptr_bak;
	int len;

	if (IsNULLorEmpty(data))
		return;

	ptr = strchr(data, ' ');	// point to command
	if (ptr == NULL)
		return;
	ptr++;

	if (strncmp(ptr, "332 ", 4) != 0)
		return;		// 332 = TOPIC

	ptr_bak = ptr;
	ptr = strchr(ptr, '#');	// point to #channel
	if (ptr == NULL) {
		ptr = strchr(ptr_bak, '&');	// point to &channel
		if (ptr == NULL) {
			ptr = strchr(ptr_bak, '!');	// point to !channel
			if (ptr == NULL)
				return;
		}
	}

	len = strchr(ptr, ' ') - ptr;
	if (len >= CONTACT_SIZE - 2)
		return;		// channel string too long, something went wrong
	strncpy(channel, ptr, len);
	channel[len] = '\0';

	ptr = strchr(ptr, ':');	// point to topic msg start
	if (ptr == NULL)
		return;
	ptr++;

	decrypted = g_string_new("");
	if (FiSH_decrypt(server, ptr, channel, decrypted)) {
		g_string_prepend_len(decrypted, data, strlen(data) - strlen(ptr));
		signal_continue(2, server, decrypted->str);
		ZeroMemory(decrypted->str, decrypted->len);
	}
	g_string_free(decrypted, TRUE);
}
Ejemplo n.º 13
0
static void sig_complete_topic_plus(GList **list, WINDOW_REC *window,
                                    const char *word, const char *line,
                                    int *want_space)
{
	char *p;

	char *topic;
	int topic_len;

	const char *mark;
	int mark_len;

	g_return_if_fail(list != NULL);
	g_return_if_fail(word != NULL);

	if (*word == '\0' && IS_CHANNEL(window->active)) {
		topic = g_strdup(CHANNEL(window->active)->topic);
		if (topic != NULL) {
			mark = settings_get_str("mark_encrypted");
			if (!IsNULLorEmpty(mark)) {
				topic_len = strlen(topic);
				mark_len = strlen(mark);
				if (settings_get_int("mark_position") == 0) { // suffix
					p = topic + (topic_len - mark_len);
					if (strncmp(p, mark, mark_len) == 0) {
						*p = '\0'; // Remove mark
					}
				}
				else { // prefix
					if (strncmp(topic, mark, mark_len) == 0) {
						g_memmove(topic, topic + mark_len, topic_len - mark_len);
					}
				}
			}

			*list = g_list_append(NULL, topic);
			signal_stop();
		}
	}
}
Ejemplo n.º 14
0
/*
 * Decrypt a base64 cipher text (using key for target)
 */
int FiSH_decrypt(const SERVER_REC * serverRec, char *msg_ptr,
		 const char *target, GString* decrypted_msg)
{
	char contactName[CONTACT_SIZE] = "";
	char theKey[KEYBUF_SIZE] = "";
	char bf_dest[1000] = "";
	char myMark[20] = "";
	char *recoded;
	int msg_len, i, mark_broken_block = 0, action_found = 0, markPos;

	if (IsNULLorEmpty(msg_ptr) || decrypted_msg == NULL || IsNULLorEmpty(target))
		return 0;

	if (settings_get_bool("process_incoming") == 0)
		return 0;

	if (strncmp(msg_ptr, "+OK ", 4) == 0) 
		msg_ptr += 4;
	// TODO: Maybe remove this?
	else if (strncmp(msg_ptr, "mcps ", 5) == 0)
		msg_ptr += 5;
	else
		return 0;	// don't process, blowcrypt-prefix not found

	// Verify base64 string
	msg_len = strlen(msg_ptr);
	if ((strspn(msg_ptr, B64) != (size_t) msg_len) || (msg_len < 12))
		return 0;

	if (getIniSectionForContact(serverRec, target, contactName) == FALSE)
		return 0;

	if (getContactKey(contactName, theKey) == FALSE)
		return 0;

	// usually a received message does not exceed 512 chars, but we want to prevent evil buffer overflow
	if (msg_len >= (int)(sizeof(bf_dest) * 1.5))
		msg_ptr[(int)(sizeof(bf_dest) * 1.5) - 20] = '\0';

	// block-align blowcrypt strings if truncated by IRC server (each block is 12 chars long)
	// such a truncated block is destroyed and not needed anymore
	if (msg_len != (msg_len / 12) * 12) {
		msg_len = (msg_len / 12) * 12;
		msg_ptr[msg_len] = '\0';
		strncpy(myMark, settings_get_str("mark_broken_block"),
			sizeof(myMark));
		if (*myMark == '\0' || isNoChar(*myMark))
			mark_broken_block = 0;
		else
			mark_broken_block = 1;
	}

	decrypt_string(theKey, msg_ptr, bf_dest, msg_len);
	ZeroMemory(theKey, KEYBUF_SIZE);

	if (*bf_dest == '\0')
		return 0;	// don't process, decrypted msg is bad

	// recode message again, last time it was the encrypted message...
	if (settings_get_bool("recode") && serverRec != NULL) {
		recoded = recode_in(serverRec, bf_dest, target);
		if (recoded) {
			strncpy(bf_dest, recoded, sizeof(bf_dest));
			ZeroMemory(recoded, strlen(recoded));
			g_free(recoded);
		}
	}

	i = 0;
	while (bf_dest[i] != 0x0A && bf_dest[i] != 0x0D && bf_dest[i] != '\0')
		i++;
	bf_dest[i] = '\0';	// in case of wrong key, decrypted message might have control characters -> cut message

	if (strncmp(bf_dest, "\001ACTION ", 8) == 0) {
		// ACTION message found
		if (bf_dest[i - 1] == '\001')
			bf_dest[i - 1] = '\0';	// remove 0x01 control character
		action_found = 1;
	}
	// append broken-block-mark?
	if (mark_broken_block)
		strcat(bf_dest, myMark);

	// append crypt-mark?
	strncpy(myMark, settings_get_str("mark_encrypted"), sizeof(myMark));
	if (*myMark != '\0') {
		markPos = settings_get_int("mark_position");
		if (markPos == 0 || action_found)
			strcat(bf_dest, myMark);	// append mark at the end (default for ACTION messages)
		else {		// prefix mark
			i = strlen(myMark);
			memmove(bf_dest + i, bf_dest, strlen(bf_dest) + 1);
			strncpy(bf_dest, myMark, i);
		}
	}

	g_string_assign(decrypted_msg, bf_dest);
	ZeroMemory(bf_dest, sizeof(bf_dest));

	return 1;
}
Ejemplo n.º 15
0
/*
 * Decrypt a base64 cipher text (using key for target)
 */
int FiSH_decrypt(const SERVER_REC *server, char *msg_ptr, char *msg_bak, const char *target)
{
    char contactName[CONTACT_SIZE]="", theKey[KEYBUF_SIZE]="", bf_dest[1000]="";
    char myMark[20]="", markPos[20]="", *recoded;
    int msg_len, i, mark_broken_block=0, action_found=0;


    if (IsNULLorEmpty(msg_ptr) || msg_bak==NULL || IsNULLorEmpty(target)) return 0;

    if (GetBlowIniSwitch("FiSH", "process_incoming", "1") == 0) return 0;

    if (strncmp(msg_ptr, "+OK ", 4)==0) msg_ptr += 4;
    else if (strncmp(msg_ptr, "mcps ", 5)==0) msg_ptr += 5;
    else return 0;		// don't process, blowcrypt-prefix not found

    // Verify base64 string
    msg_len=strlen(msg_ptr);
    if ((strspn(msg_ptr, B64) != (size_t)msg_len) || (msg_len < 12)) return 0;

    if (GetIniSectionForContact(server, target, contactName)==FALSE) return 0;

    if (LoadKeyForContact(contactName, theKey)==FALSE) return 0;

    // usually a received message does not exceed 512 chars, but we want to prevent evil buffer overflow
    if (msg_len >= (int)(sizeof(bf_dest)*1.5)) msg_ptr[(int)(sizeof(bf_dest)*1.5)-20]='\0';

    // block-align blowcrypt strings if truncated by IRC server (each block is 12 chars long)
    // such a truncated block is destroyed and not needed anymore
    if (msg_len != (msg_len/12)*12) {
        msg_len=(msg_len/12)*12;
        msg_ptr[msg_len]='\0';
        GetPrivateProfileString("FiSH", "mark_broken_block", " \002&\002", myMark, sizeof(myMark), iniPath);
        if (*myMark=='\0' || isNoChar(*myMark)) mark_broken_block=0;
        else mark_broken_block=1;
    }

    decrypt_string(theKey, msg_ptr, bf_dest, msg_len);
    ZeroMemory(theKey, KEYBUF_SIZE);

    if (*bf_dest=='\0') return 0;	// don't process, decrypted msg is bad

#ifdef FiSH_USE_IRSSI_RECODE
    // recode message again, last time it was the encrypted message...
    if (settings_get_bool("recode") && server!=NULL) {
        recoded = recode_in(server, bf_dest, target);
        if (recoded) {
            strncpy(bf_dest, recoded, sizeof(bf_dest));
            ZeroMemory(recoded, strlen(recoded));
            g_free(recoded);
        }
    }
#endif

    i=0;
    while (bf_dest[i] != 0x0A && bf_dest[i] != 0x0D && bf_dest[i] != '\0') i++;
    bf_dest[i]='\0';	// in case of wrong key, decrypted message might have control characters -> cut message

    if (strncmp(bf_dest, "\001ACTION ", 8)==0) {
        // ACTION message found
        if (bf_dest[i-1] == '\001') bf_dest[i-1] = '\0';	// remove 0x01 control character
        action_found = 1;
    }

    // append broken-block-mark?
    if (mark_broken_block) strcat(bf_dest, myMark);

    // append crypt-mark?
    if (GetBlowIniSwitch(contactName, "mark_encrypted", "1") != 0) {
        GetPrivateProfileString("FiSH", "mark_encrypted", "", myMark, sizeof(myMark), iniPath);	// global setting
        if (*myMark != '\0') {
            GetPrivateProfileString("FiSH", "mark_position", "0", markPos, sizeof(markPos), iniPath);
            if (*markPos=='0' || action_found) strcat(bf_dest, myMark);		// append mark at the end (default for ACTION messages)
            else {	// prefix mark
                i=strlen(myMark);
                memmove(bf_dest+i, bf_dest, strlen(bf_dest)+1);
                strncpy(bf_dest, myMark, i);
            }
        }
    }

    strcpy(msg_bak, bf_dest);	// copy decrypted message back (overwriting the base64 cipher text)
    ZeroMemory(bf_dest, sizeof(bf_dest));

    return 1;
}