/** * Prepares the message headers for display inside a template. The links are calculated, * color for row highlighting is calculated and optionally the strings are truncated. * * @param array $aMailbox (reference) mailbox retrieved from sqm_api_mailbox_select * @param array $aProps properties * @return array $aFormattedMessages array with message headers and format info * @since 1.5.1 * @author Marc Groot Koerkamp */ function prepareMessageList(&$aMailbox, $aProps) { /* Globalize link attributes so plugins can share in modifying them */ global $link, $title, $target, $onclick, $link_extra, $preselected; /* retrieve the properties */ $my_email_address = isset($aProps['email']) ? $aProps['email'] : false; $highlight_list = isset($aProps['config']['highlight_list']) ? $aProps['config']['highlight_list'] : false; $aColumnDesc = isset($aProps['columns']) ? $aProps['columns'] : false; $aExtraColumns = isset($aProps['extra_columns']) ? $aProps['extra_columns'] : array(); $iAccount = isset($aProps['account']) ? (int) $aProps['account'] : 0; $sMailbox = isset($aProps['mailbox']) ? $aProps['mailbox'] : false; $sTargetModule = isset($aProps['module']) ? $aProps['module'] : 'read_body'; /* * TODO 1, retrieve array with identity email addresses in order to match against to,cc and set a flag * $aFormattedMessages[$iUid]['match_identity'] = true * The template can show some image if there is a match. * TODO 2, makes sure the matching is done fast by doing a strpos call on the returned $value */ /** * Only retrieve values for displayable columns */ foreach ($aColumnDesc as $k => $v) { switch ($k) { case SQM_COL_FROM: $aCol[SQM_COL_FROM] = 'from'; break; case SQM_COL_DATE: $aCol[SQM_COL_DATE] = 'date'; break; case SQM_COL_SUBJ: $aCol[SQM_COL_SUBJ] = 'subject'; break; case SQM_COL_FLAGS: $aCol[SQM_COL_FLAGS] = 'FLAGS'; break; case SQM_COL_SIZE: $aCol[SQM_COL_SIZE] = 'SIZE'; break; case SQM_COL_PRIO: $aCol[SQM_COL_PRIO] = 'x-priority'; break; case SQM_COL_ATTACHMENT: $aCol[SQM_COL_ATTACHMENT] = 'content-type'; break; case SQM_COL_INT_DATE: $aCol[SQM_COL_INT_DATE] = 'INTERNALDATE'; break; case SQM_COL_TO: $aCol[SQM_COL_TO] = 'to'; break; case SQM_COL_CC: $aCol[SQM_COL_CC] = 'cc'; break; case SQM_COL_BCC: $aCol[SQM_COL_BCC] = 'bcc'; break; default: break; } } $aExtraHighLightColumns = array(); foreach ($aExtraColumns as $v) { switch ($v) { case SQM_COL_FROM: $aExtraHighLightColumns[] = 'from'; break; case SQM_COL_SUBJ: $aExtraHighLightColumns[] = 'subject'; break; case SQM_COL_TO: $aExtraHighLightColumns[] = 'to'; break; case SQM_COL_CC: $aExtraHighLightColumns[] = 'cc'; break; case SQM_COL_BCC: $aExtraHighLightColumns[] = 'bcc'; break; default: break; } } $aFormattedMessages = array(); $iSetIndx = $aMailbox['SETINDEX']; $aId = $aMailbox['UIDSET'][$iSetIndx]; $aHeaders =& $aMailbox['MSG_HEADERS']; /* use a reference to avoid a copy. MSG_HEADERS can contain large amounts of data */ $iOffset = $aMailbox['OFFSET']; $sort = $aMailbox['SORT']; $iPageOffset = $aMailbox['PAGEOFFSET']; $sMailbox = $aMailbox['NAME']; $sSearch = isset($aMailbox['SEARCH'][$aMailbox['SETINDEX']]) && $aMailbox['SEARCH'][$aMailbox['SETINDEX']] != 'ALL' ? $aMailbox['SEARCH'][$aMailbox['SETINDEX']] : false; $aSearch = $sSearch ? array('search.php', $aMailbox['SETINDEX']) : null; /* avoid improper usage */ if ($sMailbox && isset($iAccount) && $sTargetModule) { $aInitQuery = array("account={$iAccount}", 'mailbox=' . urlencode($sMailbox)); } else { $aInitQuery = false; } if ($aMailbox['SORT'] & SQSORT_THREAD) { $aIndentArray =& $aMailbox['THREAD_INDENT'][$aMailbox['SETINDEX']]; $bThread = true; } else { $bThread = false; } /* * Retrieve value for checkbox column */ if (!sqgetGlobalVar('checkall', $checkall, SQ_GET)) { $checkall = false; } /* * Loop through and display the info for each message. */ $iEnd = $aMailbox['SHOWALL'][$iSetIndx] ? $aMailbox['EXISTS'] : $iOffset + $aMailbox['LIMIT']; for ($i = $iOffset, $t = 0; $i < $iEnd; ++$i) { if (isset($aId[$i])) { $bHighLight = false; $value = $title = $link = $target = $onclick = $link_extra = ''; $aQuery = $aInitQuery !== false ? $aInitQuery : false; $aMsg = $aHeaders[$aId[$i]]; if (isset($aSearch) && count($aSearch) > 1 && $aQuery) { $aQuery[] = "where=" . $aSearch[0]; $aQuery[] = "what=" . $aSearch[1]; } $iUid = isset($aMsg['UID']) ? $aMsg['UID'] : $aId[$i]; if ($aQuery) { $aQuery[] = "passed_id={$aId[$i]}"; $aQuery[] = "startMessage={$iPageOffset}"; } foreach ($aCol as $k => $v) { $title = $link = $target = $onclick = $link_extra = ''; $aColumns[$k] = array(); $value = isset($aMsg[$v]) ? $aMsg[$v] : ''; $sUnknown = _("Unknown recipient"); switch ($k) { case SQM_COL_FROM: $sUnknown = _("Unknown sender"); case SQM_COL_TO: case SQM_COL_CC: case SQM_COL_BCC: $sTmp = false; if ($value) { if ($highlight_list && !$bHighLight) { $bHighLight = highlightMessage($aCol[$k], $value, $highlight_list, $aFormattedMessages[$iUid]); } $aAddressList = parseRFC822Address($value); $sTmp = getAddressString($aAddressList, array('best' => true)); $title = $title_maybe = ''; foreach ($aAddressList as $aAddr) { $sPersonal = isset($aAddr[SQM_ADDR_PERSONAL]) ? $aAddr[SQM_ADDR_PERSONAL] : ''; $sMailbox = isset($aAddr[SQM_ADDR_MAILBOX]) ? $aAddr[SQM_ADDR_MAILBOX] : ''; $sHost = isset($aAddr[SQM_ADDR_HOST]) ? $aAddr[SQM_ADDR_HOST] : ''; if ($sPersonal) { $title .= sm_encode_html_special_chars($sMailbox . '@' . $sHost) . ', '; } else { // if $value gets truncated we need to add the addresses with no // personal name as well $title_maybe .= sm_encode_html_special_chars($sMailbox . '@' . $sHost) . ', '; } } if ($title) { $title = substr($title, 0, -2); // strip ', '; } $sTmp = decodeHeader($sTmp); if (isset($aColumnDesc[$k]['truncate']) && $aColumnDesc[$k]['truncate']) { $sTrunc = sm_truncate_string($sTmp, $aColumnDesc[$k]['truncate'], '...', TRUE); if ($sTrunc != $sTmp) { if (!$title) { $title = $sTmp; } else { if ($title_maybe) { $title = $title . ', ' . $title_maybe; $title = substr($title, 0, -2); // strip ', '; } } } $sTmp = $sTrunc; } } $value = $sTmp ? substr($sTmp, 0, 6) == '"' && substr($sTmp, -6) == '"' ? substr(substr($sTmp, 0, -6), 6) : $sTmp : $sUnknown; break; case SQM_COL_SUBJ: // subject is mime encoded, decode it. // value is sanitized in decoding function. // TODO, verify if it should be done before or after the highlighting $value = decodeHeader($value); if ($highlight_list && !$bHighLight) { $bHighLight = highlightMessage('SUBJECT', $value, $highlight_list, $aFormattedMessages[$iUid]); } $iIndent = isset($aIndentArray[$aId[$i]]) ? $aIndentArray[$aId[$i]] : 0; // FIXME: don't break 8bit symbols and html entities during truncation if (isset($aColumnDesc[$k]['truncate']) && $aColumnDesc[$k]['truncate']) { $sTmp = sm_truncate_string($value, $aColumnDesc[$k]['truncate'] - $iIndent, '...', TRUE); // drop any double spaces since these will be displayed in the title // Nah, it's nice to always have a roll-over //$title = ($sTmp != $value) ? preg_replace('/\s{2,}/', ' ', $value) : ''; $title = preg_replace('/\\s{2,}/', ' ', $value); $value = $sTmp; } /* generate the link to the message */ if ($aQuery) { // TODO, $sTargetModule should be a query parameter so that we can use a single entrypoint $link = $sTargetModule . '.php?' . implode('&', $aQuery); // see top of this function for which attributes are available // in the global scope for plugin use (like $link, $target, // $onclick, $link_extra, $title, and so forth) // plugins are responsible for sharing nicely (such as for // setting the target, etc) $temp = array(&$iPageOffset, &$sSearch, &$aSearch, $aMsg); do_hook('subject_link', $temp); } $value = trim($value) ? $value : _("(no subject)"); /* add thread indentation */ $aColumns[$k]['indent'] = $iIndent; break; case SQM_COL_SIZE: $value = show_readable_size($value); break; case SQM_COL_DATE: case SQM_COL_INT_DATE: $value = getTimeStamp(explode(' ', trim($value))); $title = getDateString($value, TRUE); $value = getDateString($value); break; case SQM_COL_FLAGS: $aFlagColumn = array('seen' => false, 'deleted' => false, 'answered' => false, 'forwarded' => false, 'flagged' => false, 'draft' => false); if (!is_array($value)) { $value = array(); } foreach ($value as $sFlag => $v) { switch ($sFlag) { case '\\seen': $aFlagColumn['seen'] = true; break; case '\\deleted': $aFlagColumn['deleted'] = true; break; case '\\answered': $aFlagColumn['answered'] = true; break; case '$forwarded': $aFlagColumn['forwarded'] = true; break; case '\\flagged': $aFlagColumn['flagged'] = true; break; case '\\draft': $aFlagColumn['draft'] = true; break; default: break; } } $value = $aFlagColumn; break; case SQM_COL_PRIO: $value = $value ? (int) $value : 3; break; case SQM_COL_ATTACHMENT: $value = is_array($value) && $value[0] == 'multipart' && $value[1] == 'mixed' ? true : false; break; case SQM_COL_CHECK: $value = $checkall || in_array($iUid, $preselected); break; default: break; } if ($title) { $aColumns[$k]['title'] = $title; } if ($link) { $aColumns[$k]['link'] = $link; } if ($link_extra) { $aColumns[$k]['link_extra'] = $link_extra; } if ($onclick) { $aColumns[$k]['onclick'] = $onclick; } if ($target) { $aColumns[$k]['target'] = $target; } $aColumns[$k]['value'] = $value; } /* columns which will not be displayed but should be inspected because the highlight list contains rules with those columns */ foreach ($aExtraHighLightColumns as $v) { if ($highlight_list && !$bHighLight && isset($aMsg[$v])) { $bHighLight = highlightMessage($v, $aMsg[$v], $highlight_list, $aFormattedMessages[$iUid]); } } $aFormattedMessages[$iUid]['columns'] = $aColumns; } else { break; } } return $aFormattedMessages; }
/** * OBSOLETE FUNCTION should be removed after mailbox_display, * printMessage function is adapted */ function parseAddress($address, $max = 0) { $aAddress = parseRFC822Address($address, array('limit' => $max)); /* * Because the expected format of the array element is changed we adapt it now. * This also implies that this function is obsolete and should be removed after the * rest of the source is adapted. See Rfc822Address.php for the new function. */ array_walk($aAddress, '_adaptAddress'); return $aAddress; }