Commit 2e9f835f authored by Elliot Lee's avatar Elliot Lee
Browse files

The ten minute version of kwebsearch. Handle forms (POST is untested and



* components/websearch, configure.in: The ten minute version of kwebsearch.
* components/html/ntl-web-browser.c: Handle forms (POST is untested and probably buggy).
* src/ntl-uri-map.c: Check result of file_info retrieval. Load web search by default.
* src/ntl-prefs.[ch]: First (lame) attempt at implementing application preferences.
* src/ntl-app.c: Load prefs at startup
parent 05729d18
2000-01-03 Elliot Lee <sopwith@redhat.com>
* components/websearch, configure.in: The ten minute version of kwebsearch.
* components/html/ntl-web-browser.c: Handle forms (POST is untested and probably buggy).
* src/ntl-uri-map.c: Check result of file_info retrieval. Load web search by default.
* src/ntl-prefs.[ch]: First (lame) attempt at implementing application preferences.
* src/ntl-app.c: Load prefs at startup
2000-01-03 John Sullivan <sullivan@eazel.com>
Added underline-accelerators to Add Bookmark and
......
......@@ -18,6 +18,9 @@
#endif
#include "glibwww.h"
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
#include <gnome.h>
#include <libnautilus/libnautilus.h>
#include <gtkhtml/gtkhtml.h>
......@@ -29,116 +32,121 @@ typedef struct {
NautilusViewClient *vc;
GtkWidget *htmlw;
char *base_url, *base_target_url;
int prevsel;
HTMethod method;
char *post_data;
} BrowserInfo;
static char *
canonicalize_url (const char *in_url, const char *base_url)
{
char *ctmp, *ctmp2, *retval, *removebegin, *removeend, *curpos;
char *ctmp, *ctmp2, *retval, *removebegin, *removeend, *curpos;
g_return_val_if_fail(in_url, NULL);
g_return_val_if_fail(in_url, NULL);
ctmp = strstr(in_url, "://");
if(ctmp)
ctmp = strstr(in_url, "://");
if(ctmp)
{
retval = g_strdup(in_url);
goto out;
}
else if(*in_url == '/')
{
ctmp = base_url?strstr(base_url, "://"):NULL;
if(!ctmp)
{
retval = g_strdup(in_url);
goto out;
retval = g_strconcat("file://", in_url, NULL);
goto out;
}
else if(*in_url == '/')
{
ctmp = base_url?strstr(base_url, "://"):NULL;
if(!ctmp)
{
retval = g_strconcat("file://", in_url, NULL);
goto out;
}
ctmp2 = strchr(ctmp + 3, '/');
ctmp2 = strchr(ctmp + 3, '/');
retval = g_strconcat(base_url, in_url, NULL);
goto out;
}
retval = g_strconcat(base_url, in_url, NULL);
goto out;
}
/* XXX TODO - We should really do processing of .. and . in URLs */
/* XXX TODO - We should really do processing of .. and . in URLs */
ctmp = base_url?strstr(base_url, "://"):NULL;
if(!ctmp)
{
char *cwd;
ctmp = base_url?strstr(base_url, "://"):NULL;
if(!ctmp)
{
char *cwd;
cwd = g_get_current_dir();
ctmp = g_strconcat("file://", cwd, "/", in_url, NULL);
g_free(cwd);
cwd = g_get_current_dir();
ctmp = g_strconcat("file://", cwd, "/", in_url, NULL);
g_free(cwd);
retval = ctmp;
goto out;
}
retval = ctmp;
goto out;
}
retval = g_strconcat(base_url, "/", in_url, NULL);
retval = g_strconcat(base_url, "/", in_url, NULL);
out:
/* Now fix up the /. and /.. pieces */
ctmp = strstr(retval, "://");
g_assert(ctmp);
ctmp += 3;
ctmp = strchr(ctmp, '/');
if(!ctmp) {
ctmp = retval;
retval = g_strconcat(retval, "/", NULL);
g_free(ctmp);
return retval;
}
/* Now fix up the /. and /.. pieces */
ctmp = strstr(retval, "://");
g_assert(ctmp);
ctmp += 3;
ctmp = strchr(ctmp, '/');
if(!ctmp) {
ctmp = retval;
retval = g_strconcat(retval, "/", NULL);
g_free(ctmp);
return retval;
}
removebegin = removeend = NULL;
do {
if(removebegin && removeend)
{
memmove(removebegin, removeend, strlen(removeend) + 1);
removebegin = removeend = NULL;
do {
if(removebegin && removeend)
{
memmove(removebegin, removeend, strlen(removeend) + 1);
removebegin = removeend = NULL;
}
curpos = ctmp;
redo:
ctmp2 = strstr(curpos, "/.");
if(!ctmp2)
break;
if(*(ctmp2 + 2) == '.') /* We have to skip over stuff like /...blahblah or /.foo */
{
if(*(ctmp2 + 3) != '/'
&& *(ctmp2 + 3) != '\0')
{
curpos = ctmp2 + 3;
goto redo;
}
}
else if(*(ctmp2 + 2) != '/' && *(ctmp2 + 2) != '\0')
{
curpos = ctmp2 + 2;
goto redo;
}
switch(*(ctmp2+2))
{
case '/':
case '\0':
removebegin = ctmp2;
removeend = ctmp2 + 2;
break;
case '.':
removeend = ctmp2 + 3;
ctmp2--;
while((ctmp2 >= ctmp) && *ctmp2 != '/')
ctmp2--;
if(*ctmp2 == '/')
removebegin = ctmp2;
break;
}
} while(removebegin);
return retval;
}
curpos = ctmp;
redo:
ctmp2 = strstr(curpos, "/.");
if(!ctmp2)
break;
if(*(ctmp2 + 2) == '.') /* We have to skip over stuff like /...blahblah or /.foo */
{
if(*(ctmp2 + 3) != '/'
&& *(ctmp2 + 3) != '\0')
{
curpos = ctmp2 + 3;
goto redo;
}
}
else if(*(ctmp2 + 2) != '/' && *(ctmp2 + 2) != '\0')
{
curpos = ctmp2 + 2;
goto redo;
}
switch(*(ctmp2+2))
{
case '/':
case '\0':
removebegin = ctmp2;
removeend = ctmp2 + 2;
break;
case '.':
removeend = ctmp2 + 3;
ctmp2--;
while((ctmp2 >= ctmp) && *ctmp2 != '/')
ctmp2--;
if(*ctmp2 == '/')
removebegin = ctmp2;
break;
}
} while(removebegin);
return retval;
}
static void
......@@ -236,15 +244,45 @@ do_request_delete(gpointer req)
}
static int
request_terminator (HTRequest * request, HTResponse * response, void * param, int status) {
request_terminator (HTRequest * request, HTResponse * response, void * param, int status)
{
gpointer d;
if (status != HT_LOADED)
g_print("Load couldn't be completed successfully (%p)\n", request);
d = HTRequest_context(request);
g_return_val_if_fail(d, HT_OK);
HTRequest_setContext(request, NULL);
g_idle_add(do_request_delete, request);
return HT_OK;
}
static int
browser_do_post(HTRequest *request, HTStream *stream)
{
BrowserInfo *bi = HTRequest_context(request);
int status;
g_assert(bi);
status = (*stream->isa->put_block)(stream, bi->post_data, strlen(bi->post_data));
g_message("browser_do_post got status %d", status);
switch(status)
{
case HT_LOADED:
case HT_OK:
g_free(bi->post_data); bi->post_data = NULL;
(*stream->isa->flush)(stream);
default:
return status;
break;
}
}
static void
browser_url_requested(GtkWidget *htmlw, const char *url, GtkHTMLStreamHandle handle, BrowserInfo *bi)
......@@ -257,10 +295,14 @@ browser_url_requested(GtkWidget *htmlw, const char *url, GtkHTMLStreamHandle han
request = HTRequest_new();
writer = netin_stream_new(bi, handle);
HTRequest_setContext(request, writer);
HTRequest_setContext(request, bi);
HTRequest_setOutputFormat(request, WWW_SOURCE);
HTRequest_setOutputStream(request, writer);
if(bi->method == METHOD_POST)
HTRequest_setPostCallback(request, browser_do_post);
HTRequest_setAnchor(request, HTAnchor_findAddress(real_url));
HTRequest_setMethod(request, bi->method);
bi->method = METHOD_GET;
if(HTLoad(request, NO) == NO)
{
......@@ -326,6 +368,59 @@ browser_goto_url(GtkWidget *htmlw, const char *url, BrowserInfo *bi)
g_free(real_url);
}
static void
browser_select_url(GtkWidget *htmlw, const char *url, BrowserInfo *bi)
{
Nautilus_SelectionRequestInfo si;
char *real_url = NULL;
memset(&si, 0, sizeof(si));
if(url && !bi->prevsel)
{
si.selected_uris._length = 1;
real_url = canonicalize_url(url, bi->base_target_url);
si.selected_uris._buffer = &real_url;
}
else if(!url && bi->prevsel)
{
si.selected_uris._length = 0;
}
nautilus_view_client_request_selection_change(bi->vc, &si);
g_free(real_url);
bi->prevsel = url?1:0;
}
static void
browser_submit(GtkWidget *htmlw, const char *method, const char *url, const char *encoding, BrowserInfo *bi)
{
g_free(bi->post_data); bi->post_data = NULL;
if(!strcasecmp(method, "POST"))
{
char **pieces = g_strsplit(encoding, "&", -1);
if(pieces)
{
char *ctmp;
ctmp = g_strjoinv("\r\n", pieces);
bi->post_data = g_strconcat(ctmp, "\r\n", NULL);
g_free(ctmp);
g_strfreev(pieces);
bi->method = METHOD_POST;
}
browser_goto_url(htmlw, url, bi);
}
else
{
char tmp_url[4096];
g_snprintf(tmp_url, sizeof(tmp_url), "%s?%s", url, encoding);
browser_goto_url(htmlw, tmp_url, bi);
}
}
static void
browser_notify_location_change(NautilusViewClient *vc, Nautilus_NavigationInfo *ni, BrowserInfo *bi)
{
......@@ -368,6 +463,8 @@ make_obj(GnomeGenericFactory *Factory, const char *goad_id, void *closure)
gtk_signal_connect(GTK_OBJECT(bi->htmlw), "set_base", browser_set_base, bi);
gtk_signal_connect(GTK_OBJECT(bi->htmlw), "set_base_target", browser_set_base_target, bi);
gtk_signal_connect(GTK_OBJECT(bi->htmlw), "url_requested", browser_url_requested, bi);
gtk_signal_connect(GTK_OBJECT(bi->htmlw), "on_url", browser_select_url, bi);
gtk_signal_connect(GTK_OBJECT(bi->htmlw), "submit", browser_submit, bi);
wtmp = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(wtmp), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
......
bin_PROGRAMS=ntl-web-search
INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GNOMEUI_CFLAGS) $(BONOBO_CFLAGS) $(WERROR)
LDADD=$(top_builddir)/libnautilus/libnautilus.la $(BONOBO_LIBS) $(GNOMEUI_LIBS)
ntl_web_search_SOURCES=ntl-web-search.c
goaddir=$(sysconfdir)/CORBA/servers
goad_DATA=ntl-web-search.goad
enginesdir=$(datadir)/ntl-web-search
engines_DATA=standard.eng
EXTRA_DIST=$(goad_DATA) $(engines_DATA)
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* Nautilus
*
* Copyright (C) 1999, 2000 Red Hat, Inc.
*
* This library 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 library 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
* along with this library; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Author: Elliot Lee <sopwith@redhat.com>
*
*/
/* ntl-web-search.c: Rewrite KWebSearch using Gtk+ and Nautilus */
#include "config.h"
#include <libnautilus/libnautilus.h>
#include <limits.h>
#include <ctype.h>
typedef struct {
char *name, *url_head, *url_tail;
} EngineInfo;
typedef struct {
NautilusViewClient *view;
GtkCList *clist;
GtkWidget *btn_search;
GtkWidget *ent_params;
GtkWidget *opt_engine;
GtkWidget *menu_engine;
EngineInfo *last_sel;
GnomeUIHandler *uih;
} WebSearchView;
static int object_count = 0;
static void
web_search_notify_location_change (NautilusViewClient *view,
Nautilus_NavigationInfo *loci,
WebSearchView *hview)
{
}
static void
do_search(GtkWidget *widget, WebSearchView *hview)
{
Nautilus_NavigationRequestInfo nri;
char uri[PATH_MAX], real_query[PATH_MAX], *ctmp;
int i, j;
EngineInfo *ei;
memset(&nri, 0, sizeof(nri));
ctmp = gtk_entry_get_text(GTK_ENTRY(hview->ent_params));
g_return_if_fail(ctmp);
ei = hview->last_sel;
for(i = j = 0; ctmp[i]; i++)
{
if(isalnum(ctmp[i]))
real_query[j++] = ctmp[i];
else
{
char dump[4];
g_snprintf(dump, sizeof(dump), "%%%02x", (guint)ctmp[i]);
real_query[j] = '\0';
strcat(&real_query[j], dump);
j += 3;
}
}
real_query[j] = '\0';
g_snprintf(uri, sizeof(uri), "%s%s%s", ei->url_head?ei->url_head:"", real_query, ei->url_tail?ei->url_tail:"");
nri.requested_uri = uri;
nri.new_window_default = Nautilus_V_FALSE;
nri.new_window_suggested = Nautilus_V_FALSE;
nri.new_window_enforced = Nautilus_V_UNKNOWN;
nautilus_view_client_request_location_change(hview->view, &nri);
}
static void
do_destroy(GtkObject *obj)
{
object_count--;
if(object_count <= 0)
gtk_main_quit();
}
static void
select_item(GtkObject *item, WebSearchView *hview)
{
hview->last_sel = gtk_object_get_data(item, "EngineInfo");
}
static void
web_search_populate_engines(WebSearchView *hview)
{
FILE *fh;
char *fn;
char aline[LINE_MAX];
fn = gnome_datadir_file("ntl-web-search/standard.eng");
g_return_if_fail(fn);
fh = fopen(fn, "r");
g_free(fn);
g_return_if_fail(fh);
while(fgets(aline, sizeof(aline), fh))
{
EngineInfo *ei;
char **pieces;
GtkWidget *w;
g_strstrip(aline);
if(aline[0] == '#' || !aline[0])
continue;
pieces = g_strsplit(aline, "|", 3);
if(!pieces || !pieces[0] || !pieces[1])
{
g_strfreev(pieces);
continue;
}
ei = g_new0(EngineInfo, 1);
ei->name = pieces[0];
ei->url_head = pieces[1];
ei->url_tail = pieces[2];
g_free(pieces);
w = gtk_menu_item_new_with_label(ei->name);
gtk_signal_connect(GTK_OBJECT(w), "activate", select_item, hview);
gtk_object_set_data(GTK_OBJECT(w), "EngineInfo", ei);
gtk_container_add(GTK_CONTAINER(hview->menu_engine), w);
gtk_widget_show(w);
if(!hview->last_sel) {
hview->last_sel = ei;
gtk_option_menu_set_history(GTK_OPTION_MENU(hview->opt_engine), 0);
}
}
}
static GnomeObject *
make_obj(GnomeGenericFactory *Factory, const char *goad_id, gpointer closure)
{
GtkWidget *client, *vbox;
GnomeObject *ctl;
WebSearchView *hview;
g_return_val_if_fail(!strcmp(goad_id, "ntl_websearch_view"), NULL);
hview = g_new0(WebSearchView, 1);
client = gtk_widget_new(nautilus_meta_view_client_get_type(), NULL);
gtk_signal_connect(GTK_OBJECT(client), "destroy", do_destroy, NULL);
object_count++;
ctl = nautilus_view_client_get_gnome_object(NAUTILUS_VIEW_CLIENT(client));
vbox = gtk_vbox_new(FALSE, GNOME_PAD);
gtk_container_add(GTK_CONTAINER(client), vbox);
hview->btn_search = gnome_pixmap_button(gnome_stock_pixmap_widget(client, GNOME_STOCK_PIXMAP_SEARCH), _("Search"));
gnome_button_can_default(GTK_BUTTON(hview->btn_search), TRUE);
gtk_signal_connect(GTK_OBJECT(hview->btn_search), "clicked", do_search, hview);
gtk_box_pack_start(GTK_BOX(vbox), hview->btn_search, FALSE, FALSE, GNOME_PAD);
hview->opt_engine = gtk_option_menu_new();
hview->menu_engine = gtk_menu_new();
gtk_option_menu_set_menu(GTK_OPTION_MENU(hview->opt_engine), hview->menu_engine);
gtk_container_add(GTK_CONTAINER(vbox), hview->opt_engine);
web_search_populate_engines(hview);
hview->ent_params = gtk_entry_new();
gtk_signal_connect(GTK_OBJECT(hview->ent_params), "activate", do_search, hview);
gtk_container_add(GTK_CONTAINER(vbox), hview->ent_params);
#if 0
/* For now we just display the results as HTML */
/* Results list */
col_titles[0] = _("Results");
clist = gtk_clist_new_with_titles(1, col_titles);
gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_BROWSE);
gtk_clist_columns_autosize(GTK_CLIST(clist));
wtmp = gtk_scrolled_window_new(gtk_clist_get_hadjustment(GTK_CLIST(clist)),
gtk_clist_get_vadjustment(GTK_CLIST(clist)));
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(wtmp),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_container_add(GTK_CONTAINER(vbox), wtmp);
gtk_container_add(GTK_CONTAINER(wtmp), clist);
gtk_signal_connect(GTK_OBJECT(clist), "select_row", web_search_select_row, hview);
#endif
gtk_widget_show_all(client);
/* handle events */
gtk_signal_connect(GTK_OBJECT(client), "notify_location_change", web_search_notify_location_change, hview);
/* set description */
nautilus_meta_view_client_set_label(NAUTILUS_META_VIEW_CLIENT(client),
_("WebSearch"));
hview->view = (NautilusViewClient *)client;
hview->clist = NULL;