<?php
/**
 * $Horde: trean/data.php,v 1.57 2008-01-02 11:14:01 jan Exp $
 *
 * Copyright 2002-2008 The Horde Project (http://www.horde.org/)
 *
 * See the enclosed file LICENSE for license information (BSD). If you did not
 * did not receive this file, see http://www.horde.org/licenses/bsdl.php.
 *
 * @author  Mike Cochrane <mike@graftonhall.co.nz>
 * @package Trean
 */

function export($folder, $depth, $recursive = true)
{
    $name = $folder->get('name');
    if (empty($name)) {
        $name = _("Bookmarks");
    }

    $output = '';
    if ($folder->getId() != $GLOBALS['trean_shares']->getId(Auth::getAuth())) {
        $output .= sprintf('%1$s<DT><H3 FOLDED ADD_DATE="%2$s">%3$s</H3>' . "\n" . '%1$s<DL><p>' . "\n",
                           str_repeat(' ', $depth * 4), time(), $name);
    }

    $bookmarks = $folder->listBookmarks();
    foreach ($bookmarks as $bookmark) {
        $output .= sprintf('%s<DT><A HREF="%s" ADD_DATE="%s" LAST_VISIT="0" LAST_MODIFIED="0">%s</A>' . "\n",
                           str_repeat(' ', ($depth + 1) * 4),
                           $bookmark->url,
                           time(),
                           $bookmark->title);
    }

    if ($recursive) {
        $folders = Trean::listFolders(PERMS_SHOW, $folder->getName(), false);
        if (is_a($folders, 'PEAR_Error')) {
            $notification->push(sprintf(_("An error occured listing folders: %s"), $folders->getMessage()), 'horde.error');
        } else {
            foreach ($folders as $subfolder) {
                $output .= export($subfolder, $depth + 1);
            }
        }
    }

    return $output . str_repeat(' ', $depth * 4) . '</DL><p>'  . "\n";
}

$tags = null;
$curtag_id = -1;

function startElement($parser, $name, $attrs)
{
	global $tags;
	global $curtag_id;

	$tag = array (
		"name" => trim(strip_tags($name)),
		"attrs" => $attrs,
		"parent_id" => $curtag_id
	);

	if (!isset($tags)) {
		$tags = array(0 => $tag);
		$curtag_id = 0;
	} else {
		$tags[] = $tag;
		$curtag_id = count($tags) - 1;
	}
}

function endElement($parser, $name)
{
	global $tags;
	global $curtag_id;

	$curtag_id = $tags[$curtag_id]['parent_id'];
}

function characterDataElement($parser, $data)
{
	global $tags;
	global $curtag_id;

	$tags[$curtag_id]["cdata"] .= trim(strip_tags($data));
}

@define('TREAN_BASE', dirname(__FILE__));
require_once TREAN_BASE . '/lib/base.php';

$folders_exceeded = Trean::hasPermission('max_folders') !== true &&
Trean::hasPermission('max_folders') <= Trean::countFolders();
if ($folders_exceeded) {
    $message = @htmlspecialchars(sprintf(_("You are not allowed to create more than %d folders."), Trean::hasPermission('max_folders')), ENT_COMPAT, NLS::getCharset());
    if (!empty($conf['hooks']['permsdenied'])) {
        $message = Horde::callHook('_perms_hook_denied', array('trean:max_folders'), 'horde', $message);
    }
    $notification->push($message, 'horde.warning', array('content.raw'));
}
$bookmarks_exceeded = Trean::hasPermission('max_bookmarks') !== true &&
Trean::hasPermission('max_bookmarks') <= $trean_shares->countBookmarks();
if ($bookmarks_exceeded) {
    $message = @htmlspecialchars(sprintf(_("You are not allowed to create more than %d bookmarks."), Trean::hasPermission('max_bookmarks')), ENT_COMPAT, NLS::getCharset());
    if (!empty($conf['hooks']['permsdenied'])) {
        $message = Horde::callHook('_perms_hook_denied', array('trean:max_bookmarks'), 'horde', $message);
    }
    $notification->push($message, 'horde.warning', array('content.raw'));
}

switch (Util::getFormData('actionID')) {
case 'import':
    $result = Browser::wasFileUploaded('import_file');
    if (is_a($result, 'PEAR_Error')) {
        $notification->push($result->getMessage(), 'horde.error');
        break;
    }

    $target = Util::getFormData('target', $trean_shares->getId(Auth::getAuth()));
    $root = &$trean_shares->getFolder($target);
    if (is_a($root, 'PEAR_Error')) {
        $notification->push($root, 'horde.error');
        break;
    }

    $contents = implode ("", file($_FILES['import_file']['tmp_name']));

    // start from the "root folder"
    $bookmark_data = stristr($contents, "<dl>");

    // remove non significant tags
    $bookmark_data = eregi_replace("(<p>|<hr>)", "", $bookmark_data);

    $bookmark_data = ereg_replace("&", "&amp;", $bookmark_data);

    // close opened tags
    $bookmark_data = ereg_replace("(<DT>[^\n]*</H3>)\n", "\\1</DT>\n", $bookmark_data);
    $bookmark_data = ereg_replace("(<DT>[^\n]*</A>)\n", "\\1</DT>\n", $bookmark_data);
    $bookmark_data = ereg_replace("(<DD>[^\n]*)(\n[ \t\n]*(<D[TL]>|</DL>))", "\\1</DD>\\2", $bookmark_data);

    $xml_parser = xml_parser_create();

    xml_set_element_handler($xml_parser, "startElement", "endElement");
    xml_set_character_data_handler($xml_parser, "characterDataElement");

    if (!xml_parse($xml_parser, $bookmark_data, TRUE)) {
        $message = @htmlspecialchars(sprintf(_("XML error: %s at line %d"), xml_error_string(xml_get_error_code($xml_parser)), xml_get_current_line_number($xml_parser)));
        if (!empty($conf['hooks']['permsdenied'])) {
            $message = Horde::callHook('_perms_hook_denied', array('trean:max_folders'), 'horde', $message);
        }
        $notification->push($message, 'horde.error', array('content.raw'));
        xml_parser_free($xml_parser);
        exit;
    }

    xml_parser_free($xml_parser);



    $folders = 0;
    $bookmarks = 0;
    $folder = &$root;
    $bookmark = null;
    $stack = array();
    $stack_dl_id = array();
    $max_folders = Trean::hasPermission('max_folders');
    $num_folders = Trean::countFolders();
    $stop_folders = false;
    $max_bookmarks = Trean::hasPermission('max_bookmarks');
    $num_bookmarks = $trean_shares->countBookmarks();

    foreach ($tags as $key => $tag) {
        if ($tag['name'] == "H3" && $tags[$tag['parent_id']]['name'] == "DT") {
            /* Start of a folder. */
            if ($stop_folders) {
                continue;
            }
            if ($max_folders !== true && $num_folders >= $max_folders) {
                $message = @htmlspecialchars(sprintf(_("You are not allowed to create more than %d folders."), Trean::hasPermission('max_folders')), ENT_COMPAT, NLS::getCharset());
                if (!empty($conf['hooks']['permsdenied'])) {
                    $message = Horde::callHook('_perms_hook_denied', array('trean:max_folders'), 'horde', $message);
                }
                $notification->push($message, 'horde.error', array('content.raw'));
                $stop_folders = true;
                continue;
            }

            $stack[] = $folder->getId();
            $folderId = $folder->addFolder(array('name' => $tag['cdata']));
            $folder = &$trean_shares->getFolder($folderId);
            $bookmark = null;
            $folders++;
            $num_folders++;

        } elseif (count($stack) > 0 && $tag['name'] == "DL") {
            $stack_dl_id[] = $key;

	} elseif (count($stack) > 0 && $tag['name'] == "DT" && $tag['parent_id'] != end($stack_dl_id)) {
            if (count($stack) > 0) {
                $folder = &$trean_shares->getFolder(array_pop($stack));
                $bookmark = null;
                array_pop($stack_dl_id);
            }

        } elseif ($tag['name'] == "A" && $tags[$tag['parent_id']]['name'] == "DT") {
            /* A bookmark. */
            if ($max_bookmarks !== true && $num_bookmarks >= $max_bookmarks) {
                $message = @htmlspecialchars(sprintf(_("You are not allowed to create more than %d bookmarks."), Trean::hasPermission('max_bookmarks')), ENT_COMPAT, NLS::getCharset());
                if (!empty($conf['hooks']['permsdenied'])) {
                    $message = Horde::callHook('_perms_hook_denied', array('trean:max_bookmarks'), 'horde', $message);
                }
                $notification->push($message, 'horde.error', array('content.raw'));
                $stop_bookmarks = true;
                break;
            }

            $bookmark_id = $folder->addBookmark(array(
                'bookmark_url' => trim($tag['attrs']['HREF']),
                'bookmark_title' => $tag['cdata'],
                'bookmark_description' => ''));
            $bookmark = $trean_shares->getBookmark($bookmark_id);
            $bookmarks++;
            $num_bookmarks++;
        } elseif ($tag['name'] == "DD" && $tags[$tag['parent_id']]['name'] == "DL") {
            if (!is_null($bookmark)) {
                $bookmark->description = $tag['cdata'];
                $bookmark->save();
                $bookmark = null;
            }
        }
    }

    $notification->push(sprintf(_("%d Folders and %d Bookmarks imported."), $folders, $bookmarks), 'horde.success');

    $url = Util::addParameter('browse.php', 'f', $root->getId());
    header('Location: ' . Horde::applicationUrl($url, true));
    exit;

case 'export':
    $folderId = Util::getFormData('export_folder');
    $recursive = Util::getFormData('export_recursive');
    $output = <<<EOH
<!DOCTYPE NETSCAPE-Bookmark-file-1>
<!--This is an automatically generated file.
It will be read and overwritten.
Do Not Edit! -->
<Title>Bookmarks</Title>
<H1>Bookmarks</H1>
<DL><p>

EOH;
    $folder = $trean_shares->getFolder($folderId);
    $output .= export($folder, 1, $recursive) . '</DL><p>' . "\n";

    $browser->downloadHeaders('bookmarks.html', 'text/html', false,
                              strlen($output));
    echo $output;
    exit;
}

$title = _("Import Bookmarks");
require TREAN_TEMPLATES . '/common-header.inc';
require TREAN_TEMPLATES . '/menu.inc';
if (!$folders_exceeded || !$bookmarks_exceeded) {
    require TREAN_TEMPLATES . '/data/import.inc';
}
require TREAN_TEMPLATES . '/data/export.inc';
require $registry->get('templates', 'horde') . '/common-footer.inc';