Introduction:
This PHP script reads a standard firefox bookmarks.html file and displays it via an easy to navigate user interface.
It is quick and easy to use and I am now using it to navigate and categorize my haystack of surfing history, that is 1200+ bookmarks most of which I had forgotton existed.
The bookmarks.html file is a third party (mozilla) code, so parsing it is an inherently fragile method, due to the possibility of future changes to its code, beyond our control.
However, it is quite easy to analyse and fix a broken parser script, provided one has copies of the old and new files and from that you can work out the changes necessary.
Sometimes though, the parsed file is no longer available or has changed so much, that a complete rewrite or abandonment is the only option.
I wrote this script based upon a bookmarks.html file I exported from Seamonkey 2,24 (Bookmarks, Manage Bookmarks, Tools, Export HTML).
The script only reads and does not alter the firefox/seamonkey/palemoon bookmarks.html file.
Requirements:
1. Firefox or Seamonkey or Palemoon browser, you need one of these to export your bookmarks to a bookmarks.html file.
After that, the script will display the firefox bookmarks on other browsers too, like Opera.
2. The ability to run PHP pages locally on your computer and display the resulting HTML pages in your web browser.
To do this I suggest installing Hiawatha Server and then test a simple PHP page at for example http://localhost/index.php (browser address).
This page will probably be located at /root/httpd/hiawatha/index.php (file manager location).
Some server installations install to a folder called 'webserver'.
Installation and configuration of a local server is beyond the scope of this post.
Make sure that the server is working and runs every time you start Puppy.
To view the example PHP page (spoken about above) type the address http://localhost/index.php into your browser address bar.
File Permissions note:
Set the file permissions as indicated below or alter them according to your security/functionality requirements.
The permissions are important as the bookmark script needs to read the bookmarks.html file and also read and write the list-1.txt, list-2.txt list-3.txt files.
Files required:
1. /root/httpd/hiawatha/bookmarks.html (rw-r--r--)
(standard bookmarks.html exported from browser dialog)
2. /root/httpd/hiawatha/bookmarks.php (rwxr--r--)
Code: Select all
<?php // **** PREVENT BROWSER CACHE ****
//header('Cache-Control: no-cache, must-revalidate');
//header('Pragma: no-cache');
//header('Expires: Sat,1 Jan 2000 00:00:01 GMT');
error_reporting (E_ALL ^ E_NOTICE);
$search=$_POST['word'];
$list=$_POST['list'];
$hide_domain=$_POST['dn'];
if(strlen($hide_domain)<1) {$hide_domain=1;};
$t1=$_POST['t1'];
$t2=$_POST['t2'];
$t3=$_POST['t3'];
$list1=@file_get_contents("list-1.txt");
$list2=@file_get_contents("list-2.txt");
$list3=@file_get_contents("list-3.txt");
$title1=get_string_between($list1,'<t>','</t>');
$title2=get_string_between($list2,'<t>','</t>');
$title3=get_string_between($list3,'<t>','</t>');
if($_POST['button1']){//change button1 name by pressing for 2 seconds
$list1=str_replace('<t>'.$title1.'</t>','<t>'.$t1.'</t>',$list1);
$title1=$t1;
$list1=preg_replace('/^\n+|^[\t\s]*\n+/m','',$list1);//strip some whitespace
$fh=fopen("list-1.txt","w+");
fwrite($fh, $list1);
fclose($fh);
}
if($_POST['button2']){//change button2 name by pressing for 2 seconds
$list2=str_replace('<t>'.$title2.'</t>','<t>'.$t2.'</t>',$list2);
$title2=$t2;
$list2=preg_replace('/^\n+|^[\t\s]*\n+/m','',$list2);//strip some whitespace
$fh=fopen("list-2.txt","w+");
fwrite($fh, $list2);
fclose($fh);
}
if($_POST['button3']){//change button3 name by pressing for 2 seconds
$list3=str_replace('<t>'.$title3.'</t>','<t>'.$t3.'</t>',$list3);
$title3=$t3;
$list3=preg_replace('/^\n+|^[\t\s]*\n+/m','',$list3);//strip some whitespace
$fh=fopen("list-3.txt","w+");
fwrite($fh, $list3);
fclose($fh);
}
if(strlen($list)<1) {$list=1;};
$fg=0;//flag you are trying to add a name already in one of the lists
$ss1=explode('<s>', $list1);$ss1[0]=$ss1[1];
for($n=0;$n<=(count($ss1)-1);$n++){
$ss1[$n]=get_string_between($ss1[$n],'<w>','</w>');
if($ss1[$n]==$search){$fg=1;};}
$ss2=explode('<s>', $list2);$ss2[0]=$ss2[1];
for($n=0;$n<=(count($ss2)-1);$n++){
$ss2[$n]=get_string_between($ss2[$n],'<w>','</w>');
if($ss2[$n]==$search){$fg=1;};}
$ss3=explode('<s>', $list3);$ss3[0]=$ss3[1];
for($n=0;$n<=(count($ss3)-1);$n++){
$ss3[$n]=get_string_between($ss3[$n],'<w>','</w>');
if($ss3[$n]==$search){$fg=1;};}
if(($fg!=1)&&($search!='')&&($_POST['add'])){
$fh=fopen("list-".$list.".txt","a+");
fwrite($fh,PHP_EOL."<s><w>".$search."</w>"); //write to txtfile
fclose($fh);}
if($_POST['remove']){
$dat=@file_get_contents("list-".$list.".txt") ;
$dat=str_replace('<s><w>'.$search.'</w>','', $dat);
$dat=preg_replace('/^\n+|^[\t\s]*\n+/m','',$dat);//strip some whitespace
$fh=fopen("list-".$list.".txt","w+");
fwrite($fh, $dat);
fclose($fh);}
function get_string_between($string, $start, $end)
{
$string = " ".$string;
$ini = strpos($string,$start);
if ($ini == 0) return "";
$ini += strlen($start);
$len = strpos($string,$end,$ini) - $ini;
return substr($string,$ini,$len);
}
$links='bookmarks.html';
$pg1=@file_get_contents($links) or die ('<html><body><p>Sorry for any inconvenience, error 1, fault will be fixed soon. Try reloading the page using your browser refresh button</p></body></html>');
$file='list-'.$list.'.txt';
$pg2=@file_get_contents($file) or die ('<html><body><p>Sorry for any inconvenience, error 2, fault will be fixed soon. Try reloading the page using your browser refresh button</p></body></html>');
?>
<!DOCTYPE html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Bookmarks</title>
<link rel="shortcut icon" href="bookmark.ico">
<style type="text/css">
body{font:normal 24px 'Arial';color:#000;background-color:#ddd;background-image:url(ptv2.jpg);}
a:link,a:visited,a:active{text-decoration:none;color:#036}
.m1,.r1{display:inline;float:left;border-radius:0.2em;cursor:pointer;font:bold 24px "Arial";padding:4px 4px 4px 4px;background-color:#bbb;color:#036;margin:4px 4px 4px 4px;border:solid 2px #040}
.r1{display:block;}
.m1:hover{background-color:#0ee;}
.r1:hover{background-color:#fdd;}
#form{display:block;margin-right:100%;margin-top:10px}
#links{display:block;float:left;width:100%;margin-top:10px;margin-bottom:10px}
#word{display:inline;width:200px;height:30px;margin:10px 10px 0px 6px;font:normal 24px 'Arial'}
#buttons{margin-top:-20px;width:670px}
.num{background-color:#eca;}
.b1{border-radius:0.2em;margin:auto;text-align:left;text-decoration:none;display:block;font:bold 24px "Arial";border:solid 1px #060;overflow:hidden;margin:4px 4px 4px 4px;color:#036;background-color:#bbb;min-height:30px;padding:4px 4px 4px 4px;width:638px}
.b1{color:#036;background-color:#ddd;}
.b1:hover{text-decoration:none;color:#036;background-color:#ff0}
.b1:visited{text-decoration:none;color:#000;background-color:#eca}
.s1{background-color:#e00;color:#fff;border-radius:0.2em}
.s2{background-color:#cec;color:#000;border-radius:0.2em}
</style>
<script type="text/javascript">
<!--
if (top.location != self.location) {top.location = self.location}
function init()
{
document.form.reset();
}
// -->
</script>
</head>
<body onload="document.form.add.value='0';document.form.button1.value='0';document.form.button2.value='0';document.form.button3.value='0';window.focus()" onunload="window.blur()">
<div class='r1' onfocus='this.blur()' <?php if($list=='1'){echo ('style="background-color:lime" ');}?>onclick="document.form.list.value='1';document.form.submit();" onmousedown="timer=window.setTimeout(function(){document.form.t1.value=document.form.word.value;document.form.button1.value='1';document.form.submit();},2000)" onmouseup="clearTimeout(timer)"><?php echo $title1; ?></div>
<div class='r1' onfocus='this.blur()' <?php if($list=='2'){echo ('style="background-color:lime" ');}?>onclick="document.form.list.value='2';document.form.submit();" onmousedown="timer=window.setTimeout(function(){document.form.t2.value=document.form.word.value;document.form.button2.value='1';document.form.submit();},2000)" onmouseup="clearTimeout(timer)"><?php echo $title2; ?></div>
<div class='r1' onfocus='this.blur()' <?php if($list=='3'){echo ('style="background-color:lime" ');}?>onclick="document.form.list.value='3';document.form.submit();" onmousedown="timer=window.setTimeout(function(){document.form.t3.value=document.form.word.value;document.form.button3.value='1';document.form.submit();},2000)" onmouseup="clearTimeout(timer)"><?php echo $title3; ?></div>
<div class='r1' onfocus='this.blur()' onclick="document.form.dn.value='<?php if($hide_domain=='1'){echo '0';}else {echo '1';}?>';document.form.submit();">DOMAIN</div>
<form name="form" id="form" method="post" action="bookmarks.php">
<div>
<input type='text' style="" name='word' id='word' value='<?php echo $search; ?>' title='Search - (2 or more characters) - Then Hit Enter'>
<input type="hidden" name="add" value="0">
<input type="hidden" name="remove" value="0">
<input type="hidden" name="button1" value="0">
<input type="hidden" name="button2" value="0">
<input type="hidden" name="button3" value="0">
<input type="hidden" name="list" value="<?php echo $list; ?>">
<input type="hidden" name="t1" value="<?php echo $t1; ?>">
<input type="hidden" name="t2" value="<?php echo $t2; ?>">
<input type="hidden" name="t3" value="<?php echo $t3; ?>">
<input type="hidden" name="dn" value="<?php echo $hide_domain; ?>">
<input style="visibility:hidden" type="submit" onclick="document.form.add.value='1';">
</div>
</form>
<div id='buttons'>
<div class='r1' onfocus='this.blur()' <?php if($search==''){echo ('style="background-color:#ff0" ');}?>onclick="this.style.backgroundColor='#ff0';document.form.word.value='';document.form.submit();">ALL</div>
<?php
$ss=explode('<s>', $pg2);
$ss[0]=$ss[1];
natcasesort($ss);//puts buttons in natural case sorted order
for($n=-1;$n<=(count($ss)-1);$n++){$sp[$n]=str_replace(' ',' ', $ss[$n]);//replace spaces
$ss[$n]=get_string_between($ss[$n],'<w>','</w>');
$ss=array_values(array_unique($ss));
$ss = array_values($ss);
if($search==$ss[$n]){$style='style="background-color:#ff0" ';}else{$style='';};$sp[$n]=$ss[$n];$ss[$n]=str_replace(' ',' ', $ss[$n]);//replace spaces but not in posted word
if($ss[$n]!=''){echo '<div class="m1" onfocus="this.blur()" '.$style.'onclick="this.style.backgroundColor=\'#ff0\';document.form.word.value=\''.$sp[$n].'\';document.form.submit();" onmousedown="timer=window.setTimeout(function(){document.form.remove.value=\'1\';document.form.submit();},2000)" onmouseup="clearTimeout(timer)">'.$ss[$n].'</div>'."\n";};$ss[$n]=str_replace(' ',' ', $ss[$n]);//replace spaces
};
?>
</div>
<div id='links'>
<?php
if (strlen($search)<2){//NO SEARCH
if($hide_domain=='1'){//domain hidden
$dd=explode('<HR> <DT><A', $pg1);
$pg1=$dd[1];
$pg1='<DT><A'.$pg1;
$pg1 = str_replace('<DD>','', $pg1);//remove
$pg1 = str_replace('<DL>','', $pg1);//remove
$pg1 = str_replace('</DL>','', $pg1);//remove
$pg1 = str_replace('<p>','', $pg1);//remove
$pg1 = str_replace('FEEDURL','HREF', $pg1);//replace
$pg1 = preg_replace('/\<DT><H3[^\>]+\>/', '', $pg1);//remove
$pg1 = str_replace('</H3>','', $pg1);//remove
$pg2 = preg_replace('/\<A HREF=[^\>]+\>/','',$pg1);//remove everything before title to allow title to be sorted first
$tt=explode('<DT>', $pg1);//array 1
$rr=explode('<DT>', $pg2);//array 2
$tt[0]=$tt[1];//$tt[0] will be empty, so make it equal to $tt[1].
$rr[0]=$rr[1];//$rr[0] will be empty, so make it equal to $rr[1].
for($n=1;$n<=(count($tt)-1);$n++){$tt[$n]='<sort_title_first>'.$rr[$n].'<then_sort_url>'.$tt[$n].'<if_domain_hidden>';}//combine arrays for sorting if domain hidden
natcasesort($tt);//puts titles of links in natural case sorted order
}else{//domain visible
$pg1 = str_replace('<DT><H3','', $pg1);//replace
$dd=explode('<HR> <DT><A', $pg1);
$pg1=$dd[1];
$pg1='<DT><A'.$pg1;
$pg1 = str_replace('FEEDURL','HREF', $pg1);//replace
$pg1 = preg_replace('/^\n+|^[\t\s]*\n+/m','',$pg1);//strip some whitespace
$tt=explode('<DT>', $pg1);
$tt[0]=$tt[1];//$tt[0] will be empty, so make it equal to $tt[1].
natcasesort($tt);//puts urls of links in natural case sorted order
}
for($n=1;$n<=(count($tt)-1);$n++){
$url[$n]=get_string_between($tt[$n], '<A HREF="', '" ');
$title[$n]=get_string_between($tt[$n], '">', '</A>');
$domain[$n]=get_string_between($url[$n], '://', '/');
$spn=strpos($url[$n],'https');
if($spn!==false){$span='s2';}else{$span='s1';};
$tt=array_values(array_unique($tt));//removes array duplicates and re-indexes array
if($title[$n]==''){$title[$n]=$url[$n];}
if($hide_domain=='0'){$dn='<span class="'.$span.'"> '.$domain[$n].' </span><br>';}else{$dn='';};
if($n>1){echo '<a class="b1" target="new" href="'.$url[$n].'">'.$dn.''.$title[$n].'</a>'."\n";};}
}
else{//SEARCH
if($hide_domain=='1'){//domain hidden
$dd=explode('<HR> <DT><A', $pg1);
$pg1=$dd[1];
$pg1='<DT><A'.$pg1;
$pg1 = str_replace('<DD>','', $pg1);//remove
$pg1 = str_replace('<DL>','', $pg1);//remove
$pg1 = str_replace('</DL>','', $pg1);//remove
$pg1 = str_replace('<p>','', $pg1);//remove
$pg1 = str_replace('FEEDURL','HREF', $pg1);//replace
$pg1 = preg_replace('/\<DT><H3[^\>]+\>/', '', $pg1);//remove
$pg1 = str_replace('</H3>','', $pg1);//remove
$pg2 = preg_replace('/\<A HREF=[^\>]+\>/','',$pg1);//remove everything before title to allow title to be sorted first
$tt=explode('<DT>', $pg1);//array 1
$rr=explode('<DT>', $pg2);//array 2
$tt[0]=$tt[1];//$tt[0] will be empty, so make it equal to $tt[1].
$rr[0]=$rr[1];//$rr[0] will be empty, so make it equal to $rr[1].
for($n=1;$n<=(count($tt)-1);$n++){$tt[$n]='<sort_title_first>'.$rr[$n].'<then_sort_url>'.$tt[$n].'<if_domain_hidden>';}//combine arrays for sorting if domain hidden
natcasesort($tt);//puts titles of links in natural case sorted order
$tt=array_values(array_unique($tt));//removes array duplicates and re-indexes array
}else{//domain visible
$pg1 = str_replace('<DT><H3','', $pg1);//replace
$dd=explode('<HR> <DT><A', $pg1);
$pg1=$dd[1];
$pg1='<DT><A'.$pg1;
$pg1 = str_replace('FEEDURL','HREF', $pg1);//replace
$pg1 = preg_replace('/^\n+|^[\t\s]*\n+/m','',$pg1);//strip some whitespace
$tt=explode('<DT>', $pg1);
$tt[0]=$tt[1];//$tt[0] will be empty, so make it equal to $tt[1].
//$tt=array_unique($tt);//removes array duplicates
natcasesort($tt);//puts urls of links in natural case sorted order
$tt=array_values(array_unique($tt));//removes array duplicates and re-indexes array
}
for($n=1;$n<=(count($tt)-1);$n++){
$url[$n]=get_string_between($tt[$n], '<A HREF="', '" ');
$title[$n]=get_string_between($tt[$n], '">', '</A>');
$domain[$n]=get_string_between($url[$n], '://', '/');
$spn=strpos($url[$n],'https');
if($spn!==false){$span='s2';}else{$span='s1';};
//$domain[$n]= str_replace('www.','',$domain[$n]);//replace
if($hide_domain=='0'){$dn='<span class="'.$span.'"> '.$domain[$n].' </span><br>';}else{$dn='';};
$surl=stripos($url[$n], $search);
$stit=stripos($title[$n], $search);
if(($surl!==false)||($stit!==false)){if($title[$n]==''){$title[$n]=$url[$n];};echo '<a class="b1" target="new" href="'.$url[$n].'">'.$dn.''.$title[$n].'</a>'."\n";
};};};
?>
</div>
</body>
</html>
Code: Select all
<t>portugal</t>
<s><w>flashcard</w>
<s><w>rafa</w>
<s><w>grammar</w>
<s><w>conj</w>
<s><w>transl</w>
<s><w>portug</w>
<s><w>phrase</w>
<s><w>lingu</w>
<s><w>teletext</w>
<s><w>verb</w>
Code: Select all
<t>technical</t>
<s><w>javascript</w>
<s><w>tiny</w>
<s><w>lxde</w>
<s><w>puppy</w>
<s><w>ubuntu</w>
<s><w>sourcef</w>
<s><w>bacon</w>
<s><w>firefox</w>
<s><w>css</w>
<s><w>pup</w>
<s><w>css3</w>
<s><w>linux</w>
<s><w>python</w>
<s><w>openbox</w>
<s><w>debian</w>
<s><w>css2</w>
<s><w>mouse</w>
<s><w>gtk</w>
<s><w>script</w>
<s><w> php</w>
<s><w>tint</w>
<s><w>village</w>
<s><w>php.net</w>
<s><w>hiaw</w>
Code: Select all
<t>other</t>
Use your own tile.
7. /root/httpd/hiawatha/bookmark.ico (rw-r--r--)
Use your own icon.
Summary:
(remember to alter file permissions if necessary - see above):
File 1 is the mozilla bookmarks.html file
File 2 is the PHP script.
Files 3,4 and 5 are text files that hold the shortcut button configurations.
File 6 is the background wallpaper image for the PHP page.
File 7 is the shortcut (fav) icon for the PHP page.
Setting up:
1. Copy the above files to the specified locations.
2. Ensure file permissions are set correctly (otherwise you will get PHP error messages).
3. Place a shortcut icon on your browser toolbar to the PHP script (/root/httpd/hiawatha/bookmarks.php).
Description and how to use:
1. This PHP script only displays an existing bookmarks.html file.
2. Any recent bookmarks added to your browser toolbar will not appear until you export them to a new bookmarks.html file.
3. Domains starting 'https' are highlighted in light green all other domains are highlighted red.
4. The domain names can be distracting, so there is a DOMAIN button at the top ... click it to turn the highlighted domains on or off.
5. There are 3 Master Category buttons at the top, it is possible to alter a button's name by way of mousedown (left click and hold down) on the button for 2 seconds, then the text box contents will load onto the button.
6. Obviously you could alter the code and text files for more or less Master Category buttons or automate adding and removing them.
7. Below the text box are the Search buttons, when you search your links a Search button will be added in alphabetical order.
8. Mousedown (left click and hold down) on a Search button for 2 seconds whilst it is highlighted yellow and that will remove the button.
9. The browser 'mozilla, seamonkey default links' are not included in the results but you can easily add them manually.
10. The searches are case insensitive and search both the complete url string and the bookmark title, so nothing is missed.
11. When domain names are visible hyperlinks are listed in 'alphabetical order by url and then bookmark'. When domain names are hidden hyperlinks are listed in 'alphabetical order by bookmark and then url'.
12. Note that some links look identical, hover on them and the browser status bar reveals the complete url strings to be different pages.
Duplicate links are sometimes shown. Delete them if you want. It can be informative to compare the results obtained here, with searches obtained using the firefox bookmarks manager.
EDIT Script updated 23:50 UTC 2015-01-25 to alphabetically sort bookmarks when domains hidden. Please note: bookmarks.php code changed.
EDIT Script updated 00:30 UTC 2015-01-26 to set default state when page is first opened to domains hidden. if(strlen($hide_domain)<1) {$hide_domain=1;};
EDIT The script can read and display correctly with all browsers I have tried ... Firefox, Opera, Seamonkey, Pale Moon.
To create a correctly formatted bookmarks.html file (export HTML), I found that browsers Pale Moon 25.2.0 (x86) and Sea Monkey 2.24 (User agent: Mozilla/5.0 (X11; Linux i686; rv:27.0) Gecko/20100101 Firefox/27.0 SeaMonkey/2.24) worked identically and perfectly.
However a newer version of Firefox (Firefox 35.0) did not export 'correctly' and produced a jumbled and incomplete list of links when viewed with my script.
So I recommend trying an earlier version of Firefox (Firefox 27.0) on which Seamonkey 2.24 is based, when exporting the bookmarks.html file.
Once you have a good exported bookmarks.html file it doesn't matter which version of Firefox you use.
This reinforces the statement at the beginning of this post.
The bookmarks.html file is a third party (mozilla) code, so parsing it is an inherently fragile method, due to the possibility of future changes to its code, beyond our control.