netsurf/desktop/searchweb.c
John Mark Bell 69f02e926f Make the high-level cache drop contents of unacceptable type on the floor.
svn path=/trunk/netsurf/; revision=10238
2010-04-04 17:17:24 +00:00

302 lines
7.3 KiB
C

/*
* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf 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; version 2 of the License.
*
* NetSurf 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* web search (core)
*/
#include "utils/config.h"
#include <ctype.h>
#include <string.h>
#include "content/content.h"
#include "content/hlcache.h"
#include "desktop/browser.h"
#include "desktop/gui.h"
#include "desktop/options.h"
#include "desktop/searchweb.h"
#include "utils/config.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/url.h"
#include "utils/utils.h"
static struct search_provider {
char *name; /**< readable name such as 'google', 'yahoo', etc */
char *hostname; /**< host address such as www.google.com */
char *searchstring; /** < such as "www.google.com?search=%s" */
char *ico; /** < location of domain's favicon */
} current_search_provider;
static hlcache_handle *search_ico = NULL;
char *search_engines_file_location;
char *search_default_ico_location;
static nserror search_web_ico_callback(hlcache_handle *ico,
const hlcache_event *event, void *pw);
/**
* creates a new browser window according to the search term
* \param searchterm such as "my search term"
*/
bool search_web_new_window(struct browser_window *bw, const char *searchterm)
{
char *encsearchterm;
char *url;
if (url_escape(searchterm,0, true, NULL, &encsearchterm) !=
URL_FUNC_OK)
return false;
url = search_web_get_url(encsearchterm);
free(encsearchterm);
browser_window_create(url, bw, NULL, false, true);
free(url);
return true;
}
/** simplistic way of checking whether an entry from the url bar is an
* url / a search; could be improved to properly test terms
*/
bool search_is_url(const char *url)
{
char *url2, *host;
if (url_normalize(url, &url2) != URL_FUNC_OK)
return false;
if (url_host(url2, &host) != URL_FUNC_OK) {
free(url2);
return false;
}
free(url2);
return true;
}
/**
* caches the details of the current web search provider
* \param reference the enum value of the provider
* browser init code [as well as changing preferences code] should call
* search_web_provider_details(option_search_provider)
*/
void search_web_provider_details(int reference)
{
char buf[300];
int ref = 0;
FILE *f;
if (search_engines_file_location == NULL)
return;
f = fopen(search_engines_file_location, "r");
if (f == NULL)
return;
while (fgets(buf, sizeof(buf), f) != NULL) {
if (buf[0] == '\0')
continue;
buf[strlen(buf)-1] = '\0';
if (ref++ == (int)reference)
break;
}
fclose(f);
if (current_search_provider.name != NULL)
free(current_search_provider.name);
current_search_provider.name = strdup(strtok(buf, "|"));
if (current_search_provider.hostname != NULL)
free(current_search_provider.hostname);
current_search_provider.hostname = strdup(strtok(NULL, "|"));
if (current_search_provider.searchstring != NULL)
free(current_search_provider.searchstring);
current_search_provider.searchstring = strdup(strtok(NULL, "|"));
if (current_search_provider.ico != NULL)
free(current_search_provider.ico);
current_search_provider.ico = strdup(strtok(NULL, "|"));
return;
}
/**
* escapes a search term then creates the appropriate url from it
*/
char *search_web_from_term(const char *searchterm)
{
char *encsearchterm, *url;
if (url_escape(searchterm, 0, true, NULL, &encsearchterm)
!= URL_FUNC_OK)
return strdup(searchterm);
url = search_web_get_url(encsearchterm);
free(encsearchterm);
return url;
}
/** accessor for global search provider name */
char *search_web_provider_name(void)
{
if (current_search_provider.name)
return strdup(current_search_provider.name);
return strdup("google");
}
/** accessor for global search provider hostname */
char *search_web_provider_host(void)
{
if (current_search_provider.hostname)
return strdup(current_search_provider.hostname);
return strdup("www.google.com");
}
/** accessor for global search provider ico name */
char *search_web_ico_name(void)
{
if (current_search_provider.ico)
return strdup(current_search_provider.ico);
return strdup("http://www.google.com/favicon.ico");
}
/**
* creates a full url from an encoded search term
*/
char *search_web_get_url(const char *encsearchterm)
{
char *pref, *ret;
int len;
if (current_search_provider.searchstring)
pref = strdup(current_search_provider.searchstring);
else
pref = strdup("http://www.google.com/search?q=%s");
if (pref == NULL) {
warn_user(messages_get("NoMemory"), 0);
return NULL;
}
len = strlen(encsearchterm) + strlen(pref);
ret = malloc(len -1); /* + '\0' - "%s" */
if (ret == NULL) {
warn_user(messages_get("NoMemory"), 0);
free(pref);
return NULL;
}
snprintf(ret, len-1, pref, encsearchterm);
free(pref);
return ret;
}
/**
* function to retrieve the search web ico, from cache / from local
* filesystem / from the web
* \param localdefault true when there is no appropriate favicon
* update the search_ico cache else delay until fetcher callback
*/
void search_web_retrieve_ico(bool localdefault)
{
static const content_type accept[] = {
#ifdef WITH_BMP
CONTENT_ICO,
#endif
CONTENT_UNKNOWN
};
char *url;
nserror error;
if (localdefault) {
if (search_default_ico_location == NULL)
return;
url = malloc(SLEN("file://") + strlen(
search_default_ico_location) + 1);
if (url == NULL) {
warn_user(messages_get("NoMemory"), 0);
return;
}
strcpy(url, "file://");
strcat(url, search_default_ico_location);
} else {
url = search_web_ico_name();
}
if (url == NULL) {
warn_user(messages_get("NoMemory"), 0);
return;
}
error = hlcache_handle_retrieve(url, 0, NULL, NULL,
search_web_ico_callback, NULL, NULL, accept,
&search_ico);
if (error != NSERROR_OK)
search_ico = NULL;
free(url);
}
/**
* returns a reference to the static global search_ico [ / NULL]
* caller may adjust ico's settings; clearing / free()ing is the core's
* responsibility
*/
hlcache_handle *search_web_ico(void)
{
return search_ico;
}
/**
* callback function to cache ico then notify front when successful
* else retry default from local file system
*/
nserror search_web_ico_callback(hlcache_handle *ico,
const hlcache_event *event, void *pw)
{
switch (event->type) {
case CONTENT_MSG_LOADING:
case CONTENT_MSG_READY:
break;
case CONTENT_MSG_DONE:
LOG(("got favicon '%s'", content_get_url(ico)));
#ifdef WITH_BMP
if (content_get_type(ico) == CONTENT_ICO) {
gui_window_set_search_ico(search_ico);
} else
#endif
{
hlcache_handle_release(ico);
search_ico = NULL;
search_web_retrieve_ico(true);
}
break;
case CONTENT_MSG_ERROR:
LOG(("favicon %s error: %s",
content_get_url(ico), event->data.error));
hlcache_handle_release(search_ico);
search_ico = NULL;
search_web_retrieve_ico(true);
break;
case CONTENT_MSG_STATUS:
break;
default:
assert(0);
}
return NSERROR_OK;
}