/** * @brief Display the statistics page to the requesting connection. * @param con a pointer to the connection object across which the server statistics will be transmitted. * @return This function returns no value. */ void statistics_process(connection_t *con) { time_t sm_time; chr_t buffer[256]; stringer_t *raw; struct tm tm_time; http_page_t *page; if (!(page = http_page_get("statistics/statistics"))) { http_print_500(con); return; } statistics_refresh(); if ((sm_time = time(NULL)) == ((time_t)-1) || !localtime_r(&sm_time, &tm_time) || strftime(buffer, 256, "These statistics were last updated %A, %B %e, %Y at %I:%M:%S %p %Z.", &tm_time) <= 0) { log_pedantic("Unable to build the time string."); } else { // Update the time. xml_set_xpath_ns(page->xpath_ctx, (xmlChar *)"//xhtml:p[@id='time']", (uchr_t *)buffer); } xml_set_xpath_uint64(page->xpath_ctx, (xmlChar *)"//xhtml:td[@id='total_users']", portal_stats[portal_stat_total_users].val); xml_set_xpath_uint64(page->xpath_ctx, (xmlChar *)"//xhtml:td[@id='checked_email_today']", portal_stats[portal_stat_users_checked_email_today].val); xml_set_xpath_uint64(page->xpath_ctx, (xmlChar *)"//xhtml:td[@id='checked_email_week']", portal_stats[portal_stat_users_checked_email_week].val); xml_set_xpath_uint64(page->xpath_ctx, (xmlChar *)"//xhtml:td[@id='sent_email_today']", portal_stats[portal_stat_users_sent_email_today].val); xml_set_xpath_uint64(page->xpath_ctx, (xmlChar *)"//xhtml:td[@id='sent_email_week']", portal_stats[portal_stat_users_sent_email_week].val); xml_set_xpath_uint64(page->xpath_ctx, (xmlChar *)"//xhtml:td[@id='emails_received_today']", portal_stats[portal_stat_emails_received_today].val); xml_set_xpath_uint64(page->xpath_ctx, (xmlChar *)"//xhtml:td[@id='emails_received_week']", portal_stats[portal_stat_emails_received_week].val); xml_set_xpath_uint64(page->xpath_ctx, (xmlChar *)"//xhtml:td[@id='emails_sent_today']", portal_stats[portal_stat_emails_sent_today].val); xml_set_xpath_uint64(page->xpath_ctx, (xmlChar *)"//xhtml:td[@id='emails_sent_week']", portal_stats[portal_stat_emails_sent_week].val); xml_set_xpath_uint64(page->xpath_ctx, (xmlChar *)"//xhtml:td[@id='users_registered_today']", portal_stats[portal_stat_users_registered_today].val); xml_set_xpath_uint64(page->xpath_ctx, (xmlChar *)"//xhtml:td[@id='users_registered_week']", portal_stats[portal_stat_users_registered_week].val); if (!(raw = xml_dump_doc(page->doc_obj))) { http_print_500(con); http_page_free(page); return; } http_response_header(con, 200, page->content->type, st_length_get(raw)); con_write_st(con, raw); http_page_free(page); st_free(raw); return; }
/** * @brief Retrieve a user's message, in response to a POP3 RETR command. * @note This function will fail if a deleted message was specified by the user. * @param con the POP3 client connection issuing the command. * @return This function returns no value. */ void pop_retr(connection_t *con) { uint64_t number; meta_message_t *meta; mail_message_t *message; if (con->pop.session_state != 1) { pop_invalid(con); return; } // Which message are we getting. if (!pop_num_parse(con, &number, true)) { con_write_bl(con, "-ERR The retrieve command requires a numeric argument.\r\n", 56); return; } meta_user_rlock(con->pop.user); // Get the message. if (!(meta = pop_get_message(con->pop.user->messages, number))) { meta_user_unlock(con->pop.user); con_write_bl(con, "-ERR Message not found.\r\n", 25); return; } // Check for deletion. if ((meta->status & MAIL_STATUS_HIDDEN) == MAIL_STATUS_HIDDEN) { meta_user_unlock(con->pop.user); con_write_bl(con, "-ERR This message has been marked for deletion.\r\n", 49); return; } // Load the message and spit back the right number of lines. if (!(message = mail_load_message(meta, con->pop.user, con->server, 1))) { meta_user_unlock(con->pop.user); con_write_bl(con, "-ERR The message you requested could not be loaded into memory. It has either been " "deleted by another connection or is corrupted.\r\n", 131); return; } meta_user_unlock(con->pop.user); // Dot stuff the message. st_replace(&(message->text), PLACER("\n.", 2), PLACER("\n..", 3)); // Tell the client to prepare for a message. The size is strictly informational. con_print(con, "+OK %u characters follow.\r\n", st_length_get(message->text)); // We use raw socket IO because it is much faster when writing large amounts of data. con_write_st(con, message->text); // If the message didn't end with a line break, spit two. if (*(st_char_get(message->text) + st_length_get(message->text) - 1) == '\n') { con_write_bl(con, ".\r\n", 3); } else { con_write_bl(con, "\r\n.\r\n", 5); } mail_destroy(message); return; }