<?php
/*
 * $Horde: imp/folders.php,v 2.125.2.26 2004/05/28 12:15:03 jan Exp $
 *
 * Copyright 2000-2004 Charles J. Hagenbuch <chuck@horde.org>
 * Copyright 2000-2004 Jon Parise <jon@horde.org>
 * Copyright 2000-2004 Anil Madhavapeddy <avsm@horde.org>
 *
 * See the enclosed file COPYING for license information (GPL).  If you
 * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
 */

define('IMP_BASE', dirname(__FILE__));

$session_control = 'cache_ssl_downloads';
require_once IMP_BASE . '/lib/base.php';
require_once IMP_BASE . '/lib/Tree.php';
require_once IMP_BASE . '/lib/Folder.php';

/* Redirect back to the mailbox if folder use is not allowed. */
if (!$conf['user']['allow_folders']) {
    header('Location: ' . Horde::applicationUrl('mailbox.php', true));
    exit;
}

IMP::checkAuthentication(OP_HALFOPEN);

$quota_html = '';
if (!empty($conf['hooks']['quota']) && function_exists($conf['hooks']['quota'])) {
    imap_close($imp['stream']);
    $quota_html = call_user_func($conf['hooks']['quota'], $imp);
    IMP::authenticate(OP_HALFOPEN, true);
}

$imaptree = &new IMP_Tree($conf['server']['show_dotfiles'], $conf['server']['hierarchies']);

/* Check to see if user has a defined set of folders to poll */
if (!$prefs->isLocked('nav_poll')) {
    $folderPollList = @unserialize($prefs->getValue('nav_poll'));
}

/* If not, then only check the INBOX */
if (!isset($folderPollList) || !is_array($folderPollList)) {
    $folderPollList = array('INBOX' => true);
}

/* This reinitializes the $imaptree variable and recalculates the
 * folder list */
function initializeTree() {
    global $prefs, $imaptree, $showAll;
    $imaptree->init($prefs->getValue('subscribe') && !$showAll);
    switch ($prefs->getValue('nav_expanded')) {
    case 1:
        $imaptree->expandAllFolders();
        break;
    case 2:
        $imaptree->expandAsLast();
        break;
    }
}

/* Utility function to return a url for the various folder images */
function folderImage($name, $alt, $width, $height) {
    return Horde::img('folders/' . $name,
                      'hspace="0" alt="' . $alt . '" width="' . $width . '" height="' . $height . '"');
}

/* Decide whether or not to show all the unsubscribed folders */
if ($prefs->getValue('subscribe') && isset($imp['showunsub'])) {
    $showAll = $imp['showunsub'];
} else {
    $showAll = false;
}

if (isset($imp['imaptree']) && is_array($imp['imaptree'])) {
    $imaptree->unpickle($imp['imaptree']);
} else {
    initializeTree();
}

$refresh_time = $prefs->getValue('refresh_time');

/* Run through the action handlers */
$actionID = Horde::getFormData('actionID', NO_ACTION);
switch ($actionID) {

 case NO_ACTION:
     break;

 case EXPAND_FOLDER:
     $folder = Horde::getFormData('folder');
     if (!empty($folder)) {
         $imaptree->expand($folder);
     }
     break;

 case EXPAND_ALL_FOLDERS:
     $imaptree->expandAllFolders();
     break;

 case COLLAPSE_FOLDER:
     $folder = Horde::getFormData('folder');
     if (!empty($folder)) {
         $imaptree->collapse($folder);
     }
     break;

 case COLLAPSE_ALL_FOLDERS:
     $imaptree->collapseAllFolders();
     break;

 case REFRESH_FOLDERS:
     initializeTree();
     break;

 case DELETE_FOLDER:
     $folder_list = Horde::getFormData('folder_list');
     if (is_array($folder_list)) {
         if (IMP_Folder::delete($imp['stream'], $folder_list, $prefs->getValue('subscribe'))) {
             foreach ($folder_list as $folder) {
                 $imaptree->delete(IMP::serverString() . $folder);
                 if (isset($folderPollList[$folder])) {
                     unset($folderPollList[$folder]);
                 }
             }
             $prefs->setValue('nav_poll', serialize($folderPollList));
             $prefs->store();
         }
     }
     break;

 case DOWNLOAD_FOLDER:
     $download_folders = Horde::getFormData('folder_list');
     if (is_array($download_folders)) {
         $mbox = IMP_Folder::generateMbox($imp['stream'],
                                          $download_folders,
                                          false);

         header('Content-Length: ' . strlen($mbox));
         header('Content-Type: application/RFC822');

         /* This should force a save file dialog.  According to a note
          * in MSDN, the suggested filename should NOT be in quotes.
          *
          * For IE 5.5, we break the header in a special way that makes
          * things work. I don't really want to know. */
         if ($browser->hasQuirk('break_disposition_header')) {
             header('Content-Disposition: filename=' . $download_folders[0] . '.mbox');
         } else {
             header('Content-Disposition: attachment; filename=' . $download_folders[0] . '.mbox');
         }
         /* Overwrite Pragma: and other caching headers for IE. */
         if ($browser->hasQuirk('cache_ssl_downloads')) {
            header('Expires: 0');
            header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
            header('Pragma: public');
         }
         echo $mbox;
         exit;
     }
     break;

 case CREATE_FOLDER:
     $new_mailbox = Horde::getFormData('new_mailbox');
     if (!empty($new_mailbox)) {
         $new_mailbox = IMP::utf7Encode($new_mailbox);
         $folder_list = Horde::getFormData('folder_list');
         if (is_array($folder_list) &&
             count($folder_list) == 1) {
             $new_mailbox = $folder_list[0] . $imaptree->delimiter . $new_mailbox;
         } elseif (!empty($imp['folders'])) {
             $new_mailbox = $imp['folders'] . $new_mailbox;
         }

         if (IMP_Folder::create($imp['stream'], $new_mailbox, $prefs->getValue('subscribe'))) {
             initializeTree();
         }
     }
     break;

 case RENAME_FOLDER:
     $new_names = explode("\n", Horde::getFormData('new_names'));
     $old_names = explode("\n", Horde::getFormData('old_names'));
     if (!empty($new_names) && !empty($old_names) &&
         (count($new_names) == count($old_names))) {
         for ($i = 0; $i < sizeof($new_names); $i++) {
             IMP_Folder::rename($imp['stream'], $old_names[$i],
                                IMP::addPreambleString(IMP::utf7Encode($new_names[$i])),
                                $prefs->getValue('subscribe'));
         }
         initializeTree();
     }
     break;

 case SUBSCRIBE_FOLDER:
     $folder_list = Horde::getFormData('folder_list');
     if (is_array($folder_list)) {
         IMP_Folder::subscribe($imp['stream'], $folder_list);
     } else {
         Horde::raiseMessage(_("No folders were specified"), HORDE_MESSAGE);
     }
     initializeTree();
     break;

 case UNSUBSCRIBE_FOLDER:
     $folder_list = Horde::getFormData('folder_list');
     if (is_array($folder_list)) {
         IMP_Folder::unsubscribe($imp['stream'], $folder_list);
     } else {
         Horde::raiseMessage(_("No folders were specified"), HORDE_MESSAGE);
     }
     initializeTree();
     break;

 case TOGGLE_SUBSCRIBED_VIEW:
     if ($prefs->getValue('subscribe')) {
         $imp['showunsub'] = ($showAll = !$showAll);
     }
     initializeTree();
     break;

 case POLL_FOLDER:
     $folder_list = Horde::getFormData('folder_list');
     if (is_array($folder_list) && !$prefs->isLocked('nav_poll')) {
         foreach ($folder_list as $folder) {
             $folderPollList[$folder] = true;
         }
         $prefs->setValue('nav_poll', serialize($folderPollList));
         $prefs->store();
     }
     break;

 case NOPOLL_FOLDER:
     $folder_list = Horde::getFormData('folder_list');
     if (is_array($folder_list) && !$prefs->isLocked('nav_poll')) {
         foreach ($folder_list as $folder) {
             if (isset($folderPollList[$folder])) {
                 unset($folderPollList[$folder]);
             }
         }
         $prefs->setValue('nav_poll', serialize($folderPollList));
         $prefs->store();
     }
     break;

 case EMPTY_MAILBOX:
     $folder_list = Horde::getFormData('folder_list');
     if (is_array($folder_list) && count($folder_list)) {
         foreach ($folder_list as $folder) {
             $display_folder = IMP::displayFolder($folder);
             if (@imap_reopen($imp['stream'], IMP::serverString() . $folder) !== true) {
                 Horde::raiseMessage(sprintf(_("Could not delete messages from %s: %s"), $display_folder, imap_last_error()), HORDE_ERROR);
             } else {
                 $check = @imap_check($imp['stream']);
                 if (!is_object($check)) {
                     Horde::raiseMessage(sprintf(_("%s does not appear to be a valid mailbox."), $display_folder), HORDE_ERROR);
                 } elseif (empty($check->Nmsgs)) {
                     Horde::raiseMessage(sprintf(_("%s is already empty."), $display_folder), HORDE_MESSAGE);
                 } elseif (!@imap_delete($imp['stream'], '1:*')) {
                     Horde::raiseMessage(sprintf(_("Could not delete messages from %s: %s"), $display_folder, imap_last_error()), HORDE_ERROR);
                 } elseif (!@imap_expunge($imp['stream'])) {
                     Horde::raiseMessage(sprintf(_("Could not delete messages from %s: %s"), $display_folder, imap_last_error()), HORDE_ERROR);
                 }
                 else {
                     Horde::raiseMessage(sprintf(_("Cleared all messages from %s."), $display_folder), HORDE_MESSAGE);
                 }
             }
         }
     }
     break;
}

/* Display the correct message on the action bar */
$subToggleText = $showAll ? _("Hide Unsubscribed") : _("Show Unsubscribed");

/* Set the URL to refresh the page to in the META tag */
$refresh_url = Horde::applicationUrl('folders.php', true);

if ($conf['compress_pages']) {
    ob_start('ob_gzhandler');
}

$title = _("Folder Navigator");
$js_onLoad = null;
require IMP_TEMPLATES . '/common-header.inc';
require IMP_BASE . '/menu.php';
require IMP_BASE . '/status.php';
echo $quota_html;

/* Default to the very top of the hierarchy */
if (!isset($pattern)) {
    $pattern = '%';
}

$i = 0;
$imaptree->reset();
$newmsgs = array();
$rowct = false;

require IMP_TEMPLATES . '/folders/javascript.inc';
require IMP_TEMPLATES . '/folders/head.inc';
require IMP_TEMPLATES . '/folders/actions.inc';

/* Always poll the INBOX for new mail */
$nm = $imaptree->updateMessageInfo();
$hd = $imaptree->head();
if (isset($hd['newmsg']) && $hd['newmsg'] > 0) {
    $newmsgs['INBOX'] = $hd['newmsg'];
}

if ($showAll) {
    $unsubList = IMP::flistUnsubscribed();
}

/* Start iterating through the list of mailboxes, displaying them */
$mailbox = $imaptree->head();

while (isset($mailbox) && is_array($mailbox)) {
    /* Determine if we need to poll this mailbox for new messages */
    if (isset($folderPollList[$mailbox['value']])) {
        $updateCache = true;
    } else {
        $updateCache = false;
    }

    /* If we have stale information in the imaptree cache, then zero it */
    if (!$updateCache && isset($mailbox['messages'])) {
        $imaptree->flushMessageInfo();
        $mailbox = $imaptree->current();
    }

    /* If we need message information for this folder, update it now */
    if ($updateCache) {
        $imaptree->updateMessageInfo();
        $mailbox = $imaptree->current();
    }

    /* Populate the $newmsgs hash with new msgs since last view of the navigator */
    if (isset($mailbox['newmsg']) && $mailbox['newmsg'] > 0) {
        $newmsgs[$mailbox['value']] = $mailbox['newmsg'];
    }

    /* Highlight mailboxes with unread messages in bold */
    if (isset($mailbox['unseen']) && $mailbox['unseen'] > 0) {
        $mailbox['label'] = '<b>' . $mailbox['label'] . '</b>';
    }

    if (!($mailbox['attributes'] & LATT_NOSELECT)) {
        $name = Horde::link(Horde::applicationUrl('mailbox.php?newmail_popup=no&mailbox=' . urlencode($mailbox['value'])),
                _("View messages in ") . IMP::displayFolder($mailbox['value'])) .
                $mailbox['label'] . '</a>';

        if ($mailbox['value'] == 'INBOX') {
            $dir2 = folderImage('inbox.gif', _("INBOX"), 16, 16);
        } elseif ($mailbox['attributes'] & LATT_MARKED) {
            $dir2 = folderImage('mbox_marked.gif', _("Mailbox"), 16, 16);
        } elseif ($mailbox['attributes'] & LATT_UNMARKED) {
            $dir2 = folderImage('mbox_unmarked.gif', _("Mailbox"), 16, 16);
        } else {
            $dir2 = folderImage('mbox.gif', _("Mailbox"), 16, 16);
        }
    } else {
        $name = $mailbox['label'];
        if ($imaptree->isOpen($mailbox)) {
            $dir2 = folderImage('folder_open.gif', _("Open Folder"), 16, 16);
        } else {
            $dir2 = folderImage('folder.gif', _("Closed Folder"), 16, 16);
        }
    }

    if ($imaptree->hasChildren($mailbox)) {

        if ($imaptree->isOpen($mailbox)) {
            $dir = Horde::link(Horde::applicationUrl('folders.php?actionID=' . COLLAPSE_FOLDER . "&folder=" .
                   urlencode($imaptree->server . $mailbox['value'])), _("Collapse Folder")) .
                   folderImage('expanded.gif', _("Collapse Folder"), 18, 18) . "</a>$dir2";
        } else {
            $dir = Horde::link(Horde::applicationUrl('folders.php?actionID=' . EXPAND_FOLDER . "&folder=" .
                   urlencode($imaptree->server . $mailbox['value'])), _("Expand Folder")) .
                   folderImage('collapsed.gif', _("Expand Folder"), 18, 18) . "</a>$dir2";
        }
    } else {
        $dir = folderImage('empty.gif','', 18, 18) . $dir2;
    }

    /* set up status information */
    if ($name == $mailbox['label']) {
        $msgs = '&nbsp;';
        $new  = '&nbsp;';
    } else {
        if (isset($mailbox['messages'])) {
            $msgs = $mailbox['messages'];
        } else {
            $msgs = '&nbsp;';
        }
        if (isset($mailbox['unseen'])) {
            $new = $mailbox['unseen'];
        } else {
            $new = '&nbsp;';
        }
    }

    if ($showAll && isset($unsubList[$mailbox['value']])) {
        $navclass = 'folderunsub';
    } else {
        $navclass = ($rowct = !$rowct) ? 'list' : 'listlt';
    }

    $indent_level = $mailbox['level'];
    if ($imaptree->prefix != '' && $mailbox['value'] != 'INBOX' &&
        substr($mailbox['value'], 0, strlen($imaptree->noTrailingDelimiter($imaptree->prefix))) == $imaptree->noTrailingDelimiter($imaptree->prefix)) {
        // We have a folder prefix, shift each folder in the hierarchy
        // up one level before showing it to the user
        $indent_level--;
    }
    if ($indent_level < 0) {
        // This is a folder prefix; hide it from the user, and revert
        // rowct, since we hide the folder prefix
        $rowct = !$rowct;
    } else {
        // Display the folder
        include IMP_TEMPLATES . '/folders/row.inc';
        $displayNames[] = addslashes(IMP::displayFolder($mailbox['value']));
        $i++;
    }

    if ($imaptree->isOpen($mailbox)) {
        $mailbox = $imaptree->next();
    } else {
        $mailbox = $imaptree->nextOnLevel();
    }
}

/* Put the tree back into the session object for caching */
$imp['imaptree'] = $imaptree->pickle();

require IMP_TEMPLATES . '/folders/actions.inc';
require IMP_TEMPLATES . '/folders/foot.inc';

/* Check to see if user wants new mail notification */
if ($prefs->getValue('nav_popup') && 
    (Horde::getFormData('newmail_popup') != 'no')) {
    $alert = '';
    $count = 0;
    foreach ($newmsgs as $mb => $nm) {
        $count++;
        $mailbox_message = $mb;
        $alert .= IMP::displayFolder($mailbox_message) . ($nm > 1 ? _(" - $nm new messages") : _(" - $nm new message")) . '\n';
    }
    if (!empty($alert)) {
        if ($count == 1) {
            include IMP_TEMPLATES . '/folders/confirm.inc';
        } else {
            include IMP_TEMPLATES . '/folders/alert.inc';
        }
    }
}

$registry->shutdown();

require IMP_TEMPLATES . '/common-footer.inc';

// Catch error messages from c-client.
imap_errors();
