#!/usr/bin/perl -w # # # $Id: operahotlist2html,v 2.15 2006/06/07 18:26:13 alanh Exp $ # If this downloaded as the "daily binary" the previous line is inaccurate. # # Copyright (C) 2003 Alan Hoyle # # Converts Opera Hotlist files into HTML. # # This program is a derivitive of: # # hotlist2xbel.pl # Copyright (C) 2001 Haakon Nilsen # # This program 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 program 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # # $Log: operahotlist2html,v $ # Revision 2.15 2006/06/07 18:26:13 alanh # Added #SEPERATOR support # Added Google Analytics support # Added favicon.ico support # # Revision 2.14 2004/02/12 18:40:21 alanh # Bug: Wasn't compatible with Mozilla 1.5 and Firefox 0.8. # Fix: Patch supplied by Gottfried Necker # # Revision 2.13 2003/10/24 20:38:04 alanh # Added "SHORT NAME"/"SHORTCUTURL" conversion to --mozilla # (Thanks to Oliver Fobel) # # Revision 2.12 2003/08/29 18:36:48 alanh # modularized some translations (folderid, URI) # incorporated Rijk van Geijtenbeek 's suggested changes: # # - changed various markup to produce clean HTML 4 strict # - no

elements, but

# - a clumsy attempt to prevent these ID values from starting with anything but a-Z # - no inline styles or deprecated attributes, only class names # - as a result, some extra rules are needed in the CSS file to get a really nice layout # - added a validate CSS button # # - added option 'nodateontop', which prevents the printing of the date stamp on top # # See his hotlist: # http://people.opera.com/rijk/opera/hl/hotlist.html # # Revision 2.11 2003/07/02 21:50:07 alanh # BUGFIX: -x, --exclude-folder work for subfolders! # -x, --exclude-folder now uses a regex! # Changed exclusion of special folders (Trash, Find Results)to use regex. # Deprecated --exclude in favor of --exclude-folder # Removed --delimiter command line option (generates warning) # Added comments to variable names # # Revision 2.10 2003/07/01 14:14:01 alanh # Now includes description field in output (both regular and mozilla) # --descr-sep can modify the description separation HTML (default &mdash) # Changed folder names to not be  's, but the and links use _'s. # Renamed %attrib to %folder in parse_folder. # # Revision 2.9 2003/06/11 15:05:37 alanh # Now works on Windows hotlists without needing things like unix2dos. # Folder names now use _ instead of spaces in the # (makes it possible to link directly to a folder from another place) # # Revision 2.8 2003/06/10 20:10:59 alanh # Changed spaces in folder names/links to  's # # Revision 2.7 2003/04/14 16:03:39 alanh # Version number now in a nicer format, but still autogenerated # Ignore list partially works, but is still buggy (no sub-folders) # Added -v, --version option # Added ability to suppress warning messages (-q, --quiet) # 'Trash' bookmark folder excluded by default (include with --include-extra-folders) # renamed --include-find-results to --include-extra-foldersAdded more comments. # Tested with Opera 7 bookmarks (works!) # Reorganized code (e.g. moved -h code to a better place) # Added more comments. # # Revision 2.6 2003/02/25 13:01:36 alanh # Added ability to include dates into Mozilla hotlists. # Added utf-8 encoding to the html headers # (fixes display on Konquorer, Mozilla, and allows better import into Mozilla) # Removed "Find Results" folder from default output. # (will later expand to have an "Ignore" list) # Added --include-find-results command line option # # Revision 2.5 2003/02/21 16:15:06 alanh # added folder list sorting the default # added --unsort-folder-list command-line option # added and corrected command line help # removed older 1.x log entries # # Revision 2.5 2003/02/21 16:09:21 alanh # added folder list sorting the default # added --unsort-folder-list command-line option # added and corrected command line help # # Revision 2.4 2003/02/21 15:29:09 alanh # Mozilla bookmark file output. # # Revision 2.3 2003/02/20 17:59:18 alanh # renamed without .pl # updated help to be more accurate # # Revision 2.2 2003/02/19 15:44:18 alanh # fixed typographical error in help text # # Revision 2.1 2003/02/19 05:26:06 alanh # New version # added command line options. # unified with myophotlist2html # use Time::Local; use strict; use Getopt::Long; '$Revision: 2.15 $' =~ m/\d+\.\d+/; my $VERSION = $&; # The following $def* variables are used to get around the GetOptions # input. They are used to keep output from being inaccurate if # erroneous options are included with --help my $defhr = '
'; my $defheader ='

My Opera Hotlist

'; my $deftitle = 'My Opera Hotlist'; my $myheader = $defheader; # the

of the HTML output my $mytitle = $deftitle; # the of HTML output my $mystyle = ""; # the Stylesheet to use my $myhr = $defhr; my $infile = 0; # if defined, use as input file my $outfile = 0; # if defined, use this as output file my @folders; # used to generate Folder List my $indent = 1; # the current indention level my $PRINT_THIS = 1; # if 0, don't print the results. Used to supress # output from certain folders. my $HELP = 0; # Switch to display help and then quit. my $DEBUG = 0; # Switch to display debugging output. my $VERBOSE = 0; # Switch to display debugging output. my $DISP_VERSION = 0; # Switch to display version and then quit. my $MOZILLA = 0; # if set, go into Mozilla bookmark file mode my $INCLUDE_EXTRA_FOLDERS = 0; # if set, print the Find Results and Trash folder my $INCLUDE_DATES = 0; # if set, include dates in Mozilla output my $UNSORT_FOLDERS = 0; # if set, don't sort the folder list my $QUIET = 0; # if set, supress warning messages my $SPECIAL_FOLDERS = "\\A(Trash|Find Results)\\Z" ; # Regular expression of special folders to exclude my $EXCLUDE_FOLDERS = "" ; # Regular expression of folders to exclude #my $EXCLUDE_URI = "" ; # Regular expression of URIs to exclude my $DESCR_SEP = " — "; # HTML to separate the link from the description my $NODATEONTOP = 0; # if set, don't print 'Synched ..' line beneath header my $NO_FAVICONS = 0; # if set, don't include favicons my $FAVICON_SIZE = 0; # if set, force height/width of favicons to this my $GOOGLE_ANALYTICS = 0; # if set include google analytics script my $DELIMITER =0; #old, unused, now generates warning message GetOptions ('t|title=s' => \$mytitle, 'd|header=s' => \$myheader, 's|style=s' => \$mystyle, 'r|hr:s' => \$myhr, 'i|input=s' => \$infile, 'o|output=s' => \$outfile, 'x|exclude|exclude-folder=s' => \$EXCLUDE_FOLDERS, 'm|mozilla' => \$MOZILLA, 'descr-sep=s' => \$DESCR_SEP, 'include-dates' => \$INCLUDE_DATES, 'unsort-folder-list' => \$UNSORT_FOLDERS, 'include-extra-folders' => \$INCLUDE_EXTRA_FOLDERS, 'no-favicons' => \$NO_FAVICONS, 'favicon-size:s' => \$FAVICON_SIZE, 'google-analytics' =>\$GOOGLE_ANALYTICS, 'q|quiet' => \$QUIET, 'debug' => \$DEBUG, 'v|version' => \$DISP_VERSION, 'h|help' => \$HELP, 'delimiter:s' => \$DELIMITER, 'n|nodateontop' => \$NODATEONTOP, ); if ($DISP_VERSION){ # Print the version message and exit. print("OperaHotlist2HTMl $VERSION by Alan Hoyle \n", " derived from hotlist2xbel.pl 1.0 by Haakon Nilsen \n" ); exit; } if ($HELP) { # Print the help message and exit. print("OperaHotlist2HTMl $VERSION by Alan Hoyle \n", " derived from hotlist2xbel.pl 1.0 by Haakon Nilsen \n", " Reads Opera Hotlist 2.0 from stdin, writes HTML to stdout.\n", " Use options listed below to personalize the output HTML.\n", "Usage:\n", " operahotlist2html [options] [ < INPUT.adr] [ > OUTPUT.html]\n", # Uncomment the following line to help get the format right for 80 column screens. # "123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-\n", "Options:\n", " -h, --help Print this help message\n", " -q, --quiet Supress warning messages\n", " -v, --version Print version\n", " --debug Print debugging output to STDERR\n", " -i, --input=PATH Use this file as input instead of STDIN\n", " -o, --output=PATH Output to this file instead of STDOUT\n", " -d, --header=STRING Heading at top of page\n", " -t, --title=STRING Title in HTML header\n", " -s, --style=STRING Stylesheet for output HTML\n", " --google-analytics Include Google Analytics script\n", " --descr-sep=STRING HTML to Separate descript from title\n", " -x, --exclude-folder=STRING Regular expression of folders to exclude\n", " e.g. \"\\A(News and Weather|Sports)\\Z\"\n", " --no-favicons Don't include favicons in output.\n", " --favicon-size=STRING Force height, width of favicons.\n", " -m, --mozilla Generate Mozilla/Netscape bookmark file \n", " --include-dates In Mozilla output, include bookmark dates\n", " --unsort-folder-list Print folder list unsorted \n", " --include-extra-folders Include the 'Find Results' and 'Trash' folders\n", " -r, --hr=STRING HTML for a separator instead of $defhr\n", " -n, --nodateontop Print datestamp only at bottom \n", "\n", # Uncomment the following line to help get the format right for 80 column screens. # "123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-\n", "" ); exit; } my $INFILE = *STDIN; my $OUTFILE = *STDOUT; my $ERR = *STDERR; if ($infile) { open ($INFILE, "< $infile") or die "can't open $infile: $!";} if ($outfile) { open ($OUTFILE, "> $outfile") or die "can't open $outfile: $!";} if (!$QUIET) { print $ERR ("Warning: --delimiter command line option isn't valid anymore!\n") if $DELIMITER || ($DELIMITER eq ""); if ($MOZILLA) { print $ERR ("Warning: -m or --mozilla option breaks HTML 4.01 compliance.\n"); if ($UNSORT_FOLDERS) { print $ERR ("Warning: --unsort-folder-list ignored, no folder list with --mozilla\n"); } } else { if ($INCLUDE_DATES) { print $ERR ("Warning: --include-dates only works with -m or --mozilla\n"); } } } # $EXCLUDE_FOLDERS = $mydelim .$EXCLUDE_FOLDERS . $mydelim ; print $ERR ("Excluding folders: <$EXCLUDE_FOLDERS>\n") if $DEBUG; sub get_next_line { if (!eof($INFILE)) { $a = <$INFILE>; $a =~ s/\n//; # Chop didn't work... $a =~ s/\r//; # remove CR: thanks to Mattias Johansson $a =~ s/\t//; return $a; } } sub write_html ($) # writes the parameter to the HTML file { print $OUTFILE (&get_indent ."$_[0]") if $PRINT_THIS; } sub write_html_noformat ($) # writes the parameter to the HTML file { print $OUTFILE ("$_[0]") if $PRINT_THIS; } sub parse { &inc_indent; while (!eof($INFILE)) { my $line = get_next_line; SWITCH: { if ($line eq "#FOLDER") { &parse_folder; last SWITCH; } if ($line eq "#URL") { &parse_url; last SWITCH; } if ($line eq "#SEPERATOR") { &parse_seperator; last SWITCH; } } } &dec_indent; } sub parse_seperator { print STDERR "found seperator\n" if $DEBUG; &write_html("$myhr\n"); my $line = get_next_line; while ($line ne "") { $line = get_next_line; } } sub parse_folder { my ($line, $name, $value); my %folder; $folder{"DESCRIPTION"}=""; $folder{"NAME"}=""; $line = get_next_line; while ($line ne "") { if ($line =~ /=/) { ($name, $value) = split(/=/, $line,2); $folder{$name} = $value; } $line = get_next_line; } if ( ($folder{"NAME"} =~ /$SPECIAL_FOLDERS/ && !$INCLUDE_EXTRA_FOLDERS) || $folder{"NAME"} =~ /$EXCLUDE_FOLDERS/ ) { $PRINT_THIS = 0; print $ERR ("excluding $folder{'NAME'} - PRINT_THIS = $PRINT_THIS\n") if $DEBUG; while ($line ne "-") { $line = get_next_line; SWITCH: { if ($line eq "#FOLDER") { &parse_folder; last SWITCH; } if ($line eq "#URL") { &parse_url; } if ($line eq "#SEPERATOR") { &parse_seperator; } } } $PRINT_THIS = 1; } else { print $ERR ("excluding $folder{'NAME'} - PRINT_THIS = $PRINT_THIS\n") if $DEBUG && !$PRINT_THIS; print $ERR ("including $folder{'NAME'} - PRINT_THIS = $PRINT_THIS\n") if $DEBUG && $PRINT_THIS;; $folder{"NAME"} = &encode_html ($folder{"NAME"}); my $folderid = &encode_folderid($folder{"NAME"}); push @folders, $folder{"NAME"} if $PRINT_THIS; if (!$MOZILLA) { &write_html("
  • "); &write_html_noformat("

    " .$folder{"NAME"} ); if ($folder{"DESCRIPTION"}) { &write_html_noformat($DESCR_SEP ."".$folder{"DESCRIPTION"}. "");} &write_html_noformat("

    \n"); &write_html("
      \n"); } else { if (!$INCLUDE_DATES) { &write_html("

      " .$folder{"NAME"} ."

      \n"); &write_html("
      ".$folder{"DESCRIPTION"}."
      \n"); &write_html("

      \n"); } else { &write_html("

      " .$folder{"NAME"} ."

      \n"); &write_html("
      ".$folder{"DESCRIPTION"}."
      \n"); &write_html("

      \n"); } } &inc_indent; my $has_entries = 0; while ($line ne "-") { $line = get_next_line; SWITCH: { if ($line eq "#FOLDER") { &parse_folder; $has_entries = 1; last SWITCH; } if ($line eq "#URL") { &parse_url; $has_entries = 1; } if ($line eq "#SEPERATOR") { &parse_seperator; } } } if ($has_entries == 0) { if (!$MOZILLA) { &write_html ("

    •  
    • \n"); } else { &write_html ("
       
      \n"); } } &dec_indent; if (!$MOZILLA) { &write_html("
    \n"); } else { &write_html("

    \n"); } } # from the Extra Folders if...else } sub ico_to_uri ($) { my $input = shift; $input =~ s/\....\Z//; return "http://$input/favicon.ico"; } sub parse_url { my (%bookmark, $line, $name, $value); $line = get_next_line; $bookmark{"DESCRIPTION"}=""; $bookmark{"URL"}=""; $bookmark{"NAME"}=""; $bookmark{"ICONFILE"}=""; $bookmark{"CREATED"}=""; $bookmark{""}=""; # if ($bookmark {"URL"} =~ /$EXCLUDE_URI/ && $PRINT_THIS) { # $PRINT_THIS = 0;} while ($line ne "") { if ($line =~ /=/) { ($name, $value) = split(/=/, $line,2); $bookmark{$name} = $value; } $line = get_next_line; } $bookmark{"NAME"} = &encode_html ($bookmark{"NAME"}); $bookmark{"URL"} = &encode_html ($bookmark{"URL"}); if (!$MOZILLA) { &write_html("

  • "); if (!$NO_FAVICONS &&$bookmark{"ICONFILE"}) { &write_html_noformat ("\"\""); "); } &write_html_noformat ($bookmark{"NAME"} ."\n"); &write_html ($DESCR_SEP ."".$bookmark{"DESCRIPTION"}."\n") if ($bookmark{"DESCRIPTION"}); &write_html("
  • \n"); } else { # i.e. MOZILLA output.... &write_html("
    ". $bookmark{"NAME"} ."
    \n"); &write_html("
    ".$bookmark{"DESCRIPTION"}."
    \n") if $bookmark{"DESCRIPTION"}; } } sub encode_html ($) { my $name = shift; $name =~ s/\&\;/\&/g; $name =~ s/\>\;/\>/g; $name =~ s/\<\;/\/\>\;/g; $name =~ s/\\n"); } else { &write_html ("\n"); &write_html ("\n"); &write_html ("\n"); &write_html ("Bookmarks\n"); &write_html ("

    Bookmarks

    \n"); } &write_html("\n"); &inc_indent; if (!$MOZILLA) { &write_html("\n"); &inc_indent; &write_html("$mytitle\n"); if ($mystyle ne "") { &write_html("\n"); } &write_html("\n"); &write_html("\n\n") if $GOOGLE_ANALYTICS; &dec_indent; &write_html("\n"); } &write_html("\n"); &inc_indent; &write_html("$myheader\n") if (!$MOZILLA); my $time = scalar localtime; if (!$NODATEONTOP) { write_html("

    Synced with Opera Hotlist at: " .$time .".

    \n") if (!$MOZILLA); } if (!$MOZILLA) { &write_html("

    Folder list

    \n") if (!$MOZILLA); &write_html("$myhr\n"); } if (!$MOZILLA) { &write_html("
      \n");} else { &write_html("

      \n");} &parse; if (!$MOZILLA) { &write_html("

    \n");} else { &write_html("

    \n");} if (!$MOZILLA) { &write_html("$myhr\n"); &write_html("

    Folder list:

    \n"); &write_html("

    \n"); if (!$UNSORT_FOLDERS) { @folders = sort { (lc$a) cmp lc($b) } @folders; } foreach my $folder (@folders){ my $folderid = &encode_folderid($folder); &write_html("[$folder]\n"); } &write_html("

    "); } &write_html("$myhr"); if (!$MOZILLA) { &write_html("
    \n"); &inc_indent; &write_html("\"Valid\n"); if ($mystyle ne "") { &write_html("\n"); } &dec_indent; &write_html("
    "); } &write_html("

    Synced with Opera Hotlist at: " .$time .".
    \n"); &write_html("Generated with OperaHotlist2html $VERSION

    \n"); &dec_indent; &write_html("\n"); &dec_indent; &write_html("\n"); } exit;