aboutsummaryrefslogtreecommitdiffstats
path: root/win32/bitlbeewin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'win32/bitlbeewin.cpp')
-rw-r--r--win32/bitlbeewin.cpp210
1 files changed, 210 insertions, 0 deletions
diff --git a/win32/bitlbeewin.cpp b/win32/bitlbeewin.cpp
new file mode 100644
index 00000000..e18ae3cd
--- /dev/null
+++ b/win32/bitlbeewin.cpp
@@ -0,0 +1,210 @@
+// bitlbee.cpp : Defines the class behaviors for the application.
+//
+
+#define BITLBEE_CORE
+#include "bitlbeewin.h"
+#include "traynot.h"
+#include "maindlg.h"
+#include <afxsock.h>
+extern "C" {
+#include "config.h"
+#include "bitlbee.h"
+#include <stdarg.h>
+#include <gmodule.h>
+int
+inet_aton(const char *cp, struct in_addr *addr)
+{
+ addr->s_addr = inet_addr(cp);
+ return (addr->s_addr == INADDR_NONE) ? 0 : 1;
+}
+
+void glib_logger (const gchar *log_domain, GLogLevelFlags log_level, const gchar *msg, gpointer user_data);
+
+}
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CBitlbeeApp
+
+BEGIN_MESSAGE_MAP(CBitlbeeApp, CWinApp)
+ //{{AFX_MSG_MAP(CBitlbeeApp)
+ ON_COMMAND(IDM_EXIT, OnExit)
+ ON_COMMAND(IDM_SHOW, OnShow)
+ //}}AFX_MSG_MAP
+ ON_COMMAND(ID_HELP, CWinApp::OnHelp)
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CBitlbeeApp construction
+
+CBitlbeeApp::CBitlbeeApp()
+{
+ // TODO: add construction code here,
+ // Place all significant initialization in InitInstance
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// The one and only CBitlbeeApp object
+
+CBitlbeeApp theApp;
+
+/////////////////////////////////////////////////////////////////////////////
+// CBitlbeeApp initialization
+
+static UINT bb_loop(LPVOID data)
+{
+ g_main_run(global.loop);
+ return 0;
+}
+
+
+gboolean bitlbee_new_client(GIOChannel *src, GIOCondition cond, gpointer data);
+global_t global; // Against global namespace pollution
+
+BOOL CBitlbeeApp::InitInstance()
+{
+ if (!AfxSocketInit())
+ {
+ AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
+ return FALSE;
+ }
+
+ // Standard initialization
+ // If you are not using these features and wish to reduce the size
+ // of your final executable, you should remove from the following
+ // the specific initialization routines you do not need.
+
+#ifdef _AFXDLL
+ Enable3dControls(); // Call this when using MFC in a shared DLL
+#else
+ Enable3dControlsStatic(); // Call this when linking to MFC statically
+#endif
+
+ HKEY key;
+ unsigned char databuf[256];
+ DWORD len;
+ RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Bitlbee", &key);
+
+ memset( &global, 0, sizeof( global_t ) );
+ g_log_set_handler("GLib", static_cast<GLogLevelFlags>(G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION), glib_logger, NULL);
+ global.loop = g_main_new(FALSE);
+ nogaim_init();
+
+ SetRegistryKey("Bitlbee");
+ conf_t *conf = (conf_t *)g_new0( conf_t, 1 );
+ global.conf = conf;
+ global.conf->iface = g_strdup(GetProfileString("main", "interface", "0.0.0.0"));
+ global.conf->port = GetProfileInt("main", "port", 6667);
+ global.conf->verbose = GetProfileInt("main", "verbose", 0);
+ global.conf->password = g_strdup(GetProfileString("main", "password", ""));
+ global.conf->ping_interval = GetProfileInt("main", "ping_interval_timeout", 60);
+ global.conf->hostname = g_strdup(GetProfileString("main", "hostname", "localhost"));
+ if(RegQueryValueEx(key, "configdir", NULL, NULL, databuf, &len) != ERROR_SUCCESS) strcpy((char *)databuf, "");
+ global.conf->configdir = g_strdup(GetProfileString("main", "configdir", (char *)databuf));
+ if(RegQueryValueEx(key, "motdfile", NULL, NULL, databuf, &len) != ERROR_SUCCESS) strcpy((char *)databuf, "");
+ global.conf->motdfile = g_strdup(GetProfileString("main", "motdfile", (char *)databuf));
+ if(RegQueryValueEx(key, "helpfile", NULL, NULL, databuf, &len) != ERROR_SUCCESS) strcpy((char *)databuf, "");
+ global.helpfile = g_strdup(GetProfileString("main", "helpfile", (char *)databuf));
+ global.conf->runmode = RUNMODE_DAEMON;
+ global.conf->authmode = (enum authmode) GetProfileInt("main", "AuthMode", AUTHMODE_CLOSED);
+ strcpy(proxyhost, GetProfileString("proxy", "host", ""));
+ strcpy(proxyuser, GetProfileString("proxy", "user", ""));
+ strcpy(proxypass, GetProfileString("proxy", "password", ""));
+ proxytype = GetProfileInt("proxy", "type", PROXY_NONE);
+ proxyport = GetProfileInt("proxy", "port", 3128);
+
+ dlg = new CMainDlg();
+ not = new CTrayNot(dlg);
+ dlg->ShowWindow(SW_HIDE);
+ m_pMainWnd = not;
+
+ if(help_init(&(global.help)) == NULL) {
+ log_message(LOGLVL_WARNING, "Unable to initialize help");
+ }
+
+ if(bitlbee_daemon_init() != 0) {
+ return FALSE;
+ }
+
+ AfxBeginThread(bb_loop, NULL);
+
+
+ return TRUE;
+}
+
+void log_error(char *a) {
+ ::MessageBox(NULL, a, "Bitlbee error", MB_OK | MB_ICONEXCLAMATION);
+}
+
+/* Dummy function. log output always goes to screen anyway */
+void log_link(int level, int out) {}
+
+void conf_loaddefaults(irc_t *irc) {}
+double gettime() {
+ return CTime::GetCurrentTime().GetTime();
+}
+
+void load_protocol(char *name, char *init_function_name, struct prpl *p) {
+ void (*init_function) (struct prpl *);
+
+ char *path = g_module_build_path(NULL, name);
+ if(!path) {
+ log_message(LOGLVL_WARNING, "Can't build path for %s\n", name);
+ return;
+ }
+
+ GModule *mod = g_module_open(path, G_MODULE_BIND_LAZY);
+ if(!mod) {
+ log_message(LOGLVL_INFO, "Can't find %s, not loading", name);
+ return;
+ }
+
+ if(!g_module_symbol(mod,init_function_name,(void **) &init_function)) {
+ log_message(LOGLVL_WARNING, "Can't find function %s in %s\n", init_function_name, path);
+ return;
+ }
+ g_free(path);
+
+ init_function(p);
+}
+
+void jabber_init(struct prpl *p) { load_protocol("jabber", "jabber_init", p); }
+void msn_init(struct prpl *p) { load_protocol("msn", "msn_init", p); }
+void byahoo_init(struct prpl *p) { load_protocol("yahoo", "byahoo_init", p); }
+void oscar_init(struct prpl *p) { load_protocol("oscar", "oscar_init", p); }
+
+void CBitlbeeApp::OnExit()
+{
+ AfxGetApp()->ExitInstance();
+ exit(0);
+}
+
+void CBitlbeeApp::OnShow()
+{
+ dlg->ShowWindow(SW_SHOW);
+}
+
+int CBitlbeeApp::ExitInstance()
+{
+ WriteProfileString("main", "interface", global.conf->iface);
+ WriteProfileInt("main", "port", global.conf->port);
+ WriteProfileInt("main", "verbose", global.conf->verbose);
+ WriteProfileString("main", "password", global.conf->password);
+ WriteProfileString("main", "configdir", global.conf->configdir);
+ WriteProfileString("main", "hostname", global.conf->hostname);
+ WriteProfileString("main", "motdfile", global.conf->motdfile);
+ WriteProfileInt("main", "authmode", global.conf->authmode);
+ WriteProfileInt("proxy", "type", proxytype);
+ WriteProfileString("proxy", "host", proxyhost);
+ WriteProfileString("proxy", "user", proxyuser);
+ WriteProfileString("proxy", "password", proxypass);
+ WriteProfileInt("proxy", "port", proxyport);
+ WriteProfileInt("main", "ping_interval_timeout", global.conf->ping_interval);
+ delete not;
+ return CWinApp::ExitInstance();
+}
.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
  /********************************************************************\
  * BitlBee -- An IRC to other IM-networks gateway                     *
  *                                                                    *
  * Copyright 2002-2004 Wilmer van der Gaast and others                *
  \********************************************************************/

/*
 * nogaim
 *
 * Gaim without gaim - for BitlBee
 *
 * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
 *                          (and possibly other members of the Gaim team)
 * Copyright 2002-2004 Wilmer van der Gaast <lintux@lintux.cx>
 */

/*
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License with
  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
  Suite 330, Boston, MA  02111-1307  USA
*/

/* Parts from util.c from gaim needed by nogaim */
#define BITLBEE_CORE
#include "nogaim.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <time.h>

char *utf8_to_str(const char *in)
{
	int n = 0, i = 0;
	int inlen;
	char *result;

	if (!in)
		return NULL;

	inlen = strlen(in);

	result = g_malloc(inlen + 1);

	while (n <= inlen - 1) {
		long c = (long)in[n];
		if (c < 0x80)
			result[i++] = (char)c;
		else {
			if ((c & 0xC0) == 0xC0)
				result[i++] =
				    (char)(((c & 0x03) << 6) | (((unsigned char)in[++n]) & 0x3F));
			else if ((c & 0xE0) == 0xE0) {
				if (n + 2 <= inlen) {
					result[i] =
					    (char)(((c & 0xF) << 4) | (((unsigned char)in[++n]) & 0x3F));
					result[i] =
					    (char)(((unsigned char)result[i]) |
						   (((unsigned char)in[++n]) & 0x3F));
					i++;
				} else
					n += 2;
			} else if ((c & 0xF0) == 0xF0)
				n += 3;
			else if ((c & 0xF8) == 0xF8)
				n += 4;
			else if ((c & 0xFC) == 0xFC)
				n += 5;
		}
		n++;
	}
	result[i] = '\0';

	return result;
}

char *str_to_utf8(const char *in)
{
	int n = 0, i = 0;
	int inlen;
	char *result = NULL;

	if (!in)
		return NULL;

	inlen = strlen(in);

	result = g_malloc(inlen * 2 + 1);

	while (n < inlen) {
		long c = (long)in[n];
		if (c == 27) {
			n += 2;
			if (in[n] == 'x')
				n++;
			if (in[n] == '3')
				n++;
			n += 2;
			continue;
		}
		/* why are we removing newlines and carriage returns?
		if ((c == 0x0D) || (c == 0x0A)) {
			n++;
			continue;
		}
		*/
		if (c < 128)
			result[i++] = (char)c;
		else {
			result[i++] = (char)((c >> 6) | 192);
			result[i++] = (char)((c & 63) | 128);
		}
		n++;
	}
	result[i] = '\0';

	return result;
}

void strip_linefeed(gchar *text)
{
	int i, j;
	gchar *text2 = g_malloc(strlen(text) + 1);

	for (i = 0, j = 0; text[i]; i++)
		if (text[i] != '\r')
			text2[j++] = text[i];
	text2[j] = '\0';

	strcpy(text, text2);
	g_free(text2);
}

char *add_cr(char *text)
{
	char *ret = NULL;
	int count = 0, j;
	unsigned int i;

	if (text[0] == '\n')
		count++;
	for (i = 1; i < strlen(text); i++)
		if (text[i] == '\n' && text[i - 1] != '\r')
			count++;

	if (count == 0)
		return g_strdup(text);

	ret = g_malloc0(strlen(text) + count + 1);

	i = 0; j = 0;
	if (text[i] == '\n')
		ret[j++] = '\r';
	ret[j++] = text[i++];
	for (; i < strlen(text); i++) {
		if (text[i] == '\n' && text[i - 1] != '\r')
			ret[j++] = '\r';
		ret[j++] = text[i];
	}

	return ret;
}

static char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" "0123456789+/";

/* XXX Find bug */
char *tobase64(const char *text)
{
	char *out = NULL;
	const char *c;
	unsigned int tmp = 0;
	int len = 0, n = 0;

	c = text;

	while (*c) {
		tmp = tmp << 8;
		tmp += *c;
		n++;

		if (n == 3) {
			out = g_realloc(out, len + 4);
			out[len] = alphabet[(tmp >> 18) & 0x3f];
			out[len + 1] = alphabet[(tmp >> 12) & 0x3f];
			out[len + 2] = alphabet[(tmp >> 6) & 0x3f];
			out[len + 3] = alphabet[tmp & 0x3f];
			len += 4;
			tmp = 0;
			n = 0;
		}
		c++;
	}
	switch (n) {

	case 2:
		tmp <<= 8;
		out = g_realloc(out, len + 5);
		out[len] = alphabet[(tmp >> 18) & 0x3f];
		out[len + 1] = alphabet[(tmp >> 12) & 0x3f];
		out[len + 2] = alphabet[(tmp >> 6) & 0x3f];
		out[len + 3] = '=';
		out[len + 4] = 0;
		break;
	case 1:
		tmp <<= 16;
		out = g_realloc(out, len + 5);
		out[len] = alphabet[(tmp >> 18) & 0x3f];
		out[len + 1] = alphabet[(tmp >> 12) & 0x3f];
		out[len + 2] = '=';
		out[len + 3] = '=';
		out[len + 4] = 0;
		break;
	case 0:
		out = g_realloc(out, len + 1);
		out[len] = 0;
		break;
	}
	return out;
}

char *normalize(const char *s)
{
	static char buf[BUF_LEN];
	char *t, *u;
	int x = 0;

	g_return_val_if_fail((s != NULL), NULL);

	u = t = g_strdup(s);

	strcpy(t, s);
	g_strdown(t);

	while (*t && (x < BUF_LEN - 1)) {
		if (*t != ' ') {
			buf[x] = *t;
			x++;
		}
		t++;
	}
	buf[x] = '\0';
	g_free(u);
	return buf;
}

time_t get_time(int year, int month, int day, int hour, int min, int sec)
{
	struct tm tm;

	tm.tm_year = year - 1900;
	tm.tm_mon = month - 1;
	tm.tm_mday = day;
	tm.tm_hour = hour;
	tm.tm_min = min;
	tm.tm_sec = sec >= 0 ? sec : time(NULL) % 60;
	return mktime(&tm);
}

typedef struct htmlentity
{
	char code[8];
	char is;
} htmlentity_t;

/* FIXME: This is ISO8859-1(5) centric, so might cause problems with other charsets. */

static htmlentity_t ent[] =
{
	{ "lt",     '<' },
	{ "gt",     '>' },
	{ "amp",    '&' },
	{ "quot",   '"' },
	{ "aacute", '�' },
	{ "eacute", '�' },
	{ "iacute", '�' },
	{ "oacute", '�' },
	{ "uacute", '�' },
	{ "agrave", '�' },
	{ "egrave", '�' },
	{ "igrave", '�' },
	{ "ograve", '�' },
	{ "ugrave", '�' },
	{ "acirc",  '�' },
	{ "ecirc",  '�' },
	{ "icirc",  '�' },
	{ "ocirc",  '�' },
	{ "ucirc",  '�' },
	{ "nbsp",   ' ' },
	{ "",        0  }
};

void strip_html( char *in )
{
	char *start = in;
	char *out = g_malloc( strlen( in ) + 1 );
	char *s = out, *cs;
	int i, matched;
	
	memset( out, 0, strlen( in ) + 1 );
	
	while( *in )
	{
		if( *in == '<' && ( isalpha( *(in+1) ) || *(in+1) == '/' ) )
		{
			/* If in points at a < and in+1 points at a letter or a slash, this is probably
			   a HTML-tag. Try to find a closing > and continue there. If the > can't be
			   found, assume that it wasn't a HTML-tag after all. */
			
			cs = in;
			
			while( *in && *in != '>' )
				in ++;
			
			if( *in )
			{
				if( g_strncasecmp( cs+1, "br", 2) == 0 )
					*(s++) = '\n';
				in ++;
			}
			else
			{
				in = cs;
				*(s++) = *(in++);
			}
		}
		else if( *in == '&' )
		{
			cs = ++in;
			while( *in && isalpha( *in ) )
				in ++;
			
			if( *in == ';' ) in ++;
			matched = 0;
			
			for( i = 0; *ent[i].code; i ++ )
				if( g_strncasecmp( ent[i].code, cs, strlen( ent[i].code ) ) == 0 )
				{
					*(s++) = ent[i].is;
					matched = 1;
					break;
				}

			/* None of the entities were matched, so return the string */
			if( !matched )
			{
				in = cs - 1;
				*(s++) = *(in++);
			}
		}
		else
		{
			*(s++) = *(in++);
		}
	}
	
	strcpy( start, out );
	g_free( out );
}

char *escape_html( const char *html )
{
	const char *c = html;
	GString *ret;
	char *str;
	
	if( html == NULL )
		return( NULL );
	if( g_strncasecmp( html, "<html>", 6 ) == 0 )
		return( g_strdup( html ) );
	
	ret = g_string_new( "" );
	
	while( *c )
	{
		switch( *c )
		{
			case '&':
				ret = g_string_append( ret, "&amp;" );
				break;
			case '<':
				ret = g_string_append( ret, "&lt;" );
				break;
			case '>':
				ret = g_string_append( ret, "&gt;" );
				break;
			case '"':
				ret = g_string_append( ret, "&quot;" );
				break;
			default:
				ret = g_string_append_c( ret, *c );
		}
		c ++;
	}
	
	str = ret->str;
	g_string_free( ret, FALSE );
	return( str );
}

void info_string_append(GString *str, char *newline, char *name, char *value)
{
	if( value && value[0] )
		g_string_sprintfa( str, "%s%s: %s", newline, name, value );
}