public function compareReadmes($a, $b) { if ($this->_isHtmlReadme($a)) { return self::CHOOSE_A; } if ($this->_isHtmlReadme($b)) { return self::CHOOSE_B; } $a_len = Horde_String::length($a->getFileName()); $b_len = Horde_String::length($b->getFileName()); if ($a_len < $b_len) { return self::CHOOSE_A; } elseif ($b_len < $a_len) { return self::CHOOSE_B; } else { return strcasecmp($a->getFileName(), $b->getFileName()); } }
/** * Return a string containing an <option> listing of the given * gallery array. * * @param array $params An array of options: * <pre> * (integer)selected The gallery_id of the gallery that is selected * (integer)perm The permissions filter to use [Horde_Perms::SHOW] * (mixed)attributes Restrict the galleries returned to those matching * the filters. Can be an array of attribute/values * pairs or a gallery owner username. * (boolean)all_levels * (integer)from The gallery to start listing at. * (integer)count The number of galleries to return. * (integer)ignore An Ansel_Gallery id to ignore when building the tree. * </pre> * * @return string The HTML to display the option list. */ public static function selectGalleries($params = array()) { $galleries = $GLOBALS['injector']->getInstance('Ansel_Storage')->listGalleries($params); $params = new Horde_Support_Array($params); $tree = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Tree')->create('gallery_tree', 'Select'); // Remove the ignored gallery, make sure it's also not the selected if ($params->ignore) { if ($params->selected == $params->ignore) { $params->selected = null; } } foreach ($galleries as $gallery) { $gallery_id = $gallery->id; $gallery_name = $gallery->get('name'); $label = Horde_String::abbreviate($gallery_name); $len = Horde_String::length($gallery_name); $treeparams = array(); $treeparams['selected'] = $gallery_id == $params->selected; $parent = $gallery->getParent(); $parent = empty($parent) ? null : $parent->id; $tree->addNode(array('id' => $gallery->id, 'parent' => $parent, 'label' => $label, 'params' => $treeparams)); } return $tree->getTree(); }
/** */ protected function _init() { global $injector, $notification, $page_output, $prefs, $registry, $session; $mailbox = $this->indices->mailbox; /* Call the mailbox redirection hook, if requested. */ try { $redirect = $injector->getInstance('Horde_Core_Hooks')->callHook('mbox_redirect', 'imp', array($mailbox)); if (!empty($redirect)) { Horde::url($redirect, true)->redirect(); } } catch (Horde_Exception_HookNotSet $e) { } $mailbox_url = Horde::url('basic.php')->add('page', 'mailbox'); $mailbox_imp_url = $mailbox->url('mailbox')->add('newmail', 1); $imp_flags = $injector->getInstance('IMP_Flags'); $imp_imap = $mailbox->imp_imap; $imp_search = $injector->getInstance('IMP_Search'); /* Run through the action handlers */ if (($actionID = $this->vars->actionID) && $actionID != 'message_missing') { try { $session->checkToken($this->vars->token); } catch (Horde_Exception $e) { $notification->push($e); $actionID = null; } } /* We know we are going to be exclusively dealing with this mailbox, * so select it on the IMAP server (saves some STATUS calls). Open * R/W to clear the RECENT flag. This call will catch invalid * mailboxes. */ $imp_imap->openMailbox($mailbox, Horde_Imap_Client::OPEN_READWRITE); $imp_mailbox = $mailbox->list_ob; /* Determine if mailbox is readonly. */ $readonly = $mailbox->readonly; switch ($actionID) { case 'change_sort': $mailbox->setSort($this->vars->sortby, $this->vars->sortdir); break; case 'blacklist': $injector->getInstance('IMP_Filter')->blacklistMessage($this->indices); break; case 'whitelist': $injector->getInstance('IMP_Filter')->whitelistMessage($this->indices); break; case 'spam_report': $injector->getInstance('IMP_Factory_Spam')->create(IMP_Spam::SPAM)->report($this->indices); break; case 'innocent_report': $injector->getInstance('IMP_Factory_Spam')->create(IMP_Spam::INNOCENT)->report($this->indices); break; case 'message_missing': $notification->push(_("Requested message not found."), 'horde.error'); break; case 'fwd_digest': case 'redirect_messages': case 'template_edit': if (count($this->indices)) { $compose_actions = array('fwd_digest' => 'fwd_digest', 'redirect_messages' => 'redirect_compose', 'template_edit' => 'template_edit'); $clink = new IMP_Compose_Link($this->vars); $options = array_merge(array('actionID' => $compose_actions[$actionID], 'muid' => strval($this->indices)), $clink->args); if ($prefs->getValue('compose_popup')) { $page_output->addInlineScript(array(Horde::popupJs(IMP_Basic_Compose::url(), array('novoid' => true, 'params' => array_merge(array('popup' => 1), $options)))), true); } else { IMP_Basic_Compose::url()->add($options)->redirect(); } } break; case 'delete_messages': $injector->getInstance('IMP_Message')->delete($this->indices, array('mailboxob' => $imp_mailbox)); break; case 'undelete_messages': $injector->getInstance('IMP_Message')->undelete($this->indices); break; case 'move_messages': case 'copy_messages': if (isset($this->vars->targetMbox) && count($this->indices) && (!$readonly || $actionID == 'copy_messages')) { $targetMbox = IMP_Mailbox::formFrom($this->vars->targetMbox); if (!empty($this->vars->newMbox) && $this->vars->newMbox == 1) { $targetMbox = IMP_Mailbox::get($this->vars->targetMbox)->namespace_append; $newMbox = true; } else { $targetMbox = IMP_Mailbox::formFrom($this->vars->targetMbox); $newMbox = false; } $injector->getInstance('IMP_Message')->copy($targetMbox, $actionID == 'move_messages' ? 'move' : 'copy', $this->indices, array('create' => $newMbox, 'mailboxob' => $imp_mailbox)); } break; case 'flag_messages': if (!$readonly && $this->vars->flag && count($this->indices)) { $flag = $imp_flags->parseFormId($this->vars->flag); $injector->getInstance('IMP_Message')->flag(array($flag['set'] ? 'add' : 'remove' => array($flag['flag'])), $this->indices); } break; case 'filter_messages': if (!$readonly) { $filter = IMP_Mailbox::formFrom($this->vars->filter); $q_ob = null; if (strpos($filter, self::FLAG_FILTER_PREFIX) === 0) { /* Flag filtering. */ $flag_filter = $imp_flags->parseFormId(substr($filter, strpos($filter, "") + 1)); try { $q_ob = $imp_search->createQuery(array(new IMP_Search_Element_Flag($flag_filter['flag'], $flag_filter['set'])), array('mboxes' => array($mailbox), 'type' => IMP_Search::CREATE_QUERY)); } catch (InvalidArgumentException $e) { } } else { /* Pre-defined filters. */ try { $q_ob = $imp_search->applyFilter($filter, array($mailbox)); } catch (InvalidArgumentException $e) { } } if ($q_ob) { IMP_Mailbox::get($q_ob)->url('mailbox')->redirect(); exit; } } break; case 'hide_deleted': $mailbox->setHideDeletedMsgs(!$prefs->getValue('delhide')); break; case 'expunge_mailbox': $injector->getInstance('IMP_Message')->expungeMailbox(array(strval($mailbox) => 1), array('mailboxob' => $imp_mailbox)); break; case 'filter': $mailbox->filter(); break; case 'empty_mailbox': $injector->getInstance('IMP_Message')->emptyMailbox(array(strval($mailbox))); break; case 'view_messages': $mailbox->url(IMP_Basic_Thread::url(), null, false)->add(array('mode' => 'msgview', 'muid' => strval($this->indices)))->redirect(); break; } /* Token to use in requests. */ $token = $session->getToken(); $search_mbox = $mailbox->search; /* Deal with filter options. */ if (!$readonly && IMP_Filter::canApplyFilters() && !$mailbox->filterOnDisplay() && ($mailbox->inbox || $prefs->getValue('filter_any_mailbox') && !$search_mbox)) { $filter_url = $mailbox_imp_url->copy()->add(array('actionID' => 'filter', 'token' => $token)); } /* Generate folder options list. */ if ($imp_imap->access(IMP_Imap::ACCESS_FOLDERS)) { $iterator = new IMP_Ftree_IteratorFilter($injector->getInstance('IMP_Ftree')); $iterator->add($iterator::NONIMAP); $folder_options = new IMP_Ftree_Select(array('heading' => _("Messages to"), 'inc_notepads' => true, 'inc_tasklists' => true, 'iterator' => $iterator, 'new_mbox' => true)); } /* Build the list of messages in the mailbox. */ $pageOb = $imp_mailbox->buildMailboxPage($this->vars->mpage, $this->vars->start); $show_preview = $prefs->getValue('preview_enabled'); $mbox_info = $imp_mailbox->getMailboxArray(range($pageOb['begin'], $pageOb['end']), array('headers' => true, 'preview' => (int) $show_preview, 'type' => $prefs->getValue('atc_flag'))); /* Determine sorting preferences. */ $sortpref = $mailbox->getSort(); $thread_sort = $sortpref->sortby == Horde_Imap_Client::SORT_THREAD; /* Determine if we are going to show the Hide/Purge Deleted Message * links. */ if (!($use_trash = $prefs->getValue('use_trash')) && !$mailbox->vinbox) { $showdelete = array('hide' => true, 'purge' => $mailbox->access_expunge); } else { $showdelete = array('hide' => false, 'purge' => false); } if ($showdelete['hide'] && !$prefs->isLocked('delhide')) { if ($prefs->getValue('delhide')) { $deleted_prompt = _("Show Deleted"); } else { $deleted_prompt = _("Hide Deleted"); } } /* Generate paging links. */ if ($pageOb['pagecount']) { if ($pageOb['page'] == 1) { $url_first = $url_prev = null; $pages_first = 'navfirstgreyImg'; $pages_prev = 'navleftgreyImg'; } else { $url_first = $mailbox_imp_url->copy()->add('mpage', 1); $pages_first = 'navfirstImg'; $url_prev = $mailbox_imp_url->copy()->add('mpage', $pageOb['page'] - 1); $pages_prev = 'navleftImg'; } if ($pageOb['page'] == $pageOb['pagecount']) { $url_last = $url_next = null; $pages_last = 'navlastgreyImg'; $pages_next = 'navrightgreyImg'; } else { $url_next = $mailbox_imp_url->copy()->add('mpage', $pageOb['page'] + 1); $pages_next = 'navrightImg'; $url_last = $mailbox_imp_url->copy()->add('mpage', $pageOb['pagecount']); $pages_last = 'navlastImg'; } } /* Generate RSS link. */ if ($mailbox->inbox) { $rss_box = ''; } else { $ns_info = $mailbox->namespace_info; if (is_null($ns_info)) { $rss_box = null; } else { $rss_box = str_replace(rawurlencode($ns_info->delimiter), '/', rawurlencode($ns_info->delimiter . ($ns_info->type == $ns_info::NS_PERSONAL ? $ns_info->stripNamespace($mailbox) : $mailbox))); } } if (!is_null($rss_box)) { $page_output->addLinkTag(array('href' => Horde::url('rss.php', true, -1) . $rss_box)); } /* If user wants the mailbox to be refreshed, set time here. */ $refresh_url = $mailbox_imp_url->copy()->add('mpage', $pageOb['page']); if (isset($filter_url)) { $filter_url->add('mpage', $pageOb['page']); } /* Determine if we are showing previews. */ $preview_tooltip = $show_preview ? $prefs->getValue('preview_show_tooltip') : false; if (!$preview_tooltip) { $strip_preview = $prefs->getValue('preview_strip_nl'); } $unread = $imp_mailbox->unseenMessages(Horde_Imap_Client::SEARCH_RESULTS_COUNT); $page_output->addInlineJsVars(array('ImpMailbox.pop3' => intval(!$mailbox->is_imap), 'ImpMailbox.text' => array('delete_messages' => _("Are you sure you wish to PERMANENTLY delete these messages?"), 'delete_all' => _("Are you sure you wish to delete all mail in this mailbox?"), 'delete_vfolder' => _("Are you sure you want to delete this Virtual Folder Definition?"), 'innocent_report' => _("Are you sure you wish to report this message as innocent?"), 'moveconfirm' => _("Are you sure you want to move the message(s)? (Some message information might get lost, like message headers, text formatting or attachments!)"), 'newmbox' => _("You are copying/moving to a new mailbox.") . "\n" . _("Please enter a name for the new mailbox:") . "\n", 'no' => _("No"), 'selectone' => _("You must select at least one message first."), 'selectonlyone' => _("You must select only one message for this action."), 'spam_report' => _("Are you sure you wish to report this message as spam?"), 'submit' => _("You must select at least one message first."), 'target_mbox' => _("You must select a target mailbox first.")), 'ImpMailbox.unread' => intval($unread))); $pagetitle = $this->title = $mailbox->label; if ($mailbox->editvfolder) { $query_text = wordwrap($imp_search[$mailbox]->querytext); $pagetitle .= ' [' . Horde::linkTooltip('#', $query_text, '', '', '', $query_text) . _("Virtual Folder") . '</a>]'; $this->title .= ' [' . _("Virtual Folder") . ']'; } elseif ($mailbox->editquery) { $query_text = wordwrap($imp_search[$mailbox]->querytext); $pagetitle = Horde::linkTooltip('#', $query_text, '', '', '', $query_text) . $pagetitle . '</a>'; } else { $pagetitle = $this->title = htmlspecialchars($this->title); } /* Generate mailbox summary string. */ $subinfo = new IMP_View_Subinfo(array('mailbox' => $mailbox)); $subinfo->value = $pagetitle . ' ('; if (empty($pageOb['end'])) { $subinfo->value .= _("No Messages"); } else { $subinfo->value .= $pageOb['pagecount'] > 1 ? sprintf(_("%d Messages"), $pageOb['msgcount']) . ' / ' . sprintf(_("Page %d of %d"), $pageOb['page'], $pageOb['pagecount']) : sprintf(_("%d Messages"), $pageOb['msgcount']); } $subinfo->value .= ')'; $injector->getInstance('Horde_View_Topbar')->subinfo = $subinfo->render(); $page_output->addScriptFile('hordecore.js', 'horde'); $page_output->addScriptFile('mailbox.js'); $page_output->addScriptPackage('Horde_Core_Script_Package_Dialog'); $page_output->metaRefresh($prefs->getValue('refresh_time'), $refresh_url); /* Prepare the header template. */ $view = new Horde_View(array('templatePath' => IMP_TEMPLATES . '/basic/mailbox')); $view->addHelper('FormTag'); $view->addHelper('Horde_Core_View_Helper_Accesskey'); $view->addHelper('Tag'); $hdr_view = clone $view; $hdr_view->readonly = $readonly; $hdr_view->refresh_url = $refresh_url; if (isset($filter_url)) { $hdr_view->filter_url = $filter_url; } if ($mailbox->access_search) { if (!$search_mbox) { $hdr_view->search_url = $mailbox->url(IMP_Basic_Searchbasic::url()); } else { if ($mailbox->editvfolder) { $edit_search = _("Edit Virtual Folder"); } elseif ($mailbox->query) { if ($mailbox->editquery) { $edit_search = _("Edit Search Query"); } else { /* Basic search results. */ $search_mailbox = IMP_Mailbox::get($imp_search[$mailbox]->mboxes[0]); $hdr_view->search_url = $search_mailbox->url(IMP_Basic_Searchbasic::url()); $hdr_view->searchclose = $search_mailbox->url('mailbox'); } } if (isset($edit_search)) { $hdr_view->edit_search_url = $imp_search->editUrl($mailbox); $hdr_view->edit_search_title = $edit_search; } } } if ($mailbox->access_empty) { $hdr_view->empty = $mailbox_imp_url->copy()->add(array('actionID' => 'empty_mailbox', 'token' => $token)); } $this->output = $hdr_view->render('header'); /* If no messages, exit immediately. */ if (empty($pageOb['end'])) { if ($pageOb['anymsg'] && isset($deleted_prompt)) { /* Show 'Show Deleted' prompt if mailbox has no viewable * message but has hidden, deleted messages. */ $del_view = clone $view; $del_view->hide = Horde::widget(array('url' => $refresh_url->copy()->add(array('actionID' => 'hide_deleted', 'token' => $token)), 'class' => 'hideAction', 'title' => $deleted_prompt)); if ($mailbox->access_expunge) { $del_view->purge = Horde::widget(array('url' => $refresh_url->copy()->add(array('actionID' => 'expunge_mailbox', 'token' => $token)), 'class' => 'purgeAction', 'title' => _("Pur_ge Deleted"))); } $this->output .= $del_view->render('actions_deleted'); } $empty_view = clone $view; $empty_view->search_mbox = $search_mbox; $this->output .= $empty_view->render('empty_mailbox'); return; } $clink_ob = new IMP_Compose_Link(); $clink = $clink_ob->link(); /* Display the navbar and actions if there is at least 1 message in * mailbox. */ if ($pageOb['msgcount']) { /* Prepare the navbar template. */ $n_view = clone $view; $n_view->id = 1; $n_view->readonly = $readonly; $filtermsg = false; if ($mailbox->access_flags) { $args = array('imap' => true, 'mailbox' => $search_mbox ? null : $mailbox); $form_set = $form_unset = array(); foreach ($imp_flags->getList($args) as $val) { if ($val->canset) { $form_set[] = array('f' => $val->form_set, 'l' => $val->label, 'v' => IMP_Mailbox::formTo(self::FLAG_FILTER_PREFIX . $val->form_set)); $form_unset[] = array('f' => $val->form_unset, 'l' => $val->label, 'v' => IMP_Mailbox::formTo(self::FLAG_FILTER_PREFIX . $val->form_unset)); } } $n_view->flaglist_set = $form_set; $n_view->flaglist_unset = $form_unset; if (!$search_mbox && $mailbox->access_search) { $filtermsg = $n_view->flag_filter = true; } } if (!$search_mbox && $mailbox->access_filters) { $filters = array(); $iterator = IMP_Search_IteratorFilter::create(IMP_Search_IteratorFilter::FILTER); foreach ($iterator as $val) { $filters[] = array('l' => $val->label, 'v' => IMP_Mailbox::formTo($val)); } if (!empty($filters)) { $filtermsg = true; $n_view->filters = $filters; } } $n_view->filtermsg = $filtermsg; if ($imp_imap->access(IMP_Imap::ACCESS_FOLDERS)) { $n_view->move = Horde::widget(array('url' => '#', 'class' => 'moveAction', 'title' => _("Move"), 'nocheck' => true)); $n_view->copy = Horde::widget(array('url' => '#', 'class' => 'copyAction', 'title' => _("Copy"), 'nocheck' => true)); $n_view->folder_options = $folder_options; } $n_view->mailbox_url = $mailbox_url; $n_view->mailbox = $mailbox->form_to; if ($pageOb['pagecount'] > 1) { $n_view->multiple_page = true; $n_view->pages_first = $pages_first; $n_view->url_first = $url_first; $n_view->pages_prev = $pages_prev; $n_view->url_prev = $url_prev; $n_view->pages_next = $pages_next; $n_view->url_next = $url_next; $n_view->pages_last = $pages_last; $n_view->url_last = $url_last; $n_view->page_val = $pageOb['page']; $n_view->page_size = Horde_String::length($pageOb['pagecount']); } $this->output .= $n_view->render('navbar'); /* Prepare the actions template. */ $a_view = clone $view; if ($mailbox->access_deletemsgs) { $del_class = $use_trash && $mailbox->trash ? 'permdeleteAction' : 'deleteAction'; $a_view->delete = Horde::widget(array('url' => '#', 'class' => $del_class, 'title' => _("_Delete"))); } if ($showdelete['purge'] || $mailbox->vtrash) { $a_view->undelete = Horde::widget(array('url' => '#', 'class' => 'undeleteAction', 'title' => _("_Undelete"))); } $mboxactions = array(); if ($showdelete['purge']) { $mailbox_link = $mailbox_imp_url->copy()->add('mpage', $pageOb['page']); if (isset($deleted_prompt)) { $mboxactions[] = Horde::widget(array('url' => $mailbox_link->copy()->add(array('actionID' => 'hide_deleted', 'token' => $token)), 'class' => 'hideAction', 'title' => $deleted_prompt)); } $mboxactions[] = Horde::widget(array('url' => $mailbox_link->copy()->add(array('actionID' => 'expunge_mailbox', 'token' => $token)), 'class' => 'purgeAction', 'title' => _("Pur_ge Deleted"))); } if (!$sortpref->sortby_locked && $sortpref->sortby != Horde_Imap_Client::SORT_SEQUENCE) { $mboxactions[] = Horde::widget(array('url' => $mailbox_imp_url->copy()->add(array('sortby' => Horde_Imap_Client::SORT_SEQUENCE, 'actionID' => 'change_sort', 'token' => $token)), 'title' => _("Clear Sort"))); } if ($mailbox->templates) { $a_view->templateedit = Horde::widget(array('url' => '#', 'class' => 'templateeditAction', 'title' => _("Edit Template"))); $mboxactions[] = Horde::widget(array('url' => $clink->copy()->add(array('actionID' => 'template_new')), 'title' => _("Create New Template"))); } $a_view->mboxactions = $mboxactions; if ($registry->hasMethod('mail/blacklistFrom')) { $a_view->blacklist = Horde::widget(array('url' => '#', 'class' => 'blacklistAction', 'title' => _("_Blacklist"))); } if ($registry->hasMethod('mail/whitelistFrom')) { $a_view->whitelist = Horde::widget(array('url' => '#', 'class' => 'whitelistAction', 'title' => _("_Whitelist"))); } if (IMP_Compose::canCompose()) { $a_view->forward = Horde::widget(array('url' => '#', 'class' => 'forwardAction', 'title' => _("Fo_rward"))); $a_view->redirect = Horde::widget(array('url' => '#', 'class' => 'redirectAction', 'title' => _("Redirect"))); } if ($mailbox->spam_show) { $a_view->spam = Horde::widget(array('url' => '#', 'class' => 'spamAction', 'title' => _("Report as Spam"))); } if ($mailbox->innocent_show) { $a_view->innocent = Horde::widget(array('url' => '#', 'class' => 'innocentAction', 'title' => _("Report as Innocent"))); } $a_view->view_messages = Horde::widget(array('url' => '#', 'class' => 'viewAction', 'title' => _("View Messages"))); $this->output .= $a_view->render('actions'); } /* Define some variables now so we don't have to keep redefining in * the foreach loop or the templates. */ $lastMbox = ''; $mh_count = 0; $sortImg = $sortpref->sortdir ? 'sortup' : 'sortdown'; $headers = array(Horde_Imap_Client::SORT_TO => array('id' => 'mboxto', 'stext' => _("Sort by To Address"), 'text' => _("To")), Horde_Imap_Client::SORT_FROM => array('id' => 'mboxfrom', 'stext' => _("Sort by From Address"), 'text' => _("Fro_m")), Horde_Imap_Client::SORT_THREAD => array('id' => 'mboxthread', 'stext' => _("Sort by Thread"), 'text' => _("_Thread")), Horde_Imap_Client::SORT_SUBJECT => array('id' => 'mboxsubject', 'stext' => _("Sort by Subject"), 'text' => _("Sub_ject")), IMP::IMAP_SORT_DATE => array('id' => 'mboxdate', 'stext' => _("Sort by Date"), 'text' => _("Dat_e")), Horde_Imap_Client::SORT_SIZE => array('id' => 'mboxsize', 'stext' => _("Sort by Message Size"), 'text' => _("Si_ze"))); /* If this is the Drafts or Sent-Mail mailbox, sort by To instead of * From. */ if ($mailbox->special_outgoing) { unset($headers[Horde_Imap_Client::SORT_FROM]); } else { unset($headers[Horde_Imap_Client::SORT_TO]); } /* Determine which of Subject/Thread to emphasize. */ if (!$mailbox->access_sortthread || $sortpref->sortby_locked) { unset($headers[Horde_Imap_Client::SORT_THREAD]); if ($sortpref->sortby_locked && $thread_sort) { $sortpref->sortby = Horde_Imap_Client::SORT_SUBJECT; } } else { if ($thread_sort) { $extra = Horde_Imap_Client::SORT_SUBJECT; $standard = Horde_Imap_Client::SORT_THREAD; } else { $extra = Horde_Imap_Client::SORT_THREAD; $standard = Horde_Imap_Client::SORT_SUBJECT; } $headers[$standard]['altsort'] = Horde::widget(array('url' => $mailbox_imp_url->copy()->add(array('actionID' => 'change_sort', 'token' => $token, 'sortby' => $extra)), 'title' => $headers[$extra]['text'])); unset($headers[$extra]); } foreach ($headers as $key => $val) { $ptr =& $headers[$key]; if ($sortpref->sortby == $key) { $csl_icon = '<span class="iconImg ' . $sortImg . '"></span>'; if ($sortpref->sortdir_locked) { $ptr['change_sort_link'] = $csl_icon; $ptr['change_sort_widget'] = Horde::stripAccessKey($val['text']); } else { $tmp = $mailbox_imp_url->copy()->add(array('sortby' => $key, 'sortdir' => intval(!$sortpref->sortdir), 'actionID' => 'change_sort', 'token' => $token)); $ptr['change_sort_link'] = Horde::link($tmp, $val['stext'], null, null, null, $val['stext']) . $csl_icon . '</a>'; $ptr['change_sort_widget'] = Horde::widget(array('url' => $tmp, 'title' => $val['text'])); } } else { $ptr['change_sort_link'] = null; $ptr['change_sort_widget'] = $sortpref->sortby_locked ? Horde::stripAccessKey($val['text']) : Horde::widget(array('url' => $mailbox_imp_url->copy()->add(array('actionID' => 'change_sort', 'token' => $token, 'sortby' => $key)), 'title' => $val['text'])); } $ptr['class'] = 'horde-split-left'; } /* Output the form start. */ $f_view = clone $view; $f_view->mailbox = $mailbox->form_to; $f_view->mailbox_url = $mailbox_url; $f_view->page = $pageOb['page']; $f_view->token = $token; $this->output .= $f_view->render('form_start'); /* Prepare the message headers template. */ $mh_view = clone $view; $mh_view->headers = $headers; if (!$search_mbox) { $mh_view->show_checkbox = !$mh_count++; $this->output .= $mh_view->render('message_headers'); } /* Initialize repetitively used variables. */ $fromlinkstyle = $prefs->getValue('from_link'); $imp_ui = new IMP_Mailbox_Ui($mailbox); /* Display message information. */ $msgs = array(); $search_view = clone $view; $summary_view = clone $view; while (list(, $ob) = each($mbox_info['overview'])) { if ($search_mbox) { if (empty($lastMbox) || $ob['mailbox'] != $lastMbox) { if (!empty($lastMbox)) { $this->_outputSummaries($msgs, $summary_view); $msgs = array(); } $mbox = IMP_Mailbox::get($ob['mailbox']); $search_view->mbox_link = Horde::link($mbox->url($mailbox_url), sprintf(_("View messages in %s"), $mbox->display), 'smallheader') . $mbox->display_html . '</a>'; $this->output .= $search_view->render('searchmbox'); $mh_view->show_checkbox = !$mh_count++; $this->output .= $mh_view->render('message_headers'); } } $lastMbox = $ob['mailbox']; /* Initialize the data fields. */ $msg = array('bg' => '', 'buid' => $imp_mailbox->getBuid($ob['mailbox'], $ob['uid']), 'class' => '', 'date' => $imp_ui->getDate($ob['envelope']->date), 'preview' => '', 'status' => '', 'size' => IMP::sizeFormat($ob['size'])); /* Generate the target link. */ if ($mailbox->drafts || $mailbox->templates) { $clink_copy = clone $clink_ob; $clink_copy->args['buid'] = $msg['buid']; $clink_copy->args['mailbox'] = $mailbox; $target = $clink_copy->link()->add(array('actionID' => $mailbox->drafts ? 'draft' : 'template')); } else { $target = $mailbox->url('message', $msg['buid']); } /* Get all the flag information. */ $flag_parse = $imp_flags->parse(array('flags' => $ob['flags'], 'headers' => $ob['headers'], 'runhook' => $ob, 'personal' => $ob['envelope']->to)); $css_class = $subject_flags = array(); foreach ($flag_parse as $val) { if ($val instanceof IMP_Flag_User) { $subject_flags[] = $val; } else { if (!$val->bgdefault) { $msg['bg'] = $val->bgcolor; } $css_class[] = $val->css; $msg['status'] .= $val->span; } } $msg['class'] = implode(' ', $css_class); /* Show message preview? */ if ($show_preview && isset($ob['preview'])) { if (empty($ob['preview'])) { $ptext = '[[' . _("No Preview Text") . ']]'; } else { $ptext = empty($strip_preview) ? str_replace("\r", '', $ob['preview']) : preg_replace(array('/\\n/', '/(\\s)+/'), array(' ', '$1'), str_replace("\r", "\n", $ob['preview'])); if (!$preview_tooltip) { $ptext = $injector->getInstance('Horde_Core_Factory_TextFilter')->filter($ptext, 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::NOHTML)); } $maxlen = $prefs->getValue('preview_maxlen'); if (Horde_String::length($ptext) > $maxlen) { $ptext = Horde_String::truncate($ptext, $maxlen); } elseif (empty($ob['previewcut'])) { $ptext .= '[[' . _("END") . ']]'; } } $msg['preview'] = $ptext; } /* Format the From: Header. */ $getfrom = $imp_ui->getFrom($ob['envelope']); $msg['from'] = htmlspecialchars($getfrom['from'], ENT_QUOTES, 'UTF-8'); switch ($fromlinkstyle) { case 0: $from_tmp = array(); foreach ($getfrom['from_list']->base_addresses as $from_ob) { $from_tmp[] = call_user_func_array(array('Horde', $preview_tooltip ? 'linkTooltip' : 'link'), array($clink->copy()->add(array('actionID' => 'mailto_link', 'to' => strval($from_ob))), sprintf(_("New Message to %s"), $from_ob->label))) . htmlspecialchars($from_ob->label, ENT_QUOTES, 'UTF-8') . '</a>'; } if (!empty($from_tmp)) { $msg['from'] = implode(', ', $from_tmp); } break; default: $from_uri = $mailbox->url('message', $msg['buid']); $msg['from'] = Horde::link($from_uri) . $msg['from'] . '</a>'; break; } /* Format the Subject: Header. */ $msg['subject'] = $imp_ui->getSubject($ob['envelope']->subject, true); $msg['subject'] = $preview_tooltip ? substr(Horde::linkTooltip($target, $msg['preview'], '', '', '', $msg['preview']), 0, -1) . ' class="mboxSubject">' . $msg['subject'] . '</a>' : substr(Horde::link($target, $imp_ui->getSubject($ob['envelope']->subject)), 0, -1) . ' class="mboxSubject">' . $msg['subject'] . '</a>' . (!empty($msg['preview']) ? '<br /><small>' . $msg['preview'] . '</small>' : ''); /* Add subject flags. */ foreach ($subject_flags as $val) { $flag_label = Horde_String::truncate($val->label, 12); $msg['subject'] = '<span class="' . $val->css . '" style="' . ($val->bgdefault ? '' : 'background:' . htmlspecialchars($val->bgcolor) . ';') . 'color:' . htmlspecialchars($val->fgcolor) . '" title="' . htmlspecialchars($val->label) . '">' . htmlspecialchars($flag_label) . '</span>' . $msg['subject']; } /* Set up threading tree now. */ if ($thread_sort) { $t_ob = $imp_mailbox->getThreadOb($ob['idx']); $msg['subject'] = ($sortpref->sortdir ? $t_ob->reverse_img : $t_ob->img) . ' ' . $msg['subject']; } $msgs[$msg['buid']] = $msg; } $this->_outputSummaries($msgs, $summary_view); $this->output .= '</form>'; /* If there are 20 messages or less, don't show the actions/navbar * again. */ if ($pageOb['end'] - $pageOb['begin'] >= 20) { $this->output .= $a_view->render('actions'); $n_view->id = 2; $this->output .= $n_view->render('navbar'); } }
/** * Returns the main text body of the message suitable for sending over * EAS response. * * @param array $options An options array containgin: * - bodyprefs: (array) Bodypref settings * DEFAULT: none (No bodyprefs used). * - mimesupport: (integer) Indicates if MIME is supported or not. * Possible values: 0 - Not supported 1 - Only S/MIME or * 2 - All MIME. * DEFAULT: 0 (No MIME support) * - protocolversion: (float) The EAS protocol we are supporting. * DEFAULT 2.5 * * @return array An array of one or both of 'plain' and 'html' content. * * @throws Horde_ActiveSync_Exception, Horde_Exception_NotFound */ public function getMessageBodyData(array $options = array()) { $version = empty($options['protocolversion']) ? Horde_ActiveSync::VERSION_TWOFIVE : $options['protocolversion']; // Look for the parts we need. We try to detect and fetch only the parts // we need, while ensuring we have something to return. So, e.g., if we // don't have BODYPREF_TYPE_HTML, we only request plain text, but if we // can't find plain text but we have a html body, fetch that anyway. $text_id = $this->_message->findBody('plain'); $html_id = $this->_message->findBody('html'); // Deduce which part(s) we need to request. $want_html_text = $version >= Horde_ActiveSync::VERSION_TWELVE && (!empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_HTML]) || !empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_MIME])); $want_plain_text = $version == Horde_ActiveSync::VERSION_TWOFIVE || empty($options['bodyprefs']) || !empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_PLAIN]) || !empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_RTF]) || !empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_MIME]) || $want_html_text && empty($html_id); $want_html_as_plain = false; if (!empty($text_id) && $want_plain_text) { $text_body_part = $this->_message->getPart($text_id); $charset = $text_body_part->getCharset(); } elseif ($want_plain_text && !empty($html_id) && empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_MIME])) { $want_html_text = true; $want_html_as_plain = true; } if (!empty($html_id) && $want_html_text) { $html_body_part = $this->_message->getPart($html_id); $html_charset = $html_body_part->getCharset(); } // Sanity check the truncation stuff if (empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_PLAIN]) && !empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_HTML]) && $want_plain_text && $want_html_text) { // We only have HTML truncation data, requested HTML body but only // have plaintext. $options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_PLAIN] = $options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_HTML]; } $query = new Horde_Imap_Client_Fetch_Query(); $query_opts = array('decode' => true, 'peek' => true); // Get body information if ($version >= Horde_ActiveSync::VERSION_TWELVE) { if (!empty($html_id)) { $query->bodyPartSize($html_id); $query->bodyPart($html_id, $query_opts); } if (!empty($text_id)) { $query->bodyPart($text_id, $query_opts); $query->bodyPartSize($text_id); } } else { // EAS 2.5 Plaintext body $query->bodyPart($text_id, $query_opts); $query->bodyPartSize($text_id); } try { $fetch_ret = $this->_imap->fetch($this->_mbox, $query, array('ids' => new Horde_Imap_Client_Ids(array($this->_uid)))); } catch (Horde_Imap_Client_Exception $e) { throw new Horde_ActiveSync_Exception($e); } if (!($data = $fetch_ret->first())) { throw new Horde_Exception_NotFound(sprintf('Could not load message %s from server.', $this->_uid)); } $return = array(); if (!empty($text_id) && $want_plain_text) { $text = $data->getBodyPart($text_id); if (!$data->getBodyPartDecode($text_id)) { $text_body_part->setContents($text); $text = $text_body_part->getContents(); } $text_size = !is_null($data->getBodyPartSize($text_id)) ? $data->getBodyPartSize($text_id) : Horde_String::length($text); if (!empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize'])) { // EAS >= 12.0 truncation $text = Horde_String::substr($text, 0, $options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize'], $charset); } $truncated = $text_size > Horde_String::length($text); if ($version >= Horde_ActiveSync::VERSION_TWELVE && $truncated && !empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['allornone'])) { $text = ''; } $return['plain'] = array('charset' => $charset, 'body' => $text, 'truncated' => $truncated, 'size' => $text_size); } if (!empty($html_id) && $want_html_text) { $html = $data->getBodyPart($html_id); if (!$data->getBodyPartDecode($html_id)) { $html_body_part->setContents($html); $html = $html_body_part->getContents(); } // Size of the original HTML part. $html_size = !is_null($data->getBodyPartSize($html_id)) ? $data->getBodyPartSize($html_id) : Horde_String::length($html); if (!empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_HTML]['truncationsize'])) { $html = Horde_String::substr($html, 0, $options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_HTML]['truncationsize'], $html_charset); } elseif ($want_html_as_plain) { $html = Horde_Text_Filter::filter($html, 'Html2text', array('charset' => $html_charset)); // Get the new size, since it probably changed. $html_size = Horde_String::length($html); if (!empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize'])) { // EAS >= 12.0 truncation $html = Horde_String::substr($html, 0, $options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize'], $html_charset); } } // Was the part truncated? $truncated = $html_size > Horde_String::length($html); if ($want_html_as_plain) { $return['plain'] = array('charset' => $html_charset, 'body' => $html, 'truncated' => $truncated, 'size' => $html_size); } if ($version >= Horde_ActiveSync::VERSION_TWELVE && !($truncated && !empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_HTML]['allornone']))) { $return['html'] = array('charset' => $html_charset, 'body' => $html, 'estimated_size' => $html_size, 'truncated' => $truncated); } } return $return; }
/** * Helper method to build a view object for a tweet. * * @param stdClass $tweet The tweet object. * * @return Horde_View The view object, populated with tweet data. */ protected function _buildTweet($tweet) { global $injector, $registry; $view = new Horde_View(array('templatePath' => HORDE_TEMPLATES . '/block')); $view->addHelper('Tag'); $view->ajax_uri = $registry->getServiceLink('ajax', $registry->getApp()); $filter = $injector->getInstance('Horde_Core_Factory_TextFilter'); $instance = $this->vars->i; // Links and media $map = $previews = array(); foreach ($tweet->entities->urls as $link) { $replace = '<a target="_blank" href="' . $link->url . '" title="' . $link->expanded_url . '">' . htmlspecialchars($link->display_url) . '</a>'; $map[$link->indices[0]] = array($link->indices[1], $replace); } if (!empty($tweet->entities->media)) { foreach ($tweet->entities->media as $picture) { $replace = '<a target="_blank" href="' . $picture->url . '" title="' . $picture->expanded_url . '">' . htmlentities($picture->display_url, ENT_COMPAT, 'UTF-8') . '</a>'; $map[$picture->indices[0]] = array($picture->indices[1], $replace); $previews[] = ' <a href="#" onclick="return Horde[\'twitter' . $instance . '\'].showPreview(\'' . $picture->media_url . ':small\');"><img src="' . Horde_Themes::img('mime/image.png') . '" /></a>'; } } if (!empty($tweet->entities->user_mentions)) { foreach ($tweet->entities->user_mentions as $user) { $replace = ' <a target="_blank" title="' . $user->name . '" href="http://twitter.com/' . $user->screen_name . '">@' . htmlentities($user->screen_name, ENT_COMPAT, 'UTF-8') . '</a>'; $map[$user->indices[0]] = array($user->indices[1], $replace); } } if (!empty($tweet->entities->hashtags)) { foreach ($tweet->entities->hashtags as $hashtag) { $replace = ' <a target="_blank" href="http://twitter.com/search?q=#' . urlencode($hashtag->text) . '">#' . htmlentities($hashtag->text, ENT_COMPAT, 'UTF-8') . '</a>'; $map[$hashtag->indices[0]] = array($hashtag->indices[1], $replace); } } $body = ''; $pos = 0; while ($pos <= Horde_String::length($tweet->text) - 1) { if (!empty($map[$pos])) { $entity = $map[$pos]; $body .= $entity[1]; $pos = $entity[0]; } else { $body .= Horde_String::substr($tweet->text, $pos, 1); ++$pos; } } foreach ($previews as $preview) { $body .= $preview; } $view->body = $body; /* If this is a retweet, use the original author's profile info */ if (!empty($tweet->retweeted_status)) { $tweetObj = $tweet->retweeted_status; } else { $tweetObj = $tweet; } /* These are all referencing the *original* tweet */ $view->profileLink = Horde::externalUrl('http://twitter.com/' . htmlspecialchars($tweetObj->user->screen_name), true); $view->profileImg = $GLOBALS['browser']->usingSSLConnection() ? $tweetObj->user->profile_image_url_https : $tweetObj->user->profile_image_url; $view->authorName = '@' . htmlspecialchars($tweetObj->user->screen_name); $view->authorFullname = htmlspecialchars($tweetObj->user->name); $view->createdAt = $tweetObj->created_at; $view->clientText = $filter->filter($tweet->source, 'xss'); $view->tweet = $tweet; $view->instanceid = $instance; return $view; }
/** * Create an AS memo from this task * * @param array $memo A memo array. * @param array $options * * @return Horde_ActiveSync_Message_Note */ public function toASNote($memo, $options = array()) { $message = new Horde_ActiveSync_Message_Note(array('protocolversion' => $options['protocolversion'])); $message->subject = $memo['desc']; $bp = $options['bodyprefs']; $body = new Horde_ActiveSync_Message_AirSyncBaseBody(); // When the note is encrypted, we won't have the passphrase so the // body will be a Mnemo_Exception. if ($memo['body'] instanceof Mnemo_Exception) { $memo['body'] = $memo['body']->getMessage(); } if (isset($bp[Horde_ActiveSync::BODYPREF_TYPE_HTML])) { $body->type = Horde_ActiveSync::BODYPREF_TYPE_HTML; $memo['body'] = Horde_Text_Filter::filter($memo['body'], 'Text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO)); if (isset($bp[Horde_ActiveSync::BODYPREF_TYPE_HTML]['truncationsize']) && Horde_String::length($memo['body']) > $bp[Horde_ActiveSync::BODYPREF_TYPE_HTML]['truncationsize']) { $body->data = Horde_String::substr($memo['body'], $bp[Horde_ActiveSync::BODYPREF_TYPE_HTML]['truncationsize']); $body->truncated = 1; } else { $body->data = $memo['body']; } } else { $body->type = Horde_ActiveSync::BODYPREF_TYPE_PLAIN; if (isset($bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize']) && Horde_String::length($memo['body']) > $bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize']) { $body->data = Horde_String::substr($memo['body'], 0, $bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize']); $body->truncated = 1; } else { $body->data = $memo['body']; } } $body->estimateddatasize = Horde_String::length($memo['body']); $message->body = $body; if (!empty($memo['tags'])) { $message->categories = $memo['tags']; } $history = $GLOBALS['injector']->getInstance('Horde_History'); $last = $history->getActionTimeStamp('mnemo:' . $memo['memolist_id'] . ':' . $memo['uid'], 'modify'); if (empty($last)) { $last = $history->getActionTimeStamp('mnemo:' . $memo['memolist_id'] . ':' . $memo['uid'], 'add'); } $message->lastmodified = new Horde_Date($last); return $message; }
/** * Takes all necessary actions for the given import step, parameters and * form values and returns the next necessary step. * * @param integer $action The current step. One of the IMPORT_* constants. * @param array $param An associative array containing needed * parameters for the current step. Keys for this * driver: * - check_charset: (boolean) Do some checks to see if the correct * charset has been provided. Throws charset exception * on error. * - import_mapping: TODO * * @return mixed Either the next step as an integer constant or imported * data set after the final step. * @throws Horde_Data_Exception * @throws Horde_Data_Exception_Charset */ public function nextStep($action, array $param = array()) { switch ($action) { case Horde_Data::IMPORT_FILE: parent::nextStep($action, $param); /* Move uploaded file so that we can read it again in the next step after the user gave some format details. */ $file_name = $_FILES['import_file']['tmp_name']; if (($file_data = file_get_contents($file_name)) === false) { throw new Horde_Data_Exception(Horde_Data_Translation::t("The uploaded file could not be saved.")); } /* Do charset checking now, if requested. */ if (isset($param['check_charset'])) { $charset = isset($this->_vars->charset) ? Horde_String::lower($this->_vars->charset) : 'utf-8'; switch ($charset) { case 'utf-8': $error = !Horde_String::validUtf8($file_data); break; default: $error = $file_data != Horde_String::convertCharset(Horde_String::convertCharset($file_data, $charset, 'UTF-8'), 'UTF-8', $charset); break; } if ($error) { $e = new Horde_Data_Exception_Charset(Horde_Data_Translation::t("Incorrect charset given for the data.")); $e->badCharset = $charset; throw $e; } } $this->storage->set('charset', $this->_vars->charset); $this->storage->set('file_data', $file_data); /* Read the file's first two lines to show them to the user. */ $first_lines = ''; if ($fp = @fopen($file_name, 'r')) { for ($line_no = 1, $line = fgets($fp); $line_no <= 3 && $line; $line_no++, $line = fgets($fp)) { $line = Horde_String::convertCharset($line, $this->_vars->charset, 'UTF-8'); $first_lines .= Horde_String::truncate($line); if (Horde_String::length($line) > 100) { $first_lines .= "\n"; } } } $this->storage->set('first_lines', $first_lines); /* Import the first line to guess the number of fields. */ if ($first_lines) { rewind($fp); $line = self::getCsv($fp); if ($line) { $this->storage->set('fields', count($line)); } } return Horde_Data::IMPORT_CSV; case Horde_Data::IMPORT_CSV: $this->storage->set('header', $this->_vars->header); $import_mapping = array(); if (isset($param['import_mapping'])) { $import_mapping = $param['import_mapping']; } $file_name = Horde_Util::getTempFile('import'); file_put_contents($file_name, $this->storage->get('file_data')); $this->storage->set('data', $this->importFile($file_name, $this->_vars->header, $this->_vars->sep, $this->_vars->quote, $this->_vars->fields, $import_mapping, $this->storage->get('charset'), $this->storage->get('crlf'))); $this->storage->set('map'); return Horde_Data::IMPORT_MAPPED; default: return parent::nextStep($action, $param); } }
/** * Takes all necessary actions for the given import step, parameters and * form values and returns the next necessary step. * * @param integer $action The current step. One of the IMPORT_* constants. * @param array $param An associative array containing needed * parameters for the current step. * * @return mixed Either the next step as an integer constant or imported * data set after the final step. * @throws Horde_Data_Exception */ public function nextStep($action, array $param = array()) { switch ($action) { case Horde_Data::IMPORT_FILE: parent::nextStep($action, $param); $format = $this->storage->get('format'); if (in_array($format, array('mulberry', 'pine'))) { $filedata = $this->importFile($_FILES['import_file']['tmp_name']); switch ($format) { case 'mulberry': $appKeys = array('alias', 'name', 'email', 'company', 'workAddress', 'workPhone', 'homePhone', 'fax', 'notes'); $dataKeys = array(0, 1, 2, 3, 4, 5, 6, 7, 9); break; case 'pine': $appKeys = array('alias', 'name', 'email', 'notes'); $dataKeys = array(0, 1, 2, 4); break; } foreach ($appKeys as $key => $app) { $map[$dataKeys[$key]] = $app; } $data = array(); foreach ($filedata as $row) { $hash = array(); switch ($format) { case 'mulberry': if (preg_match("/^Grp:/", $row[0]) || empty($row[1])) { continue; } $row[1] = preg_replace('/^([^,"]+),\\s*(.*)$/', '$2 $1', $row[1]); foreach ($dataKeys as $key) { if (array_key_exists($key, $row)) { $hash[$key] = stripslashes(preg_replace('/\\\\r/', "\n", $row[$key])); } } break; case 'pine': if (count($row) < 3 || preg_match("/^#DELETED/", $row[0]) || preg_match("/[()]/", $row[2])) { continue; } $row[1] = preg_replace('/^([^,"]+),\\s*(.*)$/', '$2 $1', $row[1]); /* Address can be a full RFC822 address */ $addr_ob = new Horde_Mail_Rfc822_Address($row[2]); if (!$addr_ob->valid) { continue; } $row[2] = $addr_ob->bare_address; if (empty($row[1]) && !is_null($addr_ob->personal)) { $row[1] = $addr_ob->personal; } foreach ($dataKeys as $key) { if (array_key_exists($key, $row)) { $hash[$key] = $row[$key]; } } break; } $data[] = $hash; } $this->storage->set('data', $data); $this->storage->set('map', $map); return $this->nextStep(Horde_Data::IMPORT_DATA, $param); } /* Store uploaded file data so that we can read it again in the * next step after the user gives some format details. */ try { $this->_browser->wasFileUploaded('import_file', Horde_Data_Translation::t("TSV file")); } catch (Horde_Browser_Exception $e) { throw new Horde_Data_Exception($e); } $file_name = $_FILES['import_file']['tmp_name']; if (($file_data = file_get_contents($file_name)) === false) { throw new Horde_Data_Exception(Horde_Data_Translation::t("The uploaded file could not be saved.")); } $this->storage->set('file_data', $file_data); /* Read the file's first two lines to show them to the user. */ $first_lines = ''; if ($fp = @fopen($file_name, 'r')) { $line_no = 1; while ($line_no < 3 && ($line = fgets($fp))) { $newline = Horde_String::length($line) > 100 ? "\n" : ''; $first_lines .= substr($line, 0, 100) . $newline; ++$line_no; } } $this->storage->set('first_lines', $first_lines); return Horde_Data::IMPORT_TSV; case Horde_Data::IMPORT_TSV: $file_name = Horde_Util::getTempFile('import'); file_put_contents($file_name, $this->storage->get('file_data')); $this->storage->set('header', $this->_vars->header); $this->storage->set('data', $this->importFile($file_name, $this->storage->get('header'))); $this->storage->set('map'); return Horde_Data::IMPORT_MAPPED; } return parent::nextStep($action, $param); }
/** * Formats the name according to the user's preference. * * If the format is 'none', the full name with all parts is returned. If * the format is 'last_first' or 'first_last', only the first name and * last name are returned. * * @param Turba_Object $ob The object to get a name from. * @param string $name_format The formatting. One of 'none', 'last_first' * or 'first_last'. Defaults to the user * preference. * * @return string The formatted name, either "Firstname Lastname" * or "Lastname, Firstname" depending on $name_format or * the user's preference. */ public static function formatName(Turba_Object $ob, $name_format = null) { if (!$name_format) { if (!isset(self::$_cache['defaultFormat'])) { self::$_cache['defaultFormat'] = $GLOBALS['prefs']->getValue('name_format'); } $name_format = self::$_cache['defaultFormat']; } /* If no formatting, return original name. */ if (!in_array($name_format, array('first_last', 'last_first'))) { return $ob->getValue('name'); } /* See if we have the name fields split out explicitly. */ if ($ob->hasValue('firstname') && $ob->hasValue('lastname')) { return $name_format == 'last_first' ? $ob->getValue('lastname') . ', ' . $ob->getValue('firstname') : $ob->getValue('firstname') . ' ' . $ob->getValue('lastname'); } /* One field, we'll have to guess. */ $name = $ob->getValue('name'); $lastname = self::guessLastname($name); if ($name_format == 'last_first' && !is_int(strpos($name, ',')) && Horde_String::length($name) > Horde_String::length($lastname)) { return $lastname . ', ' . preg_replace('/\\s+' . preg_quote($lastname, '/') . '/', '', $name); } if ($name_format == 'first_last' && is_int(strpos($name, ',')) && Horde_String::length($name) > Horde_String::length($lastname)) { return preg_replace('/' . preg_quote($lastname, '/') . ',\\s*/', '', $name) . ' ' . $lastname; } return $name; }
/** * Outputs data * * @param mixed $content A string or stream resource to write to the output */ private function _content($content) { if (!is_resource($content)) { if ($this->_logLevel == self::LOG_PROTOCOL && ($l = Horde_String::length($content)) > self::LOG_MAXCONTENT) { $this->_logContent(sprintf('[%d bytes of content]', $l)); } else { $this->_logContent($content); } } else { $this->_logContent('[STREAM]'); } $this->_outByte(self::STR_I); $this->_outTermStr($content); }
Horde::url('list.php', true)->redirect(); default: Horde::url('list.php', true)->redirect(); } $view = $injector->createInstance('Horde_View'); $view->formInput = Horde_Util::formInput(); $view->id = $memo_id; $view->listid = $memolist_id; $view->modify = $actionID == 'modify_memo'; $view->passphrase = $show_passphrase; $view->title = $title; $view->url = Horde::url('memo.php'); if (!$view->modify || !$view->passphrase) { $injector->getInstance('Horde_Core_Factory_Imple')->create('Mnemo_Ajax_Imple_TagAutoCompleter', array('id' => 'memo_tags')); $view->body = $memo_body; $view->count = sprintf(_("%s characters"), '<span id="mnemo-count">' . Horde_String::length(str_replace(array("\r", "\n"), '', $memo_body)) . '</span>'); $view->encrypted = $memo_encrypted; $view->encryption = $storage->encryptionSupported(); try { $view->help = Horde::callHook('description_help', array(), 'mnemo', ''); } catch (Horde_Exception_HookNotSet $e) { } $view->loadingImg = Horde::img('loading.gif', _("Loading...")); $view->notepads = array(); if (!$prefs->isLocked('default_notepad')) { foreach (Mnemo::listNotepads(false, Horde_Perms::SHOW) as $id => $notepad) { if (!$notepad->hasPermission($user, Horde_Perms::EDIT)) { continue; } $view->notepads[] = array('id' => $id, 'selected' => $id == $memolist_id, 'label' => Mnemo::getLabel($notepad)); }
/** * Limits a string to a given maximum length in a smarter way than just * using substr(). * * Namely, cut from the MIDDLE instead of from the end so that if we're * doing this on (for instance) a bunch of binder names that start off with * the same verbose description, and then are different only at the very * end, they'll still be different from one another after truncating. * * <code> * $str = 'The quick brown fox jumps over the lazy dog tomorrow morning.'; * $shortStr = $this->truncateMiddle($str, 40); * // $shortStr == 'The quick brown fox... tomorrow morning.' * </code> * * @param string $str A text to truncate. * @param integer $maxLength The maximum length of the text * @param string $joiner Replacement string for the truncated text. * * @return string The truncated text. */ public function truncateMiddle($str, $maxLength = 80, $joiner = '...') { if (Horde_String::length($str) <= $maxLength) { return $str; } $maxLength = $maxLength - Horde_String::length($joiner); if ($maxLength <= 0) { return $str; } $startPieceLength = (int) ceil($maxLength / 2); $endPieceLength = (int) floor($maxLength / 2); $trimmedString = rtrim(Horde_String::substr($str, 0, $startPieceLength)) . $joiner; if ($endPieceLength > 0) { $trimmedString .= ltrim(Horde_String::substr($str, -1 * $endPieceLength)); } return $trimmedString; }
/** * Regenerates body text for use in the compose screen from IMAP data. * * @param IMP_Contents $contents An IMP_Contents object. * @param array $options Additional options: * <ul> * <li>html: (boolean) Return text/html part, if available.</li> * <li>imp_msg: (integer) If non-empty, the message data was created by * IMP. Either: * <ul> * <li>self::COMPOSE</li> * <li>self::FORWARD</li> * <li>self::REPLY</li> * </ul> * </li> * <li>replylimit: (boolean) Enforce length limits?</li> * <li>toflowed: (boolean) Do flowed conversion?</li> * </ul> * * @return mixed Null if bodypart not found, or array with the following * keys: * - charset: (string) The guessed charset to use. * - flowed: (Horde_Text_Flowed) A flowed object, if the text is flowed. * Otherwise, null. * - id: (string) The MIME ID of the bodypart. * - mode: (string) Either 'text' or 'html'. * - text: (string) The body text. */ protected function _getMessageText($contents, array $options = array()) { global $conf, $injector, $notification, $prefs; $body_id = null; $mode = 'text'; $options = array_merge(array('imp_msg' => self::COMPOSE), $options); if (!empty($options['html']) && self::canHtmlCompose() && ($body_id = $contents->findBody('html')) !== null) { $mime_message = $contents->getMIMEMessage(); switch ($mime_message->getPrimaryType()) { case 'multipart': if ($body_id != '1' && $mime_message->getSubType() == 'mixed' && ($id_ob = new Horde_Mime_Id('1')) && !$id_ob->isChild($body_id)) { $body_id = null; } else { $mode = 'html'; } break; default: if (strval($body_id) != '1') { $body_id = null; } else { $mode = 'html'; } break; } } if (is_null($body_id)) { $body_id = $contents->findBody(); if (is_null($body_id)) { return null; } } if (!($part = $contents->getMimePart($body_id))) { return null; } $type = $part->getType(); $part_charset = $part->getCharset(); $msg = Horde_String::convertCharset($part->getContents(), $part_charset, 'UTF-8'); /* Enforce reply limits. */ if (!empty($options['replylimit']) && !empty($conf['compose']['reply_limit'])) { $limit = $conf['compose']['reply_limit']; if (Horde_String::length($msg) > $limit) { $msg = Horde_String::substr($msg, 0, $limit) . "\n" . _("[Truncated Text]"); } } if ($mode == 'html') { $dom = $injector->getInstance('Horde_Core_Factory_TextFilter')->filter($msg, 'Xss', array('charset' => $this->charset, 'return_dom' => true, 'strip_style_attributes' => false)); /* If we are replying to a related part, and this part refers * to local message parts, we need to move those parts into this * message (since the original message may disappear during the * compose process). */ if ($related_part = $contents->findMimeType($body_id, 'multipart/related')) { $this->_setMetadata('related_contents', $contents); $related_ob = new Horde_Mime_Related($related_part); $related_ob->cidReplace($dom, array($this, '_getMessageTextCallback'), $part_charset); $this->_setMetadata('related_contents', null); } /* Convert any Data URLs to attachments. */ $xpath = new DOMXPath($dom->dom); foreach ($xpath->query('//*[@src]') as $val) { $data_url = new Horde_Url_Data($val->getAttribute('src')); if (strlen($data_url->data)) { $data_part = new Horde_Mime_Part(); $data_part->setContents($data_url->data); $data_part->setType($data_url->type); try { $atc = $this->addAttachmentFromPart($data_part); $val->setAttribute('src', $atc->viewUrl()); $this->addRelatedAttachment($atc, $val, 'src'); } catch (IMP_Compose_Exception $e) { $notification->push($e, 'horde.warning'); } } } $msg = $dom->returnBody(); } elseif ($type == 'text/html') { $msg = $injector->getInstance('Horde_Core_Factory_TextFilter')->filter($msg, 'Html2text'); $type = 'text/plain'; } /* Always remove leading/trailing whitespace. The data in the * message body is not intended to be the exact representation of the * original message (use forward as message/rfc822 part for that). */ $msg = trim($msg); if ($type == 'text/plain') { if ($prefs->getValue('reply_strip_sig') && ($pos = strrpos($msg, "\n-- ")) !== false) { $msg = rtrim(substr($msg, 0, $pos)); } /* Remove PGP armored text. */ $pgp = $injector->getInstance('Horde_Crypt_Pgp_Parse')->parseToPart($msg); if (!is_null($pgp)) { $msg = ''; $pgp->buildMimeIds(); foreach ($pgp->partIterator() as $val) { if ($val->getPrimaryType() === 'text') { $msg .= $val->getContents(); } } } if ($part->getContentTypeParameter('format') == 'flowed') { $flowed = new Horde_Text_Flowed($msg, 'UTF-8'); if (Horde_String::lower($part->getContentTypeParameter('delsp')) == 'yes') { $flowed->setDelSp(true); } $flowed->setMaxLength(0); $msg = $flowed->toFixed(false); } else { /* If the input is *not* in flowed format, make sure there is * no padding at the end of lines. */ $msg = preg_replace("/\\s*\n/U", "\n", $msg); } if (isset($options['toflowed'])) { $flowed = new Horde_Text_Flowed($msg, 'UTF-8'); $msg = $options['toflowed'] ? $flowed->toFlowed(true) : $flowed->toFlowed(false, array('nowrap' => true)); } } if (strcasecmp($part->getCharset(), 'windows-1252') === 0) { $part_charset = 'ISO-8859-1'; } return array('charset' => $part_charset, 'flowed' => isset($flowed) ? $flowed : null, 'id' => $body_id, 'mode' => $mode, 'text' => $msg); }
/** * Returns the widget necessary to configure this block. * * @param $app TODO * @param $block TODO * @param $param_id TODO * @param $val TODO * * @return TODO */ public function getOptionsWidget($app, $block, $param_id, $val = null) { $widget = ''; /* getParams() loads $_blocks */ $this->getParams($app, $block); $param = $this->_blocks[$app][$block]['params'][$param_id]; if (!isset($param['default'])) { $param['default'] = ''; } switch ($param['type']) { case 'boolean': case 'checkbox': $checked = !empty($val[$param_id]) ? ' checked="checked"' : ''; $widget = sprintf('<input type="checkbox" name="params[%s]"%s />', $param_id, $checked); break; case 'enum': $widget = sprintf('<select name="params[%s]">', $param_id); foreach ($param['values'] as $key => $name) { if (Horde_String::length($name) > 30) { $name = substr($name, 0, 27) . '...'; } $widget .= sprintf("<option value=\"%s\"%s>%s</option>\n", htmlspecialchars($key), isset($val[$param_id]) && $val[$param_id] == $key ? ' selected="selected"' : '', htmlspecialchars($name)); } $widget .= '</select>'; break; case 'multienum': $widget = sprintf('<select multiple="multiple" name="params[%s][]">', $param_id); foreach ($param['values'] as $key => $name) { if (Horde_String::length($name) > 30) { $name = substr($name, 0, 27) . '...'; } $widget .= sprintf("<option value=\"%s\"%s>%s</option>\n", htmlspecialchars($key), isset($val[$param_id]) && in_array($key, $val[$param_id]) ? ' selected="selected"' : '', htmlspecialchars($name)); } $widget .= '</select>'; break; case 'mlenum': // Multi-level enum. if (is_array($val) && isset($val['__' . $param_id])) { $firstval = $val['__' . $param_id]; } else { $tmp = array_keys($param['values']); $firstval = current($tmp); } $blockvalues = $param['values'][$firstval]; asort($blockvalues); $widget = sprintf('<select name="params[__%s]" onchange="document.blockform.action.value=\'save-resume\';document.blockform.submit()">', $param_id) . "\n"; foreach (array_keys($param['values']) as $key) { $name = Horde_String::length($key) > 30 ? Horde_String::substr($key, 0, 27) . '...' : $key; $widget .= sprintf("<option value=\"%s\"%s>%s</option>\n", htmlspecialchars($key), $key == $firstval ? ' selected="selected"' : '', htmlspecialchars($name)); } $widget .= "</select><br />\n"; $widget .= sprintf("<select name=\"params[%s]\">\n", $param_id); foreach ($blockvalues as $key => $name) { $name = Horde_String::length($name) > 30 ? Horde_String::substr($name, 0, 27) . '...' : $name; $widget .= sprintf("<option value=\"%s\"%s>%s</option>\n", htmlspecialchars($key), $val[$param_id] == $key ? ' selected="selected"' : '', htmlspecialchars($name)); } $widget .= "</select><br />\n"; break; case 'int': case 'text': $widget = sprintf('<input type="text" name="params[%s]" value="%s" />', $param_id, !isset($val[$param_id]) ? $param['default'] : $val[$param_id]); break; case 'password': $widget = sprintf('<input type="password" name="params[%s]" value="%s" />', $param_id, !isset($val[$param_id]) ? $param['default'] : $val[$param_id]); break; case 'error': $widget = '<span class="form-error">' . $param['default'] . '</span>'; break; } return $widget; }
/** * Generate the preview text. * * @return array Array with the following keys: * - cut: (boolean) Was the preview text cut? * - text: (string) The preview text. */ public function generatePreview() { // For preview generation, don't go through overhead of scanning for // embedded parts. Necessary evil, or else very large parts (e.g // 5 MB+ text parts) will take ages to scan. $oldbuild = $this->_build; $this->_build = true; $mimeid = $this->findBody(); if (is_null($mimeid)) { $this->_build = $oldbuild; return array('cut' => false, 'text' => ''); } $maxlen = empty($GLOBALS['conf']['msgcache']['preview_size']) ? $GLOBALS['prefs']->getValue('preview_maxlen') : $GLOBALS['conf']['msgcache']['preview_size']; // Retrieve 3x the size of $maxlen of bodytext data. This should // account for any content-encoding & HTML tags. $pmime = $this->getMIMEPart($mimeid, array('length' => $maxlen * 3)); $ptext = Horde_String::convertCharset($pmime->getContents(), $pmime->getCharset(), 'UTF-8'); if ($pmime->getType() == 'text/html') { $ptext = $GLOBALS['injector']->getInstance('Horde_Core_Factory_TextFilter')->filter($ptext, 'Html2text'); } $this->_build = $oldbuild; if (Horde_String::length($ptext) > $maxlen) { return array('cut' => true, 'text' => Horde_String::truncate($ptext, $maxlen)); } return array('cut' => false, 'text' => $ptext); }
/** * Log the token. * * @param array The element array. * * @return void */ protected function _logToken($el) { switch ($el[self::EN_TYPE]) { case self::EN_TYPE_STARTTAG: if ($el[self::EN_FLAGS] & self::EN_FLAGS_CONTENT) { $spaces = str_repeat(' ', count($this->_logStack)); $this->_logStack[] = $el[self::EN_TAG]; $this->_logger->debug(sprintf('[%s] I %s <%s>', $this->_procid, $spaces, $el[self::EN_TAG])); } else { $spaces = str_repeat(' ', count($this->_logStack)); $this->_logger->debug(sprintf('[%s] I %s <%s />', $this->_procid, $spaces, $el[self::EN_TAG])); } break; case self::EN_TYPE_ENDTAG: $tag = array_pop($this->_logStack); $spaces = str_repeat(' ', count($this->_logStack)); $this->_logger->debug(sprintf('[%s] I %s </%s>', $this->_procid, $spaces, $tag)); break; case self::EN_TYPE_CONTENT: $spaces = str_repeat(' ', count($this->_logStack) + 1); if ($this->_logLevel == self::LOG_PROTOCOL && ($l = Horde_String::length($el[self::EN_CONTENT])) > self::LOG_MAXCONTENT) { $this->_logger->debug(sprintf('[%s] I %s %s', $this->_procid, $spaces, sprintf('[%d bytes of content]', $l))); } else { $this->_logger->debug(sprintf('[%s] I %s %s', $this->_procid, $spaces, $el[self::EN_CONTENT])); } break; } }
/** * Executes any code necessary after applying the filter patterns. * * @param string $text The text after the filtering. * * @return string The modified text. */ public function postProcess($text) { try { $dom = new Horde_Domhtml($text, $this->_params['charset']); // Add two to take into account the <html> and <body> nodes. if (!empty($this->_params['nestingLimit'])) { $this->_params['nestingLimit'] += 2; } $text = Horde_String::convertCharset($this->_node($dom->dom, $dom->dom), 'UTF-8', $this->_params['charset']); } catch (Exception $e) { $text = strip_tags(preg_replace("/\\<br\\s*\\/?\\>/i", "\n", $text)); } /* Bring down number of empty lines to 2 max, and remove trailing * ws. */ $text = preg_replace(array("/\\s*\n{3,}/", "/ +\n/"), array("\n\n", "\n"), $text); /* Wrap the text to a readable format. */ if ($this->_params['width']) { $text = wordwrap($text, $this->_params['width']); } /* Add link list. */ if (!empty($this->_linkList)) { $text .= "\n\n" . Horde_Text_Filter_Translation::t("Links") . ":\n" . str_repeat('-', Horde_String::length(Horde_Text_Filter_Translation::t("Links")) + 1) . "\n"; foreach ($this->_linkList as $key => $val) { $text .= '[' . ($key + 1) . '] ' . $val . "\n"; } } return ltrim(rtrim($text), "\n"); }
/** * Create an AS message from this task * * @param array $options Options: * - protocolversion: (float) The EAS version to support * DEFAULT: 2.5 * - bodyprefs: (array) A BODYPREFERENCE array. * DEFAULT: none (No body prefs enforced). * - truncation: (integer) Truncate event body to this length * DEFAULT: none (No truncation). * * @return Horde_ActiveSync_Message_Task */ public function toASTask(array $options = array()) { $message = new Horde_ActiveSync_Message_Task(array('protocolversion' => $options['protocolversion'])); /* Notes and Title */ if ($options['protocolversion'] >= Horde_ActiveSync::VERSION_TWELVE) { $bp = $options['bodyprefs']; $body = new Horde_ActiveSync_Message_AirSyncBaseBody(); $body->type = Horde_ActiveSync::BODYPREF_TYPE_PLAIN; if (isset($bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize'])) { $truncation = $bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize']; } elseif (isset($bp[Horde_ActiveSync::BODYPREF_TYPE_HTML])) { $truncation = $bp[Horde_ActiveSync::BODYPREF_TYPE_HTML]['truncationsize']; $this->desc = Horde_Text_Filter::filter($this->desc, 'Text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO)); } else { $truncation = false; } if ($truncation && Horde_String::length($this->desc) > $truncation) { $body->data = Horde_String::substr($this->desc, 0, $truncation); $body->truncated = 1; } else { $body->data = $this->desc; } $body->estimateddatasize = Horde_String::length($this->desc); $message->airsyncbasebody = $body; } else { $message->body = $this->desc; } $message->subject = $this->name; /* Completion */ if ($this->completed) { $message->datecompleted = new Horde_Date($this->completed_date); $message->complete = Horde_ActiveSync_Message_Task::TASK_COMPLETE_TRUE; } else { $message->complete = Horde_ActiveSync_Message_Task::TASK_COMPLETE_FALSE; } /* Due Date */ if (!empty($this->due)) { $message->utcduedate = new Horde_Date($this->due); $message->duedate = new Horde_Date($this->due, 'UTC'); } /* Start Date */ if (!empty($this->start)) { $message->utcstartdate = new Horde_Date($this->start); $message->startdate = new Horde_Date($this->start, 'UTC'); } /* Priority */ switch ($this->priority) { case 5: $priority = Horde_ActiveSync_Message_Task::IMPORTANCE_LOW; break; case 4: case 3: case 2: $priority = Horde_ActiveSync_Message_Task::IMPORTANCE_NORMAL; break; case 1: $priority = Horde_ActiveSync_Message_Task::IMPORTANCE_HIGH; break; default: $priority = Horde_ActiveSync_Message_Task::IMPORTANCE_NORMAL; } $message->setImportance($priority); /* Reminders */ if ($this->due && $this->alarm) { $message->setReminder(new Horde_Date($this->due - $this->alarm * 60)); } /* Recurrence */ if ($this->recurs()) { $message->setRecurrence($this->recurrence); } /* Categories */ $message->categories = $this->tags; return $message; }
/** * Returns human readable information on a PGP key. * * @param string $pgpdata The PGP data block. * * @return string Tabular information on the PGP key. * @throws Horde_Crypt_Exception */ public function pgpPrettyKey($pgpdata) { $msg = ''; $fingerprints = $this->getFingerprintsFromKey($pgpdata); $info = $this->pgpPacketInformation($pgpdata); if (empty($info['signature'])) { return $msg; } /* Making the property names the same width for all localizations .*/ $leftrow = array(Horde_Crypt_Translation::t("Name"), Horde_Crypt_Translation::t("Key Type"), Horde_Crypt_Translation::t("Key Creation"), Horde_Crypt_Translation::t("Expiration Date"), Horde_Crypt_Translation::t("Key Length"), Horde_Crypt_Translation::t("Comment"), Horde_Crypt_Translation::t("E-Mail"), Horde_Crypt_Translation::t("Hash-Algorithm"), Horde_Crypt_Translation::t("Key ID"), Horde_Crypt_Translation::t("Key Fingerprint")); array_walk($leftrow, function (&$s, $k, $m) { $s .= ':' . str_repeat(' ', $m - Horde_String::length($s)); }, max(array_map('strlen', $leftrow)) + 2); foreach ($info['signature'] as $uid_idx => $val) { if ($uid_idx == '_SIGNATURE') { continue; } $key = $this->pgpPacketSignatureByUidIndex($pgpdata, $uid_idx); $keyid = empty($key['keyid']) ? null : $this->getKeyIDString($key['keyid']); $fingerprint = isset($fingerprints[$keyid]) ? $fingerprints[$keyid] : null; $sig_key = 'sig_' . $key['keyid']; $msg .= $leftrow[0] . (isset($key['name']) ? stripcslashes($key['name']) : '') . "\n" . $leftrow[1] . ($key['key_type'] == 'public_key' ? Horde_Crypt_Translation::t("Public Key") : Horde_Crypt_Translation::t("Private Key")) . "\n" . $leftrow[2] . strftime("%D", $val[$sig_key]['created']) . "\n" . $leftrow[3] . (empty($val[$sig_key]['expires']) ? '[' . Horde_Crypt_Translation::t("Never") . ']' : strftime("%D", $val[$sig_key]['expires'])) . "\n" . $leftrow[4] . $key['key_size'] . " Bytes\n" . $leftrow[5] . (empty($key['comment']) ? '[' . Horde_Crypt_Translation::t("None") . ']' : $key['comment']) . "\n" . $leftrow[6] . (empty($key['email']) ? '[' . Horde_Crypt_Translation::t("None") . ']' : $key['email']) . "\n" . $leftrow[7] . (empty($key['micalg']) ? '[' . Horde_Crypt_Translation::t("Unknown") . ']' : $key['micalg']) . "\n" . $leftrow[8] . (empty($keyid) ? '[' . Horde_Crypt_Translation::t("Unknown") . ']' : $keyid) . "\n" . $leftrow[9] . (empty($fingerprint) ? '[' . Horde_Crypt_Translation::t("Unknown") . ']' : $fingerprint) . "\n\n"; } return $msg; }
/** * Determine the size of a MIME_Part and its child members. * * @return integer Size of the MIME_Part, in bytes. */ public function getBytes() { $bytes = 0; if (empty($this->_flags['contentsSet']) && $this->_bytes) { $bytes = $this->_bytes; } elseif ($this->getPrimaryType() == 'multipart') { reset($this->_parts); while (list(, $part) = each($this->_parts)) { /* Skip multipart entries (since this may result in double counting). */ if ($part->getPrimaryType() != 'multipart') { $bytes += $part->getBytes(); } } } else { if ($this->getPrimaryType() == 'text') { $bytes = Horde_String::length($this->_contents, $this->getCharset()); } else { $bytes = strlen($this->_contents); } } return $bytes; }
/** * Executes any code necessaray after applying the filter patterns. * * @param string $text The text after the filtering. * * @return string The modified text. */ public function postProcess($text) { /* Use cite blocks to display the different quoting levels? */ $cb = $this->_params['citeblock']; /* Cite level before parsing the current line. */ $qlevel = 0; /* Other loop variables. */ $text_out = ''; $lines = array(); $tmp = array('level' => 0, 'lines' => array()); $qcount = 0; /* Parse text line by line. */ foreach (explode("\n", $text) as $line) { /* Cite level of current line. */ $clevel = 0; $matches = array(); /* Do we have a citation line? */ if (preg_match('/^\\s*((>\\s?)+)/m', $line, $matches)) { /* Count number of > characters => cite level */ $clevel = count(preg_split('/>\\s?/', $matches[1])) - 1; } if ($cb && isset($matches[1])) { /* Strip all > characters. */ $line = substr($line, Horde_String::length($matches[1])); } /* Is this cite level lower than the current level? */ if ($clevel < $qlevel) { $lines[] = $tmp; if ($clevel == 0) { $text_out .= $this->_process($lines, $qcount); $lines = array(); $qcount = 0; } $tmp = array('level' => $clevel, 'lines' => array()); /* Is this cite level higher than the current level? */ } elseif ($clevel > $qlevel) { $lines[] = $tmp; $tmp = array('level' => $clevel, 'lines' => array()); } $tmp['lines'][] = $line; $qlevel = $clevel; if ($qlevel) { ++$qcount; } } $lines[] = $tmp; $text_out .= $this->_process($lines, $qcount); /* Remove the leading newline we added above, if it's still there. */ return $text_out[0] == "\n" ? substr($text_out, 1) : $text_out; }
public function getCostObjectType($vars) { global $registry; $clients = $vars->get('clients'); if (count($clients) == 0) { $clients = array(''); } $costobjects = array(); foreach ($clients as $client) { $criteria = array('user' => $GLOBALS['registry']->getAuth(), 'active' => true, 'client_id' => $client); foreach ($registry->listApps() as $app) { if ($registry->hasMethod('listCostObjects', $app)) { try { $res = $registry->callByPackage($app, 'listCostObjects', array($criteria)); } catch (Horde_Exception $e) { $GLOBALS['notification']->push(sprintf(_("Error retrieving cost objects from \"%s\": %s"), $registry->get('name', $app), $res->getMessage()), 'horde.error'); continue; } foreach (array_keys($res) as $catkey) { foreach (array_keys($res[$catkey]['objects']) as $okey) { $res[$catkey]['objects'][$okey]['id'] = $app . ':' . $res[$catkey]['objects'][$okey]['id']; } } $costobjects = array_merge($costobjects, $res); } } } $elts = array(); $counter = 0; foreach ($costobjects as $category) { Horde_Array::arraySort($category['objects'], 'name'); foreach ($category['objects'] as $object) { $name = $object['name']; if (Horde_String::length($name) > 80) { $name = Horde_String::substr($name, 0, 76) . ' ...'; } $elts[$object['id']] = $name; } } return $elts; }
/** * Generate the display path (the path with any root information stripped * out). * * @param string $path The path to display. * * @return string The display path. */ public static function getDisplayPath($path) { $path = Horde_Util::realPath($path); if (self::$backend['root'] != '/' && strpos($path, self::$backend['root']) === 0) { $path = substr($path, Horde_String::length(self::$backend['root'])); } return $path; }
/** * List code points for a given input. * * @param string $input * * @return array Multi-dimension array with basic, non-basic and * aggregated code points. */ protected function _codePoints($input) { $codePoints = array('all' => array(), 'basic' => array(), 'nonBasic' => array()); $len = Horde_String::length($input, 'UTF-8'); for ($i = 0; $i < $len; ++$i) { $char = Horde_String::substr($input, $i, 1, 'UTF-8'); $code = $this->_charToCodePoint($char); if ($code < 128) { $codePoints['all'][] = $codePoints['basic'][] = $code; } else { $codePoints['all'][] = $codePoints['nonBasic'][] = $code; } } return $codePoints; }
/** * Reformats the input string, where the string is 'format=flowed' plain * text as described in RFC 2646. * * @param boolean $toflowed Convert to flowed? * @param boolean $quote Add level of quoting to each line? * @param boolean $wrap Wrap unquoted lines? */ protected function _reformat($toflowed, $quote, $wrap = true) { $format_type = implode('|', array($toflowed, $quote)); if ($format_type == $this->_formattype) { return; } $this->_output = array(); $this->_formattype = $format_type; /* Set variables used in regexps. */ $delsp = $toflowed && $this->_delsp ? 1 : 0; $opt = $this->_optlength - 1 - $delsp; /* Process message line by line. */ $text = preg_split("/\r?\n/", $this->_text); $text_count = count($text) - 1; $skip = 0; reset($text); while (list($no, $line) = each($text)) { if ($skip) { --$skip; continue; } /* Per RFC 2646 [4.3], the 'Usenet Signature Convention' line * (DASH DASH SP) is not considered flowed. Watch for this when * dealing with potentially flowed lines. */ /* The next three steps come from RFC 2646 [4.2]. */ /* STEP 1: Determine quote level for line. */ if ($num_quotes = $this->_numquotes($line)) { $line = substr($line, $num_quotes); } /* Only combine lines if we are converting to flowed or if the * current line is quoted. */ if (!$toflowed || $num_quotes) { /* STEP 2: Remove space stuffing from line. */ $line = $this->_unstuff($line); /* STEP 3: Should we interpret this line as flowed? * While line is flowed (not empty and there is a space * at the end of the line), and there is a next line, and the * next line has the same quote depth, add to the current * line. A line is not flowed if it is a signature line. */ if ($line != '-- ') { while (!empty($line) && substr($line, -1) == ' ' && $text_count != $no && $this->_numquotes($text[$no + 1]) == $num_quotes) { /* If DelSp is yes and this is flowed input, we need to * remove the trailing space. */ if (!$toflowed && $this->_delsp) { $line = substr($line, 0, -1); } $line .= $this->_unstuff(substr($text[++$no], $num_quotes)); ++$skip; } } } /* Ensure line is fixed, since we already joined all flowed * lines. Remove all trailing ' ' from the line. */ if ($line != '-- ') { $line = rtrim($line); } /* Increment quote depth if we're quoting. */ if ($quote) { $num_quotes++; } /* The quote prefix for the line. */ $quotestr = str_repeat('>', $num_quotes); if (empty($line)) { /* Line is empty. */ $this->_output[] = array('text' => $quotestr, 'level' => $num_quotes); } elseif (!$wrap && !$num_quotes || empty($this->_maxlength) || Horde_String::length($line, $this->_charset) + $num_quotes <= $this->_maxlength) { /* Line does not require rewrapping. */ $this->_output[] = array('text' => $quotestr . $this->_stuff($line, $num_quotes, $toflowed), 'level' => $num_quotes); } else { $min = $num_quotes + 1; /* Rewrap this paragraph. */ while ($line) { /* Stuff and re-quote the line. */ $line = $quotestr . $this->_stuff($line, $num_quotes, $toflowed); $line_length = Horde_String::length($line, $this->_charset); if ($line_length <= $this->_optlength) { /* Remaining section of line is short enough. */ $this->_output[] = array('text' => $line, 'level' => $num_quotes); break; } else { $regex = array(); if ($min <= $opt) { $regex[] = '^(.{' . $min . ',' . $opt . '}) (.*)'; } if ($min <= $this->_maxlength) { $regex[] = '^(.{' . $min . ',' . $this->_maxlength . '}) (.*)'; } $regex[] = '^(.{' . $min . ',})? (.*)'; if ($m = Horde_String::regexMatch($line, $regex, $this->_charset)) { /* We need to wrap text at a certain number of * *characters*, not a certain number of *bytes*; * thus the need for a multibyte capable regex. * If a multibyte regex isn't available, we are * stuck with preg_match() (the function will * still work - are just left with shorter rows * than expected if multibyte characters exist in * the row). * * 1. Try to find a string as long as _optlength. * 2. Try to find a string as long as _maxlength. * 3. Take the first word. */ if (empty($m[1])) { $m[1] = $m[2]; $m[2] = ''; } $this->_output[] = array('text' => $m[1] . ' ' . ($delsp ? ' ' : ''), 'level' => $num_quotes); $line = $m[2]; } elseif ($line_length > 998) { /* One excessively long word left on line. Be * absolutely sure it does not exceed 998 * characters in length or else we must * truncate. */ $this->_output[] = array('text' => Horde_String::substr($line, 0, 998, $this->_charset), 'level' => $num_quotes); $line = Horde_String::substr($line, 998, null, $this->_charset); } else { $this->_output[] = array('text' => $line, 'level' => $num_quotes); break; } } } } } }
/** * Convert the contact to an ActiveSync contact message * * @param Turba_Object $object The turba object to convert * @param array $options Options: * - protocolversion: (float) The EAS version to support * DEFAULT: 2.5 * - bodyprefs: (array) A BODYPREFERENCE array. * DEFAULT: none (No body prefs enforced). * - truncation: (integer) Truncate event body to this length * DEFAULT: none (No truncation). * - device: (Horde_ActiveSync_Device) The device object. * * @return Horde_ActiveSync_Message_Contact */ public function toASContact(Turba_Object $object, array $options = array()) { global $injector; $message = new Horde_ActiveSync_Message_Contact(array('logger' => $injector->getInstance('Horde_Log_Logger'), 'protocolversion' => $options['protocolversion'], 'device' => !empty($options['device']) ? $options['device'] : null)); $hash = $object->getAttributes(); if (!isset($hash['lastname']) && isset($hash['name'])) { $this->_guessName($hash); } // Ensure we have at least a good guess as to separate address fields. // Not ideal, but EAS does not have a single "address" field so we must // map "common" to either home or work. I choose home since // work/non-personal installs will be more likely to have separated // address fields. if (!empty($hash['commonAddress'])) { if (!isset($hash['commonStreet'])) { $hash['commonStreet'] = $hash['commonHome']; } foreach (array('Address', 'Street', 'POBox', 'Extended', 'City', 'Province', 'PostalCode', 'Country') as $field) { $hash['home' . $field] = $hash['common' . $field]; } } else { if (isset($hash['homeAddress']) && !isset($hash['homeStreet'])) { $hash['homeStreet'] = $hash['homeAddress']; } if (isset($hash['workAddress']) && !isset($hash['workStreet'])) { $hash['workStreet'] = $hash['workAddress']; } } $hooks = $injector->getInstance('Horde_Core_Hooks'); $decode_hook = $hooks->hookExists('decode_attribute', 'turba'); foreach ($hash as $field => $value) { if ($decode_hook) { try { $value = $hooks->callHook('decode_attribute', 'turba', array($field, $value, $object)); } catch (Turba_Exception $e) { Horde::log($e); } } if (isset(self::$_asMap[$field])) { try { $message->{self::$_asMap[$field]} = $value; } catch (InvalidArgumentException $e) { } continue; } switch ($field) { case 'photo': $message->picture = base64_encode($value); break; case 'homeCountry': $message->homecountry = !empty($hash['homeCountryFree']) ? $hash['homeCountryFree'] : !empty($hash['homeCountry']) ? Horde_Nls::getCountryISO($hash['homeCountry']) : null; break; case 'otherCountry': $message->othercountry = !empty($hash['otherCountryFree']) ? $hash['otherCountryFree'] : !empty($hash['otherCountry']) ? Horde_Nls::getCountryISO($hash['otherCountry']) : null; break; case 'workCountry': $message->businesscountry = !empty($hash['workCountryFree']) ? $hash['workCountryFree'] : !empty($hash['workCountry']) ? Horde_Nls::getCountryISO($hash['workCountry']) : null; break; case 'email': $message->email1address = $value; break; case 'homeEmail': $message->email2address = $value; break; case 'workEmail': $message->email3address = $value; break; case 'emails': $address = 1; foreach (explode(',', $value) as $email) { while ($address <= 3 && $message->{'email' . $address . 'address'}) { $address++; } if ($address > 3) { break; } $message->{'email' . $address . 'address'} = $email; $address++; } break; case 'children': // Children FROM horde are a simple string value. Even though EAS // uses an array stucture to pass them, we pass as a single // string since we can't assure what delimter the user will // use and (at least in some languages) a comma can be used // within a full name. $message->children = array($value); break; case 'notes': if ($options['protocolversion'] > Horde_ActiveSync::VERSION_TWOFIVE) { $bp = $options['bodyprefs']; $note = new Horde_ActiveSync_Message_AirSyncBaseBody(); // No HTML supported in Turba's notes. Always use plaintext. $note->type = Horde_ActiveSync::BODYPREF_TYPE_PLAIN; if (isset($bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize'])) { if (Horde_String::length($value) > $bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize']) { $note->data = Horde_String::substr($value, 0, $bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize']); $note->truncated = 1; } else { $note->data = $value; } $note->estimateddatasize = Horde_String::length($value); } $message->airsyncbasebody = $note; } else { // EAS 2.5 $message->body = $value; $message->bodysize = strlen($message->body); $message->bodytruncated = 0; } break; case 'birthday': case 'anniversary': if (!empty($value) && $value != '0000-00-00') { try { $date = new Horde_Date($value); } catch (Horde_Date_Exception $e) { $message->{$field} = null; } // Some sanity checking to make sure the date was // successfully parsed. if ($date->month != 0) { $message->{$field} = $date; } else { $message->{$field} = null; } } else { $message->{$field} = null; } break; } } /* Get tags. */ $message->categories = explode(',', $object->getValue('__tags')); if (empty($this->fileas)) { $message->fileas = Turba::formatName($object); } return $message; }
/** * Export this event as a MS ActiveSync Message * * @param array $options Options: * - protocolversion: (float) The EAS version to support * DEFAULT: 2.5 * - bodyprefs: (array) A BODYPREFERENCE array. * DEFAULT: none (No body prefs enforced). * - truncation: (integer) Truncate event body to this length * DEFAULT: none (No truncation). * * @return Horde_ActiveSync_Message_Appointment */ public function toASAppointment(array $options = array()) { global $prefs, $registry; $message = new Horde_ActiveSync_Message_Appointment(array('logger' => $GLOBALS['injector']->getInstance('Horde_Log_Logger'), 'protocolversion' => $options['protocolversion'])); if (!$this->isPrivate()) { // Handle body/truncation if (!empty($options['bodyprefs'])) { if (Horde_String::length($this->description) > 0) { $bp = $options['bodyprefs']; $note = new Horde_ActiveSync_Message_AirSyncBaseBody(); // No HTML supported. Always use plaintext. $note->type = Horde_ActiveSync::BODYPREF_TYPE_PLAIN; if (isset($bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize'])) { $truncation = $bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize']; } elseif (isset($bp[Horde_ActiveSync::BODYPREF_TYPE_HTML])) { $truncation = $bp[Horde_ActiveSync::BODYPREF_TYPE_HTML]['truncationsize']; $this->description = Horde_Text_Filter::filter($this->description, 'Text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO)); } else { $truncation = false; } if ($truncation && Horde_String::length($this->description) > $truncation) { $note->data = Horde_String::substr($this->desciption, 0, $truncation); $note->truncated = 1; } else { $note->data = $this->description; } $note->estimateddatasize = Horde_String::length($this->description); $message->airsyncbasebody = $note; } } else { $message->setBody($this->description); } $message->setLocation($this->location); } $message->setSubject($this->getTitle()); $message->setDatetime(array('start' => $this->start, 'end' => $this->end, 'allday' => $this->isAllDay())); $message->setTimezone($this->start); // Organizer if (count($this->attendees)) { if ($this->creator == $registry->getAuth()) { $as_ident = $prefs->getValue('activesync_identity') == 'horde' ? $prefs->getValue('default_identity') : $prefs->getValue('activesync_identity'); $name = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Identity')->create($this->creator)->getValue('fullname', $as_ident); $email = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Identity')->create($this->creator)->getValue('from_addr', $as_ident); } else { $name = Kronolith::getUserName($this->creator); $email = Kronolith::getUserEmail($this->creator); } $message->setOrganizer(array('name' => $name, 'email' => $email)); } // Privacy $message->setSensitivity($this->private ? Horde_ActiveSync_Message_Appointment::SENSITIVITY_PRIVATE : Horde_ActiveSync_Message_Appointment::SENSITIVITY_NORMAL); // Busy Status switch ($this->status) { case Kronolith::STATUS_CANCELLED: $status = Horde_ActiveSync_Message_Appointment::BUSYSTATUS_FREE; break; case Kronolith::STATUS_CONFIRMED: $status = Horde_ActiveSync_Message_Appointment::BUSYSTATUS_BUSY; break; case Kronolith::STATUS_TENTATIVE: $status = Horde_ActiveSync_Message_Appointment::BUSYSTATUS_TENTATIVE; case Kronolith::STATUS_FREE: case Kronolith::STATUS_NONE: $status = Horde_ActiveSync_Message_Appointment::BUSYSTATUS_FREE; } $message->setBusyStatus($status); // DTStamp $message->setDTStamp($_SERVER['REQUEST_TIME']); // Recurrence if ($this->recurs()) { $message->setRecurrence($this->recurrence, $GLOBALS['prefs']->getValue('week_start_monday')); /* Exceptions are tricky. Exceptions, even those that represent * deleted instances of a recurring event, must be added. To do this * we query the storage for all the events that represent exceptions * (those with the baseid == $this->uid) and then remove the * exceptionoriginaldate from the list of exceptions we know about. * Any dates left in this list when we are done, must represent * deleted instances of this recurring event.*/ if (!empty($this->recurrence) && ($exceptions = $this->recurrence->getExceptions())) { $results = $this->boundExceptions(); foreach ($results as $exception) { $e = new Horde_ActiveSync_Message_Exception(array('protocolversion' => $options['protocolversion'])); $e->setDateTime(array('start' => $exception->start, 'end' => $exception->end, 'allday' => $exception->isAllDay())); // The start time of the *original* recurring event $e->setExceptionStartTime($exception->exceptionoriginaldate); $originaldate = $exception->exceptionoriginaldate->format('Ymd'); $key = array_search($originaldate, $exceptions); if ($key !== false) { unset($exceptions[$key]); } // Remaining properties that could be different $e->setSubject($exception->getTitle()); if (!$exception->isPrivate()) { $e->setLocation($exception->location); $e->setBody($exception->description); } $e->setSensitivity($exception->private ? Horde_ActiveSync_Message_Appointment::SENSITIVITY_PRIVATE : Horde_ActiveSync_Message_Appointment::SENSITIVITY_NORMAL); $e->setReminder($exception->alarm); $e->setDTStamp($_SERVER['REQUEST_TIME']); if ($options['protocolversion'] > Horde_ActiveSync::VERSION_TWELVEONE) { switch ($exception->status) { case Kronolith::STATUS_TENTATIVE: $e->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_TENTATIVE; break; case Kronolith::STATUS_NONE: $e->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_NORESPONSE; break; case Kronolith::STATUS_CONFIRMED: $e->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_ACCEPTED; break; default: $e->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_NONE; } } // Tags/Categories if (!$exception->isPrivate()) { foreach ($exception->tags as $tag) { $e->addCategory($tag); } } $message->addexception($e); } // Any dates left in $exceptions must be deleted exceptions foreach ($exceptions as $deleted) { $e = new Horde_ActiveSync_Message_Exception(array('protocolversion' => $options['protocolversion'])); // Kronolith stores the date only, but some AS clients need // the datetime. list($year, $month, $mday) = sscanf($deleted, '%04d%02d%02d'); $st = clone $this->start; $st->year = $year; $st->month = $month; $st->mday = $mday; $e->setExceptionStartTime($st); $e->deleted = true; $message->addException($e); } } } // Attendees if (!$this->isPrivate() && count($this->attendees)) { $message->setMeetingStatus(Horde_ActiveSync_Message_Appointment::MEETING_IS_MEETING); foreach ($this->attendees as $email => $properties) { $attendee = new Horde_ActiveSync_Message_Attendee(array('protocolversion' => $options['protocolversion'])); $adr_obj = new Horde_Mail_Rfc822_Address($email); $attendee->name = $adr_obj->label; $attendee->email = $adr_obj->bare_address; // AS only has required or optional, and only EAS Version > 2.5 if ($options['protocolversion'] > Horde_ActiveSync::VERSION_TWOFIVE) { $attendee->type = $properties['attendance'] !== Kronolith::PART_REQUIRED ? Horde_ActiveSync_Message_Attendee::TYPE_OPTIONAL : Horde_ActiveSync_Message_Attendee::TYPE_REQUIRED; switch ($properties['response']) { case Kronolith::RESPONSE_NONE: $attendee->status = Horde_ActiveSync_Message_Attendee::STATUS_NORESPONSE; break; case Kronolith::RESPONSE_ACCEPTED: $attendee->status = Horde_ActiveSync_Message_Attendee::STATUS_ACCEPT; break; case Kronolith::RESPONSE_DECLINED: $attendee->status = Horde_ActiveSync_Message_Attendee::STATUS_DECLINE; break; case Kronolith::RESPONSE_TENTATIVE: $attendee->status = Horde_ActiveSync_Message_Attendee::STATUS_TENTATIVE; break; default: $attendee->status = Horde_ActiveSync_Message_Attendee::STATUS_UNKNOWN; } } $message->addAttendee($attendee); } } else { $message->setMeetingStatus(Horde_ActiveSync_Message_Appointment::MEETING_NOT_MEETING); } // Resources if ($options['protocolversion'] > Horde_ActiveSync::VERSION_TWOFIVE) { $r = $this->getResources(); foreach ($r as $id => $data) { $resource = Kronolith::getDriver('Resource')->getResource($id); // EAS *REQUIRES* an email field for Resources. If it is missing // a number of clients will fail, losing push. if ($resource->get('email')) { $attendee = new Horde_ActiveSync_Message_Attendee(array('protocolversion' => $options['protocolversion'])); $attendee->email = $resource->get('email'); $attendee->type = Horde_ActiveSync_Message_Attendee::TYPE_RESOURCE; $attendee->name = $data['name']; $attendee->status = $data['response']; $message->addAttendee($attendee); } } } // Reminder if ($this->alarm) { $message->setReminder($this->alarm); } // Categories (tags) if (!$this->isPrivate()) { foreach ($this->tags as $tag) { $message->addCategory($tag); } } // EAS 14 if ($options['protocolversion'] > Horde_ActiveSync::VERSION_TWELVEONE) { // We don't track the actual responses we sent to other's invitations. // Set this based on the status flag. switch ($this->status) { case Kronolith::STATUS_TENTATIVE: $message->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_TENTATIVE; break; case Kronolith::STATUS_NONE: $message->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_NORESPONSE; break; case Kronolith::STATUS_CONFIRMED: $message->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_ACCEPTED; break; default: $message->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_NONE; } } // 14.1 if ($options['protocolversion'] >= Horde_ActiveSync::VERSION_FOURTEENONE) { $message->onlinemeetingexternallink = $this->url; } return $message; }
/** * Returns a plain text representation of a ticket. */ public function toString() { $fields = array('queue' => _("Queue"), 'version' => _("Version"), 'type' => _("Type"), 'state' => _("State"), 'priority' => _("Priority"), 'due' => _("Due")); /* Find longest translated field name. */ $length = 0; foreach (array_merge($fields, array(_("Summary"), _("Owners"))) as $field) { $length = max($length, Horde_String::length($field)); } $wrap_break = "\n" . str_repeat(' ', $length + 2) . '| '; $wrap_width = 73 - $length; /* Ticket properties. */ $message = ' ' . Horde_String::pad(_("Ticket"), $length) . ' | ' . $this->_id . "\n" . ' ' . Horde_String::pad(_("Summary"), $length) . ' | ' . Horde_String::wrap($this->get('summary'), $wrap_width, $wrap_break) . "\n"; foreach ($fields as $field => $label) { if ($name = $this->get($field . '_name')) { $message .= ' ' . Horde_String::pad($label, $length) . ' | ' . Horde_String::wrap($name, $wrap_width, $wrap_break) . "\n"; } } $message .= ' ' . Horde_String::pad(_("Owners"), $length) . ' | ' . Horde_String::wrap(Whups::getOwners($this->_id, false, true), $wrap_width, $wrap_break) . "\n"; return $message; }
function isValid(&$var, &$vars, $value, &$message) { $valid = true; $length = Horde_String::length(trim($value)); if ($var->isRequired() && $length <= 0) { $valid = false; $message = Horde_Form_Translation::t("This field is required."); } elseif ($length > $this->_chars) { $valid = false; $message = sprintf(Horde_Form_Translation::ngettext("There are too many characters in this field. You have entered %d character; ", "There are too many characters in this field. You have entered %d characters; ", $length), $length) . sprintf(Horde_Form_Translation::t("you must enter less than %d."), $this->_chars); } return $valid; }
/** * Generates a replacement for the matched text. * * Token options are: * * 'type' => * 'table_start' : the start of a bullet list * 'table_end' : the end of a bullet list * 'row_start' : the start of a number list * 'row_end' : the end of a number list * 'cell_start' : the start of item text (bullet or number) * 'cell_end' : the end of item text (bullet or number) * * 'cols' => the number of columns in the table (for 'table_start') * * 'rows' => the number of rows in the table (for 'table_start') * * 'span' => column span (for 'cell_start') * * 'attr' => column attribute flag (for 'cell_start') * * @param array $matches The array of matches from parse(). * * @return string A series of text and delimited tokens marking the * different table elements and cell text. * */ public function process($matches) { // Build the structure first and hope that the table isn't too large. $table = array(); // the width of columns in the table $widths = array(); // rows are separated by newlines in the matched text $rows = explode("\n", $matches[1]); // loop through each row foreach ($rows as $row) { $table_row = array(); // cells are separated by double-pipes $cells = explode('||', $row); // get the number of cells (columns) in this row $last = count($cells) - 1; // by default, cells span only one column (their own) $span = 1; // ignore cell zero, and ignore the "last" cell; cell zero // is before the first double-pipe, and the "last" cell is // after the last double-pipe. both are always empty. for ($i = 1; $i < $last; $i++) { // if there is no content at all, then it's an instance // of two sets of || next to each other, indicating a // span. if ($cells[$i] == '') { // add to the span and loop to the next cell $span += 1; continue; } // this cell has content. $table_cell = array('attr' => null, 'span' => $span); // find any special "attr"ibute cell markers switch (substr($cells[$i], 0, 2)) { case '> ': // right-align $table_cell['attr'] = 'right'; $content = substr($cells[$i], 2); break; case '= ': // center-align $table_cell['attr'] = 'center'; $content = substr($cells[$i], 2); break; case '< ': // left-align $table_cell['attr'] = 'left'; $content = substr($cells[$i], 2); break; case '~ ': $table_cell['attr'] = 'header'; $content = substr($cells[$i], 2); break; default: $content = $cells[$i]; } $table_cell['content'] = trim($content); $table_cell['length'] = Horde_String::length($table_cell['content']); $table_row[] = $table_cell; // Record the column widths. if (isset($widths[$i])) { $length = $table_cell['length']; for ($j = $table_cell['span']; $j > 1; $j--) { if (isset($widths[$i - $j + 1])) { $length -= $widths[$i - $j + 1]; } } $widths[$i] = max($widths[$i], $length); } else { $widths[$i] = ceil($table_cell['length'] / $table_cell['span']); } // reset the span. $span = 1; } $table[] = $table_row; } // our eventual return value $return = $this->wiki->addToken($this->rule, array('type' => 'table_start', 'widths' => array_values($widths))); // loop through each row foreach ($table as $row) { // start a new row $return .= $this->wiki->addToken($this->rule, array('type' => 'row_start')); foreach ($row as $cell) { // start a new cell... $return .= $this->wiki->addToken($this->rule, array('type' => 'cell_start', 'attr' => $cell['attr'], 'span' => $cell['span'], 'length' => $cell['length'])); // ...add the content... $return .= $cell['content']; // ...and end the cell. $return .= $this->wiki->addToken($this->rule, array('type' => 'cell_end', 'attr' => $cell['attr'], 'span' => $cell['span'], 'length' => $cell['length'])); } // end the row $return .= $this->wiki->addToken($this->rule, array('type' => 'row_end')); } // End the table. $return .= $this->wiki->addToken($this->rule, array('type' => 'table_end')); // we're done! return "\n{$return}\n\n"; }