Uzbl can be made to use the page's favicon as its window icon using the scripts below. This is convenient for people who use uzbl-browser without tabs.
The Old Version is not working for me, so I have written a new solution based on it. It requires Ruby instead of Python, and consists of 3 files, whose contents are below. You also need to insert this line in uzbl's config file:
@on_event LOAD_COMMIT spawn @scripts_dir/favicon.rb
Put in @scripts_dir (probably ~/.local/share/uzbl/scripts/ on Linux).
#!/usr/bin/env ruby File.open(ARGV[3], 'w') do |fifo| fifo.puts 'set icon = @(wget-cache.rb @<+@scripts_dir/favicon-url.js>@ @uri $XDG_CACHE_HOME/uzbl/favicon/)@' end
Put in @scripts_dir.
(function() {
var icon = 'favicon.ico';
[].slice.call(document.getElementsByTagName('link')).some(function(link) {
return link.attributes.getNamedItem('rel').nodeValue.match(/(^|\s)icon($|\s)/i) &&
(icon = link.attributes.getNamedItem('href').nodeValue);
});
return icon;
})();
Put in $PATH.
#!/usr/bin/env ruby
# Download and cache the file at the given URL, and output the local path of the file.
# Arguments: URL, base URL for resolving a relative URL, cache root path
# (Note: wget provides all the needed functionality, except the local path needs to be grepped
# from its output. If another program or some configuration of wget can output the path directly,
# this script can be replaced.)
require 'open3'
exit unless ARGV.length == 3
uri, base, cache = ARGV[0..2]
Open3.popen3 'wget',
'--timestamping',
'--force-directories',
'--protocol-directories',
"--base=#{base}",
"--directory-prefix=#{cache}",
'--input-file=-' do |stdin, stdout, stderr|
stdin.puts uri
stdin.close
puts stderr.read[/(?:Saving to:|Server file no newer than local file) `([^']+)'/, 1]
end
Get the code: http://gist.github.com/149026
#!/usr/bin/env python
# USAGE
# load_finish_handler should be set to something like:
# spawn $XDG_DATA_HOME/uzbl/scripts/favicon.py
#
# And remember to: mkdir -p $XDG_CACHE_HOME/uzbl/favicon
# BUGS
# The only case not handled satisfactorily is where the icon is unset in the
# config, and the site has no favicon. This means sites with no favicon will
# show the previous site's favicon.
import os, re, socket, sys, urllib2, urlparse
def urid(cache, uri):
'''cache='/root', uri='http://holizz.com/favicon.ico'
=> /root/http/holizz.com/favicon.ico'''
u=urlparse.urlsplit(uri)
p=u.path.split('/')[1:]
return os.path.join(cache, u.scheme, u.netloc, *p)
def socksend(sock, input):
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect(sock)
s.send(input)
output = ''
while '\n' not in output:
output += s.recv(1024)
s.close()
return output
def defaulticon(config):
icon = None
with open(config, 'r') as c:
for line in c.read().split('\n'):
m = re.match(r'^\s*set\s+icon\s*=\s*(.*?)\s*$', line)
if m:
icon = m.group(1)
return icon
if __name__ == '__main__':
config = sys.argv[1]
fifo = sys.argv[4]
sock = sys.argv[5]
uri = sys.argv[6]
if 'XDG_CACHE_HOME' in os.environ.keys() and os.environ['XDG_CACHE_HOME']:
cache_d = os.path.join(os.environ['XDG_CACHE_HOME'],'uzbl/favicon/')
else:
cache_d = os.path.join(os.environ['HOME'],'.cache/uzbl/favicon/')
if not os.path.isdir(cache_d):
os.makedirs(cache_d)
# Check for <link rel=icon>
data = socksend(sock, '''js var m=document.getElementsByTagName('link');for (var n=0;n<m.length;n++){var a=m[n].attributes;if(a.getNamedItem('rel').nodeValue.match(/(^|\s)icon($|\s)/i)){a.getNamedItem('href').nodeValue;break;}}\n''').strip()
favicon_u = None
if data:
favicon_u = urlparse.urljoin(uri, data)
# Check for /favicon.ico
if not favicon_u:
favicon_u = urlparse.urljoin(uri, '/favicon.ico')
if favicon_u == 'file:///favicon.ico' or favicon_u == '/favicon.ico':
favicon_f = None
else:
favicon_f = urid(cache_d, favicon_u)
# Download file if it doesn't exist
if not os.path.isfile(favicon_f):
favicon_d = os.path.join(*os.path.split(favicon_f)[:-1])
try:
input = urllib2.urlopen(favicon_u)
if not os.path.isdir(favicon_d):
os.makedirs(favicon_d)
with open(favicon_f, 'w') as output:
output.write(input.read())
except urllib2.HTTPError:
pass
if not os.path.isfile(favicon_f):
favicon_f = None
# Reset icon if site has no favicon
from_config = False
if not favicon_f:
favicon_f = defaulticon(config)
from_config = True
# Render the icon
if (from_config and favicon_f!=None) or (favicon_f and os.path.isfile(favicon_f)):
open(fifo,'a').write('set icon = %s\n' % favicon_f)
Add “spawn $XDG_CONFIG_HOME/uzbl/scripts/favicon.py” (or whatever) to your load_finish_handler. And mkdir -p $XDG_CACHE_HOME/uzbl/favicon .
The only case not handled satisfactorily is where the icon is unset in the config, and the site has no favicon. This can only be fixed in the source, as variables cannot be assigned a null value (although they can start with one).