} // archive the letter $context['text'] .= i18n::s('Archiving the new letter') . BR . "\n"; // save the letter as a published article, but don't use special categories $fields = array(); $fields['anchor'] = $anchor; $fields['title'] = $_REQUEST['letter_title']; $label = $_REQUEST['letter_recipients']; if ($_REQUEST['letter_recipients'] == 'custom' && isset($_REQUEST['mail_to'])) { $label = $_REQUEST['mail_to']; } $fields['introduction'] = sprintf(i18n::c('Sent %s to "%s"'), Skin::build_date(time(), 'full', $context['preferred_language']), $label); $fields['description'] = $_REQUEST['letter_body']; $fields['publish_name'] = Surfer::get_name(); $fields['publish_id'] = Surfer::get_id(); $fields['publish_address'] = Surfer::get_email_address(); $fields['publish_date'] = gmstrftime('%Y-%m-%d %H:%M:%S'); $fields['id'] = Articles::post($fields); // from: from configuration files if (isset($context['letter_reply_to']) && $context['letter_reply_to']) { $from = $context['letter_reply_to']; } elseif (isset($context['mail_from']) && $context['mail_from']) { $from = $context['mail_from']; } else { $from = $context['site_name']; } // to: build the list of recipients $recipients = array(); switch ($_REQUEST['letter_recipients']) { case 'all': $recipients = Users::list_by_posts(0, MAXIMUM_RECIPIENTS, 'address');
/** * remember the last action for this category * * @param string the description of the last action * @param string the id of the item related to this update * @param boolean TRUE to not change the edit date of this anchor, default is FALSE * * @see shared/anchor.php */ function touch($action, $origin = NULL, $silently = FALSE) { global $context; // don't go further on import if (preg_match('/import$/i', $action)) { return; } // no category bound if (!isset($this->item['id'])) { return; } // sanity check if (!$origin) { logger::remember('categories/category.php: unexpected NULL origin at touch()'); return; } // components of the query $query = array(); // append a reference to a new image to the description if ($action == 'image:create') { if (!Codes::check_embedded($this->item['description'], 'image', $origin)) { // the overlay may prevent embedding if (is_object($this->overlay) && !$this->overlay->should_embed_files()) { } else { // list has already started if (preg_match('/\\[image=[^\\]]+?\\]\\s*$/', $this->item['description'])) { $query[] = "description = '" . SQL::escape($this->item['description'] . ' [image=' . $origin . ']') . "'"; } else { $query[] = "description = '" . SQL::escape($this->item['description'] . "\n\n" . '[image=' . $origin . ']') . "'"; } } } // also use it as thumnail if none has been defined yet if (!isset($this->item['thumbnail_url']) || !trim($this->item['thumbnail_url'])) { include_once $context['path_to_root'] . 'images/images.php'; if (($image = Images::get($origin)) && ($url = Images::get_thumbnail_href($image))) { $query[] = "thumbnail_url = '" . SQL::escape($url) . "'"; } } // refresh stamp only if image update occurs within 6 hours after last edition if (SQL::strtotime($this->item['edit_date']) + 6 * 60 * 60 < time()) { $silently = TRUE; } // suppress a reference to an image that has been deleted } elseif ($action == 'image:delete') { // suppress reference in main description field $query[] = "description = '" . SQL::escape(Codes::delete_embedded($this->item['description'], 'image', $origin)) . "'"; // suppress references as icon and thumbnail as well include_once $context['path_to_root'] . 'images/images.php'; if ($image = Images::get($origin)) { if ($url = Images::get_icon_href($image)) { if ($this->item['icon_url'] == $url) { $query[] = "icon_url = ''"; } if ($this->item['thumbnail_url'] == $url) { $query[] = "thumbnail_url = ''"; } } if ($url = Images::get_thumbnail_href($image)) { if ($this->item['icon_url'] == $url) { $query[] = "icon_url = ''"; } if ($this->item['thumbnail_url'] == $url) { $query[] = "thumbnail_url = ''"; } } } // set an existing image as the category icon } elseif ($action == 'image:set_as_icon') { include_once $context['path_to_root'] . 'images/images.php'; if ($image = Images::get($origin)) { if ($url = Images::get_icon_href($image)) { $query[] = "icon_url = '" . SQL::escape($url) . "'"; } // also use it as thumnail if none has been defined yet if (!(isset($this->item['thumbnail_url']) && trim($this->item['thumbnail_url'])) && ($url = Images::get_thumbnail_href($image))) { $query[] = "thumbnail_url = '" . SQL::escape($url) . "'"; } } $silently = TRUE; // set an existing image as the category thumbnail } elseif ($action == 'image:set_as_thumbnail') { include_once $context['path_to_root'] . 'images/images.php'; if ($image = Images::get($origin)) { if ($url = Images::get_thumbnail_href($image)) { $query[] = "thumbnail_url = '" . SQL::escape($url) . "'"; } } $silently = TRUE; // append a new image, and set it as the article thumbnail } elseif ($action == 'image:set_as_both') { if (!Codes::check_embedded($this->item['description'], 'image', $origin)) { $query[] = "description = '" . SQL::escape($this->item['description'] . ' [image=' . $origin . ']') . "'"; } include_once $context['path_to_root'] . 'images/images.php'; if ($image = Images::get($origin)) { if ($url = Images::get_thumbnail_href($image)) { $query[] = "thumbnail_url = '" . SQL::escape($url) . "'"; } } elseif ($origin) { $query[] = "thumbnail_url = '" . SQL::escape($origin) . "'"; } // do not remember minor changes $silently = TRUE; // add a reference to a new table in the category description } elseif ($action == 'table:create') { if (!Codes::check_embedded($this->item['description'], 'table', $origin)) { $query[] = "description = '" . SQL::escape($this->item['description'] . ' [table=' . $origin . ']') . "'"; } // suppress a reference to a table that has been deleted } elseif ($action == 'table:delete') { $query[] = "description = '" . SQL::escape(Codes::delete_embedded($this->item['description'], 'table', $origin)) . "'"; } // stamp the update if (!$silently) { $query[] = "edit_name='" . Surfer::get_name() . "'," . "edit_id=" . Surfer::get_id() . "," . "edit_address='" . Surfer::get_email_address() . "'," . "edit_action='{$action}'," . "edit_date='" . strftime('%Y-%m-%d %H:%M:%S') . "'"; } // ensure we have a valid update query if (!@count($query)) { return; } // update the anchor category $query = "UPDATE " . SQL::table_name('categories') . " SET " . implode(', ', $query) . " WHERE id = " . SQL::escape($this->item['id']); if (SQL::query($query) === FALSE) { return; } // always clear the cache, even on no update Categories::clear($this->item); // get the parent if (!$this->anchor) { $this->anchor = Anchors::get($this->item['anchor']); } // propagate the touch upwards silently -- we only want to purge the cache if (is_object($this->anchor)) { $this->anchor->touch('category:update', $this->item['id'], TRUE); } }
/** * remember that surfer is enrolled in a meeting * * @param string reference of the target page */ public static function confirm($reference) { global $context; // sanity check if (!$reference) { return; } // ensure that the joiner has been enrolled... if (!($item = enrolments::get_record($reference))) { if (Surfer::get_id()) { // fields to save $query = array(); $query[] = "anchor = '" . $reference . "'"; $query[] = "approved = 'Y'"; $query[] = "edit_date = '" . SQL::escape(gmstrftime('%Y-%m-%d %H:%M:%S')) . "'"; $query[] = "user_id = " . SQL::escape(Surfer::get_id()); $query[] = "user_email = '" . SQL::escape(Surfer::get_email_address()) . "'"; // insert a new record $query = "INSERT INTO " . SQL::table_name('enrolments') . " SET " . implode(', ', $query); SQL::query($query); } // each joiner takes one seat } else { $query = "UPDATE " . SQL::table_name('enrolments') . " SET approved = 'Y' WHERE id = " . SQL::escape($item['id']); SQL::query($query); } }
if ($with_form) { // splash message $context['text'] .= '<p>' . i18n::s('Please fill out the form and it will be sent automatically to the site managers. Be as precise as possible, and mention your e-mail address to let us a chance to contact you back.') . "</p>\n"; // the form to send a query $context['text'] .= '<form method="post" action="' . $context['script_url'] . '" onsubmit="return validateDocumentPost(this)" id="main_form"><div>'; // surfer name if (!isset($item['edit_name'])) { $item['edit_name'] = Surfer::get_name(); } $label = i18n::s('Your name') . ' *'; $input = '<input type="text" name="edit_name" id="edit_name" size="45" value="' . encode_field($item['edit_name']) . '" maxlength="255" />'; $hint = i18n::s('Let us a chance to know who you are'); $fields[] = array($label, $input, $hint); // surfer address if (!isset($item['edit_address'])) { $item['edit_address'] = Surfer::get_email_address(); } $label = i18n::s('Your e-mail address') . ' *'; $input = '<input type="text" name="edit_address" size="45" value="' . encode_field($item['edit_address']) . '" maxlength="255" />'; $hint = i18n::s('To be alerted during the processing of your request'); $fields[] = array($label, $input, $hint); // stop robots if ($field = Surfer::get_robot_stopper()) { $fields[] = $field; } // the title if (!isset($item['title'])) { $item['title'] = ''; } $label = i18n::s('Query object') . ' *'; $input = '<textarea name="title" rows="2" cols="50">' . encode_field($item['title']) . '</textarea>';
if (isset($item['id'])) { $login_url = $context['url_to_root'] . 'users/login.php?url=' . urlencode('articles/edit.php?id=' . $item['id']); } elseif (is_object($anchor)) { $login_url = $context['url_to_root'] . 'users/login.php?url=' . urlencode('articles/edit.php?anchor=' . $anchor->get_reference()); } else { $login_url = $context['url_to_root'] . 'users/login.php?url=' . urlencode('articles/edit.php'); } $text .= '<p>' . sprintf(i18n::s('If you have previously registered to this site, please %s. Then the server will automatically put your name and address in following fields.'), Skin::build_link($login_url, 'authenticate')) . "</p>\n"; // the name, if any $label = i18n::s('Your name'); $input = '<input type="text" name="edit_name" size="45" maxlength="128" accesskey="n" value="' . encode_field(Surfer::get_name(' ')) . '" />'; $hint = i18n::s('Let us a chance to know who you are'); $fields[] = array($label, $input, $hint); // the address, if any $label = i18n::s('Your e-mail address'); $input = '<input type="text" name="edit_address" size="45" maxlength="128" accesskey="a" value="' . encode_field(Surfer::get_email_address()) . '" />'; $hint = i18n::s('Put your e-mail address to receive feed-back'); $fields[] = array($label, $input, $hint); // stop robots if ($field = Surfer::get_robot_stopper()) { $fields[] = $field; } } // the title if (!is_object($overlay) || !($label = $overlay->get_label('title', isset($item['id']) ? 'edit' : 'new'))) { $label = i18n::s('Title') . ' *'; } $value = ''; if (isset($item['title']) && $item['title']) { $value = $item['title']; } elseif (isset($_SESSION['pasted_title'])) {
/** * remember the last action for this article * * This function is called by related items. What does it do? * - On image creation, the adequate code is added to the description field to let the image be displayed inline * - On icon selection, the icon field is updated * - On thumbnail image selection, the thumbnail image field is updated * - On location creation, some code is inserted in the description field to display location name inline * - On table creation, some code is inserted in the description field to display the table inline * * @see articles/article.php * @see articles/edit.php * @see shared/anchor.php * * @param string one of the pre-defined action code * @param string the id of the item related to this update * @param boolean TRUE to not change the edit date of this anchor, default is FALSE */ function touch($action, $origin = NULL, $silently = FALSE) { global $context; // we make extensive use of comments below include_once $context['path_to_root'] . 'comments/comments.php'; // don't go further on import if (preg_match('/import$/i', $action)) { return; } // no article bound if (!isset($this->item['id'])) { return; } // delegate to overlay if (is_object($this->overlay) && $this->overlay->touch($action, $origin, $silently) === false) { return; // stop on false } // clear floating objects if ($action == 'clear') { $this->item['description'] .= ' [clear]'; $query = "UPDATE " . SQL::table_name('articles') . " SET description='" . SQL::escape($this->item['description']) . "'" . " WHERE id = " . SQL::escape($this->item['id']); SQL::query($query); return; } // get the related overlay, if any if (!isset($this->overlay)) { $this->overlay = NULL; if (isset($this->item['overlay'])) { $this->overlay = Overlay::load($this->item, 'article:' . $this->item['id']); } } // components of the query $query = array(); // a new comment has been posted if ($action == 'comment:create') { // purge oldest comments Comments::purge_for_anchor('article:' . $this->item['id']); // file upload } elseif ($action == 'file:create' || $action == 'file:upload') { // actually, several files have been added $label = ''; if (!$origin) { // only when comments are allowed if (!Articles::has_option('no_comments', $this->anchor, $this->item)) { // remember this as an automatic notification $fields = array(); $fields['anchor'] = 'article:' . $this->item['id']; $fields['description'] = i18n::s('Several files have been added'); $fields['type'] = 'notification'; Comments::post($fields); } // one file has been added } elseif (!Codes::check_embedded($this->item['description'], 'embed', $origin) && ($item = Files::get($origin, TRUE))) { // this file is eligible for being embedded in the page if (isset($item['file_name']) && Files::is_embeddable($item['file_name'])) { // the overlay may prevent embedding if (is_object($this->overlay) && !$this->overlay->should_embed_files()) { } else { $label = '[embed=' . $origin . ']'; } // else add a comment to take note of the upload } else { // only when comments are allowed if (!Articles::has_option('no_comments', $this->anchor, $this->item)) { // remember this as an automatic notification $fields = array(); $fields['anchor'] = 'article:' . $this->item['id']; if ($action == 'file:create') { $fields['description'] = '[file=' . $item['id'] . ',' . $item['file_name'] . ']'; } else { $fields['description'] = '[download=' . $item['id'] . ',' . $item['file_name'] . ']'; } Comments::post($fields); } } } // we are in some interactive thread if ($origin && $this->has_option('view_as_chat')) { // default is to download the file if (!$label) { $label = '[download=' . $origin . ']'; } // this is the first contribution to the thread if (!($comment = Comments::get_newest_for_anchor('article:' . $this->item['id']))) { $fields = array(); $fields['anchor'] = 'article:' . $this->item['id']; $fields['description'] = $label; // this is a continuated contribution from this authenticated surfer } elseif ($comment['type'] != 'notification' && Surfer::get_id() && (isset($comment['create_id']) && Surfer::get_id() == $comment['create_id'])) { $comment['description'] .= BR . $label; $fields = $comment; // else process the contribution as a new comment } else { $fields = array(); $fields['anchor'] = 'article:' . $this->item['id']; $fields['description'] = $label; } // only when comments are allowed if (!Articles::has_option('no_comments', $this->anchor, $this->item)) { Comments::post($fields); } // include flash videos in a regular page } elseif ($origin && $label) { $query[] = "description = '" . SQL::escape($this->item['description'] . ' ' . $label) . "'"; } // suppress references to a deleted file } elseif ($action == 'file:delete' && $origin) { // suppress reference in main description field $text = Codes::delete_embedded($this->item['description'], 'download', $origin); $text = Codes::delete_embedded($text, 'embed', $origin); $text = Codes::delete_embedded($text, 'file', $origin); // save changes $query[] = "description = '" . SQL::escape($text) . "'"; // append a reference to a new image to the description } elseif ($action == 'image:create' && $origin) { if (!Codes::check_embedded($this->item['description'], 'image', $origin)) { // the overlay may prevent embedding if (is_object($this->overlay) && !$this->overlay->should_embed_files()) { } else { // list has already started if (preg_match('/\\[image=[^\\]]+?\\]\\s*$/', $this->item['description'])) { $this->item['description'] .= ' [image=' . $origin . ']'; } else { $this->item['description'] .= "\n\n" . '[image=' . $origin . ']'; } $query[] = "description = '" . SQL::escape($this->item['description']) . "'"; } } // also use it as thumnail if none has been defined yet if (!isset($this->item['thumbnail_url']) || !trim($this->item['thumbnail_url'])) { include_once $context['path_to_root'] . 'images/images.php'; if (($image = Images::get($origin)) && ($url = Images::get_thumbnail_href($image))) { $query[] = "thumbnail_url = '" . SQL::escape($url) . "'"; } } // refresh stamp only if image update occurs within 6 hours after last edition if (SQL::strtotime($this->item['edit_date']) + 6 * 60 * 60 < time()) { $silently = TRUE; } // suppress a reference to an image that has been deleted } elseif ($action == 'image:delete' && $origin) { // suppress reference in main description field $query[] = "description = '" . SQL::escape(Codes::delete_embedded($this->item['description'], 'image', $origin)) . "'"; // suppress references as icon and thumbnail as well include_once $context['path_to_root'] . 'images/images.php'; if ($image = Images::get($origin)) { if ($url = Images::get_icon_href($image)) { if ($this->item['icon_url'] == $url) { $query[] = "icon_url = ''"; } if ($this->item['thumbnail_url'] == $url) { $query[] = "thumbnail_url = ''"; } } if ($url = Images::get_thumbnail_href($image)) { if ($this->item['icon_url'] == $url) { $query[] = "icon_url = ''"; } if ($this->item['thumbnail_url'] == $url) { $query[] = "thumbnail_url = ''"; } } } // set an existing image as the article icon } elseif ($action == 'image:set_as_icon' && $origin) { include_once $context['path_to_root'] . 'images/images.php'; if ($image = Images::get($origin)) { if ($url = Images::get_icon_href($image)) { $query[] = "icon_url = '" . SQL::escape($url) . "'"; } // also use it as thumnail if none has been defined yet if (!(isset($this->item['thumbnail_url']) && trim($this->item['thumbnail_url'])) && ($url = Images::get_thumbnail_href($image))) { $query[] = "thumbnail_url = '" . SQL::escape($url) . "'"; } } // set an existing image as the article thumbnail } elseif ($action == 'image:set_as_thumbnail' && $origin) { include_once $context['path_to_root'] . 'images/images.php'; if ($image = Images::get($origin)) { // use the thumbnail for large files, or the image itself for smaller files if ($image['image_size'] > $context['thumbnail_threshold']) { $url = Images::get_thumbnail_href($image); } else { $url = Images::get_icon_href($image); } $query[] = "thumbnail_url = '" . SQL::escape($url) . "'"; } elseif ($origin) { $query[] = "thumbnail_url = '" . SQL::escape($origin) . "'"; } // do not remember minor changes $silently = TRUE; // append a new image, and set it as the article thumbnail } elseif ($action == 'image:set_as_both' && $origin) { if (!Codes::check_embedded($this->item['description'], 'image', $origin)) { $query[] = "description = '" . SQL::escape($this->item['description'] . ' [image=' . $origin . ']') . "'"; } include_once $context['path_to_root'] . 'images/images.php'; if ($image = Images::get($origin)) { // use the thumbnail for large files, or the image itself for smaller files if ($image['image_size'] > $context['thumbnail_threshold']) { $url = Images::get_thumbnail_href($image); } else { $url = Images::get_icon_href($image); } $query[] = "thumbnail_url = '" . SQL::escape($url) . "'"; } elseif ($origin) { $query[] = "thumbnail_url = '" . SQL::escape($origin) . "'"; } // do not remember minor changes $silently = TRUE; // add a reference to a location in the article description } elseif ($action == 'location:create' && $origin) { if (!Codes::check_embedded($this->item['description'], 'location', $origin)) { $query[] = "description = '" . SQL::escape($this->item['description'] . ' [location=' . $origin . ']') . "'"; } // suppress a reference to a location that has been deleted } elseif ($action == 'location:delete' && $origin) { $query[] = "description = '" . SQL::escape(Codes::delete_embedded($this->item['description'], 'location', $origin)) . "'"; // add a reference to a new table in the article description } elseif ($action == 'table:create' && $origin) { if (!Codes::check_embedded($this->item['description'], 'table', $origin)) { $query[] = "description = '" . SQL::escape($this->item['description'] . "\n" . '[table=' . $origin . ']' . "\n") . "'"; } // suppress a reference to a table that has been deleted } elseif ($action == 'table:delete' && $origin) { $query[] = "description = '" . SQL::escape(Codes::delete_embedded($this->item['description'], 'table', $origin)) . "'"; } // stamp the update if (!$silently) { $query[] = "edit_name='" . SQL::escape(Surfer::get_name()) . "'," . "edit_id=" . SQL::escape(Surfer::get_id()) . "," . "edit_address='" . SQL::escape(Surfer::get_email_address()) . "'," . "edit_action='" . SQL::escape($action) . "'," . "edit_date='" . gmstrftime('%Y-%m-%d %H:%M:%S') . "'"; } // update the database if (count($query)) { $query = "UPDATE " . SQL::table_name('articles') . " SET " . implode(', ', $query) . " WHERE id = " . SQL::escape($this->item['id']); SQL::query($query); } // add this page to the watch list of the contributor, on any action if (Surfer::get_id()) { Members::assign('article:' . $this->item['id'], 'user:'******'article:' . $this->item['id'], $this->item['active']); // always clear the cache, even on no update Articles::clear($this->item); // get the parent if (!$this->anchor) { $this->anchor = Anchors::get($this->item['anchor']); } // propagate the touch upwards if (is_object($this->anchor)) { $this->anchor->touch('article:update', $this->item['id'], TRUE); } }
// clear assignment information if (Files::assign($item['id'], NULL)) { // inform surfer $context['text'] .= '<p>' . i18n::s('You have released this file, and other surfers can reserve it for revision.') . '</p>'; // help the surfer } else { Logger::error(i18n::s('Operation has failed.')); } // follow-up commands $context['text'] .= Skin::build_block(Skin::build_link($anchor->get_url('files'), i18n::s('Done'), 'button'), 'bottom'); // file has not been assigned, and surfer has not confirmed the detach yet } elseif ($action == 'reserve' && (!isset($item['assign_id']) || !$item['assign_id']) && Surfer::get_id()) { // change page title $context['page_title'] = sprintf(i18n::s('%s: %s'), i18n::s('Reserve'), $context['page_title']); // assign the file to this surfer $user = array('nick_name' => Surfer::get_name(), 'id' => Surfer::get_id(), 'email' => Surfer::get_email_address()); if (Files::assign($item['id'], $user)) { // inform surfer $context['text'] .= '<p>' . sprintf(i18n::s('You have reserved this file, and you are encouraged to %s as soon as possible, or to %s.'), Skin::build_link(Files::get_url($item['id'], 'edit'), i18n::s('upload an updated version'), 'basic'), Skin::build_link(Files::get_url($item['id'], 'fetch', 'release'), i18n::s('release reservation'), 'basic')) . '</p>'; // help the surfer } else { Logger::error(i18n::s('Operation has failed.')); } // follow-up commands $context['text'] .= Skin::build_block(Skin::build_link($anchor->get_url('files'), i18n::s('Done'), 'button'), 'bottom'); // file has been reserved, and surfer is not owner } elseif ($action != 'confirm' && isset($item['assign_id']) && $item['assign_id'] && !Surfer::is($item['assign_id'])) { // inform surfer $context['text'] .= Skin::build_block(sprintf(i18n::s('This file has been assigned to %s %s, and it is likely that an updated version will be made available soon.'), Users::get_link($item['assign_name'], $item['assign_address'], $item['assign_id']), Skin::build_date($item['assign_date'])), 'caution'); // commands $menu = array();
/** * remember the last action for this section * * @see articles/article.php * @see shared/anchor.php * * @param string the description of the last action * @param string the id of the item related to this update * @param boolean TRUE to not change the edit date of this anchor, default is FALSE */ function touch($action, $origin = NULL, $silently = FALSE) { global $context; // we make extensive use of comments below include_once $context['path_to_root'] . 'comments/comments.php'; // don't go further on import if (preg_match('/import$/i', $action)) { return; } // no section bound if (!isset($this->item['id'])) { return; } // delegate to overlay if (is_object($this->overlay) && $this->overlay->touch($action, $origin, $silently) === false) { return; // stop on false } // sanity check if (!$origin) { logger::remember('sections/section.php: unexpected NULL origin at touch()'); return; } // components of the query $query = array(); // a new page has been added to the section if ($action == 'article:publish' || $action == 'article:submit') { // limit the number of items attached to this section if (isset($this->item['maximum_items']) && $this->item['maximum_items'] > 10) { Articles::purge_for_anchor('section:' . $this->item['id'], $this->item['maximum_items']); } // a new comment has been posted } elseif ($action == 'comment:create') { // purge oldest comments Comments::purge_for_anchor('section:' . $this->item['id']); // file upload } elseif ($action == 'file:create' || $action == 'file:upload') { // actually, several files have been added $label = ''; if (!$origin) { $fields = array(); $fields['anchor'] = 'section:' . $this->item['id']; $fields['description'] = i18n::s('Several files have been added'); $fields['type'] = 'notification'; Comments::post($fields); // one file has been added } elseif (!Codes::check_embedded($this->item['description'], 'embed', $origin) && ($item = Files::get($origin, TRUE))) { // this file is eligible for being embedded in the page if (isset($item['file_name']) && Files::is_embeddable($item['file_name'])) { // the overlay may prevent embedding if (is_object($this->overlay) && !$this->overlay->should_embed_files()) { } else { $label = '[embed=' . $origin . ']'; } // else add a comment to take note of the upload } elseif (Comments::allow_creation($this->item, null, 'section')) { $fields = array(); $fields['anchor'] = 'section:' . $this->item['id']; if ($action == 'file:create') { $fields['description'] = '[file=' . $item['id'] . ',' . $item['file_name'] . ']'; } else { $fields['description'] = '[download=' . $item['id'] . ',' . $item['file_name'] . ']'; } Comments::post($fields); } } // include flash videos in a regular page if ($label) { $query[] = "description = '" . SQL::escape($this->item['description'] . ' ' . $label) . "'"; } // suppress references to a deleted file } elseif ($action == 'file:delete') { // suppress reference in main description field $text = Codes::delete_embedded($this->item['description'], 'download', $origin); $text = Codes::delete_embedded($text, 'embed', $origin); $text = Codes::delete_embedded($text, 'file', $origin); // save changes $query[] = "description = '" . SQL::escape($text) . "'"; // append a reference to a new image to the description } elseif ($action == 'image:create') { if (!Codes::check_embedded($this->item['description'], 'image', $origin)) { // the overlay may prevent embedding if (is_object($this->overlay) && !$this->overlay->should_embed_files()) { } else { // list has already started if (preg_match('/\\[image=[^\\]]+?\\]\\s*$/', $this->item['description'])) { $query[] = "description = '" . SQL::escape($this->item['description'] . ' [image=' . $origin . ']') . "'"; } else { $query[] = "description = '" . SQL::escape($this->item['description'] . "\n\n" . '[image=' . $origin . ']') . "'"; } } } // also use it as thumnail if none has been defined yet if (!isset($this->item['thumbnail_url']) || !trim($this->item['thumbnail_url'])) { include_once $context['path_to_root'] . 'images/images.php'; if (($image = Images::get($origin)) && ($url = Images::get_thumbnail_href($image))) { $query[] = "thumbnail_url = '" . SQL::escape($url) . "'"; } } // refresh stamp only if image update occurs within 6 hours after last edition if (SQL::strtotime($this->item['edit_date']) + 6 * 60 * 60 < time()) { $silently = TRUE; } // suppress a reference to an image that has been deleted } elseif ($action == 'image:delete') { // suppress reference in main description field $query[] = "description = '" . SQL::escape(Codes::delete_embedded($this->item['description'], 'image', $origin)) . "'"; // suppress references as icon and thumbnail as well include_once $context['path_to_root'] . 'images/images.php'; if ($image = Images::get($origin)) { if ($url = Images::get_icon_href($image)) { if ($this->item['icon_url'] == $url) { $query[] = "icon_url = ''"; } if ($this->item['thumbnail_url'] == $url) { $query[] = "thumbnail_url = ''"; } } if ($url = Images::get_thumbnail_href($image)) { if ($this->item['icon_url'] == $url) { $query[] = "icon_url = ''"; } if ($this->item['thumbnail_url'] == $url) { $query[] = "thumbnail_url = ''"; } } } // set an existing image as the section icon } elseif ($action == 'image:set_as_icon') { include_once $context['path_to_root'] . 'images/images.php'; if ($image = Images::get($origin)) { if ($url = Images::get_icon_href($image)) { $query[] = "icon_url = '" . SQL::escape($url) . "'"; } // also use it as thumnail if none has been defined yet if (!(isset($this->item['thumbnail_url']) && trim($this->item['thumbnail_url'])) && ($url = Images::get_thumbnail_href($image))) { $query[] = "thumbnail_url = '" . SQL::escape($url) . "'"; } } elseif ($origin) { $query[] = "icon_url = '" . SQL::escape($origin) . "'"; } $silently = TRUE; // set an existing image as the section thumbnail } elseif ($action == 'image:set_as_thumbnail') { include_once $context['path_to_root'] . 'images/images.php'; if ($image = Images::get($origin)) { // use the thumbnail for large files, or the image itself for smaller files if ($image['image_size'] > $context['thumbnail_threshold']) { $url = Images::get_thumbnail_href($image); } else { $url = Images::get_icon_href($image); } $query[] = "thumbnail_url = '" . SQL::escape($url) . "'"; } elseif ($origin) { $query[] = "thumbnail_url = '" . SQL::escape($origin) . "'"; } $silently = TRUE; // append a new image, and set it as the article thumbnail } elseif ($action == 'image:set_as_both') { if (!Codes::check_embedded($this->item['description'], 'image', $origin)) { $query[] = "description = '" . SQL::escape($this->item['description'] . ' [image=' . $origin . ']') . "'"; } include_once $context['path_to_root'] . 'images/images.php'; if ($image = Images::get($origin)) { // use the thumbnail for large files, or the image itself for smaller files if ($image['image_size'] > $context['thumbnail_threshold']) { $url = Images::get_thumbnail_href($image); } else { $url = Images::get_icon_href($image); } $query[] = "thumbnail_url = '" . SQL::escape($url) . "'"; } elseif ($origin) { $query[] = "thumbnail_url = '" . SQL::escape($origin) . "'"; } // do not remember minor changes $silently = TRUE; // add a reference to a new table in the section description } elseif ($action == 'table:create') { if (!Codes::check_embedded($this->item['description'], 'table', $origin)) { $query[] = "description = '" . SQL::escape($this->item['description'] . ' [table=' . $origin . ']') . "'"; } // suppress a reference to a table that has been deleted } elseif ($action == 'table:delete') { $query[] = "description = '" . SQL::escape(Codes::delete_embedded($this->item['description'], 'table', $origin)) . "'"; } // stamp the update if (!$silently) { $query[] = "edit_name='" . SQL::escape(Surfer::get_name()) . "'," . "edit_id=" . SQL::escape(Surfer::get_id()) . "," . "edit_address='" . SQL::escape(Surfer::get_email_address()) . "'," . "edit_action='{$action}'," . "edit_date='" . SQL::escape(gmstrftime('%Y-%m-%d %H:%M:%S')) . "'"; } // update the database if (@count($query)) { $query = "UPDATE " . SQL::table_name('sections') . " SET " . implode(', ', $query) . " WHERE id = " . SQL::escape($this->item['id']); SQL::query($query); } // always clear the cache, even on no update Sections::clear($this->item); // get the parent if (!$this->anchor) { $this->anchor = Anchors::get($this->item['anchor']); } // propagate the touch upwards silently -- we only want to purge the cache if (is_object($this->anchor)) { $this->anchor->touch('section:touch', $this->item['id'], TRUE); } }
/** * remember a version * * Save previous version of some object in the database. * It is recommended to call Versions::are_different() before calling Versions::save(), to * ensure that some change has taken place. * This function populates the error context, where applicable. * * @param array an array of fields * @param string the anchor attached to this version * @return the id of the new version, or FALSE on error * * @see versions/edit.php **/ public static function save($fields, $anchor) { global $context; // anchor cannot be empty if (!isset($anchor) || !$anchor) { Logger::error(i18n::s('No anchor has been found.')); return FALSE; } // pack arrays, etc. $content = serialize($fields); // save database space if (strlen($content) > 128 && is_callable('gzcompress')) { $content = base64_encode(gzcompress($content, 6)); } // versioning date $versioning_date = isset($fields['edit_date']) ? $fields['edit_date'] : gmstrftime('%Y-%m-%d %H:%M:%S'); // insert a new record $query = "INSERT INTO " . SQL::table_name('versions') . " SET " . "anchor='" . SQL::escape($anchor) . "'," . "content='" . SQL::escape($content) . "'," . "edit_name='" . SQL::escape(isset($fields['edit_name']) ? $fields['edit_name'] : Surfer::get_name()) . "', " . "edit_id=" . SQL::escape(isset($fields['edit_id']) ? $fields['edit_id'] : Surfer::get_id()) . ", " . "edit_address='" . SQL::escape(isset($fields['edit_address']) ? $fields['edit_address'] : Surfer::get_email_address()) . "', " . "edit_date='" . SQL::escape($versioning_date) . "'"; // actual insert if (SQL::query($query) === FALSE) { return FALSE; } // remember the id of the new item $id = SQL::get_last_id($context['connection']); // clear the cache for versions; update section index as well Cache::clear(array('articles', 'versions')); // return the id of the new item return $id; }
/** * stamp an article * * This function is used to change various dates for one article. * * [*] If a publication date is provided, it is saved along the article. * An optional expiry date will be saved as well. * * [*] If only an expiry date is provided, it is saved along the article. * * [*] If no date is provided, the review field is updated to the current date and time. * * Dates are supposed to be in UTC time zone. * * The name of the surfer is registered as the official publisher. * As an alternative, publisher attributes ('name', 'id' and 'address') can be provided * in parameters. * * @param int the id of the item to publish * @param string the target publication date, if any * @param string the target expiration date, if any * @param array attributes of the publisher, if any * @return string either a null string, or some text describing an error to be inserted into the html response * * @see articles/publish.php * @see sections/manage.php **/ public static function stamp($id, $publication = NULL, $expiry = NULL, $publisher = NULL) { global $context; // id cannot be empty if (!$id || !is_numeric($id)) { return i18n::s('No item has the provided id.'); } // server offset $server_offset = 0; if (isset($context['gmt_offset'])) { $server_offset = intval($context['gmt_offset']); } // surfer offset $surfer_offset = Surfer::get_gmt_offset(); // no publication time is provided if (!isset($publication) || !$publication) { $publication_stamp = 0; } elseif (preg_match('/GMT$/', $publication) && strlen($publication) == 19) { // YYMMDD-HH:MM:SS GMT -> HH, MM, SS, MM, DD, YY $publication_stamp = gmmktime(intval(substr($publication, 7, 2)), intval(substr($publication, 10, 2)), intval(substr($publication, 13, 2)), intval(substr($publication, 2, 2)), intval(substr($publication, 4, 2)), intval(substr($publication, 0, 2))); // time()-like stamp } elseif (intval($publication) > 1000000000) { // adjust to UTC time zone $publication_stamp = intval($publication) + $context['gmt_offset'] * 3600; // YYYY-MM-DD HH:MM:SS, or a string that can be readed } elseif (($publication_stamp = SQL::strtotime($publication)) != -1) { } else { return sprintf(i18n::s('"%s" is not a valid date'), $publication); } // no expiry date if (!isset($expiry) || !$expiry) { $expiry_stamp = 0; } elseif (preg_match('/GMT$/', $expiry) && strlen($expiry) == 19) { // YYMMDD-HH:MM:SS GMT -> HH, MM, SS, MM, DD, YY $expiry_stamp = gmmktime(substr($expiry, 7, 2), substr($expiry, 10, 2), substr($expiry, 13, 2), substr($expiry, 2, 2), substr($expiry, 4, 2), substr($expiry, 0, 2)); // time()-like stamp } elseif (intval($expiry) > 1000000000) { // adjust to server time zone $expiry_stamp = intval($expiry) + $context['gmt_offset'] * 3600; // YYYY-MM-DD HH:MM:SS, or a string that can be readed } elseif (($expiry_stamp = SQL::strtotime($expiry)) != -1) { } else { return sprintf(i18n::s('"%s" is not a valid date'), $expiry); } // review date $review_stamp = 0; if (!$publication_stamp && !$expiry_stamp) { $review_stamp = time(); } // shape the query $query = array(); if ($publication_stamp > 0) { $query[] = "publish_name='" . SQL::escape(isset($publisher['name']) ? $publisher['name'] : Surfer::get_name()) . "'," . "publish_id=" . SQL::escape(isset($publisher['id']) ? $publisher['id'] : Surfer::get_id()) . "," . "publish_address='" . SQL::escape(isset($publisher['address']) ? $publisher['address'] : Surfer::get_email_address()) . "'," . "publish_date='" . gmstrftime('%Y-%m-%d %H:%M:%S', $publication_stamp) . "'," . "edit_name='" . SQL::escape(isset($publisher['name']) ? $publisher['name'] : Surfer::get_name()) . "'," . "edit_id=" . SQL::escape(isset($publisher['id']) ? $publisher['id'] : Surfer::get_id()) . "," . "edit_address='" . SQL::escape(isset($publisher['address']) ? $publisher['address'] : Surfer::get_email_address()) . "'," . "edit_action='article:publish'," . "edit_date='" . gmstrftime('%Y-%m-%d %H:%M:%S') . "'"; } if ($expiry_stamp > 0) { $query[] = "expiry_date='" . gmstrftime('%Y-%m-%d %H:%M:%S', $expiry_stamp) . "'"; } if ($review_stamp > 0) { $query[] = "review_date='" . gmstrftime('%Y-%m-%d %H:%M:%S', $review_stamp) . "'"; } // update an existing record $query = "UPDATE " . SQL::table_name('articles') . " SET " . implode(',', $query) . " WHERE id = " . SQL::escape($id); if (SQL::query($query) === FALSE) { return NULL; } // remember the publication in weekly and monthly categories if ($publication_stamp > 0) { Categories::remember('article:' . $id, gmstrftime('%Y-%m-%d %H:%M:%S', $publication_stamp)); } // end of job return NULL; }
/** * build a pretty link to the profile page of this surfer * * This function is a proxy for Users::get_link(), limited to current surfer. * * @return string some text describing this surfer, with a link to get more information * * @see users/users.php */ public static function get_link() { global $context; return Users::get_link(Surfer::get_name(), Surfer::get_email_address(), Surfer::get_id()); }
/** * notify an event * * This script calls [code]Logger::remember()[/code] to save the event locally, then attempts to send an e-mail * message if possible. * * @param string a one-line label that can be used as a mail title (e.g. 'creation of a new article') * @param string a more comprehensive description, if any * @return void */ public static function notify($label, $description = '') { global $context; // local storage Logger::remember($label, $description); // send also a message if (isset($context['mail_logger_recipient']) && $context['mail_logger_recipient']) { // except to current surfer if ($self_address = Surfer::get_email_address()) { $context['mail_logger_recipient'] = preg_replace('/' . preg_quote($self_address, '/') . '[ \\s,]*/i', '', $context['mail_logger_recipient']); } // do we have a recipient after all? if (!trim($context['mail_logger_recipient'])) { return; } // message footer $description .= '<div>' . sprintf(i18n::c('This message has been generated automatically by %s. If you wish to stop these automatic alerts please visit the following link and remove your address from recipients of system events.'), $context['site_name']) . '</div>' . '<p><a href="' . $context['url_to_home'] . $context['url_to_root'] . 'control/configure.php' . '">' . i18n::s('System parameters') . '</a></p>'; // actual mail message Mailer::notify(NULL, $context['mail_logger_recipient'], $label, $description); } }
/** * remember the last action for this user * * @param string the description of the last action * @param string the id of the item related to this update * @param boolean TRUE to not change the edit date of this anchor, default is FALSE * * @see shared/anchor.php */ function touch($action, $origin = NULL, $silently = FALSE) { global $context; // don't go further on import if (preg_match('/import$/i', $action)) { return; } // no item bound if (!isset($this->item['id'])) { return; } // sanity check if (!$origin) { logger::remember('users/user.php: unexpected NULL origin at touch()'); return; } // components of the query $query = array(); // append a reference to a new image to the description if ($action == 'image:create') { if (!Codes::check_embedded($this->item['description'], 'image', $origin)) { // the overlay may prevent embedding if (is_object($this->overlay) && !$this->overlay->should_embed_files()) { } else { // list has already started if (preg_match('/\\[image=[^\\]]+?\\]\\s*$/', $this->item['description'])) { $query[] = "description = '" . SQL::escape($this->item['description'] . ' [image=' . $origin . ']') . "'"; } else { $query[] = "description = '" . SQL::escape($this->item['description'] . "\n\n" . '[image=' . $origin . ']') . "'"; } } } // refresh stamp only if image update occurs within 6 hours after last edition if (SQL::strtotime($this->item['edit_date']) + 6 * 60 * 60 < time()) { $silently = TRUE; } // suppress a reference to an image that has been deleted } elseif ($action == 'image:delete') { // suppress reference in main description field $query[] = "description = '" . SQL::escape(Codes::delete_embedded($this->item['description'], 'image', $origin)) . "'"; // suppress references as icon and thumbnail as well include_once $context['path_to_root'] . 'images/images.php'; if ($image = Images::get($origin)) { if ($url = Images::get_icon_href($image)) { if ($this->item['avatar_url'] == $url) { $query[] = "avatar_url = ''"; } } if ($url = Images::get_thumbnail_href($image)) { if ($this->item['avatar_url'] == $url) { $query[] = "avatar_url = ''"; } } } // set an existing image as the user avatar } elseif ($action == 'image:set_as_avatar') { include_once $context['path_to_root'] . 'images/images.php'; if ($image = Images::get($origin)) { if ($url = Images::get_icon_href($image)) { $query[] = "avatar_url = '" . SQL::escape($url) . "'"; } } $silently = TRUE; // set an existing image as the user thumbnail } elseif ($action == 'image:set_as_thumbnail') { include_once $context['path_to_root'] . 'images/images.php'; if ($image = Images::get($origin)) { if ($url = Images::get_thumbnail_href($image)) { $query[] = "avatar_url = '" . SQL::escape($url) . "'"; } } $silently = TRUE; // append a new image } elseif ($action == 'image:set_as_both') { if (!Codes::check_embedded($this->item['description'], 'image', $origin)) { $query[] = "description = '" . SQL::escape($this->item['description'] . ' [image=' . $origin . ']') . "'"; } // do not remember minor changes $silently = TRUE; // add a reference to a location in the article description } elseif ($action == 'location:create') { if (!Codes::check_embedded($this->item['description'], 'location', $origin)) { $query[] = "description = '" . SQL::escape($this->item['description'] . ' [location=' . $origin . ']') . "'"; } // suppress a reference to a location that has been deleted } elseif ($action == 'location:delete') { $query[] = "description = '" . SQL::escape(Codes::delete_embedded($this->item['description'], 'location', $origin)) . "'"; // add a reference to a new table in the user description } elseif ($action == 'table:create') { if (!Codes::check_embedded($this->item['description'], 'table', $origin)) { $query[] = "description = '" . SQL::escape($this->item['description'] . ' [table=' . $origin . ']') . "'"; } // suppress a reference to a table that has been deleted } elseif ($action == 'table:delete') { $query[] = "description = '" . SQL::escape(Codes::delete_embedded($this->item['description'], 'table', $origin)) . "'"; } // stamp the update if (!$silently) { $query[] = "edit_name='" . SQL::escape(Surfer::get_name()) . "'," . "edit_id=" . SQL::escape(Surfer::get_id()) . "," . "edit_address='" . SQL::escape(Surfer::get_email_address()) . "'," . "edit_action='{$action}'," . "edit_date='" . SQL::escape(gmstrftime('%Y-%m-%d %H:%M:%S')) . "'"; } // clear the cache for users, even for minor updates (e.g., image deletion) Users::clear($this->item); // ensure we have a valid update query if (!@count($query)) { return; } // update the anchor user $query = "UPDATE " . SQL::table_name('users') . " SET " . implode(', ', $query) . " WHERE id = " . SQL::escape($this->item['id']); SQL::query($query, FALSE, $context['users_connection']); }
// // assistant-like bottom of the page $context['text'] .= $context['page_bottom']; // transmit the id as a hidden field if (isset($item['id']) && $item['id']) { $context['text'] .= '<input type="hidden" name="id" value="' . $item['id'] . '" />'; } // end of the form $context['text'] .= '</div></form>'; // clear session data now that we have populated the form unset($_SESSION['anchor_reference']); unset($_SESSION['pasted_blogid']); unset($_SESSION['pasted_introduction']); unset($_SESSION['pasted_name']); unset($_SESSION['pasted_section']); unset($_SESSION['pasted_source']); unset($_SESSION['pasted_text']); unset($_SESSION['pasted_title']); // assign the page to the surfer if (isset($item['id']) && Surfer::get_id()) { $query = "UPDATE " . SQL::table_name('articles') . " SET " . " assign_name = '" . SQL::escape(Surfer::get_name()) . "'," . " assign_id = " . SQL::escape(Surfer::get_id()) . "," . " assign_address = '" . SQL::escape(Surfer::get_email_address()) . "'," . " assign_date = '" . SQL::escape(gmstrftime('%Y-%m-%d %H:%M:%S')) . "'" . " WHERE (id = " . SQL::escape($item['id']) . ")"; // do not stop on error SQL::query($query); // for subsequent heartbits $_SESSION['assigned'] = $item['id']; // current item $context['current_action'] = 'edit'; } } // render the skin render_skin();
// surfer address is in $_REQUEST['surfer_address'] $context['text'] .= '<p>' . sprintf(i18n::s('%s: %s'), i18n::s('Your e-mail address'), $_REQUEST['surfer_address']) . '</p>'; // description is in $_REQUEST['description'] $context['text'] .= '<p>' . sprintf(i18n::s('%s: %s'), i18n::s('Your contribution'), BR . $_REQUEST['description']) . '</p>'; // display the form } else { // where to upload data $context['text'] .= '<form method="post" action="' . $context['script_url'] . '" id="main_form"><div>'; // surfer name $label = i18n::s('Your name'); $input = '<input type="text" name="surfer_name" id="edit_name" size="45" value="' . encode_field(Surfer::get_name()) . '" maxlength="255" />'; $hint = i18n::s('Give us a chance to know who you are'); $fields[] = array($label, $input, $hint); // surfer address $label = i18n::s('Your e-mail address'); $input = '<input type="text" name="surfer_address" size="45" value="' . encode_field(Surfer::get_email_address()) . '" maxlength="255" />'; $hint = i18n::s('We will use this to contact you back'); $fields[] = array($label, $input, $hint); // some text $label = i18n::s('Your message'); $input = '<textarea name="description" rows="20" cols="50"></textarea>'; $hint = i18n::s('Please include all elements we could need'); $fields[] = array($label, $input, $hint); // build the form $context['text'] .= Skin::build_form($fields); // the submit button $context['text'] .= '<p>' . Skin::build_submit_button(i18n::s('Submit')) . '</p>' . "\n"; // end of the form $context['text'] .= '</div></form>'; } // render the page
// main panel // $information = ''; // lay fields in a table $information .= Skin::table_prefix('form'); $lines = 1; // a link to the user profile $cells = array(); $cells[] = i18n::s('Your profile'); $cells[] = 'left=' . Surfer::get_link(); $information .= Skin::table_row($cells, $lines++); // the email field if (Surfer::get_email_address()) { $cells = array(); $cells[] = i18n::s('Your address'); $cells[] = 'left=' . Surfer::get_email_address(); $information .= Skin::table_row($cells, $lines++); } // the capability field - associate, member, or subscriber $cells = array(); $cells[] = i18n::s('Your status'); if (Surfer::is_associate()) { $cells[] = 'left=' . i18n::s('As an associate of this community, you may contribute freely to any part of this server.'); } elseif (Surfer::is_member()) { $cells[] = 'left=' . i18n::s('As a member of this community, you may access freely most pages of this server.'); } else { $cells[] = 'left=' . i18n::s('As a subscriber of this community, you may freely access most pages of this server.'); } if (isset($cells[1])) { $information .= Skin::table_row($cells, $lines++); }