#!/usr/bin/perl
# $Id: prontobrowser,v 1.5 2001/04/12 06:58:58 muhri Exp $
BEGIN {
	$libpath = $0;
	$libpath =~ s!/[^/]+$!!;
	$libpath =~ s!/bin$!/lib/pronto!;
	if (! -e $libpath) {
		die _("Can't find required files in ") . $libpath . "\n";
	};
}

use lib "$libpath";
use lib "$libpath/modules/lib/perl5/site_perl/5.005";
my ($HTMLWIDGET);
eval 'use Csc::HTML; $HTMLWIDGET = "CscHTML";' or eval 'use Gtk::HTML; $HTMLWIDGET = "GtkHTML";';
use Gtk;
init Gtk;
use URI::URL;
use IO::Socket;
use MIME::Types;
use File::Copy;
require 'prontolib.pl';

Gtk::Widget->set_default_colormap(Gtk::Gdk::Rgb->get_cmap());
Gtk::Widget->set_default_visual(Gtk::Gdk::Rgb->get_visual());

if ($HTMLWIDGET eq "GtkHTML") {
        init Gtk::HTML;
	} else {
        init Csc::HTML;
}
		

&read_prefs;
$conn=&open_db_conn;
$url = $ARGV[0];
if ($url ne "") {
&init_webbrowser($url);
} else { &init_webbrowser }

sub init_webbrowser {
	my ($url) = @_;
	my ($window, $bg, $query, $sql, @row);
	if (not defined $url) { $url = $prefs{'HomePage'};} 
	$wb_win = new Gtk::Window("toplevel");
	$wb_win->signal_connect('destroy' => sub { $wb_win->destroy; undef $wb_win; Gtk->exit(0);});
	$wb_win->signal_connect('delete_event' => \&Gtk::false);
	$wb_win->set_default_size('640','480');
	$wb_win->set_policy(1,1,0);
	$wb_win->set_title("Pronto Mini Browser");
	$wb_win->{'vbox'} = new Gtk::VBox(0,0);
	$wb_win->{'vbox'}->show;
	$wb_win->show;
	$wb_win->add($wb_win->{'vbox'});
	$window = $wb_win->window;
	$bg = $wb_win->style->bg('normal');
  	
	$wb_win->{'menu'} = new Gtk::MenuBar;
  	$wb_win->{'menu'}->{'file'} = new Gtk::MenuItem("File");
  	$wb_win->{'menu'}->{'file'}->show;
	$wb_win->{'menu'}->show;
  	$wb_win->{'menu'}->append($wb_win->{'menu'}->{'file'});
  	
	$wb_win->{'menu'}->{'view'} = new Gtk::MenuItem("View");
	$wb_win->{'menu'}->{'view'}->show;
	$wb_win->{'menu'}->append($wb_win->{'menu'}->{'view'});
	$wb_win->{'view_menu'} = new Gtk::Menu;
	$wb_win->{'menu'}->{'view'}->set_submenu($wb_win->{'view_menu'});
	$wb_win->{'view_menu'}->{'debug'} = new Gtk::CheckMenuItem("Debug");
	$wb_win->{'view_menu'}->{'debug'}->set_active(0);
	$wb_win->{'view_menu'}->{'debug'}->show;
	$wb_win->{'view_menu'}->{'debug'}->signal_connect("toggled" => \&debug);
	$wb_win->{'view_menu'}->append($wb_win->{'view_menu'}->{'debug'});
	
	$wb_win->{'file_menu'} = new Gtk::Menu;
	$wb_win->{'menu'}->{'file'}->set_submenu($wb_win->{'file_menu'});
  	$wb_win->{'file_menu'}->{'new'} = new Gtk::MenuItem("New Window ..");
	$wb_win->{'file_menu'}->{'new'}->signal_connect("activate" => \&new_window);
	$wb_win->{'file_menu'}->{'new'}->show;
	$wb_win->{'file_menu'}->append($wb_win->{'file_menu'}->{'new'});
	$wb_win->{'file_menu'}->{'home'} = new Gtk::MenuItem("Home");
	$wb_win->{'file_menu'}->{'home'}->signal_connect("activate" => \&wb_view_url, $prefs{'HomePage'});
  	$wb_win->{'file_menu'}->{'home'}->show;
  	$wb_win->{'file_menu'}->append($wb_win->{'file_menu'}->{'home'});
  	$wb_win->{'file_menu'}->{'back'} = new Gtk::MenuItem("Back");
	$wb_win->{'file_menu'}->{'back'}->signal_connect("activate" => \&wb_view_url, "back");
  	$wb_win->{'file_menu'}->{'back'}->show;
  	$wb_win->{'file_menu'}->append($wb_win->{'file_menu'}->{'back'});
	$wb_win->{'file_menu'}->{'search'} = new Gtk::MenuItem("Search");
	$wb_win->{'file_menu'}->{'search'}->show;
	$wb_win->{'file_menu'}->append($wb_win->{'file_menu'}->{'search'});
  	$wb_win->{'file_menu'}->{'close'} = new Gtk::MenuItem("Close");
  	$wb_win->{'file_menu'}->{'close'}->signal_connect("activate" => sub { $wb_win->destroy; undef $wb_win; Gtk->exit(0); });
  	$wb_win->{'file_menu'}->{'close'}->show;
  	$wb_win->{'file_menu'}->append($wb_win->{'file_menu'}->{'close'});
	$wb_win->{'file_menu'}->show;
	$wb_win->{'vbox'}->pack_start($wb_win->{'menu'},0,0,0);
	$wb_win->{'handlebox'} = new Gtk::HandleBox();
	$wb_win->{'handlebox'}->show;
	$wb_win->{'toolbar'} = new Gtk::Toolbar('horizontal', 'both');
	$wb_win->{'toolbar'}->set_button_relief('none');
	$wb_win->{'toolbar'}->set_tooltips($prefs{'ToolTips'});
	$wb_win->{'toolbar'}->border_width('2');
	$wb_win->{'toolbar'}->show;
	$wb_win->{'handlebox'}->add($wb_win->{'toolbar'});
	$wb_win->{'vbox'}->pack_start($wb_win->{'handlebox'},0,0,0);
	$wb_win->{'back_button'} = $wb_win->{'toolbar'}->append_item("Back","Click here to go back a page", "",new_pixmap("$prefs{'PixmapDir'}/back.xpm", $window, $bg));
	$wb_win->{'home_button'} = $wb_win->{'toolbar'}->append_item("Home","Click here to go to your homepage", "",new_pixmap("$prefs{'PixmapDir'}/top.xpm", $window, $bg));
	$wb_win->{'entry'} = new Gtk::Entry;
	$wb_win->{'entry'}->set_text($url);
	$wb_win->{'entry'}->show;
	$wb_win->{'toolbar'}->append_widget($wb_win->{'entry'}, "Type a URL here and press enter to go to that page", "");
	$wb_win->{'entry'}->set_usize(300,25);
	$wb_win->{'go_button'} = new Gtk::Button;
	$wb_win->{'go_button'}->show;
	my ($pixmap,$mask)=Gtk::Gdk::Pixmap->create_from_xpm($window,$bg,"$prefs{'PixmapDir'}/go.xpm");
	$wb_win->{'go_button'}->{'pixmap'} = new Gtk::Pixmap($pixmap, $mask);
	$wb_win->{'go_button'}->{'pixmap'}->show;
	$wb_win->{'go_button'}->add($wb_win->{'go_button'}->{'pixmap'});
	$wb_win->{'bookmarks'}->{'button'}= new Gtk::Button("Bookmarks");
	$wb_win->{'bookmarks'}->{'button'}->set_usize(75,25);
	$wb_win->{'bookmarks'}->{'button'}->show;
	$wb_win->{'toolbar'}->append_widget($wb_win->{'go_button'}, "Click here to load page", "");
	$wb_win->{'toolbar'}->append_widget($wb_win->{'bookmarks'}->{'button'}, "Bookmarks", "");
	$wb_win->{'toolbar'}->insert_space(2);
	$wb_win->{'toolbar'}->insert_space(4);
	$wb_win->{'toolbar'}->insert_space(6);
	$wb_win->{'toolbar'}->set_space_size(10);
	$wb_win->{'statusbar'} = new Gtk::Statusbar;
	$wb_win->{'statusbar'}->show;
	$wb_win->{'progress'}=new Gtk::ProgressBar;
	$wb_win->{'progress'}->set_usize(200,20);
	$wb_win->{'progress'}->show;
	$wb_win->{'popup'} = new Gtk::Menu;
	$wb_win->{'popup'}->{'sep'} = new Gtk::MenuItem;
	$wb_win->{'popup'}->show;
	$wb_win->{'popup'}->{'sep'}->show;
	$wb_win->{'popup'}->append($wb_win->{'popup'}->{'sep'});
	$wb_win->{'popup'}->{'new'} = new Gtk::MenuItem("Open in a new Window...");
	$wb_win->{'popup'}->{'new'}->signal_connect("activate" => \&load_new); 
	$wb_win->{'popup'}->append($wb_win->{'popup'}->{'new'});
	$wb_win->{'popup'}->{'new'}->show;
	$wb_win->{'popup'}->{'save'} = new Gtk::MenuItem("Save Link As...");
	$wb_win->{'popup'}->{'save'}->signal_connect("activate" => \&download_url);
	$wb_win->{'popup'}->{'save'}->show;
	$wb_win->{'popup'}->append($wb_win->{'popup'}->{'save'});
	$wb_win->{'bookmarks'}->{'popup'} = new Gtk::Menu;
	$wb_win->{'bookmarks'}->{'popup'}->{'bm_page'} = new Gtk::MenuItem("Bookmark Current Page");
	$wb_win->{'bookmarks'}->{'popup'}->{'bm_page'}->signal_connect("activate" => \&add_bookmark, $wb_win);
	$wb_win->{'bookmarks'}->{'popup'}->{'bm_page'}->show;
	$wb_win->{'bookmarks'}->{'popup'}->append($wb_win->{'bookmarks'}->{'popup'}->{'bm_page'});
	$wb_win->{'bookmarks'}->{'popup'}->{'sep'} = new Gtk::MenuItem;
	$wb_win->{'bookmarks'}->{'popup'}->{'sep'}->show;
	$wb_win->{'bookmarks'}->{'popup'}->append($wb_win->{'bookmarks'}->{'popup'}->{'sep'});
	$sql = "select id, title, url from bookmarks order by id";
	$query=$conn->prepare($sql);
	$query->execute();
	while (@row=$query->fetchrow_array()) {
		$wb_win->{'bookmarks'}->{'popup'}->{$row[0]} = new Gtk::MenuItem($row[1]);
		$wb_win->{'bookmarks'}->{'popup'}->{$row[0]}->signal_connect("activate" => \&wb_view_url, $row[2]);
		$wb_win->{'bookmarks'}->{'popup'}->{$row[0]}->show;
		$wb_win->{'bookmarks'}->{'popup'}->append($wb_win->{'bookmarks'}->{'popup'}->{$row[0]});
	}
	if ($HTMLWIDGET eq "GtkHTML") {
		$wb_win->{'html'} = new Gtk::HTML;
	} else {
		$wb_win->{'html'} = new Csc::HTML;
	}
	if ($THREADS == 1) {
	    	$wb_win->{'html'}->signal_connect('url_requested' => \&thread_lwu);
	} else {
	    	$wb_win->{'html'}->signal_connect('url_requested' => \&load_wb_url);
	}
	$wb_win->{'html'}->signal_connect('link_clicked' => \&wb_view_url);
	$wb_win->{'html'}->signal_connect('title_changed' => \&set_title); 
	$wb_win->{'html'}->signal_connect('on_url' => \&wb_status);
	$wb_win->{'html'}->signal_connect('submit' => \&on_submit);
	$wb_win->{'html'}->signal_connect('redirect' => \&on_redirect);
   	$wb_win->{'html'}->set_editable(0);
   	$wb_win->{'html'}->enable_debug(0);
   	$wb_win->{'sw'} = new Gtk::ScrolledWindow(undef, undef);
   	$wb_win->{'sw'}->set_policy('automatic', 'automatic');
   	$wb_win->{'sw'}->show;
   	$wb_win->{'sw'}->add($wb_win->{'html'});
   	$wb_win->{'vbox'}->pack_start($wb_win->{'sw'},1,1,0);
	$wb_win->{'hbox'}= new Gtk::HBox(0,0);
	$wb_win->{'hbox'}->show;
	$wb_win->{'vbox'}->pack_end($wb_win->{'hbox'},0,0,0);
	$wb_win->{'hbox'}->pack_start($wb_win->{'statusbar'},1,1,0);
	$wb_win->{'hbox'}->pack_end($wb_win->{'progress'},0,0,0);
   	$wb_win->{'html'}->realize;
   	$wb_win->{'html'}->show;
	$wb_win->{'html'}->signal_connect('button_press_event' => \&wb_mouse_click);

	$wb_win->{'entry'}->signal_connect("activate" => \&wb_entry_url);
	$wb_win->{'back_button'}->signal_connect("clicked" => \&wb_view_url, "back");
	$wb_win->{'home_button'}->signal_connect("clicked" => \&wb_view_url, $prefs{'HomePage'});
	$wb_win->{'go_button'}->signal_connect("clicked" => \&wb_entry_url);
	$wb_win->{'bookmarks'}->{'button'}->signal_connect("clicked" => sub {$wb_win->{'bookmarks'}->{'popup'}->popup(undef, undef, 0, 0);});
  	$wb_win->{'file_menu'}->{'search'}->signal_connect("activate" => sub { $wb_win->{'html'}->search; });
	&wb_view_url(undef, $url);
	return 1;
}

sub set_title {
	my ($widget, $title) = @_;
	$wb_win->set_title($title)
}

sub add_bookmark {
	my ($widget, $wb_win) = @_;
	my ($sql, $query, $title, $address, $id);
	$title = $wb_win->{'html'}->get_title();
	$address = $wb_win->{'current'}->as_string;
	print ("title = $title\naddress = $address\n");
	$sql = "insert into bookmarks (id, title, url) values (?, ?, ?)";
	$query = $conn->prepare($sql);
	$id = &newid('bookmarks', $conn);
	$query->execute($id, $title, $address);
	$wb_win->{'bookmarks'}->{'popup'}->{$id} = new Gtk::MenuItem($title);
	$wb_win->{'bookmarks'}->{'popup'}->{$id}->signal_connect("activate" => \&wb_view_url, $address);
	$wb_win->{'bookmarks'}->{'popup'}->{$id}->show;
	$wb_win->{'bookmarks'}->{'popup'}->append($wb_win->{'bookmarks'}->{'popup'}->{$id});
	return 1;
}
 
sub debug {
	my ($widget) = @_;
	if ($widget->active) {
		$wb_win->{'html'}->enable_debug(0);
	} else {
		$wb_win->{'html'}->enable_debug(1);
  	}
}

sub on_submit {
	my ($widget, $method, $action, $encoding) = @_;
	if ($method eq "GET") {
		$action.="?$encoding";
		&wb_view_url(undef, $action);
	} elsif ($method eq "POST") {
		$wb_win->{'length'} = length($encoding);
		$wb_win->{'message'} = $encoding;
		print ("$wb_win->{'message'}\n");
		if (!$action) {$action = $wb_win->{'current'}; }
		&wb_view_url(undef, $action);
	} else {
		print ("Unsupported Form Method: $method\nAction: $action\nEncoding: $encoding\n");
	}
	return 1;
}

sub redirect_timer_event {
	my ($redirect_url) = @_;
	Gtk->timeout_remove($redirect_timerID);
	undef $redirect_timerID;
	&wb_view_url(undef, $redirect_url);
}

sub on_redirect {
	my ($widget, $url, $delay) = @_;
	if (not defined $redirect_timerID) {
		$redirect_timerID = Gtk->timeout_add($delay * 1000, \&redirect_timer_event, $url);
	}
}

sub wb_mouse_click {
	
	my ($widget, $event) = @_;
	if ($event->{'button'} != 3) {
		return 1;
	}
	if (!$wb_win->{'mouse_url'}) {
		return 1;
	}
	$wb_win->{'popup'}->popup(undef, undef, $event->{'button'}, $event->{'time'});
	return 1;	
}

sub gtkhtml_mouse_click {
	my ($widget, $popup, $url, $event) = @_;
        if ($event->{'button'} != 3) {
                return 1;
        }
	if(!defined $$url) {
		return 1;
	}
	if($$url =~ /^file:$prefs{'MailDir'}\/tmp\//) {
        	$popup->popup(undef, undef, $event, $event->{'time'});
	}
        return 1;
}

sub wb_status {
	shift;
	my $url = shift;
	if (defined $url) {
		my $stat = (new URI::URL $url, $wb_win->{'base'})->abs($wb_win->{'base'},1);
		$wb_win->{'statusbar'}->push(1,$stat);
		$wb_win->{'mouse_url'} = $stat;
	} else {
		$wb_win->{'statusbar'}->pop(1);
		$wb_win->{'mouse_url'} = "";
	}
	return 1;
}

sub wb_entry_url {
	my ($url);
	$url = $wb_win->{'entry'}->get_text;
	if ($url !~ /^\w+:/) { $url = "http://" . $url; }
	&wb_view_url(undef, $url);
	return 1;
}

sub wb_view_url {
	my ($widget, $url) = @_;
	if (!$url) {  return 1; }
	my ($request, $host, $port, $path, $type, $header, $status, $st_num, $full_url, $socket, $redirect_url, $back);
	$back = 0;
	if ($url =~ /^mailto:(.+)/) {
		
		my ($address, @fields);
		$address = $1;
		$fields[0] = $address;    
		$fields[1] = "";
		$fields[2] = "";
		my $child;
		unless ($child = fork) {
		die "cannot fork: $~" unless defined $child;
		exec("pronto  $address");
		}
							  
		#&init_msg_window(0, undef, \@fields);
		return 1;
	}

	if (not defined $wb_win) {
       		&init_webbrowser($url);
		return 1;
	}
	if ($url eq "back") {
		if (defined @{$wb_win->{'history'}}) {
			my $tmp = pop @{$wb_win->{'history'}};
			if ($tmp) { $url = $tmp; $back = 1;} else { return 1; }
		} else {
			return 1;
		}
	}
	if (defined $wb_win) {
		$wb_win->{'statusbar'}->pop(1);
	}
	$wb_win->{'progress'}->set_activity_mode(1);
	if ($url =~ /^file:(.+)/) {
		$full_url = $url;
		my $path = $1;
		if (-d $path) {   # its a directory
			if ($path !~ /\/$/) { $path.="/"; }
			$wb_win->{'entry'}->set_text($full_url);
			$wb_win->{'current'} = $full_url;
			$wb_win->{'base'} = $full_url;
			$type = "text/html";
			my $i = 1000;
			opendir DIR, $path;
			my @entries = grep !/^\.\.?$/, readdir DIR;
			closedir(DIR);
			
			open (TMP,">$prefs{'MailDir'}/temp.html");
		        print TMP ("<html><head><title>Items in $path</title></head><body>\n");
			print TMP ("<p><h1>Items in $path</h1></p>\n");
			print TMP ("<a href=\"file:$path\">.</a><br>\n");
			my $tmp = $path;
			$tmp =~ s/(.*\/)\w+\/$/$1/;
			print TMP ("<a href=\"file:$tmp\">..</a><br>\n");
			foreach (sort(@entries)) {
				if (-d "$path$_") {
					print TMP ("<a href=\"file:$path$_/\">$_</a><br>\n");
				} else {
					print TMP ("<a href=\"file:$path$_\">$_</a><br>\n");
				}
			}
			
			
			print TMP ("</body></html>");
			
			close(TMP);
			$full_url = "file:$prefs{'MailDir'}/temp.html";
		} else {		# its a file of some sort
			($type) = MIME::Types::by_suffix($1);
			if (!$type) { $type = "application/unknown"; }
		}
	} else {
		$full_url = (new URI::URL $url, $wb_win->{'base'})->abs($wb_win->{'base'},1);
#		$full_url =~ s/%(\w\w)/chr(hex($1))/eg;
		$full_url =~ /http:\/\/([\w\.-]+)([:\d]*)(.*)/;
		if (!$3) { $path = "/"; } else { $path = $3; }
		if (!$2) { $port = 80; } else { $port = $2; }
		if (!$1) { return 1; } else { $host = $1; }
		if ($prefs{'Proxy'}) {
			$socket = IO::Socket::INET->new(PeerAddr => $prefs{'Proxy'}, PeerPort => $prefs{'ProxyPort'}, Proto => "TCP", Timeout => "30", Type => SOCK_STREAM) or return 1;
			print $socket "HEAD $full_url HTTP/1.1\r\nHost: $host\r\nUser-Agent: Pronto/$version\r\nConnection: close\r\n\r\n";
		} else {
			$socket = IO::Socket::INET->new(PeerAddr => $host, PeerPort => $port, Proto => "TCP", Timeout => "30", Type => SOCK_STREAM) or return 1;
			print $socket "HEAD $path HTTP/1.1\r\nHost: $host\r\nUser-Agent: Pronto/$version\r\nConnection: close\r\n\r\n";

		}
CONTINUE:	$status = <$socket>;
		$/ = "";
		$header = <$socket>;
		$/ = "\n";
		$status =~ /HTTP\/\d.\d (\d+)/ and $st_num = $1;
		if ($st_num == 301 || $st_num == 302) {
			$header =~ /Location: ?(.+)/i and $redirect_url = $1;
			&wb_view_url(undef, $redirect_url);
			return 1;
		} elsif ($st_num == 100) {
			goto CONTINUE;
		} elsif ($st_num != 200) {
			&err_dialog("$status");
			return 1;
		}
		$header =~ /Content-Type: ?(.+)/i and $type = $1;
	}
	if ($type !~ /text\//i) {
		if ($type =~ /image\//) {
			$full_url =~ s/ /%20/g;
		     	open (TMP,">$prefs{'MailDir'}/temp.html");
			print TMP ("<html><head><title>$full_url</title></head><body><img src=$full_url></body></html>");
			close(TMP);
			$full_url = "file:$prefs{'MailDir'}/temp.html";
		} else {
			&download_url(undef, $full_url);
			return 1;
		}
	}

	if (defined $wb_win->{'current'} && $back != 1) {
		push @{$wb_win->{'history'}}, $wb_win->{'current'};
	}
	$wb_win->{'current'} = $full_url;
	$wb_win->{'base'} = $full_url;
	$wb_win->{'entry'}->set_text($full_url);
	if ($THREADS == 1) {
		&thread_lwu($wb_win->{'html'}, $full_url, $wb_win->{'html'}->begin)
	} else {
		&load_wb_url($wb_win->{'html'}, $full_url, $wb_win->{'html'}->begin)
	}					
	$wb_win->{'progress'}->set_activity_mode(0);
	return 1;
}

sub download_url {
	my ($widget, $url) = @_;
	if (!$url && !($url = $wb_win->{'mouse_url'})) { return 1; }
	my ($filename, $fs_window);
	$url =~ /\/([-\w\.]+)$/ and $filename = $1;
	if (!$filename) { $filename=""; }
	print ("File before: $filename\n");
	$fs_window = new Gtk::FileSelection "Download File";
	$fs_window->position(-mouse);
	$fs_window->signal_connect("destroy", sub {$fs_window->destroy;});
	$fs_window->signal_connect("delete_event" => \&Gtk::false);
	$fs_window->ok_button->signal_connect("clicked", \&begin_dl, $fs_window, $url);
	$fs_window->cancel_button->signal_connect("clicked", sub {$fs_window->destroy;});
	$fs_window->set_filename($filename);
	$fs_window->show;
	return 1;
}

sub begin_dl {
	my ($widget, $fs_window, $url) = @_;
	my ($fh, $status_dialog, $sd_vbox, $sd_label, $sd_pbar, $sd_button, $path, $port, $host, $socket, $status, $st_num, $length, $count, $d);
	my ($answer, $header) = ("","");
	my $filename = $fs_window->get_filename();
	print ("Filename: $filename\n");
	$fs_window->destroy;
	if ($url =~ /^file:(.+)/) {
		my $from = $1;
		copy($from, $filename);
		return 1;
	}
	$status_dialog = new Gtk::Dialog; 
	$status_dialog->signal_connect("destroy" => sub { $status_dialog->destroy; });
	$status_dialog->signal_connect("delete_event" => sub { $status_dialog->destroy; });
	$status_dialog->set_title("Downloading File...");
	$status_dialog->border_width(0);
	$sd_vbox=new Gtk::VBox(0,5);
	$sd_vbox->border_width(10);
	$status_dialog->vbox->pack_start($sd_vbox,1,1,0);
	$sd_vbox->show;
	$sd_label=new Gtk::Label "Downloading $filename...";
	$sd_label->set_alignment(0.0,0.5);
	$sd_vbox->pack_start($sd_label,0,1,0);
	$sd_label->show;
	$sd_pbar=new Gtk::ProgressBar;
	$sd_pbar->set_usize(200,20);
	$sd_vbox->pack_start($sd_pbar,1,1,0);
	$sd_pbar->show;
	$sd_pbar->set_show_text(1);
	$sd_pbar->set_text_alignment(0.5,0.5);
	$sd_pbar->set_format_string("%v of %u - %p %%");
	$sd_button=new Gtk::Button "Cancel Transfer";
	$sd_button->can_default(1);
	$status_dialog->action_area->pack_start($sd_button,1,1,0);
	$sd_button->grab_default;
	$sd_button->show;
	$status_dialog->show;
	$sd_button->signal_connect("clicked", sub { $status_dialog->destroy; $fh->close; $socket->close; return 1; });
#	$url =~ s/%(\w\w)/chr(hex($1))/eg;
#	$url =~ s/ //g;
	$url =~ /http:\/\/([\w\.-]+)([:\d]*)(.*)/;
	if (!$3) { $path = "/"; } else { $path = $3; }
	if (!$2) { $port = 80; } else { $port = $2; }
	if (!$1) { return 1; } else { $host = $1; }
	print ("Host: $host\nPath: $path\nPort: $port\n");
	if ($prefs{'Proxy'}) {
		$socket = IO::Socket::INET->new(PeerAddr => $prefs{'Proxy'}, PeerPort => $prefs{'ProxyPort'}, Proto => "TCP", Timeout => "30", Type => SOCK_STREAM);
		print $socket "GET $url HTTP/1.1\r\nHost: $host\r\nUser-Agent: Pronto/$version\r\nConnection: close\r\n\r\n";

	} else {
		$socket = IO::Socket::INET->new(PeerAddr => $host, PeerPort => $port, Proto => "TCP", Timeout => "30", Type => SOCK_STREAM);
		print $socket "GET $path HTTP/1.1\r\nHost: $host\r\nUser-Agent: Pronto/$version\r\nConnection: close\r\n\r\n";
	}
CONTINUE:	$status = <$socket>;
	$status =~ /HTTP\/\d.\d (\d+)/ and $st_num = $1;
	while (defined $answer and $answer ne "\n") {
	$answer = <$socket>;
		if ($answer) {
			$answer =~ s/\r//g;
			$header.= $answer;
		}
	}
	if ($st_num == 301 || $st_num ==302) {
		$header =~ /\nLocation: ?(.+)/i and $url = $1;
		&begin_dl($widget, $fs_window, $url);
		return 1;
	} elsif ($st_num == 100) {
		goto CONTINUE;
	} elsif ($st_num != 200) {
		&err_dialog("$status");
		return 1;
	}
	print ("$header\n");
	$header =~ /Content-Length: ?(\d+)/i and $length = $1;
	$sd_pbar->configure(0,0,$length);
	if ($fh = new IO::File ">$filename") {
		if (defined $length && $length > 8192) {
			my $numfullpackets = int($length/8192);
			my $lastpacket = $length - ($numfullpackets * 8192);
			for (my $i = 1; $i <= $numfullpackets; $i++) {
				$count+=8192;
				$sd_pbar->set_value($count);
				while (Gtk->events_pending) {
					Gtk->main_iteration;
				}
				$socket->read($d, 8192);
				print $fh $d;
			}
			$socket->read($d, $lastpacket);
		} else {
			$socket->read($d, 8192);
		}
		print $fh $d;
	}
	$status_dialog->destroy;
	return 1;
}

sub thread_lwu {
	my ($html, $url, $handle) = @_;
	my $t = new Thread \&thread_start_lwu, $html, $url, $handle;
	$t->detach;
	return 1;
}

sub thread_start_lwu {
	my ($html, $url, $handle) = @_;
	Gtk::Gdk->threads_enter();
	&load_wb_url($html, $url, $handle);
	Gtk::Gdk->threads_leave();
	POSIX::_exit();
}

sub load_wb_url {
	my ($html, $url, $handle) = @_;
	my ($full_url, $socket, $answer, $length, $header, $host, $path, $port, $d, $xferencode, $status, $st_num);
	$header=""; 
	$answer = "";
	$full_url = (new URI::URL $url, $wb_win->{'base'})->abs($wb_win->{'base'},1);
	if ($full_url->as_string =~ /^file:(.+)/) {
		my $path = $1;
		$path =~ s/%(\w\w)/chr(hex($1))/eg;
		my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size)=stat $path;
		$socket = IO::File->new($path) or return 1;
		$socket->read($d, $size);
		$html->write($handle, $d);
		$html->end($handle, 'ok');
		return 1;
	}
	$full_url =~ /http:\/\/([\w\.-]+)([:\d]*)(.*)/;
	if (!$3) { $path = "/"; } else { $path = $3; }
	if (!$2) { $port = 80; } else { $port = $2; }
	if ($1) { $host = $1; } else { return 1; }
	if ($prefs{'Proxy'}) {
		$socket = IO::Socket::INET->new(PeerAddr => $prefs{'Proxy'}, PeerPort => $prefs{'ProxyPort'}, Proto => "TCP", Timeout => "30", Type => SOCK_STREAM) or return 1;
	} else {
		$socket = IO::Socket::INET->new(PeerAddr => $host, PeerPort => $port, Proto => "TCP", Timeout => "30", Type => SOCK_STREAM) or return 1;
	}
	if (!$wb_win->{'message'}) {
		if ($prefs{'Proxy'}) {
			print $socket "GET $full_url HTTP/1.1\r\nHost: $host\r\nUser-Agent: Pronto/$version\r\nConnection: close\r\n\r\n";
		} else {
			print $socket "GET $path HTTP/1.1\r\nHost: $host\r\nUser-Agent: Pronto/$version\r\nConnection: close\r\n\r\n";
		}
	} else {
		if ($prefs{'Proxy'}) {
			print $socket "POST $full_url HTTP/1.1\r\nHost: $host\r\nUser-Agent: Pronto/$version\r\nConnection: close\r\nContent-type: application/x-www-form-urlencode\r\nContent-length: $wb_win->{'length'}\r\n\r\n$wb_win->{'message'}\r\n";
		} else {
			print $socket "POST $path HTTP/1.1\r\nHost: $host\r\nUser-Agent: Pronto/$version\r\nConnection: close\r\nContent-type: application/x-www-form-urlencode\r\nContent-length: $wb_win->{'length'}\r\n\r\n$wb_win->{'message'}\r\n";
		}
		undef $wb_win->{'message'};
		undef $wb_win->{'length'};
	}
CONTINUE:	$status = <$socket>;
	$status =~ /HTTP\/\d.\d (\d+)/ and $st_num = $1;
	while (defined $answer and $answer ne "\n") {
		$answer = <$socket>;
		if ($answer) {
			$answer =~ s/\r//g;
			$header.= $answer;
		}
	}
	if ($st_num == 301 || $st_num ==302) {
		$url = "";
		$header =~ /Location: ?(.+)/i and $url = $1;
		unless ($url eq "") {
			&load_wb_url($html, $url, $handle);
			return 1;
		}
	} elsif ($st_num == 100) {
		$answer = "";
		goto CONTINUE;
	} elsif ($st_num != 200) {
		&err_dialog("$status");
		return 1;
	}
	$header =~ /Content-Length: ?(\d+)/i and $length = $1;
	$header =~ /\nTransfer-Encoding: ?(.+)/i and $xferencode = $1;
	if (defined $xferencode && $xferencode =~ /chunked/) {
		$wb_win->{'progress'}->set_activity_mode(1);
		my ($body, $line);
		$/ = "\r\n"; 
		$line = <$socket>;
		$/ = "\n";
		$line =~ /^(\w+)/ and $length = $1;
		while (hex($length) > 0) {
			$socket->read($d, hex($length));
			$body.=$d;
			$/ = "\r\n";
			$line = <$socket>;
			$line = <$socket>;
			$length = 0;
			$line =~ /^(\w+)/ and $length = $1;
			$/ = "\n";
		}
		$html->write($handle, $body);
		$wb_win->{'progress'}->set_activity_mode(0);
	} else {
		if (defined $length && $length > 8192) {
			$wb_win->{'progress'}->configure(0,0,$length);
			my $numfullpackets = int($length/8192);
			my $lastpacket = $length - ($numfullpackets * 8192);
			for (my $i = 1; $i <= $numfullpackets; $i++) {
				$socket->read($d, 8192);
				$wb_win->{'progress'}->set_value($i * 8192);
				$html->write($handle, $d);
			}
			$wb_win->{'progress'}->set_value($length);
			$socket->read($d, $lastpacket);
		} else {
			$socket->read($d, 65535);
		}
		$html->write($handle, $d);
	}
	$html->end($handle, 'ok');
	$wb_win->{'progress'}->set_value(0);
	return 1;
}
	
sub new_pixmap {
	my ($filename, $window, $background) = @_;
	my ($pixmap, $mask) = create_from_xpm Gtk::Gdk::Pixmap($window, $background, $filename);
	return new Gtk::Pixmap($pixmap, $mask);
}

sub load_new {

        my ($widget, $url) = @_;
        if (!$url && !($url = $wb_win->{'mouse_url'})) { return 1; }
	my $child;
	unless ($child = fork) {
	die "cannot fork: $~" unless defined $child;
	exec("prontobrowser $url");
	 }
	 
}

sub new_window {

         my $child;
         unless ($child = fork) {
	 die "cannot fork: $~" unless defined $child;
	 exec("prontobrowser");
	 }
}				  

main Gtk;
