function mime_split($text, $_boundary = null) { $top = substr($text, 0, 500); $boundary = $_boundary; // guess the boundary if none was provided if (is_null($_boundary) && preg_match('#^\\s*(?:.{0,80})?\\s*--(\\S{6,})\\s*[-\\w]+: #', $top, $m)) { $boundary = $m[1]; } if ($boundary) { $parts = explode('--' . $boundary, $text); #echo "<pre>";var_dump("boundary is $boundary", count($parts).' parts');echo "</pre>"; $out = array(); foreach ($parts as $part) { $headers = mime_headers($part); #echo '<pre>';var_dump($headers);echo '</pre>'; if (!$headers) { continue; } if (strpos($headers['content-type'], 'multipart') === 0) { $subparts = mime_split($headers['content']); $out = array_merge($out, $subparts); } else { $out[] = new mime_part($headers['content'], $headers); } #if ( preg_match('#^Content-Type:\s*multipart/alternative;\s*boundary="([^"]+)"#im', $top, $m) ) { } #var_dump("finished with ".count($out)." real parts extracted"); return $out; } #var_dump("no boundary in this message: $top"); #return array(new mime_part($text, array('content-type' => 'text/plain', 'content-transfer-encoding' => 'quoted-printable'))); // use quoted-printable if it looks like it contains encoded characters. skip otherwise to avoid false decoding. if (preg_match_all('/=(?:20|3F|5F|0A|0D|A0)/i', $text, $dummy) > 1) { return array(new mime_part($text, array('content-type' => 'text/plain', 'content-transfer-encoding' => 'quoted-printable'))); } elseif (preg_match('#^\\s*[A-Za-z0-9+/]{64,76}[\\r\\n]+[A-Za-z0-9+/=]{1,76}[\\r\\n]+#ms', trim($text))) { // looks like a base64 block return array(new mime_part($text, array('content-type' => 'text/plain', 'content-transfer-encoding' => 'base64'))); } else { return array(new mime_part($text, array('content-type' => 'text/plain'))); } }
} } #$recent = $db->get_results( "SELECT * FROM support_threads $where ORDER BY dt DESC LIMIT $offset, 20" ); // this query is uuugly but it works - it's called a group-wise maximum query. // it finds the threads with the highest message_ids (i.e. the threads that have most recently been replied to) $query = "FROM {$db->threads} INNER JOIN {$db->messages} ON {$db->messages}.thread_id={$db->threads}.thread_id {$where} AND {$db->messages}.message_id=(SELECT MAX(m2.message_id) FROM {$db->messages} m2 WHERE m2.thread_id={$db->threads}.thread_id) ORDER BY {$db->messages}.dt DESC"; $recent = $db->get_results("SELECT *, {$db->threads}.email as t_email {$query} LIMIT {$offset}, 20"); if (!empty($db->last_error)) { var_dump($db->last_error, $db->last_query); } $i = 0; $total = $db->get_var("SELECT COUNT(*) {$query}"); foreach ((array) $recent as $t) { $class = $i % 2 ? ' class="alt"' : ''; $excerpt = ''; $parts = mime_split($t->content); if ($part = find_first_part($parts)) { $excerpt = substr(message_meat($part->content), 0, 300); } echo "<tr {$class} id='tr{$t->thread_id}'>\r\n\t<td><input type='checkbox' name='thread_ids[]' value='{$t->thread_id}' class='mcheck' id='mcheck{$t->thread_id}' /></td>\r\n\t<td><a href='index.php?email={$t->email}'>{$t->t_email}</a></td><td><a title='" . htmlspecialchars($excerpt, ENT_QUOTES) . "' href='thread.php?t={$t->thread_id}&replies={$t->messages}'>" . htmlspecialchars($t->subject ? mime_header_decode($t->subject) : '-') . "</a></td>\r\n\t<td>" . thread_tags($t->thread_id) . "</td>\r\n\t<td>" . short_time_diff($t->dt) . "</td>\r\n\t<td>{$t->messages}</td>\r\n\t</tr>"; ++$i; } ?> <tr> <td colspan="2"> <label>With checked:</label> <input type="submit" name="status-close" value="Close" class="enablewhenselected" /> </td> <td colspan="3" align="right"> <?php
echo $thread_id; ?> " /> <input type="submit" name="submit" value="Send" /> <input type="submit" name="sendtickle" value="Send and Tickle" /> <input type="submit" name="sendclose" value="Send and Close" /> <input type="hidden" name="from" value="<?php echo htmlspecialchars($_SERVER['HTTP_REFERER']); ?> " /> </p> </form> <?php if ($parts = mime_split($m->content)) { foreach ($parts as $pi => $part) { echo '<div class="hidepart">'; if ($part->is_type('image')) { echo '<img src="message-image.php?message_id=' . intval($m->message_id) . '&i=' . intval($pi) . '" />'; } elseif ($pi > 0 && $part->is_type('text/plain')) { echo '<pre>'; echo htmlspecialchars($part->content); echo '</pre>'; } else { echo '<p>MIME part: <a href="message-attachment.php?message_id=' . intval($m->message_id) . '&i=' . intval($pi) . '" target="_blank">' . htmlspecialchars($part->content_type) . '</a></p>'; } echo '</div>'; } } echo '</div>';
<?php include 'init.php'; auth_redirect(); $message_id = @$_GET['message_id']; $i = @$_GET['i']; $download = !empty($_GET['dl']); if (!empty($message_id) && isset($i)) { $msg = $db->get_row($db->prepare("SELECT * FROM {$db->messages} WHERE message_id=%d", $message_id)); if ($msg) { include_once 'includes/mime.php'; $parts = mime_split($msg->content); $att = $parts[$i]; if ($att) { $content_type = $att->get_type(); $filename = intval($message_id) . '-' . intval($i); if (preg_match('/;\\s*name="([^"]+)"/', $att->content_type, $m)) { $filename .= '-' . preg_replace('/[^\\w.]/', '', $m[1]); } if ($content_type == 'application/octet-stream') { // try to use a slightly more helpful content type $filename_parts = pathinfo($filename); $ext = preg_replace('/[^\\w]/', '', $filename_parts['extension']); if ($ext) { $content_type = 'application/' . strtolower($ext); } } #var_dump($filename_parts, $content_type);die; header('Content-type: ' . $content_type); if ($download) { header('Content-Disposition: attachment; filename="' . $filename . '"');