//--------------------------------------------------------------------------- // Based on www.xchat.org provided plugin header - works ONLY with new plugin // system for xchat versions >= 2.x // // http://mircryption.sourceforge.net // By Dark Raichu and Xro, 1/03 ... // 4/27/03 fixed lines with / not being encrypted // 4/28/03 added \017 characters to format, which allows nicks to be clicked. // 5/09/03 changed default keyfile location to ~/.xchat/MircryptionKeys.txt // 5/13/03 added windows compatibility (tested with xygwin and xchat2 for win32) // 9/08/03 added support for ` prefix toggle // 12/27/03 added color stripping [hadez@darklab.org] // 03/21/04 help message was saying to call '/setkey #chan key' instead of '/setkey key' // 03/30/04 changed default outgoing tag to +OK for better default compatibility with other scripts // 05/18/04 added meow support // 12/26/04 fixing for xchat umlaout bug (utf8 stuff) // 01/08/04 added new cbc blowfish modes //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // xchat plugin version #define XMC_VERSIONSTRING "0.1.0xmc" //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // cygwin may not have WIN32 defined (which we use AND more imp xchat.h uses) #ifndef WIN32 #ifdef _MSC_VER #define WIN32 #endif #ifdef __CYGWIN__ #define WIN32 #endif #ifdef __MINGW32__ #define WIN32 #endif #endif //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // default key file name and location #ifdef WIN32 #define DEFAULTKEYFILE "MircryptionKeys.txt" #else // note if no / at front then this is relative filename off of user's home dir // remember that the . at start of name makes the file visible only w/ ls -a #define DEFAULTKEYFILE ".MircryptionKeys.txt" #endif //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // xchat function and enum definitions #include "xchat-plugin.h" //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // Application includes #include "mirc_codes.h" #include "mircryption.h" #include //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // Uncomment one of these pairs to choose how encrypted messages are formatted // Default mircryption method, use [] around encrypted text #define EMESSAGE_RECV_FORMAT "\00302[\017\00300%s\017\00302]\017\t%s\n" #define EMESSAGE_SEND_FORMAT "\00306[\017\00300%s\017\00306]\017\t%s\n" #define ENOTICE_RECV_FORMAT "\00302-[\017\00313%s\017\00302]-\017\t%s\n" #define ENOTICE_SEND_FORMAT "\00303]\017\00300%s\017\00303[\017\t%s\n" #define EMSG_SEND_FORMAT ENOTICE_SEND_FORMAT #define EACTIONFORMAT "[\00313*\017]\t%s %s\n" // Xro prefers a prefix of mc before <> //#define EMESSAGEFORMAT "mc \00303>\00300%s\00303<\00300\t%s" //#define EACTIONFORMAT "mc \00313*\00300\t%s %s" // house uses the following: //#define EMESSAGE_SEND_FORMAT "\00306[\017%s\00306]\017\t%s\n" //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // Here you can choose what outgoing tag to use; the defaul is mcps // but you can set it to +OK if you want to be compatible with others apps. // just comment out the one you *dont* want to use with a // //#define OUTGOINGETAG "mcps" #define OUTGOINGETAG "+OK" //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // If you want to force your xchat plugin to ignore meow broadcasts, you // can set this to true. Meows are just fun ways of saying hello to fello // mircryption users. #define IGNOREMEOWS false //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // global plugin handle static xchat_plugin *ph; //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // pointer to global mircryptor which does the bulk of the work MircryptionClass_xchat *mircryptor=NULL; //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // Forward declarations static int setdefault_keyfilelocation(); // static int mc_event_privdialog(char *word[], void *userdata); static int mc_event_channelmessage(char *word[], void *userdata); static int mc_event_action(char *word[], void *userdata); static int mc_event_channelnotice(char *word[], void *userdata); static int mc_event_notice(char *word[], void *userdata); static int mc_event_topic(char *word[], void *userdata); static int mc_event_topicchange(char *word[], void *userdata); static int mc_event_yourmessage(char *word[], void *userdata); static int mc_event_noticesend(char *word[], void *userdata); // static int mc_help(char *word[], char *word_eol[], void *userdata); static int mc_setkey(char *word[], char *word_eol[], void *userdata); static int mc_delkey(char *word[], char *word_eol[], void *userdata); static int mc_disablekey(char *word[], char *word_eol[], void *userdata); static int mc_enablekey(char *word[], char *word_eol[], void *userdata); static int mc_displaykey(char *word[], char *word_eol[], void *userdata); static int mc_listkeys(char *word[], char *word_eol[], void *userdata); static int mc_keypassphrase(char *word[], char *word_eol[], void *userdata); static int mc_setkeyfile(char *word[], char *word_eol[], void *userdata); static int mc_etopic(char *word[], char *word_eol[], void *userdata); static int mc_alltext(char *word[], char *word_eol[], void *userdata); static int mc_action(char *word[], char *word_eol[], void *userdata); static int mc_notice(char *word[], char *word_eol[], void *userdata); static void mylowercasify(char *str); /* Author: hadez@darklab.org Description: see function code at bottom of file for details */ void strip_mirc_colors(xchat_plugin*,char*); // meow handling bool HandleMeow(char *channelname,char *nick,char *text); // xchat umlaout issue (utf8 stuff) void Utf8DirtyFix(char *intext,char *outtext); //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // new extra safe buffer overflow checks // thanks to www.rainbowcrack-online.com and ircfuz for finding this dangeroud possibility // more serious buffer overflow checks are also now in the dll as well void mcnicksafe_strcpy(char *dest,const char*src) {mcsafe_strcpy(dest,src,MAXCHANNELNAMESIZE);}; void mclinesafe_strcpy(char *dest,const char*src) {mcsafe_strcpy(dest,src,MAXLINELEN);}; void mckeysafe_strcpy(char *dest,const char*src) {mcsafe_strcpy(dest,src,MAXSAFEKEYSIZE);}; void mcsafe_strcpy(char *dest,const char *src, int maxlen) {if (strlen(src)", 0); xchat_hook_command(ph, "notice", PRI_NORM, mc_notice, "Usage: NOTICE , sends a notice. Notices are a type of message that should be auto reacted to", 0); xchat_hook_command(ph, "", PRI_NORM, mc_alltext, "trap all input for encryption", 0); // hook the events we want to respond to xchat_hook_print(ph, "Channel Message", PRI_NORM, mc_event_channelmessage, 0); xchat_hook_print(ph, "Channel Notice", PRI_NORM, mc_event_channelnotice, 0); xchat_hook_print(ph, "Channel Action", PRI_NORM, mc_event_action, 0); xchat_hook_print(ph, "Notice", PRI_NORM, mc_event_notice, 0); xchat_hook_print(ph, "Topic", PRI_NORM, mc_event_topic, 0); xchat_hook_print(ph, "Topic Change", PRI_NORM, mc_event_topicchange, 0); xchat_hook_print(ph, "Your Message", PRI_NORM, mc_event_yourmessage, 0); xchat_hook_print(ph, "Notice Send", PRI_NORM, mc_event_noticesend, 0); xchat_hook_print(ph, "Private Message to Dialog", PRI_NORM, mc_event_privdialog, 0); // create our mircryptor class which does the bulk of the work mircryptor=new MircryptionClass_xchat; // set keyfile to ~/.MircryptionKeys.txt setdefault_keyfilelocation(); // if keyfile is not yet unlocked, then unlock them mircryptor->load_keys(); // inform user that the addon is loaded xchat_printf(ph, "Mircryption ver %s loaded - encryption currently *disabled*\n",XMC_VERSIONSTRING); xchat_printf(ph, " type /masterkey PASSPHRASE to activate, or /mircryption for help.\n"); // return 1 for success return 1; } extern "C" int xchat_plugin_deinit (xchat_plugin *plugin_handle) { // plugin needs to shut down // free mircryptor object if (mircryptor!=NULL) delete mircryptor; mircryptor=NULL; // return 1 for success return 1; } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- static int setdefault_keyfilelocation() { // set default key file location char returndata[MAXRETURNSTRINGLEN]; char keyfile[1000]; // form default keyfile name strcpy(keyfile,DEFAULTKEYFILE); #ifndef WIN32 if (keyfile[0]!='/') { // we need to grab users home explicitly, using ~/ didnt work strcpy(keyfile,getenv("HOME")); if (strlen(keyfile)>0) strcat(keyfile,"/"); strcat(keyfile,DEFAULTKEYFILE); } #endif mircryptor->mc_setkeyfilename(keyfile,returndata); } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- static int mc_event_privdialog(char *word[], void *userdata) { // handle event char returndata[MAXRETURNSTRINGLEN]; bool bretv; // get info char channelname[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(channelname,xchat_get_info(ph, "channel")); channelname[MAXCHANNELNAMESIZE-1]='\0'; // new force lowercase mylowercasify(channelname); char nick[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(nick,word[1]); nick[MAXCHANNELNAMESIZE-1]='\0'; char text[MAXLINELEN]; mclinesafe_strcpy(text,word[2]); // decrypt it bretv=mircryptor->mc_decrypt2(channelname,text,returndata); if (!bretv) { if (strcmp(returndata,text)!=0 && returndata[0]!='\0') xchat_print(ph,returndata); return EAT_NONE; } else if (strcmp(returndata,text)!=0 && returndata[0]!='\0') { // it was decrypted so we handle it //xchat_printf(ph,"[%s] %s",nick,returndata); //xchat_commandf(ph,"recv :%s!%s@mircryption PRIVMSG %s :(e) %s",nick,nick,channelname,returndata); strip_mirc_colors(ph,returndata); //check if it's a fish stype crypted action [hadez] if(strncmp(returndata,"\001ACTION ",8) == 0) { // something smells fishy here // get rid of the trailing \001 returndata[strlen(returndata)-1] = '\0'; // ignore the "\001ACTION " part and print it in eaction format xchat_printf(ph,EACTIONFORMAT,nick,returndata+8); } else { xchat_printf(ph,EMESSAGE_RECV_FORMAT,nick,returndata); } //xchat_printf(ph,EMESSAGE_RECV_FORMAT,nick,returndata); return EAT_ALL; } // don't eat this event, let xchat handle it also return EAT_NONE; } static int mc_event_channelmessage(char *word[], void *userdata) { // handle event char returndata[MAXRETURNSTRINGLEN]; bool bretv; // get info char channelname[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(channelname,xchat_get_info(ph, "channel")); // new force lowercase mylowercasify(channelname); char nick[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(nick,word[1]); char text[MAXLINELEN]; mclinesafe_strcpy(text,word[2]); // is this a meow? if (strncmp(text,"mcps meow meow",14)==0) { if (HandleMeow(channelname,nick,text)) return EAT_ALL; } // decrypt it bretv=mircryptor->mc_decrypt2(channelname,text,returndata); if (!bretv) { if (strcmp(returndata,text)!=0 && returndata[0]!='\0') xchat_print(ph,returndata); return EAT_NONE; } else if (strcmp(returndata,text)!=0 && returndata[0]!='\0') { // it was decrypted so we handle it //xchat_printf(ph,"[%s] %s",nick,returndata); //xchat_commandf(ph,"recv :%s!%s@mircryption PRIVMSG %s :(e) %s",nick,nick,channelname,returndata); strip_mirc_colors(ph,returndata); //check if it's a fish stype crypted action [hadez] if(strncmp(returndata,"\001ACTION ",8) == 0) { // something smells fishy here // get rid of the trailing \001 returndata[strlen(returndata)-1]='\0'; // ignore the "\001ACTION " part and print it in eaction format xchat_printf(ph,EACTIONFORMAT,nick,returndata+8); } else { xchat_printf(ph,EMESSAGE_RECV_FORMAT,nick,returndata); } //xchat_printf(ph,EMESSAGE_RECV_FORMAT,nick,returndata); return EAT_ALL; } // don't eat this event, let xchat handle it also return EAT_NONE; } static int mc_event_action(char *word[], void *userdata) { // handle event char returndata[MAXRETURNSTRINGLEN]; bool bretv; // get info char channelname[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(channelname,xchat_get_info(ph, "channel")); // new force lowercase mylowercasify(channelname); char nick[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(nick,word[1]); char text[MAXLINELEN]; mclinesafe_strcpy(text,word[2]); // decrypt it bretv=mircryptor->mc_decrypt2(channelname,text,returndata); if (!bretv) { if (strcmp(returndata,text)!=0 && returndata[0]!='\0') xchat_print(ph,returndata); return EAT_NONE; } else if (strcmp(returndata,text)!=0 && returndata[0]!='\0') { // it was decrypted so we handle it //xchat_printf(ph,"[%s] %s",nick,returndata); //xchat_commandf(ph,"recv :%s!%s@mircryption PRIVMSG %s :[mc] %s",nick,nick,channelname,returndata); strip_mirc_colors(ph,returndata); xchat_printf(ph,EACTIONFORMAT,nick,returndata); return EAT_ALL; } // don't eat this event, let xchat handle it also return EAT_NONE; } static int mc_event_channelnotice(char *word[], void *userdata) { // handle event bool bretv; char returndata[MAXRETURNSTRINGLEN]; // get info char channelname[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(channelname,xchat_get_info(ph, "channel")); // new force lowercase mylowercasify(channelname); char nick[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(nick,word[1]); char text[MAXLINELEN]; mclinesafe_strcpy(text,word[3]); // decrypt it bretv=mircryptor->mc_decrypt2(channelname,text,returndata); if (!bretv) { if (strcmp(returndata,text)!=0 && returndata[0]!='\0') xchat_print(ph,returndata); return EAT_NONE; } if (strcmp(returndata,text)!=0 && returndata[0]!='\0') { // it was decrypted so we handle it //xchat_printf(ph,"[%s] -> %s",nick,returndata); //xchat_commandf(ph,"recv :%s!%s@mircryption NOTICE %s :(e) %s",nick,nick,channelname,returndata); strip_mirc_colors(ph,returndata); xchat_printf(ph,ENOTICE_RECV_FORMAT,channelname,returndata); return EAT_ALL; } // don't eat this event, let xchat handle it also return EAT_NONE; } static int mc_event_notice(char *word[], void *userdata) { // handle event char returndata[MAXRETURNSTRINGLEN]; bool bretv; // get info char channelname[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(channelname,xchat_get_info(ph, "channel")); // new force lowercase mylowercasify(channelname); char nick[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(nick,word[1]); char mynick[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(mynick,xchat_get_info(ph, "nick")); char text[MAXLINELEN]; mclinesafe_strcpy(text,word[2]); // decrypt it bretv=mircryptor->mc_decrypt2(channelname,text,returndata); if (!bretv) { if (strcmp(returndata,text)!=0 && returndata[0]!='\0') xchat_print(ph,returndata); return EAT_NONE; } if (strcmp(returndata,text)!=0 && returndata[0]!='\0') { // it was decrypted so we handle it //xchat_printf(ph,"[%s] -> %s",nick,returndata); //xchat_commandf(ph,"recv :%s!%s@mircryption NOTICE %s :(e) %s",nick,nick,mynick,returndata); strip_mirc_colors(ph,returndata); xchat_printf(ph,ENOTICE_RECV_FORMAT,nick,returndata); return EAT_ALL; } // don't eat this event, let xchat handle it also return EAT_NONE; } static int mc_event_topic(char *word[], void *userdata) { // handle event char returndata[MAXRETURNSTRINGLEN]; bool bretv; // get info char channelname[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(channelname,word[1]); // new force lowercase mylowercasify(channelname); char text[MAXLINELEN]; mclinesafe_strcpy(text,word[2]); char mynick[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(mynick,xchat_get_info(ph, "nick")); char server[255]; mcsafe_strcpy(server,xchat_get_info(ph, "server"),255); // decrypt it bretv=mircryptor->mc_decrypt2(channelname,text,returndata); if (!bretv) { if (strcmp(returndata,text)!=0 && returndata[0]!='\0') xchat_print(ph,returndata); return EAT_NONE; } if (strcmp(returndata,text)!=0 && returndata[0]!='\0') { // it was decrypted so we handle it // we dont need to print it since it will be displayed automatically // xchat_printf(ph,"Topic for %s is decrypted as: %s",channelname,returndata); strip_mirc_colors(ph,returndata); xchat_commandf(ph,"recv :%s 332 %s %s :(e) %s",server,mynick,channelname,returndata); return EAT_ALL; } // don't eat this event, let xchat handle it also return EAT_NONE; } static int mc_event_topicchange(char *word[], void *userdata) { // handle event char returndata[MAXRETURNSTRINGLEN]; bool bretv; // get info char channelname[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(channelname,xchat_get_info(ph, "channel")); // new force lowercase mylowercasify(channelname); char nick[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(nick,word[1]); char text[MAXLINELEN]; mclinesafe_strcpy(text,word[2]); // decrypt it bretv=mircryptor->mc_decrypt2(channelname,text,returndata); if (!bretv) { if (strcmp(returndata,text)!=0 && returndata[0]!='\0') xchat_print(ph,returndata); return EAT_NONE; } if (strcmp(returndata,text)!=0 && returndata[0]!='\0') { // it was decrypted so we handle it // no need to annnounce it, it will get announced automatically by xchat // xchat_printf(ph,"%s has encrypted the topic for %s to: %s",nick,channelname,returndata); strip_mirc_colors(ph,returndata); xchat_commandf(ph,"recv :%s!%s@mircryption TOPIC %s :(e) %s",nick,nick,channelname,returndata); return EAT_ALL; } //xchat_printf(ph,"TOPICCHANGE nick='%s' chjannel='%s' text='%s' return='%s'",nick,channelname,text,returndata); // don't eat this event, let xchat handle it also return EAT_NONE; } static int mc_event_yourmessage(char *word[], void *userdata) { // issue a command to xchat // this is kind of wierd because SOMETIMES encryption is handled prior to this in mc_alltext() char returndata[MAXRETURNSTRINGLEN]; bool bretv; // get info char channelname[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(channelname,xchat_get_info(ph, "channel")); // new force lowercase mylowercasify(channelname); char nick[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(nick,word[1]); char text[MAXLINELEN]; mclinesafe_strcpy(text,word[2]); if (strncmp(text,"mcps ",5)==0) return EAT_ALL; if (strncmp(text,OUTGOINGETAG,strlen(OUTGOINGETAG))==0) return EAT_ALL; // don't eat this event, let xchat handle it also return EAT_NONE; } static int mc_event_noticesend(char *word[], void *userdata) { char returndata[MAXRETURNSTRINGLEN]; bool bretv; // get info char dest[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(dest,word[1]); char text[MAXLINELEN]; mclinesafe_strcpy(text,word[2]); // if its a meow reply then its already displayed by us so we do nothing here if (strncmp(text,"mcps meow meowreply",19)==0) return EAT_ALL; //lets see if we can decrypt the notice we just sent bretv=mircryptor->mc_decrypt2(dest,text,returndata); if (!bretv) { if (strcmp(returndata,"")!=0) { xchat_print(ph,returndata); return EAT_ALL; } else return EAT_NONE; } else if (strcmp(returndata,text)!=0 && returndata[0]!='\0') { xchat_printf(ph,ENOTICE_SEND_FORMAT,dest,returndata); return EAT_ALL; } // don't eat this event, let xchat handle it also return EAT_NONE; } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- static int mc_help(char *word[], char *word_eol[], void *userdata) { xchat_print(ph,"-\n"); xchat_print(ph,". Mircryption - xchat version - Dark Raichu & Xro\n"); xchat_print(ph,". blowfish encryption algorithms are by bruce schneier and jim conger.\n"); xchat_print(ph,".... /setkey [keyphrase]' enables encryption/decryption on specified channel (defaults to current channel), using key specified. can be used to add or modify keys.\n"); xchat_print(ph,".... /delkey [channel]' removes encryption key for specified channel (defaults to current channel).\n"); xchat_print(ph,".... /disablekey' temporarily disables encryption for current channel\n"); xchat_print(ph,".... /enablekey' re-enables encryption for current channel\n"); xchat_print(ph,".... /displaykey' shows you (and only you) the key for the current channel\n"); // xchat_print(ph,".... /plain ...' send ... text without encryption\n"); xchat_print(ph,".... /listkeys' lists all channel encryption keys currently stored\n"); xchat_print(ph,"... /keypassphrase [phrase]' set or change current master keyfile passphrase to keyword\n"); // xchat_print(ph,".... /mcscheme X' set color/identification scheme, where X is the number 1-3\n"); xchat_print(ph,".... /etopic [text]' set an encrypted topic for the channel.\n"); // xchat_print(ph,".... /encryptecho channelname text' echoes encrypted version of text IF channel is set to encrypt, otherwise plaintext\n"); // xchat_print(ph,".... /decryptecho channelname text' echoes decrypted version of text IF channel has a key, otherwise plaintext\n"); xchat_print(ph,".... /setkeyfile filename' set the name of the file to be used for storing/retrieving keys\n"); // xchat_print(ph,".... /emsg channelname test... replacement for /msg - encrypts text if appropriate (good for bots, etc.)\n"); // xchat_print(ph,".... /mcmeow [channelname] broadcast handshake query to channel\n"); // xchat_print(ph,".... /etext text... same as typing text... in encrypted channel, BUT igores disabling, and wont send to channel without encryption\n"); // xchat_print(ph,".... /textpad launches the textpad dialog for copy and paste of big text\n"); xchat_print(ph,"-\n"); /// eat this command so xchat and other plugins can't process it return EAT_ALL; } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- static int mc_setkey(char *word[], char *word_eol[], void *userdata) { // handle this command char returndata[MAXRETURNSTRINGLEN]; // get info char keyphrase[MAXKEYSIZE]; mckeysafe_strcpy(keyphrase,word_eol[2]); // get info char channelname[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(channelname,xchat_get_info(ph, "channel")); // new force lowercase mylowercasify(channelname); // execute command mircryptor->mc_setkey(channelname,keyphrase,returndata); // display result xchat_printf(ph, "%s",returndata); /// eat this command so xchat and other plugins can't process it return EAT_ALL; } static int mc_delkey(char *word[], char *word_eol[], void *userdata) { // handle this command char returndata[MAXRETURNSTRINGLEN]; // get info char channelname[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(channelname,xchat_get_info(ph, "channel")); // new force lowercase mylowercasify(channelname); // execute command mircryptor->mc_delkey(channelname,returndata); // display result xchat_printf(ph, "%s",returndata); /// eat this command so xchat and other plugins can't process it return EAT_ALL; } static int mc_disablekey(char *word[], char *word_eol[], void *userdata) { // handle this command char returndata[MAXRETURNSTRINGLEN]; // get info char channelname[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(channelname,xchat_get_info(ph, "channel")); // new force lowercase mylowercasify(channelname); // execute command mircryptor->mc_disablekey(channelname,returndata); // display result xchat_printf(ph, "%s",returndata); /// eat this command so xchat and other plugins can't process it return EAT_ALL; } static int mc_enablekey(char *word[], char *word_eol[], void *userdata) { // handle this command char returndata[MAXRETURNSTRINGLEN]; // get info char channelname[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(channelname,xchat_get_info(ph, "channel")); // new force lowercase mylowercasify(channelname); // execute command mircryptor->mc_enablekey(channelname,returndata); // display result xchat_printf(ph, "%s",returndata); /// eat this command so xchat and other plugins can't process it return EAT_ALL; } static int mc_displaykey(char *word[], char *word_eol[], void *userdata) { // handle this command char returndata[MAXRETURNSTRINGLEN]; // get info char channelname[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(channelname,xchat_get_info(ph, "channel")); // new force lowercase mylowercasify(channelname); // execute command mircryptor->mc_displaykey(channelname,returndata); // display result xchat_printf(ph, "%s",returndata); /// eat this command so xchat and other plugins can't process it return EAT_ALL; } static int mc_listkeys(char *word[], char *word_eol[], void *userdata) { // handle this command char returndata[MAXRETURNSTRINGLEN]; // execute command mircryptor->mc_listkeys(returndata); /// eat this command so xchat and other plugins can't process it return EAT_ALL; } static int mc_keypassphrase(char *word[], char *word_eol[], void *userdata) { // handle this command char returndata[MAXRETURNSTRINGLEN]; // get info char keyphrase[MAXKEYSIZE]; strcpy(keyphrase,word_eol[2]); // execute command mircryptor->mc_setunlockpassphrase(keyphrase,returndata); // display result xchat_printf(ph, "%s",returndata); /// eat this command so xchat and other plugins can't process it return EAT_ALL; } static int mc_setkeyfile(char *word[], char *word_eol[], void *userdata) { // handle this command char returndata[MAXRETURNSTRINGLEN]; // get info char keyfile[MAXKEYSIZE]; strcpy(keyfile,word_eol[2]); // execute command mircryptor->mc_setkeyfilename(keyfile,returndata); // display result xchat_printf(ph, "%s",returndata); /// eat this command so xchat and other plugins can't process it return EAT_ALL; } static int mc_etopic(char *word[], char *word_eol[], void *userdata) { // handle this command bool bretv; char returndata[MAXRETURNSTRINGLEN]; // get info char text[MAXLINELEN]; char text2[MAXLINELEN]; strcpy(text,word_eol[2]); // get info char channelname[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(channelname,xchat_get_info(ph, "channel")); // new force lowercase mylowercasify(channelname); // utf8 fix for text Utf8DirtyFix(text,text2); // encrypt it bretv=mircryptor->mc_encrypt2(channelname,text2,returndata); // xchat_printf(ph,"debug: topic for %s:tried to encrypt '%s' to '%s'",channelname,text,returndata); if (!bretv) { if (strcmp(returndata,"")!=0) { xchat_print(ph,returndata); return EAT_ALL; } else return EAT_NONE; } else if (strcmp(returndata,text)!=0 && returndata[0]!='\0') { // it was encrypted so we handle it // send the encrypted text xchat_commandf(ph,"TOPIC %s %s",channelname,returndata); // we dont actually display it here, as it will be displayed on the event we trigger when we set the topic // xchat_printf(ph,"Encrypted topic for [%s] set to: %s",channelname,text); return EAT_ALL; } else { // error xchat_printf(ph,"topic could not be encrypted, so it wasnt set."); } /// eat this command so xchat and other plugins can't process it return EAT_ALL; } static int mc_alltext(char *word[], char *word_eol[], void *userdata) { // handle this command bool bretv; char returndata[MAXRETURNSTRINGLEN]; // get info char channelname[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(channelname,xchat_get_info(ph, "channel")); // new force lowercase mylowercasify(channelname); char text[MAXLINELEN]; char text2[MAXLINELEN]; mclinesafe_strcpy(text,word_eol[1]); char nick[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(nick,xchat_get_info(ph, "nick")); // note we dont need this (in fact it causes problems) because xchat, unlike mirc // will not invoke mc_alltext on commands /* if (word_eol[1][0]=='/') { // a command, so not for us return EAT_NONE; } */ // are they using the reverse-encryption prefix? bool isencrypting=mircryptor->mc_isencrypting(channelname,returndata); if (text[0]=='`') { // yes they are using the prefix. remove it. strcpy(text,&text[1]); if (isencrypting) { // they are normally set to encrypt, so we disable it and send plain text xchat_commandf(ph,"MSG %s %s",channelname,text); // we dont show the user what they typed here, it will be shown in event_ourmessage // xchat_printf(ph,MESSAGE_SEND_FORMAT,nick,text); return EAT_ALL; } // encryption is disabled normally (or doesnt exist at all) // we just drop through in this case. } else if (!isencrypting) return EAT_NONE; // utf8 fix for text Utf8DirtyFix(text,text2); // encrypt it bretv=mircryptor->mc_forceencrypt(channelname,text2,returndata); if (!bretv) { if (strcmp(returndata,"")!=0) { xchat_print(ph,returndata); return EAT_ALL; } else return EAT_NONE; } else if (strcmp(returndata,text)!=0 && returndata[0]!='\0') { // it was encrypted so we handle it // send the encrypted text xchat_commandf(ph,"MSG %s %s %s",channelname,OUTGOINGETAG,returndata); // show user their own text //xchat_printf(ph,"[%s] %s",nick,text); //xchat_commandf(ph,"recv :%s!%s@mircryption PRIVMSG %s :(e) %s",nick,nick,channelname,text); xchat_printf(ph,EMESSAGE_SEND_FORMAT,nick,text); return EAT_ALL; } // let xchat handle this normally return EAT_NONE; } static int mc_action(char *word[], char *word_eol[], void *userdata) { // handle this command bool bretv; char returndata[MAXRETURNSTRINGLEN]; // get info char text[MAXLINELEN]; char text2[MAXLINELEN]; strcpy(text,word_eol[2]); // get info char channelname[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(channelname,xchat_get_info(ph, "channel")); // new force lowercase mylowercasify(channelname); char nick[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(nick,xchat_get_info(ph, "nick")); if (strcmp(word[2],"mcps")==0 || strcmp(word[2],OUTGOINGETAG)==0) { //we already encrypted it //even though this is a not-nice hack //it is necessary to avoid recursive calls return EAT_NONE; } // utf8 fix for text Utf8DirtyFix(text,text2); // encrypt it bretv=mircryptor->mc_encrypt(channelname,text2,returndata); if (!bretv) { if (strcmp(returndata,"")!=0) { xchat_print(ph,returndata); return EAT_ALL; } else return EAT_NONE; } else if (strcmp(returndata,text)!=0 && returndata[0]!='\0') { // it was encrypted so we handle it // send the encrypted text xchat_commandf(ph,"me %s %s",OUTGOINGETAG,returndata); //xchat_printf(ph,"mc \00313*\00300\t%s %s",nick,text); //xchat already does that when the action comes back from the server return EAT_ALL; } else { // error xchat_printf(ph,"action could not be encrypted, so it wasnt set."); } /// eat this command so xchat and other plugins can't process it return EAT_ALL; } static int mc_notice(char *word[], char *word_eol[], void *userdata) { // handle this command bool bretv; char returndata[MAXRETURNSTRINGLEN]; // get info char text[MAXLINELEN]; char text2[MAXLINELEN]; mclinesafe_strcpy(text,word_eol[3]); // get destination (nick/channel) char dest[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(dest,word[2]); // new force lowercase mylowercasify(dest); if (strcmp(word[3],"mcps")==0 || strcmp(word[3],OUTGOINGETAG)==0) { //we already encrypted it //even though this is a not-nice hack //it is necessary to avoid recursive calls return EAT_NONE; } // utf8 fix for text Utf8DirtyFix(text,text2); // encrypt it bretv=mircryptor->mc_encrypt(dest,text2,returndata); if (!bretv) { if (strcmp(returndata,"")!=0) { xchat_print(ph,returndata); return EAT_ALL; } else return EAT_NONE; } else if (strcmp(returndata,text)!=0 && returndata[0]!='\0') { // it was encrypted so we handle it // send the encrypted text xchat_commandf(ph,"notice %s %s %s",dest,OUTGOINGETAG,returndata); //xchat_printf(ph,"mc \00313*\00300\t%s %s",nick,text); //xchat already does that when the action comes back from the server return EAT_ALL; } else { // error xchat_printf(ph,"notice could not be encrypted, so it wasnt sent."); } /// eat this command so xchat and other plugins can't process it return EAT_ALL; } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- char *MircryptionClass_xchat::get_classversionstring() { // return some version information - you dont have to override this one return "Mircryption class for xchat"; } bool MircryptionClass_xchat::present_messsagebox(char *messagetext,char *windowtitle) { // present some info to the user, preferably in a pop-up modal dialog // returns true on success display_statustext(messagetext); return false; } // we need the user to give us a valid master passphrase bool MircryptionClass_xchat::request_unlockpassphrase() { // return true if user gives us a valid passphrase, and unlock the keys, false if not // I dont know how to ask xchat client for info yet, so instead we just return false and expect uuser to set it with /keypassphrase return false; } bool MircryptionClass_xchat::send_irccommand(char *irccommand,char *text) { // send an irc command to server // returns true on success xchat_commandf(ph,"%s %s",irccommand,text); return false; } bool MircryptionClass_xchat::display_statustext(char *messagetext) { // display some information for the user in some default text area (like status window in mirc) // returns true on success xchat_print(ph, messagetext); return true; } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- void mylowercasify(char *str) { if (str==NULL) return; int len=strlen(str); char c; for (int count=0;count='A' && c<='Z') str[count]=c+32; } } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- /* Author: hadez@darklab.org Date: 27.12.03 22:09 Description: frontend to mirc_codes.h */ void strip_mirc_colors(xchat_plugin* ph, char* textline) { int i; const char *str; if (xchat_get_prefs(ph,"text_stripcolor",&str, &i) == 3) // successfully got boolan value { if(i == 1) // stripping enabled { mirc_codes::clean(textline); } } } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- bool HandleMeow(char *channelname,char *nick,char *text) { // handle a meow and return true on success char returndata[MAXRETURNSTRINGLEN],estatus[MAXRETURNSTRINGLEN]; bool bretv; // grab sender string char *senderstring,*inteststring; senderstring=strtok(text," "); senderstring=strtok(NULL," "); senderstring=strtok(NULL," "); senderstring=strtok(NULL," ");senderstring=strtok(NULL," "); inteststring=strtok(NULL," "); // if they want to ignore meows if (IGNOREMEOWS || senderstring==NULL || inteststring==NULL) { xchat_printf(ph,"ignoring meow broadcast from %s on channel %s (set IGNOREMEOWS to false in mircryption.cpp to stop ignoring).",nick,channelname); return true; } // decrypt the test string char teststring[MAXRETURNSTRINGLEN]; sprintf(teststring,"mcps %s",inteststring); bretv=mircryptor->mc_decrypt2(channelname,teststring,returndata); if (!bretv || strcmp(returndata,teststring)==0 || returndata[0]=='\0') { // no key for chan strcpy(estatus,"no encryption key for this channel"); } else { // does it match meow senders key if (strcmp(returndata,"meow")==0) strcpy(estatus,"crypting (key match)"); else strcpy(estatus,"crypting (key mismatch)"); } // get our nick char mynick[MAXCHANNELNAMESIZE]; mcnicksafe_strcpy(mynick,xchat_get_info(ph, "nick")); // show user what we are replying xchat_printf(ph,"[=^.^=] [%s] %s -> meow %s %s",senderstring,nick,channelname,estatus); // send reply as notice sprintf(returndata,"mcps meow meowreply %s %s [%s] %s -> %s",nick,channelname,XMC_VERSIONSTRING,mynick,estatus); xchat_commandf(ph,"notice %s %s",nick,returndata); // return success return true; } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- void Utf8DirtyFix(char *intext,char *outtext) { // walk through the string and change any xchat encoded utf8 (glib) special characters // really the ideal way to fix this is for xchat developers to expose a function to conver the plugin-passed utf8 text to local text // but for now we use this quick fix unsigned char c,c2; int len=strlen(intext); int desti=0; for (int count=0;count