#!/usr/bin/perl # Filename: ? # Author: David Ljung Madison # See License: http://MarginalHacks.com/License # Description: Reads in netscape bookmark files use strict; ################################################## # Setup the variables ################################################## my $PROGNAME = $0; $PROGNAME =~ s|.*/||; my $UMASK = 0755; my $NETSCAPE = "netscape"; my $ICON = ""; my $ICON_FOLDER = "gnome-folder.png"; my @IGNORE = ("Personal Toolbar Folder"); ################################################## # Usage ################################################## sub usage { my $msg; foreach $msg (@_) { print "ERROR: $msg\n"; } print "\n"; print "Usage:\t$PROGNAME [-d] \n"; print "\tParses a netscape bookmark file\n"; print "\t-d\tSet debug mode\n"; print "\t-rev\tWrite bookmarks in reverse order\n"; print "\n"; exit -1; } sub parse_args { my $file; my $arg; while ($#ARGV>=0) { $arg=shift(@ARGV); if ($arg =~ /^-h$/) { usage(); } if ($arg =~ /^-d$/) { $MAIN::DEBUG=1; next; } if ($arg =~ /^-rev(erse)?$/) { $MAIN::REVERSE=1; next; } if ($arg =~ /^-/) { usage("Unknown option: $arg"); } usage("Too many files specified [$arg and $file]") if (defined($file)); $file=$arg; } usage("No file defined") if (!defined($file)); $file; } sub ignore { my ($name) = @_; my $ignore; foreach $ignore ( @IGNORE ) { return 1 if ($name =~ /$ignore/); } 0; } sub parse_netscape { my ($file) = @_; # Open the file and prep it open(FILE,$file) || usage("Couldn't open file: $file"); # Read up to the first
tag while() { last if (/
/i); } my %bm; # Bookmark data structure my $bm_H = \%bm; # The pointer $bm_H->{'parent'}=$bm_H; # Parse the bookmarks while() { # Start a list (should always follow

folder..) next if (/
/i); # We actually just ignore these # Bookmark if (/
(.*)<\/a>/i) { my $next = $MAIN::REVERSE ? 0 : ($#{$bm_H->{'bookmarks_L'}}+1); unshift(@{$bm_H->{'bookmarks_L'}},undef) unless ($next); $bm_H->{'bookmarks_L'}[$next]{'href'}=$1; $bm_H->{'bookmarks_L'}[$next]{'add_date'}=$2; $bm_H->{'bookmarks_L'}[$next]{'last_visit'}=$3; $bm_H->{'bookmarks_L'}[$next]{'last_modified'}=$4; $bm_H->{'bookmarks_L'}[$next]{'name'}=$5; # Bookmark description } elsif (/
(.*)/i) { next unless $1; my $current = $MAIN::REVERSE ? 0 : $#{$bm_H->{'bookmarks_L'}}; $bm_H->{'bookmarks_L'}[$current]{'comment'}=$1 if ($current>=0); # Folder } elsif (/

(.*)<\/h3>/i) { my ($name,$add_date,$folded) = ($3, $2, $1 ? 1 : 0); if (ignore($name)) { while() { last if (/<\/dl>/i); } next; } my $next = $MAIN::REVERSE ? 0 : ($#{$bm_H->{'bookmarks_L'}}+1); unshift(@{$bm_H->{'bookmarks_L'}},undef) unless ($next); $bm_H->{'bookmarks_L'}[$next]{'name'}=$name; $bm_H->{'bookmarks_L'}[$next]{'add_date'}=$add_date; $bm_H->{'bookmarks_L'}[$next]{'folded'}=$folded; $bm_H->{'bookmarks_L'}[$next]{'folder'}{'parent'}=$bm_H; $bm_H=$bm_H->{'bookmarks_L'}[$next]{'folder'}; # End folder } elsif (/<\/dl>/i) { $bm_H=$bm_H->{'parent'}; # More of a comment } else { my $current = $MAIN::REVERSE ? 0 : $#{$bm_H->{'bookmarks_L'}}; if ($bm_H->{'bookmarks_L'}[$current]{'comment'} =~ /
$/i) { $bm_H->{'bookmarks_L'}[$current]{'comment'}="$`\n$_"; } else { print STDERR "Can't parse [$.]: $_\n"; } } } close(FILE); \%bm; } # Make a name safe for the filesystem sub safe_name { my ($name) = @_; $name =~ s|/|\\|g; # Take '/' out of directory names $name =~ s|/^./|dot|; # Don't hide directories $name = "noname" unless ($name); return $name unless (-r $name); my $count=1; while (1) { $count++; return "$name.$count" unless (-r $name); } } sub print_kde { my ($bm_H, $name) = @_; mkdir($name,$UMASK) || die("[$PROGNAME] Couldn't make directory [$name]\n"); chdir($name); open(DIRECTORY,">.directory") || die("[$PROGNAME] Couldn't write [.directory]\n"); print DIRECTORY "# KDE Config File [written by $PROGNAME]\n"; print DIRECTORY "[Desktop Entry]\n"; print DIRECTORY "Icon=$ICON_FOLDER\n"; print DIRECTORY "Name=$name\n"; print DIRECTORY "Type=Directory\n"; # Rats. We don't have this data anymore #$bm_H->{'bookmarks_L'}[$next]{'folded'}=$1 ? 1 : 0; #$bm_H->{'bookmarks_L'}[$next]{'add_date'}=$2; #$bm_H->{'bookmarks_L'}[$next]{'name'}=$3; close(DIRECTORY); my $entry_H; my @order; foreach $entry_H ( @{$bm_H->{'bookmarks_L'}} ) { if ($entry_H->{'folder'}) { my $name = safe_name($entry_H->{'name'}); push(@order,$name); print_kde($entry_H->{'folder'}, $name); chdir(".."); } else { my $file = safe_name($entry_H->{'name'}) . ".desktop"; push(@order,$file); open(ENTRY, ">$file") || die("[$PROGNAME] Couldn't write [$file]\n");; print ENTRY "[Desktop Entry]\n"; print ENTRY "Name=$entry_H->{'name'}\n"; my $comment = $entry_H->{'comment'} || $entry_H->{'name'}; print ENTRY "Comment=$comment\n"; print ENTRY "Exec=$NETSCAPE $entry_H->{'href'}\n"; print ENTRY "Icon=$ICON\n"; print ENTRY "Terminal=0\n"; print ENTRY "Type=Application\n"; print ENTRY "Add_Date=$entry_H->{'add_date'}\n"; print ENTRY "Last_Visit=$entry_H->{'last_visit'}\n"; print ENTRY "Last_Modified=$entry_H->{'last_modified'}\n"; close(ENTRY); } } open(ORDER,">.order") || die("[$PROGNAME] Couldn't write [.order]\n"); print ORDER join("\n",@order); close(ORDER); } sub print_bm { my ($bm_H, $lvl) = @_; my $entry_H; foreach $entry_H ( @{$bm_H->{'bookmarks_L'}} ) { if ($entry_H->{'folder'}) { print "\n"; print " "x($lvl+2), "$entry_H->{'name'}\n"; print " "x($lvl+2), "-"x(length($entry_H->{'name'})), "\n"; print_bm($entry_H->{'folder'}, $lvl+2); print "\n"; } else { #print " "x$lvl, "$entry_H->{'name'} -> $entry_H->{'href'}\n"; print " "x$lvl, "$entry_H->{'name'}\n"; } } } ################################################## # Main code ################################################## sub main { my $file = parse_args(); my $bm_H=parse_netscape($file); print_kde($bm_H, "bookmarks"); #print_bm($bm_H); } main();