+/**
+ * @brief Subpage to modify the server wide block list via the admin panel.
+ *
+ * This function generates the subpage of the admin panel to allow the
+ * modification of the node wide block/black list to block entire
+ * remote servers from communication with this node. The page allows
+ * adding, removing and editing of entries from the blocklist.
+ *
+ * @param App $a
+ * @return string
+ */
+function admin_page_blocklist(App $a) {
+ $blocklist = Config::get('system', 'blocklist');
+ $blocklistform = array();
+ if (is_array($blocklist)) {
+ foreach($blocklist as $id => $b) {
+ $blocklistform[] = array(
+ 'domain' => array("domain[$id]", t('Blocked domain'), $b['domain'], '', t('The blocked domain'), 'required', '', ''),
+ 'reason' => array("reason[$id]", t("Reason for the block"), $b['reason'], t('The reason why you blocked this domain.').'('.$b['domain'].')', 'required', '', ''),
+ 'delete' => array("delete[$id]", t("Delete domain").' ('.$b['domain'].')', False , t("Check to delete this entry from the blocklist"))
+ );
+ }
+ }
+ $t = get_markup_template("admin_blocklist.tpl");
+ return replace_macros($t, array(
+ '$title' => t('Administration'),
+ '$page' => t('Server Blocklist'),
+ '$intro' => t('This page can be used to define a black list of servers from the federated network that are not allowed to interact with your node. For all entered domains you should also give a reason why you have blocked the remote server.'),
+ '$public' => t('The list of blocked servers will be made publically available on the /friendica page so that your users and people investigating communication problems can find the reason easily.'),
+ '$addtitle' => t('Add new entry to block list'),
+ '$newdomain' => array('newentry_domain', t('Server Domain'), '', t('The domain of the new server to add to the block list. Do not include the protocol.'), 'required', '', ''),
+ '$newreason' => array('newentry_reason', t('Block reason'), '', t('The reason why you blocked this domain.'), 'required', '', ''),
+ '$submit' => t('Add Entry'),
+ '$savechanges' => t('Save changes to the blocklist'),
+ '$currenttitle' => t('Current Entries in the Blocklist'),
+ '$thurl' => t('Blocked domain'),
+ '$threason' => t('Reason for the block'),
+ '$delentry' => t('Delete entry from blocklist'),
+ '$entries' => $blocklistform,
+ '$baseurl' => System::baseUrl(true),
+ '$confirm_delete' => t('Delete entry from blocklist?'),
+ '$form_security_token' => get_form_security_token("admin_blocklist")
+ ));
+}
+
+/**
+ * @brief Process send data from Admin Blocklist Page
+ *
+ * @param App $a
+ */
+function admin_page_blocklist_post(App $a) {
+ if (!x($_POST,"page_blocklist_save") && (!x($_POST['page_blocklist_edit']))) {
+ return;
+ }
+
+ check_form_security_token_redirectOnErr('/admin/blocklist', 'admin_blocklist');
+
+ if (x($_POST['page_blocklist_save'])) {
+ // Add new item to blocklist
+ $blocklist = Config::get('system', 'blocklist');
+ $blocklist[] = array(
+ 'domain' => notags(trim($_POST['newentry_domain'])),
+ 'reason' => notags(trim($_POST['newentry_reason']))
+ );
+ Config::set('system', 'blocklist', $blocklist);
+ info(t('Server added to blocklist.').EOL);
+ } else {
+ // Edit the entries from blocklist
+ $blocklist = array();
+ foreach ($_POST['domain'] as $id => $domain) {
+ // Trimming whitespaces as well as any lingering slashes
+ $domain = notags(trim($domain, "\x00..\x1F/"));
+ $reason = notags(trim($_POST['reason'][$id]));
+ if (!x($_POST['delete'][$id])) {
+ $blocklist[] = array(
+ 'domain' => $domain,
+ 'reason' => $reason
+ );
+ }
+ }
+ Config::set('system', 'blocklist', $blocklist);
+ info(t('Site blocklist updated.').EOL);
+ }
+ goaway('admin/blocklist');
+
+ return; // NOTREACHED
+}
+
+/**
+ * @brief Subpage where the admin can delete an item from their node given the GUID
+ *
+ * This subpage of the admin panel offers the nodes admin to delete an item from
+ * the node, given the GUID or the display URL such as http://example.com/display/123456.
+ * The item will then be marked as deleted in the database and processed accordingly.
+ *
+ * @param App $a
+ * @return string
+ */
+function admin_page_deleteitem(App $a) {
+ $t = get_markup_template("admin_deleteitem.tpl");
+
+ return replace_macros($t, array(
+ '$title' => t('Administration'),
+ '$page' => t('Delete Item'),
+ '$submit' => t('Delete this Item'),
+ '$intro1' => t('On this page you can delete an item from your node. If the item is a top level posting, the entire thread will be deleted.'),
+ '$intro2' => t('You need to know the GUID of the item. You can find it e.g. by looking at the display URL. The last part of http://example.com/display/123456 is the GUID, here 123456.'),
+ '$deleteitemguid' => array('deleteitemguid', t("GUID"), '', t("The GUID of the item you want to delete."), 'required', 'autofocus'),
+ '$baseurl' => System::baseUrl(),
+ '$form_security_token' => get_form_security_token("admin_deleteitem")
+ ));
+}
+/**
+ * @brief Process send data from Admin Delete Item Page
+ *
+ * The GUID passed through the form should be only the GUID. But we also parse
+ * URLs like the full /display URL to make the process more easy for the admin.
+ *
+ * @param App $a
+ */
+function admin_page_deleteitem_post(App $a) {
+ if (!x($_POST['page_deleteitem_submit'])) {
+ return;
+ }
+
+ check_form_security_token_redirectOnErr('/admin/deleteitem/', 'admin_deleteitem');
+
+ if (x($_POST['page_deleteitem_submit'])) {
+ $guid = trim(notags($_POST['deleteitemguid']));
+ // The GUID should not include a "/", so if there is one, we got an URL
+ // and the last part of it is most likely the GUID.
+ if (strpos($guid, '/')) {
+ $guid = substr($guid, strrpos($guid, '/')+1);
+ }
+ // Now that we have the GUID get all IDs of the associated entries in the
+ // item table of the DB and drop those items, which will also delete the
+ // associated threads.
+ $r = dba::select('item', array('id'), array('guid'=>$guid));
+ while ($row = dba::fetch($r)) {
+ drop_item($row['id'], false);
+ }
+ dba::close($r);
+ }
+
+ info(t('Item marked for deletion.').EOL);
+ goaway('admin/deleteitem');
+ return; // NOTREACHED
+}
+