File Coverage

script/bookmarks
Criterion Covered Total %
statement 67 280 23.9
branch 18 152 11.8
condition 13 57 22.8
subroutine 12 41 29.2
pod n/a
total 110 530 20.7


line stmt bran cond sub pod time code
1             #!/usr/bin/env perl
2             #
3             # bookmarks - Export bookmarks from browsers and files
4             #
5             # Documentation at bottom of script.
6             #
7             # Implementation Notes :
8             #
9             # - For Safari, this tool relies on dirty plist parsing using Apple's 'plutil'
10             # command. It should use Mac::PropertyList instead. For performance reasons
11             # when used interactively, I've decided to keep it like that (see README.md).
12             # - Since Firefox sets an EXCLUSIVE SQLite lock, a tmp DB file copy is used.
13             # - sources are read as UTF-8.
14             #
15             # 2025.01.01 v0.35 jul : use 5.014
16             # fixed exit status
17             # added CSV and HTML output format
18             # 2024.03.09 v0.34 jul : added support for netscape
19             # 2022.12.22 v0.33 jul : fixed utf8 in stdout and firefox
20             # fixed bug in POD (wrong repo URL)
21             # doc arg "-" stdin as txt
22             # 2022.01.10 v0.32 jul : fixed bug in txt files regex (space)
23             # fixed bug with option -a (files not existing silently dropped)
24             # added support for arg '-' (read from STDIN as plain text file)
25             # 2021.03.30 v0.31 jul : skip gemini.t if URI::Find not installed
26             # 2021.03.29 v0.30 jul : added great markdown regex by Michaël Perrin
27             # process files without extension as plain text
28             # fixed extra spaces printed after empty fields
29             # added gemini support
30             # 2021.02.17 v0.28 jul : fixed missing require DBD::SQLite (firefox)
31             # 2021.02.16 v0.27 jul : added win32 Edge support, fixed Chrome bug (localappdata), fixed win32 bug (find), more tests (firefox)
32             # 2021.01.31 v0.26 jul : improved handling of optional dependencies
33             # 2021.01.31 v0.25 jul : skip bookmarks.t if URI::Find not installed
34             # 2021.01.31 v0.24 jul : fixed missing prereq URI::Find in Makefile.PL
35             # 2021.01.23 v0.23 jul : added tests and fixed firefox default location
36             # 2021.01.20 v0.22 jul : fixed firefox query again
37             # 2020.06.29 v0.21 jul : added markdown and text files support
38             # 2020.03.10 v0.20 jul : fixed EXCLUSIVE SQLite lock set by Firefox
39             # 2019.12.22 v0.19 jul : added chrome support, require, bugfixes
40             # 2019.10.22 v0.17 jul : created module
41             # 2019.10.17 v0.16 jul : fixed firefox tags
42             # 2019.09.27 v0.15 jul : added internet explorer support, fixed firefox tags
43             # 2019.08.13 v0.14 jul : added firefox support, output format
44             # 2019.07.11 v0.13 jul : use 5.010, better doc
45             # 2019.01.14 v0.12 jul : fixed case sensitive regex
46             # 2018.09.21 v0.11 jul : added arg and -a
47             # 2018.09.01 v0.10 jul : created
48              
49 1     1   5933 use 5.014;
  1         4  
50 1     1   6 use strict;
  1         2  
  1         44  
51 1     1   5 use warnings;
  1         2  
  1         60  
52 1     1   690 use utf8;
  1         359  
  1         7  
53 1     1   710 use Getopt::Std;
  1         3350  
  1         88  
54 1     1   9 use File::Basename;
  1         1  
  1         119  
55 1     1   1149 use File::Temp qw(tempdir);
  1         27722  
  1         63  
56 1     1   423 use File::Copy qw(copy);
  1         4813  
  1         63  
57 1     1   747 use open qw(:std :encoding(UTF-8));
  1         1000  
  1         7  
58 1     1   19795 use Encode qw(decode_utf8);
  1         3  
  1         78050  
59              
60 1         60891 our $VERSION = '0.35';
61 1         51 my $program = basename($0);
62 1         3 my $usage = <
63              
64             Usage: $program [-hVdas] [-f format] [file ...]
65              
66             -h, --help help
67             -V, --version version
68             -d debug (sent to STDERR)
69             -a all : process arguments and default locations
70             -f format export format : csv, csv-noheader, html, html-raw,
71             or any combination of characters t,u,d as
72             <url> <description> (default : tud) </td> </tr> <tr> <td class="h" > <a name="73">73</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> -s find schemeless URLs in text files (default : no) </td> </tr> <tr> <td class="h" > <a name="74">74</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="75">75</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> See `perldoc $program` for full documentation. </td> </tr> <tr> <td class="h" > <a name="76">76</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> EOF </td> </tr> <tr> <td class="h" > <a name="77">77</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="78">78</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # options </td> </tr> <tr> <td class="h" > <a name="79">79</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="80">80</a> </td> <td class="c3" > 1 </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 2 </td> <td class="s"> my %options = (); </td> </tr> <tr> <td class="h" > <a name="81">81</a> </td> <td class="c3" > 1 </td> <td class="c0" > <a href="script-bookmarks--branch.html#81-1"> 50 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 5 </td> <td class="s"> getopts("hVdaf:s", \%options) or die $usage; </td> </tr> <tr> <td class="h" > <a name="82">82</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="83">83</a> </td> <td class="c3" > 1 </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--condition.html#83-1"> 50 </a> </td> <td >   </td> <td >   </td> <td > 27 </td> <td class="s"> my $help = $options{h} // 0; </td> </tr> <tr> <td class="h" > <a name="84">84</a> </td> <td class="c3" > 1 </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--condition.html#84-1"> 50 </a> </td> <td >   </td> <td >   </td> <td > 3 </td> <td class="s"> my $version = $options{V} // 0; </td> </tr> <tr> <td class="h" > <a name="85">85</a> </td> <td class="c3" > 1 </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--condition.html#85-1"> 50 </a> </td> <td >   </td> <td >   </td> <td > 4 </td> <td class="s"> my $debug = $options{d} // 0; </td> </tr> <tr> <td class="h" > <a name="86">86</a> </td> <td class="c3" > 1 </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--condition.html#86-1"> 50 </a> </td> <td >   </td> <td >   </td> <td > 3 </td> <td class="s"> my $all = $options{a} // 0; </td> </tr> <tr> <td class="h" > <a name="87">87</a> </td> <td class="c3" > 1 </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--condition.html#87-1"> 50 </a> </td> <td >   </td> <td >   </td> <td > 4 </td> <td class="s"> my $format = $options{f} // "tud"; </td> </tr> <tr> <td class="h" > <a name="88">88</a> </td> <td class="c3" > 1 </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--condition.html#88-1"> 50 </a> </td> <td >   </td> <td >   </td> <td > 3 </td> <td class="s"> my $schemeless = $options{s} // 0; </td> </tr> <tr> <td class="h" > <a name="89">89</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="90">90</a> </td> <td class="c3" > 1 </td> <td class="c0" > <a href="script-bookmarks--branch.html#90-1"> 50 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 2 </td> <td class="s"> die $usage if $help; </td> </tr> <tr> <td class="h" > <a name="91">91</a> </td> <td class="c3" > 1 </td> <td class="c0" > <a href="script-bookmarks--branch.html#91-1"> 50 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 8 </td> <td class="s"> die $VERSION . "\n" if $version; </td> </tr> <tr> <td class="h" > <a name="92">92</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="93">93</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # option -a </td> </tr> <tr> <td class="h" > <a name="94">94</a> </td> <td class="c3" > 1 </td> <td class="c0" > <a href="script-bookmarks--branch.html#94-1"> 50 </a> </td> <td class="c0" > <a href="script-bookmarks--condition.html#94-1"> 33 </a> </td> <td >   </td> <td >   </td> <td > 5 </td> <td class="s"> if (!@ARGV or $all) </td> </tr> <tr> <td class="h" > <a name="95">95</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="96">96</a> </td> <td class="c0" > <a href="#98"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my @default = (); </td> </tr> <tr> <td class="h" > <a name="97">97</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> </td> </tr> <tr> <td class="h" > <a name="98">98</a> </td> <td class="c0" > <a href="#100"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#98-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> if ($^O eq "darwin") </td> </tr> <tr> <td class="h" > <a > </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--branch.html#-2"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a > </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--branch.html#-3"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="99">99</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="100">100</a> </td> <td class="c0" > <a href="#101"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> push @default, glob('~/Library/Safari/Bookmarks.plist'); </td> </tr> <tr> <td class="h" > <a name="101">101</a> </td> <td class="c0" > <a href="#102"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> push @default, glob('~/Library/Application\ Support/Firefox/Profiles/*.default*/places.sqlite'); </td> </tr> <tr> <td class="h" > <a name="102">102</a> </td> <td class="c0" > <a href="#106"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> push @default, glob('~/Library/Application\ Support/Google/Chrome/Default/Bookmarks'); </td> </tr> <tr> <td class="h" > <a name="103">103</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="104">104</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> elsif ($^O eq "linux") </td> </tr> <tr> <td class="h" > <a name="105">105</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="106">106</a> </td> <td class="c0" > <a href="#107"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> push @default, glob('~/.mozilla/firefox/*.default/places.sqlite'); </td> </tr> <tr> <td class="h" > <a name="107">107</a> </td> <td class="c0" > <a href="#111"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> push @default, glob('~/.config/google-chrome/Default/Bookmarks'); </td> </tr> <tr> <td class="h" > <a name="108">108</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="109">109</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> elsif ($^O eq "MSWin32") </td> </tr> <tr> <td class="h" > <a name="110">110</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="111">111</a> </td> <td class="c0" > <a href="#112"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> push @default, $ENV{APPDATA} . '\Mozilla\Firefox\Profiles\*.default\places.sqlite'; </td> </tr> <tr> <td class="h" > <a name="112">112</a> </td> <td class="c0" > <a href="#113"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> push @default, $ENV{LOCALAPPDATA} . '\Google\Chrome\User Data\Default\Bookmarks'; </td> </tr> <tr> <td class="h" > <a name="113">113</a> </td> <td class="c0" > <a href="#114"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> push @default, $ENV{USERPROFILE} . '\Favorites'; </td> </tr> <tr> <td class="h" > <a name="114">114</a> </td> <td class="c0" > <a href="#118"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> push @default, $ENV{LOCALAPPDATA} . '\Microsoft\Edge\User Data\Default\Bookmarks'; </td> </tr> <tr> <td class="h" > <a name="115">115</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="116">116</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> else </td> </tr> <tr> <td class="h" > <a name="117">117</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="118">118</a> </td> <td class="c0" > <a href="#122"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> die "unknown os, unable to set default files"; </td> </tr> <tr> <td class="h" > <a name="119">119</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="120">120</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> </td> </tr> <tr> <td class="h" > <a name="121">121</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # do they indeed exist? </td> </tr> <tr> <td class="h" > <a name="122">122</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> @default = grep { -e $_ } @default; </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#124"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="123">123</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> </td> </tr> <tr> <td class="h" > <a name="124">124</a> </td> <td class="c0" > <a href="#129"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> push @ARGV, @default; </td> </tr> <tr> <td class="h" > <a name="125">125</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="126">126</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="127">127</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # option -f </td> </tr> <tr> <td class="h" > <a name="128">128</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my %dispatch = ( </td> </tr> <tr> <td class="h" > <a name="129">129</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#129-1"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#129-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> 't' => sub { my ($t,$u,$d) = @_; say join ' ', grep {defined $_ and length $_} ($t); }, </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#130"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="130">130</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#130-1"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#130-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> 'tu' => sub { my ($t,$u,$d) = @_; say join ' ', grep {defined $_ and length $_} ($t,$u); }, </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#132"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="131">131</a> </td> <td class="c3" > 1 </td> <td class="c0" > <a href="script-bookmarks--branch.html#131-1"> 50 </a> </td> <td >   </td> <td class="c3" > <a href="script-bookmarks--subroutine.html#131-1"> 1 </a> </td> <td >   </td> <td > 2 </td> <td class="s"> 'tud' => sub { my ($t,$u,$d) = @_; say join ' ', grep {defined $_ and length $_} ($t,$u,$d); }, </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c3" > 1 </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 3 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c3" > 3 </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 60 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="132">132</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#132-1"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#132-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> 'tdu' => sub { my ($t,$u,$d) = @_; say join ' ', grep {defined $_ and length $_} ($t,$d,$u); }, </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#133"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="133">133</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#133-1"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#133-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> 'td' => sub { my ($t,$u,$d) = @_; say join ' ', grep {defined $_ and length $_} ($t,$d); }, </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#134"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="134">134</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#134-1"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#134-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> 'u' => sub { my ($t,$u,$d) = @_; say join ' ', grep {defined $_ and length $_} ($u); }, </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#135"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="135">135</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#135-1"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#135-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> 'ud' => sub { my ($t,$u,$d) = @_; say join ' ', grep {defined $_ and length $_} ($u,$d); }, </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#136"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="136">136</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#136-1"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#136-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> 'udt' => sub { my ($t,$u,$d) = @_; say join ' ', grep {defined $_ and length $_} ($u,$d,$t); }, </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#137"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="137">137</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#137-1"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#137-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> 'utd' => sub { my ($t,$u,$d) = @_; say join ' ', grep {defined $_ and length $_} ($u,$t,$d); }, </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#138"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="138">138</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#138-1"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#138-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> 'ut' => sub { my ($t,$u,$d) = @_; say join ' ', grep {defined $_ and length $_} ($u,$t); }, </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#139"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="139">139</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#139-1"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#139-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> 'd' => sub { my ($t,$u,$d) = @_; say join ' ', grep {defined $_ and length $_} ($d); }, </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#140"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="140">140</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#140-1"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#140-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> 'du' => sub { my ($t,$u,$d) = @_; say join ' ', grep {defined $_ and length $_} ($d,$u); }, </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#141"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="141">141</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#141-1"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#141-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> 'dut' => sub { my ($t,$u,$d) = @_; say join ' ', grep {defined $_ and length $_} ($d,$u,$t); }, </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#142"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="142">142</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#142-1"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#142-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> 'dtu' => sub { my ($t,$u,$d) = @_; say join ' ', grep {defined $_ and length $_} ($d,$t,$u); }, </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#143"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="143">143</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#143-1"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#143-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> 'dt' => sub { my ($t,$u,$d) = @_; say join ' ', grep {defined $_ and length $_} ($d,$t); }, </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#144"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="144">144</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#144-1"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#144-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> 'csv' => sub { my ($t,$u,$d) = @_; say '"' . join ('","', map { defined $_ and length $_ ? s/"/""/gr : "" } @_) . '"' . "\r"; }, </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#-2"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#145"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="145">145</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#145-1"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#145-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> 'csv-noheader' => sub { my ($t,$u,$d) = @_; say '"' . join ('","', map { defined $_ and length $_ ? s/"/""/gr : "" } @_) . '"' . "\r"; }, </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#-2"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#146"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="146">146</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#146-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> 'html' => sub { my ($t,$u,$d) = @_; say ' <DT><A HREF="' . $u . '">' . $t . '</A>'; }, </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#147"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="147">147</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#147-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> 'html-raw' => sub { my ($t,$u,$d) = @_; say '<A HREF="' . $u . '">' . $t . '</A>'; }, </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#159"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="148">148</a> </td> <td class="c3" > 1 </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 82 </td> <td class="s"> ); </td> </tr> <tr> <td class="h" > <a name="149">149</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="150">150</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # printer function </td> </tr> <tr> <td class="h" > <a name="151">151</a> </td> <td class="c3" > 1 </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 2 </td> <td class="s"> my $print_bookmark; </td> </tr> <tr> <td class="h" > <a name="152">152</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="153">153</a> </td> <td class="c3" > 1 </td> <td class="c0" > <a href="script-bookmarks--branch.html#153-1"> 50 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 4 </td> <td class="s"> if ($dispatch{$format}) </td> </tr> <tr> <td class="h" > <a name="154">154</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="155">155</a> </td> <td class="c3" > 1 </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 2 </td> <td class="s"> $print_bookmark = $dispatch{$format}; </td> </tr> <tr> <td class="h" > <a name="156">156</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="157">157</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> else </td> </tr> <tr> <td class="h" > <a name="158">158</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="159">159</a> </td> <td class="c0" > <a href="#169"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> die "unknown format"; </td> </tr> <tr> <td class="h" > <a name="160">160</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="161">161</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="162">162</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="163">163</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ############### </td> </tr> <tr> <td class="h" > <a name="164">164</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # SUBROUTINES # </td> </tr> <tr> <td class="h" > <a name="165">165</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ############### </td> </tr> <tr> <td class="h" > <a name="166">166</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="167">167</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sub _safari { </td> </tr> <tr> <td class="h" > <a name="168">168</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="169">169</a> </td> <td class="c0" > <a href="#170"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--condition.html#169-1"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#169-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> my $plist = shift // ""; </td> </tr> <tr> <td class="h" > <a name="170">170</a> </td> <td class="c0" > <a href="#173"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#170-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> warn "\$plist: $plist\n" if $debug; </td> </tr> <tr> <td class="h" > <a name="171">171</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="172">172</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # validate plutil and plist </td> </tr> <tr> <td class="h" > <a name="173">173</a> </td> <td class="c0" > <a href="#174"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $res = `plutil $plist`; </td> </tr> <tr> <td class="h" > <a name="174">174</a> </td> <td class="c0" > <a href="#177"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#174-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> die "plutil failed : $res" if $res !~ /OK$/; </td> </tr> <tr> <td class="h" > <a name="175">175</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="176">176</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # read plist as text </td> </tr> <tr> <td class="h" > <a name="177">177</a> </td> <td class="c0" > <a href="#178"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $text = `plutil -p $plist`; </td> </tr> <tr> <td class="h" > <a name="178">178</a> </td> <td class="c0" > <a href="#181"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#178-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> die "plutil failed on file $plist" if not $text; </td> </tr> <tr> <td class="h" > <a name="179">179</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> </td> </tr> <tr> <td class="h" > <a name="180">180</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # split on ddd => {} </td> </tr> <tr> <td class="h" > <a name="181">181</a> </td> <td class="c0" > <a href="#184"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my @pieces = split /\d+ => \{(.*?)\}\s+\d+ => \{/s, $text; </td> </tr> <tr> <td class="h" > <a name="182">182</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> </td> </tr> <tr> <td class="h" > <a name="183">183</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # find bookmarks among pieces </td> </tr> <tr> <td class="h" > <a name="184">184</a> </td> <td class="c0" > <a href="#187"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my @bookmarks = grep /URLString/, @pieces; </td> </tr> <tr> <td class="h" > <a name="185">185</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> </td> </tr> <tr> <td class="h" > <a name="186">186</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # print </td> </tr> <tr> <td class="h" > <a name="187">187</a> </td> <td class="c0" > <a href="#189"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> foreach my $bm (@bookmarks) </td> </tr> <tr> <td class="h" > <a name="188">188</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="189">189</a> </td> <td class="c0" > <a href="#190"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#189-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $title = $1 if $bm =~ /"title" => "(.+)"/i; </td> </tr> <tr> <td class="h" > <a name="190">190</a> </td> <td class="c0" > <a href="#191"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#190-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $url = $1 if $bm =~ /"URLString" => "(.+)"/i; </td> </tr> <tr> <td class="h" > <a name="191">191</a> </td> <td class="c0" > <a href="#193"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#191-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $description = $1 if $bm =~ /"PreviewText" => "(.+)"/i; </td> </tr> <tr> <td class="h" > <a name="192">192</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> </td> </tr> <tr> <td class="h" > <a name="193">193</a> </td> <td class="c0" > <a href="#199"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> $print_bookmark->($title, $url, $description); </td> </tr> <tr> <td class="h" > <a name="194">194</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="195">195</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="196">196</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="197">197</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sub _firefox { </td> </tr> <tr> <td class="h" > <a name="198">198</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="199">199</a> </td> <td class="c0" > <a href="#200"> 0 </a> </td> <td >   </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#199-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> eval { </td> </tr> <tr> <td class="h" > <a name="200">200</a> </td> <td class="c0" > <a href="#201"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> require DBI; </td> </tr> <tr> <td class="h" > <a name="201">201</a> </td> <td class="c0" > <a href="#203"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> require DBD::SQLite; </td> </tr> <tr> <td class="h" > <a name="202">202</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> }; </td> </tr> <tr> <td class="h" > <a name="203">203</a> </td> <td class="c0" > <a href="#205"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#203-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> if ($@) </td> </tr> <tr> <td class="h" > <a name="204">204</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="205">205</a> </td> <td class="c0" > <a href="#208"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> die "to process Firefox bookmarks, you need to install modules DBI DBD::SQLite\n"; </td> </tr> <tr> <td class="h" > <a name="206">206</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="207">207</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="208">208</a> </td> <td class="c0" > <a href="#209"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--condition.html#208-1"> 0 </a> </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $dbfile = shift // ""; </td> </tr> <tr> <td class="h" > <a name="209">209</a> </td> <td class="c0" > <a href="#212"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#209-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> warn "\$dbfile: $dbfile\n" if $debug; </td> </tr> <tr> <td class="h" > <a name="210">210</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="211">211</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # fix EXCLUSIVE SQLite lock set by Firefox </td> </tr> <tr> <td class="h" > <a name="212">212</a> </td> <td class="c0" > <a href="#213"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $dir = tempdir( CLEANUP => 1 ); </td> </tr> <tr> <td class="h" > <a name="213">213</a> </td> <td class="c0" > <a href="#216"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#213-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> copy $dbfile, $dir or die "unable to copy file : $dbfile"; </td> </tr> <tr> <td class="h" > <a name="214">214</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> </td> </tr> <tr> <td class="h" > <a name="215">215</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # from now on, we use a tmp db copy </td> </tr> <tr> <td class="h" > <a name="216">216</a> </td> <td class="c0" > <a href="#218"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> $dbfile = "$dir/" . basename($dbfile); </td> </tr> <tr> <td class="h" > <a name="217">217</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> </td> </tr> <tr> <td class="h" > <a name="218">218</a> </td> <td class="c0" > <a href="#225"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#218-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile", # DSN: dbi, driver, database file </td> </tr> <tr> <td class="h" > <a name="219">219</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> "", # no user </td> </tr> <tr> <td class="h" > <a name="220">220</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> "", # no password </td> </tr> <tr> <td class="h" > <a name="221">221</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { RaiseError => 1, PrintError => 0, AutoCommit => 0 }, # RaiseError=die() PrintError=warn() </td> </tr> <tr> <td class="h" > <a name="222">222</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ) or die DBI->errstr; </td> </tr> <tr> <td class="h" > <a name="223">223</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="224">224</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # build sql statement </td> </tr> <tr> <td class="h" > <a name="225">225</a> </td> <td class="c0" > <a href="#248"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $sql = " </td> </tr> <tr> <td class="h" > <a name="226">226</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> select b.title, p.url, t.tags as description </td> </tr> <tr> <td class="h" > <a name="227">227</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> from moz_bookmarks b </td> </tr> <tr> <td class="h" > <a name="228">228</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> left join </td> </tr> <tr> <td class="h" > <a name="229">229</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ( </td> </tr> <tr> <td class="h" > <a name="230">230</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> select fk, group_concat(tag, ' ') as tags </td> </tr> <tr> <td class="h" > <a name="231">231</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> from </td> </tr> <tr> <td class="h" > <a name="232">232</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ( </td> </tr> <tr> <td class="h" > <a name="233">233</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> select distinct </td> </tr> <tr> <td class="h" > <a name="234">234</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> b1.fk as fk, </td> </tr> <tr> <td class="h" > <a name="235">235</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> b3.title as tag </td> </tr> <tr> <td class="h" > <a name="236">236</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> from moz_bookmarks b1 </td> </tr> <tr> <td class="h" > <a name="237">237</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> left join moz_bookmarks b2 on b2.fk = b1.fk and b2.type = 1 and b2.title is null </td> </tr> <tr> <td class="h" > <a name="238">238</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> left join moz_bookmarks b3 on b3.id = b2.parent </td> </tr> <tr> <td class="h" > <a name="239">239</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> where b1.type = 1 and b1.title is not null </td> </tr> <tr> <td class="h" > <a name="240">240</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ) </td> </tr> <tr> <td class="h" > <a name="241">241</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> group by fk </td> </tr> <tr> <td class="h" > <a name="242">242</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ) t on t.fk = b.fk </td> </tr> <tr> <td class="h" > <a name="243">243</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> left join moz_places p on p.id = b.fk </td> </tr> <tr> <td class="h" > <a name="244">244</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> left join moz_origins o on o.id = p.origin_id </td> </tr> <tr> <td class="h" > <a name="245">245</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> where b.title is not null </td> </tr> <tr> <td class="h" > <a name="246">246</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> and o.prefix != 'place:' </td> </tr> <tr> <td class="h" > <a name="247">247</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> "; </td> </tr> <tr> <td class="h" > <a name="248">248</a> </td> <td class="c0" > <a href="#252"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#248-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> warn "\$sql: $sql\n" if $debug; </td> </tr> <tr> <td class="h" > <a name="249">249</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="250">250</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # prepare and execute transaction </td> </tr> <tr> <td class="h" > <a name="251">251</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> eval </td> </tr> <tr> <td class="h" > <a name="252">252</a> </td> <td class="c0" > <a href="#253"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="253">253</a> </td> <td class="c0" > <a href="#254"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $sth = $dbh->prepare($sql); </td> </tr> <tr> <td class="h" > <a name="254">254</a> </td> <td class="c0" > <a href="#256"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> $sth->execute(); </td> </tr> <tr> <td class="h" > <a name="255">255</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="256">256</a> </td> <td class="c0" > <a href="#258"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#256-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> if ($sth) </td> </tr> <tr> <td class="h" > <a name="257">257</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="258">258</a> </td> <td class="c0" > <a href="#260"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--condition.html#258-1"> 0 </a> </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> while ($sth and my $hashref = $sth->fetchrow_hashref) </td> </tr> <tr> <td class="h" > <a name="259">259</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="260">260</a> </td> <td class="c0" > <a href="#265"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> $print_bookmark->( decode_utf8($hashref->{'title'}), decode_utf8($hashref->{'url'}), decode_utf8($hashref->{'description'}) ); </td> </tr> <tr> <td class="h" > <a name="261">261</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="262">262</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="263">263</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> }; </td> </tr> <tr> <td class="h" > <a name="264">264</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> </td> </tr> <tr> <td class="h" > <a name="265">265</a> </td> <td class="c0" > <a href="#267"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#265-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> if ($@) </td> </tr> <tr> <td class="h" > <a name="266">266</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="267">267</a> </td> <td class="c0" > <a href="#268"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> warn "transaction failed : $@"; </td> </tr> <tr> <td class="h" > <a name="268">268</a> </td> <td class="c0" > <a href="#271"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> die "unable to process file : $dbfile"; </td> </tr> <tr> <td class="h" > <a name="269">269</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="270">270</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="271">271</a> </td> <td class="c0" > <a href="#276"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> $dbh->disconnect; </td> </tr> <tr> <td class="h" > <a name="272">272</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="273">273</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="274">274</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sub _chrome { </td> </tr> <tr> <td class="h" > <a name="275">275</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="276">276</a> </td> <td class="c0" > <a href="#277"> 0 </a> </td> <td >   </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#276-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> eval { </td> </tr> <tr> <td class="h" > <a name="277">277</a> </td> <td class="c0" > <a href="#278"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> require File::Slurper; </td> </tr> <tr> <td class="h" > <a name="278">278</a> </td> <td class="c0" > <a href="#280"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> require JSON; </td> </tr> <tr> <td class="h" > <a name="279">279</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> }; </td> </tr> <tr> <td class="h" > <a name="280">280</a> </td> <td class="c0" > <a href="#282"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#280-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> if ($@) </td> </tr> <tr> <td class="h" > <a name="281">281</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="282">282</a> </td> <td class="c0" > <a href="#285"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> die "to process Chrome bookmarks, you need to install modules File::Slurper JSON\n"; </td> </tr> <tr> <td class="h" > <a name="283">283</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="284">284</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="285">285</a> </td> <td class="c0" > <a href="#286"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--condition.html#285-1"> 0 </a> </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $file = shift // ""; </td> </tr> <tr> <td class="h" > <a name="286">286</a> </td> <td class="c0" > <a href="#289"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#286-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> warn "\$file: $file\n" if $debug; </td> </tr> <tr> <td class="h" > <a name="287">287</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="288">288</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # read plist as text </td> </tr> <tr> <td class="h" > <a name="289">289</a> </td> <td class="c0" > <a href="#292"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $text = File::Slurper::read_binary($file); </td> </tr> <tr> <td class="h" > <a name="290">290</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> </td> </tr> <tr> <td class="h" > <a name="291">291</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # decode utf8 json </td> </tr> <tr> <td class="h" > <a name="292">292</a> </td> <td class="c0" > <a href="#295"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $hashref = JSON::decode_json($text); </td> </tr> <tr> <td class="h" > <a name="293">293</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> </td> </tr> <tr> <td class="h" > <a name="294">294</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # print </td> </tr> <tr> <td class="h" > <a name="295">295</a> </td> <td class="c0" > <a href="#297"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> foreach my $place ( ('bookmark_bar','other') ) </td> </tr> <tr> <td class="h" > <a name="296">296</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="297">297</a> </td> <td class="c0" > <a href="#299"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $arrayref = $hashref->{'roots'}->{$place}->{'children'}; </td> </tr> <tr> <td class="h" > <a name="298">298</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> </td> </tr> <tr> <td class="h" > <a name="299">299</a> </td> <td class="c0" > <a href="#301"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> foreach my $i (@$arrayref) </td> </tr> <tr> <td class="h" > <a name="300">300</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="301">301</a> </td> <td class="c0" > <a href="#308"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> $print_bookmark->($i->{'name'}, $i->{'url'}); </td> </tr> <tr> <td class="h" > <a name="302">302</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="303">303</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="304">304</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="305">305</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="306">306</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sub _iexplorer { </td> </tr> <tr> <td class="h" > <a name="307">307</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> </td> </tr> <tr> <td class="h" > <a name="308">308</a> </td> <td class="c0" > <a href="#309"> 0 </a> </td> <td >   </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#308-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> eval { </td> </tr> <tr> <td class="h" > <a name="309">309</a> </td> <td class="c0" > <a href="#310"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> require Config::Any; </td> </tr> <tr> <td class="h" > <a name="310">310</a> </td> <td class="c0" > <a href="#311"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> require Config::Tiny; # for Config::Any::INI </td> </tr> <tr> <td class="h" > <a name="311">311</a> </td> <td class="c0" > <a href="#312"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> require Win32; # for windows rubbish </td> </tr> <tr> <td class="h" > <a name="312">312</a> </td> <td class="c0" > <a href="#314"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> require File::Find; </td> </tr> <tr> <td class="h" > <a name="313">313</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> }; </td> </tr> <tr> <td class="h" > <a name="314">314</a> </td> <td class="c0" > <a href="#316"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#314-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> if ($@) </td> </tr> <tr> <td class="h" > <a name="315">315</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="316">316</a> </td> <td class="c0" > <a href="#319"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> die "to process Internet Explorer favorites, you need to install modules Config::Any Config::Tiny Win32 File::Find\n"; </td> </tr> <tr> <td class="h" > <a name="317">317</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="318">318</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> </td> </tr> <tr> <td class="h" > <a name="319">319</a> </td> <td class="c0" > <a href="#320"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--condition.html#319-1"> 0 </a> </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $favorites = shift // ""; </td> </tr> <tr> <td class="h" > <a name="320">320</a> </td> <td class="c0" > <a href="#323"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#320-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> warn "\$favorites: $favorites\n" if $debug; </td> </tr> <tr> <td class="h" > <a name="321">321</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="322">322</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # search in favorites and subfolders </td> </tr> <tr> <td class="h" > <a name="323">323</a> </td> <td class="c0" > <a href="#324"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my @files; </td> </tr> <tr> <td class="h" > <a name="324">324</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#324-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> File::Find::find( { wanted => sub { push @files, $_ }, no_chdir => 1 }, $favorites ); </td> </tr> <tr> <td class="h" > <a > </a> </td> <td class="c0" > <a href="#326"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="325">325</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="326">326</a> </td> <td class="c0" > <a href="#328"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> foreach my $file (@files) </td> </tr> <tr> <td class="h" > <a name="327">327</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="328">328</a> </td> <td class="c0" > <a href="#331"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my @filepaths = ($file); </td> </tr> <tr> <td class="h" > <a name="329">329</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="330">330</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # force load internet shortcuts .url as INI files </td> </tr> <tr> <td class="h" > <a name="331">331</a> </td> <td class="c0" > <a href="#332"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my @plugins = ('Config::Any::INI'); </td> </tr> <tr> <td class="h" > <a name="332">332</a> </td> <td class="c0" > <a href="#335"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $cfg = Config::Any->load_files( {files => \@filepaths, force_plugins => \@plugins} ); </td> </tr> <tr> <td class="h" > <a name="333">333</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="334">334</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # workaround because system encoding != console encoding </td> </tr> <tr> <td class="h" > <a name="335">335</a> </td> <td class="c0" > <a href="#336"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $win32_old_cp = Win32::GetConsoleOutputCP(); </td> </tr> <tr> <td class="h" > <a name="336">336</a> </td> <td class="c0" > <a href="#339"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $win32_new_cp = Win32::GetACP(); </td> </tr> <tr> <td class="h" > <a name="337">337</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> </td> </tr> <tr> <td class="h" > <a name="338">338</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # change console codepage </td> </tr> <tr> <td class="h" > <a name="339">339</a> </td> <td class="c0" > <a href="#341"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> Win32::SetConsoleOutputCP($win32_new_cp); </td> </tr> <tr> <td class="h" > <a name="340">340</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="341">341</a> </td> <td class="c0" > <a href="#343"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> for (@$cfg) </td> </tr> <tr> <td class="h" > <a name="342">342</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="343">343</a> </td> <td class="c0" > <a href="#345"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my ($filename, $config) = %$_; </td> </tr> <tr> <td class="h" > <a name="344">344</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="345">345</a> </td> <td class="c0" > <a href="#346"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $title = substr(basename($filename), 0, -4); # chop ".url" </td> </tr> <tr> <td class="h" > <a name="346">346</a> </td> <td class="c0" > <a href="#348"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--condition.html#346-1"> 0 </a> </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $url = $config->{'InternetShortcut'}->{'URL'} // ""; </td> </tr> <tr> <td class="h" > <a name="347">347</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="348">348</a> </td> <td class="c0" > <a href="#352"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> $print_bookmark->($title, $url); </td> </tr> <tr> <td class="h" > <a name="349">349</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="350">350</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="351">351</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # restore console codepage </td> </tr> <tr> <td class="h" > <a name="352">352</a> </td> <td class="c0" > <a href="#358"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> Win32::SetConsoleOutputCP($win32_old_cp); </td> </tr> <tr> <td class="h" > <a name="353">353</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="354">354</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="355">355</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="356">356</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sub _txt { </td> </tr> <tr> <td class="h" > <a name="357">357</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="358">358</a> </td> <td class="c0" > <a href="#359"> 0 </a> </td> <td >   </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#358-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> eval { </td> </tr> <tr> <td class="h" > <a name="359">359</a> </td> <td class="c0" > <a href="#360"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> require URI::Find; </td> </tr> <tr> <td class="h" > <a name="360">360</a> </td> <td class="c0" > <a href="#362"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> require URI::Find::Schemeless; </td> </tr> <tr> <td class="h" > <a name="361">361</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> }; </td> </tr> <tr> <td class="h" > <a name="362">362</a> </td> <td class="c0" > <a href="#364"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#362-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> if ($@) </td> </tr> <tr> <td class="h" > <a name="363">363</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="364">364</a> </td> <td class="c0" > <a href="#367"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> die "to process text files, you need to install module URI::Find\n"; </td> </tr> <tr> <td class="h" > <a name="365">365</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="366">366</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="367">367</a> </td> <td class="c0" > <a href="#368"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--condition.html#367-1"> 0 </a> </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $file = shift // ""; </td> </tr> <tr> <td class="h" > <a name="368">368</a> </td> <td class="c0" > <a href="#371"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#368-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> warn "\$file: $file\n" if $debug; </td> </tr> <tr> <td class="h" > <a name="369">369</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="370">370</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # get uri regex </td> </tr> <tr> <td class="h" > <a name="371">371</a> </td> <td class="c0" > <a href="#373"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#371-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $class = $schemeless ? "URI::Find::Schemeless" : "URI::Find"; # copy-paste from urifind </td> </tr> <tr> <td class="h" > <a name="372">372</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $finder = $class->new( sub { </td> </tr> <tr> <td class="h" > <a name="373">373</a> </td> <td class="c0" > <a href="#374"> 0 </a> </td> <td >   </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#373-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> my ($uri, $orig_uri) = @_; </td> </tr> <tr> <td class="h" > <a name="374">374</a> </td> <td class="c0" > <a href="#375"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> return $orig_uri; </td> </tr> <tr> <td class="h" > <a name="375">375</a> </td> <td class="c0" > <a href="#377"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> }); </td> </tr> <tr> <td class="h" > <a name="376">376</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="377">377</a> </td> <td class="c0" > <a href="#378"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $regex = $finder->uri_re; </td> </tr> <tr> <td class="h" > <a name="378">378</a> </td> <td class="c0" > <a href="#381"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#378-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> $regex = $regex . '|' . $finder->schemeless_uri_re if $schemeless; </td> </tr> <tr> <td class="h" > <a name="379">379</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="380">380</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # read file as text </td> </tr> <tr> <td class="h" > <a name="381">381</a> </td> <td class="c0" > <a href="#382"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $fh; </td> </tr> <tr> <td class="h" > <a name="382">382</a> </td> <td class="c0" > <a href="#384"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#382-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> if ($file eq '-') </td> </tr> <tr> <td class="h" > <a name="383">383</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="384">384</a> </td> <td class="c0" > <a href="#388"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> $fh = *STDIN; </td> </tr> <tr> <td class="h" > <a name="385">385</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="386">386</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> else </td> </tr> <tr> <td class="h" > <a name="387">387</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="388">388</a> </td> <td class="c0" > <a href="#391"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#388-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> open($fh, '<:encoding(UTF-8)', $file) or die "unable to read file : $file"; </td> </tr> <tr> <td class="h" > <a name="389">389</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="390">390</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="391">391</a> </td> <td class="c0" > <a href="#393"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> while (my $line = <$fh>) </td> </tr> <tr> <td class="h" > <a name="392">392</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="393">393</a> </td> <td class="c0" > <a href="#395"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#393-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> if ( $line =~ /(?:(.*)\s)?($regex)(?:\s+(.*))?/ ) # match <title> <url> <description> </td> </tr> <tr> <td class="h" > <a name="394">394</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="395">395</a> </td> <td class="c0" > <a href="#396"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $title = $1; </td> </tr> <tr> <td class="h" > <a name="396">396</a> </td> <td class="c0" > <a href="#397"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $url = $2; </td> </tr> <tr> <td class="h" > <a name="397">397</a> </td> <td class="c0" > <a href="#399"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $description = $3; </td> </tr> <tr> <td class="h" > <a name="398">398</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="399">399</a> </td> <td class="c0" > <a href="#406"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> $print_bookmark->($title, $url, $description); </td> </tr> <tr> <td class="h" > <a name="400">400</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="401">401</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="402">402</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="403">403</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="404">404</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sub _gemini { </td> </tr> <tr> <td class="h" > <a name="405">405</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="406">406</a> </td> <td class="c0" > <a href="#407"> 0 </a> </td> <td >   </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#406-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> eval { </td> </tr> <tr> <td class="h" > <a name="407">407</a> </td> <td class="c0" > <a href="#408"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> require URI::Find; </td> </tr> <tr> <td class="h" > <a name="408">408</a> </td> <td class="c0" > <a href="#410"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> require URI::Find::Schemeless; </td> </tr> <tr> <td class="h" > <a name="409">409</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> }; </td> </tr> <tr> <td class="h" > <a name="410">410</a> </td> <td class="c0" > <a href="#412"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#410-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> if ($@) </td> </tr> <tr> <td class="h" > <a name="411">411</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="412">412</a> </td> <td class="c0" > <a href="#415"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> die "to process Gemini files, you need to install module URI::Find\n"; </td> </tr> <tr> <td class="h" > <a name="413">413</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="414">414</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="415">415</a> </td> <td class="c0" > <a href="#416"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--condition.html#415-1"> 0 </a> </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $file = shift // ""; </td> </tr> <tr> <td class="h" > <a name="416">416</a> </td> <td class="c0" > <a href="#419"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#416-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> warn "\$file: $file\n" if $debug; </td> </tr> <tr> <td class="h" > <a name="417">417</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="418">418</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # get uri regex </td> </tr> <tr> <td class="h" > <a name="419">419</a> </td> <td class="c0" > <a href="#421"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#419-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $class = $schemeless ? "URI::Find::Schemeless" : "URI::Find"; # copy-paste from urifind </td> </tr> <tr> <td class="h" > <a name="420">420</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $finder = $class->new( sub { </td> </tr> <tr> <td class="h" > <a name="421">421</a> </td> <td class="c0" > <a href="#422"> 0 </a> </td> <td >   </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#421-1"> 0 </a> </td> <td >   </td> <td > 0 </td> <td class="s"> my ($uri, $orig_uri) = @_; </td> </tr> <tr> <td class="h" > <a name="422">422</a> </td> <td class="c0" > <a href="#423"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> return $orig_uri; </td> </tr> <tr> <td class="h" > <a name="423">423</a> </td> <td class="c0" > <a href="#425"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> }); </td> </tr> <tr> <td class="h" > <a name="424">424</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="425">425</a> </td> <td class="c0" > <a href="#426"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $regex = $finder->uri_re; </td> </tr> <tr> <td class="h" > <a name="426">426</a> </td> <td class="c0" > <a href="#429"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#426-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> $regex = $regex . '|' . $finder->schemeless_uri_re if $schemeless; </td> </tr> <tr> <td class="h" > <a name="427">427</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="428">428</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # read file as text </td> </tr> <tr> <td class="h" > <a name="429">429</a> </td> <td class="c0" > <a href="#431"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#429-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> open(my $fh, '<:encoding(UTF-8)', $file) or die "unable to read file : $file"; </td> </tr> <tr> <td class="h" > <a name="430">430</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> </td> </tr> <tr> <td class="h" > <a name="431">431</a> </td> <td class="c0" > <a href="#433"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> while (my $line = <$fh>) </td> </tr> <tr> <td class="h" > <a name="432">432</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="433">433</a> </td> <td class="c0" > <a href="#435"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#433-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> if ( $line =~ /^=>\s+($regex)\s+(.*)/ ) # match => <url> <title> </td> </tr> <tr> <td class="h" > <a name="434">434</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="435">435</a> </td> <td class="c0" > <a href="#436"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $title = $2; </td> </tr> <tr> <td class="h" > <a name="436">436</a> </td> <td class="c0" > <a href="#437"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $url = $1; </td> </tr> <tr> <td class="h" > <a name="437">437</a> </td> <td class="c0" > <a href="#439"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> my $description = undef; </td> </tr> <tr> <td class="h" > <a name="438">438</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="439">439</a> </td> <td class="c0" > <a href="#495"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> $print_bookmark->($title, $url, $description); </td> </tr> <tr> <td class="h" > <a name="440">440</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="441">441</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="442">442</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="443">443</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="444">444</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sub _md { </td> </tr> <tr> <td class="h" > <a name="445">445</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="446">446</a> </td> <td class="c3" > 1 </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--condition.html#446-1"> 50 </a> </td> <td class="c3" > <a href="script-bookmarks--subroutine.html#446-1"> 1 </a> </td> <td >   </td> <td > 3 </td> <td class="s"> my $file = shift // ""; </td> </tr> <tr> <td class="h" > <a name="447">447</a> </td> <td class="c3" > 1 </td> <td class="c0" > <a href="script-bookmarks--branch.html#447-1"> 50 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 2 </td> <td class="s"> warn "\$file: $file\n" if $debug; </td> </tr> <tr> <td class="h" > <a name="448">448</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="449">449</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # read file as text </td> </tr> <tr> <td class="h" > <a name="450">450</a> </td> <td class="c3" > 1 </td> <td class="c0" > <a href="script-bookmarks--branch.html#450-1"> 50 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 42 </td> <td class="s"> open(my $fh, '<:encoding(UTF-8)', $file) or die "unable to read file : $file"; </td> </tr> <tr> <td class="h" > <a name="451">451</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="452">452</a> </td> <td class="c3" > 1 </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 102 </td> <td class="s"> while (my $line = <$fh>) </td> </tr> <tr> <td class="h" > <a name="453">453</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="454">454</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # regex by Michaël Perrin : </td> </tr> <tr> <td class="h" > <a name="455">455</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # http://blog.michaelperrin.fr/2019/02/04/advanced-regular-expressions/ </td> </tr> <tr> <td class="h" > <a name="456">456</a> </td> <td class="c3" > 2 </td> <td class="c3" > <a href="script-bookmarks--branch.html#456-1"> 100 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 36 </td> <td class="s"> if ( $line =~ </td> </tr> <tr> <td class="h" > <a name="457">457</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> / </td> </tr> <tr> <td class="h" > <a name="458">458</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> (?<text_group> # Text group, including square brackets </td> </tr> <tr> <td class="h" > <a name="459">459</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> \[ </td> </tr> <tr> <td class="h" > <a name="460">460</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> (?> # (?> defines an atomic group, this is a performance improvement when using recursion </td> </tr> <tr> <td class="h" > <a name="461">461</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> [^\[\]]+ # Look for any char except closing square bracket </td> </tr> <tr> <td class="h" > <a name="462">462</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> |(?&text_group) # OR: find recursively an other pattern with opening and closing square brackets </td> </tr> <tr> <td class="h" > <a name="463">463</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> )* </td> </tr> <tr> <td class="h" > <a name="464">464</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> \] </td> </tr> <tr> <td class="h" > <a name="465">465</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ) </td> </tr> <tr> <td class="h" > <a name="466">466</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> (?: </td> </tr> <tr> <td class="h" > <a name="467">467</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> \( </td> </tr> <tr> <td class="h" > <a name="468">468</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> (?<url>\S*?) # URL: non-greedy non-whitespace characters </td> </tr> <tr> <td class="h" > <a name="469">469</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> (?: </td> </tr> <tr> <td class="h" > <a name="470">470</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> [ ] </td> </tr> <tr> <td class="h" > <a name="471">471</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> " </td> </tr> <tr> <td class="h" > <a name="472">472</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> (?<title> </td> </tr> <tr> <td class="h" > <a name="473">473</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> (?:[^"]|(?<=\\)")*? # Title without double quotes around </td> </tr> <tr> <td class="h" > <a name="474">474</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ) </td> </tr> <tr> <td class="h" > <a name="475">475</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> " </td> </tr> <tr> <td class="h" > <a name="476">476</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> )? </td> </tr> <tr> <td class="h" > <a name="477">477</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> \) </td> </tr> <tr> <td class="h" > <a name="478">478</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ) </td> </tr> <tr> <td class="h" > <a name="479">479</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> /x </td> </tr> <tr> <td class="h" > <a name="480">480</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ) # match [<title>](<url> "<description>") OLD was [<title>](<url>) <description> </td> </tr> <tr> <td class="h" > <a name="481">481</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="482">482</a> </td> <td class="c3" > 1 </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 3 </td> <td class="s"> my $title = $1; </td> </tr> <tr> <td class="h" > <a name="483">483</a> </td> <td class="c3" > 1 </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 2 </td> <td class="s"> my $url = $2; </td> </tr> <tr> <td class="h" > <a name="484">484</a> </td> <td class="c3" > 1 </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 2 </td> <td class="s"> my $description = $3; </td> </tr> <tr> <td class="h" > <a name="485">485</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> </td> </tr> <tr> <td class="h" > <a name="486">486</a> </td> <td class="c3" > 1 </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 7 </td> <td class="s"> $title =~ s/^\[|\]$//g; # strip [...] </td> </tr> <tr> <td class="h" > <a name="487">487</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> </td> </tr> <tr> <td class="h" > <a name="488">488</a> </td> <td class="c3" > 1 </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 3 </td> <td class="s"> $print_bookmark->($title, $url, $description); </td> </tr> <tr> <td class="h" > <a name="489">489</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="490">490</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="491">491</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="492">492</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="493">493</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sub _netscape { </td> </tr> <tr> <td class="h" > <a name="494">494</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="495">495</a> </td> <td class="c0" > <a href="#496"> 0 </a> </td> <td >   </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#495-1"> 0 </a> </td> <td >   </td> <td >   </td> <td class="s"> eval { </td> </tr> <tr> <td class="h" > <a name="496">496</a> </td> <td class="c0" > <a href="#498"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> require Netscape::Bookmarks; </td> </tr> <tr> <td class="h" > <a name="497">497</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> }; </td> </tr> <tr> <td class="h" > <a name="498">498</a> </td> <td class="c0" > <a href="#500"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#498-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> if ($@) </td> </tr> <tr> <td class="h" > <a name="499">499</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="500">500</a> </td> <td class="c0" > <a href="#503"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> die "to process Netscape files, you need to install module Netscape::Bookmarks\n"; </td> </tr> <tr> <td class="h" > <a name="501">501</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="502">502</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="503">503</a> </td> <td class="c0" > <a href="#504"> 0 </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--condition.html#503-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $file = shift // ""; </td> </tr> <tr> <td class="h" > <a name="504">504</a> </td> <td class="c0" > <a href="#507"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#504-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> warn "\$file: $file\n" if $debug; </td> </tr> <tr> <td class="h" > <a name="505">505</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="506">506</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # parse file </td> </tr> <tr> <td class="h" > <a name="507">507</a> </td> <td class="c0" > <a href="#508"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $netscape = Netscape::Bookmarks->new($file); </td> </tr> <tr> <td class="h" > <a name="508">508</a> </td> <td class="c0" > <a href="#511"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#508-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> die "unable to parse file : $file" if not $netscape->isa('Netscape::Bookmarks::Category'); </td> </tr> <tr> <td class="h" > <a name="509">509</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="510">510</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $callback = sub { </td> </tr> <tr> <td class="h" > <a name="511">511</a> </td> <td class="c0" > <a href="#512"> 0 </a> </td> <td >   </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--subroutine.html#511-1"> 0 </a> </td> <td >   </td> <td >   </td> <td class="s"> my ($object, $level) = @_; </td> </tr> <tr> <td class="h" > <a name="512">512</a> </td> <td class="c0" > <a href="#514"> 0 </a> </td> <td class="c0" > <a href="script-bookmarks--branch.html#512-1"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> if ($object->isa('Netscape::Bookmarks::Link')) </td> </tr> <tr> <td class="h" > <a name="513">513</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="514">514</a> </td> <td class="c0" > <a href="#515"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $title = $object->title; </td> </tr> <tr> <td class="h" > <a name="515">515</a> </td> <td class="c0" > <a href="#516"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $url = $object->href; </td> </tr> <tr> <td class="h" > <a name="516">516</a> </td> <td class="c0" > <a href="#518"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> my $description = undef; </td> </tr> <tr> <td class="h" > <a name="517">517</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> </td> </tr> <tr> <td class="h" > <a name="518">518</a> </td> <td class="c0" > <a href="#520"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $print_bookmark->($title, $url, $description); </td> </tr> <tr> <td class="h" > <a name="519">519</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="520">520</a> </td> <td class="c0" > <a href="#522"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> }; </td> </tr> <tr> <td class="h" > <a name="521">521</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="522">522</a> </td> <td class="c0" > <a href="#533"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> $netscape->recurse($callback); </td> </tr> <tr> <td class="h" > <a name="523">523</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="524">524</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="525">525</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="526">526</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ######## </td> </tr> <tr> <td class="h" > <a name="527">527</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # MAIN # </td> </tr> <tr> <td class="h" > <a name="528">528</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> ######## </td> </tr> <tr> <td class="h" > <a name="529">529</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="530">530</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> # header </td> </tr> <tr> <td class="h" > <a name="531">531</a> </td> <td class="c3" > 1 </td> <td class="c0" > <a href="script-bookmarks--branch.html#531-1"> 50 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td > 5 </td> <td class="s"> if ($format eq 'csv') </td> </tr> <tr> <td class="h" > <a > </a> </td> <td >   </td> <td class="c0" > <a href="script-bookmarks--branch.html#-2"> 50 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="532">532</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="533">533</a> </td> <td class="c0" > <a href="#537"> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> say '"Title","URL","Description"' . "\r"; </td> </tr> <tr> <td class="h" > <a name="534">534</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> } </td> </tr> <tr> <td class="h" > <a name="535">535</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> elsif ($format eq 'html') </td> </tr> <tr> <td class="h" > <a name="536">536</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> { </td> </tr> <tr> <td class="h" > <a name="537">537</a> </td> <td class="c0" > <a href="# "> 0 </a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td > 0 </td> <td class="s"> say "<!DOCTYPE NETSCAPE-Bookmark-file-1> </td> </tr> <tr> <td class="h" > <a name="538">538</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> <!--This is an automatically generated file. </td> </tr> <tr> <td class="h" > <a name="539">539</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> It will be read and overwritten. </td> </tr> <tr> <td class="h" > <a name="540">540</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Do Not Edit! --> </td> </tr> <tr> <td class="h" > <a name="541">541</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> <Title>Bookmarks
542            

Bookmarks

543            
";
544             }
545              
546             # body
547 1         1 foreach my $file (@ARGV)
548             {
549 1         34 my $name = basename($file);
550              
551 1 50 33     65 if (-f $file and $name =~ /\.plist$/) { _safari($file); }
  0 50 33     0  
    50 33        
    50 33        
    50 33        
    0 0        
    0 0        
    0          
    0          
552 0         0 elsif (-f $file and $name =~ /\.sqlite$/) { _firefox($file); }
553 0         0 elsif (-f $file and $name =~ /Bookmarks$/) { _chrome($file); }
554 0         0 elsif (-d $file and $name =~ /Favorites$/) { _iexplorer($file); }
555 1         3 elsif (-f $file and $name =~ /\.md$/) { _md($file); }
556 0         0 elsif (-f $file and $name =~ /\.gmi$/) { _gemini($file); }
557 0         0 elsif (-f $file and $name =~ /\.html$/) { _netscape($file); }
558 0         0 elsif (-f $file ) { _txt($file); }
559 0         0 elsif ( $file eq '-' ) { _txt($file); }
560 0         0 else { die "unable to process file : $file"; }
561             }
562              
563             # footer
564 1 50       11 if ($format eq 'html')
565             {
566 0         0 print " ";
567             }
568              
569 1         109 exit 0;
570              
571             __END__