<?php
/*
* This file is part of the Booby project.
* The booby project is located at the following location:
* http://www.nauta.be/booby/
*
* Booby - Copyright (c) 2003 - 2004 Barry Nauta
*
* The Booby project is released under the General Public License
* More detailes in the file 'gpl.html' or on the following
* website: http://www.gnu.org and look for licenses
*
* Enjoy :-)
*/
require_once ('base/util/StringUtils.php');
require_once ('base/util/ItemUtils.php');
/**
* Bookmark utilities
* This file allows import and export from and to opera bookmarks
*
* This file is a modified version of the one that can be found in
* the bookmark4u project (http://bookmark4u.sourceforge.net/)
* which I wrote some time ago
*
* @author Barry Nauta July 2003
* @package be.nauta.booby.plugins.bookmarks.util
* @copyright
*
* Copyright (c) 2003 - 2004 Barry Nauta
*
* The Booby project is released under the General Public License
* More detailes on the following
* website: <code>http://www.gnu.org</code>
* and look for licenses
*/
class BookmarkUtils extends ItemUtils
{
/**
* Empty default constructor
*/
function BookmarkUtils ()
{
parent::ItemUtils();
}
/**
* import a bookmark file into user's DB
*
* @param string userId the identifier for the user
* @param string userFile the file that contains the opera bookmarks
*/
function importOperaBookmarks ($userId, $userfile, $callback, $parentId)
{
$stringUtils = new StringUtils ();
$bookmarkOperations = $callback;
//= new BookmarkOperations ();
$name = "NAME=";
$url = "URL=";
$description = "DESCRIPTION=";
$typeIndicator = "Opera Hotlist";
// start at the root
$top=0;
$stack = array ();
$stack[$top++]=$parentId;
$fp = fopen($userfile, "r");
if ($fp == null)
{
die ("Failed to open " . $userfile);
}
// compare the first line. It should indicate that we are
// processing a bookmark file of the Opera browser
$firstLine = fgets($fp, 4096);
if (!$stringUtils->startsWith ($firstLine, $typeIndicator))
die ("Not a valid Opera file");
$processing = false;
// process the file
while (!feof($fp))
{
$currentLine = trim (fgets($fp, 4096));
// #FOLDER starts a (sub)folder
if ($currentLine == "#FOLDER")
{
$currentBookmark = new Bookmark
(null,null,null,null,
null,null,null,null,
null,null,null,null,null);
$currentBookmark->isParent=1;
$processing = true;
}
// #URL starts a bookmark
else if ($currentLine == "#URL")
{
$currentBookmark = new Bookmark
(null,null,null,null,
null,null,null,null,
null,null,null,null,null);
$currentBookmark->isParent=0;
$processing = true;
}
// - ends a folder
else if ($currentLine == "-")
{
// pop current folder from stack
$parentId = $stack[--$top];
$processing = false;
}
else if ($currentLine == "" && $processing)
{
// Ok, we found an empty line, this means that we have
// either found a folder or bookmark
//
// Attention! We will find an empty line just before a
// folder seperator and just after! Make sure that we
// are not processing the same bookmark twice (this is
// why the boolean 'processing' is used.
if ($currentBookmark->isParent == 1)
{
// place the current folder on the stack
$stack [$top++] = $parentId;
$currentBookmark->parentId=$parentId;
$parentId=$bookmarkOperations->
addItem($userId, $currentBookmark);
}
else
{
$currentBookmark->parentId=$parentId;
$bookmarkOperations->addItem
($userId, $currentBookmark);
}
$processing = false;
}
// Parse the actual bookmark content. Note that the 'processing'
// boolean is not needed here, but hey.... it cannot hurt
else if ($currentLine != "" && $processing)
{
// Parse for the string 'NAME='
if ($stringUtils->startsWith ($currentLine, $name))
{
$currentName= $stringUtils->getProperty ($currentLine, $name);
$currentBookmark->name=$currentName;
}
// Parse for the string 'DESCRIPTION='
else if ($stringUtils->startsWith ($currentLine, $description))
{
$currentDescription = $stringUtils->getProperty
($currentLine, $description);
$currentBookmark->description=$currentDescription;
}
// Parse for the string 'URL='
else if ($stringUtils->startsWith ($currentLine, $url))
{
$currentURL = $stringUtils->getProperty ($currentLine, $url);
$currentBookmark->locator=$currentURL;
}
else
{
// Ignore the rest.
}
}
}
fclose($fp);
}
/**
* Export users bookmarks (starting from a certain Id)
*
* @param string id the identifier for the user
* @param integer parent the identifier for the parent id of the bookmarks
* (to enable recursive functioncall)
*/
function exportOperaBookmarks ($id, $parent, $callback)
{
$bookmarkOperations = $callback;
$bookmarks = $bookmarkOperations->getChildren ($id, $parent);
$newline="\n";
$cnt_c = 0;
$cnt_b = 0;
for ($i=0;$i<count($bookmarks); $i++)
{
$currentBookmark = $bookmarks[$i];
if ($currentBookmark->isParent == '1') { # folder
$cnt_c++;
echo("#FOLDER$newline");
echo("\tNAME=" . $currentBookmark->name . "$newline");
echo("\tCREATED=$newline");
echo("\tVISITED=0$newline");
echo("\tORDER=$cnt_c$newline");
echo("\tEXPANDED=YES$newline");
echo("\tPERSONALBAR_POS=-1$newline");
echo("\tDESCRIPTION=".$currentBookmark->description."$newline");
echo("\tSHORT NAME=$newline$newline");
$this->exportOperaBookmarks($id, $currentBookmark->itemId, $callback);
echo("$newline-$newline");
}
else
{
$cnt_b++;
echo("#URL$newline");
echo("\tNAME=" . $currentBookmark->name . "$newline");
echo("\tURL=" . $currentBookmark->locator . "$newline");
echo("\tCREATED=$newline");
echo("\tVISITED=0$newline");
echo("\tPERSONALBAR_POS=-1$newline");
echo("\tPANEL_POS=-1$newline");
echo("\tDESCRIPTION=". $currentBookmark->description. "$newline");
echo("\tSHORT NAME=$newline");
echo("\tORDER=$cnt_b$newline$newline");
}
}
}
/**
* Imports bookmarks from a netscape file for a certain user
*
* @param string userId the identifier for the user
* @param string userfile the file that contains the netscape bookmarks
*/
function importNetscapeBookmarks($userId, $userfile, $callback, $parentId)
{
$stringUtils = new StringUtils ();
$bookmarkOperations = $callback;
$fp = fopen($userfile, "r");
// check the first line which identifies the type
$firstLine = fgets($fp, 4096);
$typeIndicator = "<!DOCTYPE NETSCAPE-Bookmark-file-1>";
if (!$stringUtils->startsWith ($firstLine, $typeIndicator))
die ("Not a valid Netscape file");
while (!feof($fp))
{
$currentLine = fgets($fp, 4096);
// Start a folder. Only used for indentation
if (ereg("^[ ]*<DL", $currentLine))
{
// nothing....
}
// Ends a (sub)folder. Only used for indentation
else if (ereg("^[ ]*<\/DL", $currentLine))
{
$top--;
// Hmm.. this seems to be a bug.... Next line should not be here.
if ($top < 0) { $top = 0; }
$parentId = $stack[$top];
}
// Starts a bookmark
else if (ereg("^[ ]*<DT", $currentLine))
{
if (ereg("<A", $currentLine))
{
$currentBookmark = new Bookmark
(null, null, null, null,
null, null, null, null,
null, null, null, null, null);
$locator = ereg_replace("([^H]*HREF=\")([^\"]*)(\".*)", "\\2", $currentLine);
$currentBookmark->locator = $locator;
$name = ereg_replace("^( *<DT><[^>]*>)([^<]*)(.*)", "\\2", $currentLine);
$currentBookmark->name = $name;
$currentBookmark->isParent = 0;
$currentBookmark->parentId = $parentId;
$bookmarkOperations->addItem
($userId, $currentBookmark);
}
// Start a folder
else
{
// the actual folder definition
$name = ereg_replace("^( *<DT><[^>]*>)([^<]*)(.*)", "\\2", $currentLine);
$currentBookmark = new Bookmark
(null, null, null, null,
null, null, null, null,
null, null, null, null, null);
$currentBookmark->isParent = 1;
$currentBookmark->parentId = $parentId;
$currentBookmark->name = $name;
// put the current folder on the stack
$stack[$top] = $parentId;
$top++;
// rertieve the new parent id by adding
// its
$parentId =
$bookmarkOperations->addItem
($userId, $currentBookmark);
}
}
}
fclose($fp);
}
/**
* Export bookmarks for a certain user starting at a certain
* item
*
* @param string userId the indentifier for the user for which we would
* like to export bookmarks
* @param integer rootId the identifier for the item and all its children
* which we would like to export.
*/
function exportNetscapeBookmarks ($userId, $rootId, $callback)
{
global $indentLevel;
$newline = "\n";
// This is not correct if we would like to generate a proper
// bookmark file from a subfolder
if ($rootId == 0)
{
echo ('<!DOCTYPE NETSCAPE-Bookmark-file-1>'.$newline);
echo ('<META HTTP-EQUIV="Content-Type" ');
echo ('CONTENT="text/html; charset=UTF-8">'.$newline);
echo ('<TITLE>Bookmarks</TITLE>'.$newline);
echo ('<H1>Bookmarks</H1>'.$newline.$newline);
echo ('<DL><p>'.$newline);
}
$bookmarkOperations = $callback;
//= new BookmarkOperations ();
$children = $bookmarkOperations->getChildren ($userId, $rootId);
for ($i=0; $i<count($children); $i++)
{
$current = $children [$i];
// We have a folder
if ($current->isParent==1)
{
// print the appropriate indentation
for ($j=0; $j<$indentLevel; $j++)
{
echo (' ');
}
// print name
echo ('<DT><H3>'.$current->name.'</H3>'.$newline);
for ($j=0; $j<$indentLevel; $j++)
{
echo (' ');
}
echo ('<DL><p>'.$newline);
// and do the same recursively for this folders
// children
$indentLevel++;
$this->exportNetscapeBookmarks ($userId,
$current->itemId, $bookmarkOperations);
$indentLevel--;
for ($j=1; $j<$indentLevel; $j++, $callback)
{
echo (' ');
}
echo ('</DL><p>'.$newline);
}
// we have a node (bookmark)
else
{
for ($j=0; $j<$indentLevel; $j++)
{
echo (' ');
}
echo ('<DT>');
echo ('<A HREF="'.$current->locator.'">');
echo ($current->name.'</A>'.$newline);
}
}
// proper closing
if ($rootId == null)
{
echo ('</DL><p>'.$newline);
}
}
}
?>