aboutsummaryrefslogtreecommitdiffstats
path: root/doc
diff options
context:
space:
mode:
authorWilmer van der Gaast <wilmer@gaast.net>2008-03-30 22:28:39 +0100
committerWilmer van der Gaast <wilmer@gaast.net>2008-03-30 22:28:39 +0100
commitddba0aea68f90b06bb6278cada982eb88889c31c (patch)
tree5f123d4266f832462cf746d6b8e7979509c0cbe3 /doc
parentf9756bd2e2711d58e06ad2a33ad3292ff10fc6da (diff)
Removing speech, in case I forget before 1.2.1.
Diffstat (limited to 'doc')
-rw-r--r--doc/RELEASE-SPEECH-1.257
1 files changed, 0 insertions, 57 deletions
diff --git a/doc/RELEASE-SPEECH-1.2 b/doc/RELEASE-SPEECH-1.2
deleted file mode 100644
index ec7c48b4..00000000
--- a/doc/RELEASE-SPEECH-1.2
+++ /dev/null
@@ -1,57 +0,0 @@
-BitlBee ... is Bitl
--------------------
-
-"I CAN HAS SPEEECH?" This is how Wilmer announced to me that he was going to do
-another BitlBee release. I was as surprised as you are. I thought he had given
-up on this whole releasing business.
-
-There is some humor in using a LOLcats reference to announce a new Bee
-release. The last major BitlBee release (1.0) was done a long time before the
-hype even begun. Between then and now we've celebrated BitlBee's fifth birthday
-and had a handful of releases, but nothing big happened. As a user this lax
-release planning worries me. What if this means that later releases will take
-even longer? I don't think we should fear this. Let us explore why this release
-took so long.
-
-Personally, I blame Google.
-
-There, I've said it. Google. The guys who are so big on "Do No Evil" and all
-that jazz. They caused this release to be so late. Let me explain why.
-
-They made Wilmer an offer. Wilmer, being the sillily naive guy he is, couldn't
-refuse. There were no decapitated horses involved, but he couldn't refuse
-nonetheless. That's not a big problem of course. Lots of guys (and gals, sure)
-work for Google. It wouldn't have become a problem if they hadn't shipped him of
-to Ireland. That's where the trouble starts.
-
-Ireland. Home of the leprechauns. These rascals joined forces with aliens and
-LOLcats to abduct Wilmer. The aliens had been trying for years to kidnap him,
-but they were on his turf and his trusty sidekicks Jelmer and Maurits were there
-to help him. All that changed when he moved to Ireland.
-
-But it wasn't just that Wilmer was all alone in some strange place. It was also
-that the aliens had created the LOLcats and made an alliance with the
-leprechauns--the real rulers of Ireland. Wilmer is cool, but he's not that
-cool. So they abducted him for a few years. When he finally came back, he
-regathered his mad coding skills and hacked a new release together.
-
-By now you're thinking, what has happened to Jelmer and Maurits? Well, they're
-still here and they worked on the Bee while Wilmer was absent. But, like open
-source, they are very Bitl--they're cool, but they're ready when they're
-ready.
-
-Well, whatever you may think of my little theory, they did take forever to
-launch this release. We're not mad at them, because it shows. They have
-added some cool new features and made plenty of changes under the hood. Let me
-give you a sneak preview of some of the new features: Jabber groupchats are
-supported. Configuration files are stored encrypted. You can now use
-ForkDaemon mode, which gives better stability over normal daemon mode, but
-doesn't require inetd. Also, server owners can now use the /OPER command to
-spy on their users. And--as I was specifically asked to mention--this is the
-first stable release that supports plugins. That's some Bitl changes for ya.
-
-BitlBee is cool, but ready when it's ready. Very Bitl.
-
-Sjoerd. LOL.
-
-(LOLBee by Erik Bosman.)
href='#n234'>234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
  /********************************************************************\
  * BitlBee -- An IRC to other IM-networks gateway                     *
  *                                                                    *
  * Copyright 2002-2005 Wilmer van der Gaast and others                *
  \********************************************************************/

/* HTTP(S) module                                                       */

/*
  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
*/

#include <string.h>
#include <stdio.h>

#include "http_client.h"
#include "url.h"
#include "sock.h"


static void http_connected( gpointer data, int source, GaimInputCondition cond );
static void http_ssl_connected( gpointer data, void *source, GaimInputCondition cond );
static void http_incoming_data( gpointer data, int source, GaimInputCondition cond );


void *http_dorequest( char *host, int port, int ssl, char *request, http_input_function func, gpointer data )
{
	struct http_request *req;
	int error = 0;
	
	req = g_new0( struct http_request, 1 );
	
	if( ssl )
	{
		req->ssl = ssl_connect( host, port, http_ssl_connected, req );
		if( req->ssl == NULL )
			error = 1;
	}
	else
	{
		req->fd = proxy_connect( host, port, http_connected, req );
		if( req->fd < 0 )
			error = 1;
	}
	
	if( error )
	{
		g_free( req );
		return( NULL );
	}
	
	req->func = func;
	req->data = data;
	req->request = g_strdup( request );
	req->request_length = strlen( request );
	
	return( req );
}

/* This one is actually pretty simple... Might get more calls if we can't write 
   the whole request at once. */
static void http_connected( gpointer data, int source, GaimInputCondition cond )
{
	struct http_request *req = data;
	int st;
	
	if( source < 0 )
		goto error;
	
	if( req->inpa > 0 )
		gaim_input_remove( req->inpa );
	
	sock_make_nonblocking( req->fd );
	
	if( req->ssl )
	{
		st = ssl_write( req->ssl, req->request + req->bytes_written,
		                req->request_length - req->bytes_written );
		if( st < 0 )
		{
			if( ssl_errno != SSL_AGAIN )
			{
				ssl_disconnect( req->ssl );
				goto error;
			}
		}
	}
	else
	{
		st = write( source, req->request + req->bytes_written,
		                    req->request_length - req->bytes_written );
		if( st < 0 )
		{
			if( !sockerr_again() )
			{
				closesocket( req->fd );
				goto error;
			}
		}
	}
	
	if( st > 0 )
		req->bytes_written += st;
	
	if( req->bytes_written < req->request_length )
		req->inpa = gaim_input_add( source,
		                            req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_WRITE,
	        	                    http_connected, req );
	else
		req->inpa = gaim_input_add( source, GAIM_INPUT_READ, http_incoming_data, req );
	
	return;
	
error:
	req->func( req );
	
	g_free( req->request );
	g_free( req );
	
	return;
}

static void http_ssl_connected( gpointer data, void *source, GaimInputCondition cond )
{
	struct http_request *req = data;
	
	if( source == NULL )
		return http_connected( data, -1, cond );
	
	req->fd = ssl_getfd( source );
	
	return http_connected( data, req->fd, cond );
}

static void http_incoming_data( gpointer data, int source, GaimInputCondition cond )
{
	struct http_request *req = data;
	int evil_server = 0;
	char buffer[2048];
	char *end1, *end2;
	int st;
	
	if( req->inpa > 0 )
		gaim_input_remove( req->inpa );
	
	if( req->ssl )
	{
		st = ssl_read( req->ssl, buffer, sizeof( buffer ) );
		if( st < 0 )
		{
			if( ssl_errno != SSL_AGAIN )
			{
				/* goto cleanup; */
				
				/* YAY! We have to deal with crappy Microsoft
				   servers that LOVE to send invalid TLS
				   packets that abort connections! \o/ */
				
				goto got_reply;
			}
		}
		else if( st == 0 )
		{
			goto got_reply;
		}
	}
	else
	{
		st = read( req->fd, buffer, sizeof( buffer ) );
		if( st < 0 )
		{
			if( !sockerr_again() )
			{
				goto cleanup;
			}
		}
		else if( st == 0 )
		{
			goto got_reply;
		}
	}
	
	if( st > 0 )
	{
		req->reply_headers = g_realloc( req->reply_headers, req->bytes_read + st + 1 );
		memcpy( req->reply_headers + req->bytes_read, buffer, st );
		req->bytes_read += st;
	}
	
	/* There will be more! */
	req->inpa = gaim_input_add( req->fd,
	                            req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_READ,
	                            http_incoming_data, req );
	
	return;

got_reply:
	/* Zero termination is very convenient. */
	req->reply_headers[req->bytes_read] = 0;
	
	/* Find the separation between headers and body, and keep stupid
	   webservers in mind. */
	end1 = strstr( req->reply_headers, "\r\n\r\n" );
	end2 = strstr( req->reply_headers, "\n\n" );
	
	if( end2 && end2 < end1 )
	{
		end1 = end2 + 1;
		evil_server = 1;
	}
	else
	{
		end1 += 2;
	}
	
	if( end1 )
	{
		*end1 = 0;
		
		if( evil_server )
			req->reply_body = end1 + 1;
		else
			req->reply_body = end1 + 2;
	}
	
	if( ( end1 = strchr( req->reply_headers, ' ' ) ) != NULL )
	{
		if( sscanf( end1 + 1, "%d", &req->status_code ) != 1 )
			req->status_code = -1;
	}
	else
	{
		req->status_code = -1;
	}
	
	if( req->status_code == 301 || req->status_code == 302 )
	{
		char *loc, *new_request, *new_host;
		int error = 0, new_port, new_proto;
		
		loc = strstr( req->reply_headers, "\nLocation: " );
		if( loc == NULL ) /* We can't handle this redirect... */
			goto cleanup;
		
		loc += 11;
		while( *loc == ' ' )
			loc ++;
		
		/* TODO/FIXME: Possibly have to handle relative redirections,
		   and rewrite Host: headers. Not necessary for now, it's
		   enough for passport authentication like this. */
		
		if( *loc == '/' )
		{
			/* Just a different pathname... */
			
			/* Since we don't cache the servername, and since we
			   don't need this yet anyway, I won't implement it. */
			
			goto cleanup;
		}
		else
		{
			/* A whole URL */
			url_t *url;
			char *s;
			
			s = strstr( loc, "\r\n" );
			if( s == NULL )
				goto cleanup;
			
			url = g_new0( url_t, 1 );
			*s = 0;
			
			if( !url_set( url, loc ) )
			{
				g_free( url );
				goto cleanup;
			}
			
			/* Okay, this isn't fun! We have to rebuild the request... :-( */
			new_request = g_malloc( req->request_length + strlen( url->file ) );
			
			/* So, now I just allocated enough memory, so I'm
			   going to use strcat(), whether you like it or not. :-) */
			
			/* First, find the GET/POST/whatever from the original request. */
			s = strchr( req->request, ' ' );
			if( s == NULL )
			{
				g_free( new_request );
				g_free( url );
				goto cleanup;
			}
			
			*s = 0;
			sprintf( new_request, "%s %s HTTP/1.0\r\n", req->request, url->file );
			*s = ' ';
			
			s = strstr( req->request, "\r\n" );
			if( s == NULL )
			{
				g_free( new_request );
				g_free( url );
				goto cleanup;
			}
			
			strcat( new_request, s + 2 );
			new_host = g_strdup( url->host );
			new_port = url->port;
			new_proto = url->proto;
			
			g_free( url );
		}
		
		if( req->ssl )
			ssl_disconnect( req->ssl );
		else
			closesocket( req->fd );
		
		req->fd = -1;
		req->ssl = 0;
		
		if( new_proto == PROTO_HTTPS )
		{
			req->ssl = ssl_connect( new_host, new_port, http_ssl_connected, req );
			if( req->ssl == NULL )
				error = 1;
		}
		else
		{
			req->fd = proxy_connect( new_host, new_port, http_connected, req );
			if( req->fd < 0 )
				error = 1;
		}
		g_free( new_host );
		
		if( error )
		{
			g_free( new_request );
			goto cleanup;
		}
		
		g_free( req->request );
		g_free( req->reply_headers );
		req->request = new_request;
		req->request_length = strlen( new_request );
		req->bytes_read = req->bytes_written = req->inpa = 0;
		req->reply_headers = req->reply_body = NULL;
		
		return;
	}
	
	/* Assume that a closed connection means we're finished, this indeed
	   breaks with keep-alive connections and faulty connections. */
	req->finished = 1;

cleanup:
	if( req->ssl )
		ssl_disconnect( req->ssl );
	else
		closesocket( req->fd );
	
	req->func( req );
	
	g_free( req->request );
	g_free( req->reply_headers );
	g_free( req );
}