#!/usr/bin/perl -w use strict; use HTTP::Cookies; use Getopt::Long; use File::Spec; # default values our %CONF = ( config => "$ENV{HOME}/.mergecookiesrc", verbose => 0 ); our %files; our $VERSION = '0.03'; # command-line options GetOptions( \%CONF, "verbose=+", "config=s" ); # read the config file @ARGV = ( $CONF{config} ); while (<>) { next if /^\s*(?:#|$)/; # ignore comments and white lines chomp; my ( $module, $file ) = split ( /\s+/, $_, 2 ); $module = $module eq 'LWP' ? 'HTTP::Cookies' : "HTTP::Cookies::$module"; $file = File::Spec->catfile( $ENV{HOME}, $file ) unless File::Spec->file_name_is_absolute($file); # portable # load the appropriate module eval "require $module;"; warn "Unable to load $module, skipping $file\n" and next if $@; warn "$file does not exist, skipping\n" and next unless -e $file; $files{$file} = $module->new( file => $file, ignore_discard => 1 ); } # merge all cookies in a single cookie jar my $cookie_jar = HTTP::Cookies->new( ignore_discard => 1 ); for my $cj ( values %files ) { $cj->scan( sub { my ( $version, $key, $val, $path, $domain, $port, $path_spec, $secure, $expires, $discard, $rest ) = @_; # check if we already have a cookie with the same name my $array = $cookie_jar->{COOKIES}{$domain}{$path}{$key}; # keep the cookie that expires last my $maxage = defined $expires ? $expires - time : undef; print STDERR "Saving $domain $path $key" if $CONF{verbose}; $cookie_jar->set_cookie( $version, $key, $val, $path, $domain, $port, $path_spec, $secure, $maxage, $discard, $rest ) unless defined $array and defined $expires and $array->[5] > $expires; } ); } # save the whole list of cookies back in each file for my $file ( keys %files ) { my $class = ref $files{$file}; no strict 'refs'; &{"${class}::save"}( $cookie_jar, $file ); } __END__ =head1 NAME mergecookies - Merge all your cookies for all of your browsers =head1 SYNOPSIS B S<[ B<--config> I ]> S<[ B<--verbose> ]> =head1 DESCRIPTION B reads all your cookie files for which a HTTP::Cookies module exists and is installed, merges all the cookies (if two identical cookies (same name, same domain) are found, the one that expires the later is kept) and saves them back in each cookie file. This way you can share your cookies between all your browsers. The configuration file looks like the following: # filenames are relative to $ENV{HOME} or absolute Netscape .netscape/cookies Mozilla .mozilla/book/kdtqv86o.slt/cookies.txt Mozilla .phoenix/default/bt7ivopl.slt/cookies.txt # file in the HTTP::Cookies format LWP /tmp/lwp-cookies.txt # there is no HTTP::Cookies::Opera for now :-( #Opera /home/book/.opera/cookies4.dat Each line holds the name of the HTTP::Cookies module (Mozilla for HTTP::Cookies::Mozilla and so on) used to read the cookie file and the path of the file (absolute or relative to $ENV{HOME}). Cookies saved with HTTP::Cookies require the C keyword. =head1 COMMAND-LINE OPTIONS B accepts the following command-line options: =over 4 =item B<--config> I Read an alternate configuration file. =item B<--verbose> Print the list of cookies handled by the script. =back =head1 AUTHOR Philippe "BooK" Bruhat Ebook@cpan.orgE This script was created as an example of use for the HTTP::Cookies modules. Version 0.01 appeared in GNU/Linux Magazine France 57 (in French). =head1 COPYRIGHT This module is free software; you can redistribute it or modify it under the same terms as Perl itself. =cut