function filerm_content(&$a) { if (!local_user()) { killme(); } $term = unxmlify(trim($_GET['term'])); $cat = unxmlify(trim($_GET['cat'])); $category = $cat ? true : false; if ($category) { $term = $cat; } $item_id = $a->argc > 1 ? intval($a->argv[1]) : 0; logger('filerm: tag ' . $term . ' item ' . $item_id); if ($item_id && strlen($term)) { file_tag_unsave_file(local_user(), $item_id, $term, $category); } if (x($_SESSION, 'return_url')) { goaway($a->get_baseurl() . '/' . $_SESSION['return_url']); } killme(); }
function drop_item($id, $interactive = true) { $a = get_app(); // locate item to be deleted $r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1", intval($id)); if (!count($r)) { if (!$interactive) { return 0; } notice(t('Item not found.') . EOL); goaway($a->get_baseurl() . '/' . $_SESSION['return_url']); } $item = $r[0]; $owner = $item['uid']; $cid = 0; // check if logged in user is either the author or owner of this item if (is_array($_SESSION['remote'])) { foreach ($_SESSION['remote'] as $visitor) { if ($visitor['uid'] == $item['uid'] && $visitor['cid'] == $item['contact-id']) { $cid = $visitor['cid']; break; } } } if (local_user() == $item['uid'] || $cid || !$interactive) { // Check if we should do HTML-based delete confirmation if ($_REQUEST['confirm']) { // <form> can't take arguments in its "action" parameter // so add any arguments as hidden inputs $query = explode_querystring($a->query_string); $inputs = array(); foreach ($query['args'] as $arg) { if (strpos($arg, 'confirm=') === false) { $arg_parts = explode('=', $arg); $inputs[] = array('name' => $arg_parts[0], 'value' => $arg_parts[1]); } } return replace_macros(get_markup_template('confirm.tpl'), array('$method' => 'get', '$message' => t('Do you really want to delete this item?'), '$extra_inputs' => $inputs, '$confirm' => t('Yes'), '$confirm_url' => $query['base'], '$confirm_name' => 'confirmed', '$cancel' => t('Cancel'))); } // Now check how the user responded to the confirmation query if ($_REQUEST['canceled']) { goaway($a->get_baseurl() . '/' . $_SESSION['return_url']); } logger('delete item: ' . $item['id'], LOGGER_DEBUG); // delete the item $r = q("UPDATE `item` SET `deleted` = 1, `title` = '', `body` = '', `edited` = '%s', `changed` = '%s' WHERE `id` = %d", dbesc(datetime_convert()), dbesc(datetime_convert()), intval($item['id'])); create_tags_from_item($item['id']); create_files_from_item($item['id']); delete_thread($item['id'], $item['parent-uri']); // clean up categories and tags so they don't end up as orphans $matches = false; $cnt = preg_match_all('/<(.*?)>/', $item['file'], $matches, PREG_SET_ORDER); if ($cnt) { foreach ($matches as $mtch) { file_tag_unsave_file($item['uid'], $item['id'], $mtch[1], true); } } $matches = false; $cnt = preg_match_all('/\\[(.*?)\\]/', $item['file'], $matches, PREG_SET_ORDER); if ($cnt) { foreach ($matches as $mtch) { file_tag_unsave_file($item['uid'], $item['id'], $mtch[1], false); } } // If item is a link to a photo resource, nuke all the associated photos // (visitors will not have photo resources) // This only applies to photos uploaded from the photos page. Photos inserted into a post do not // generate a resource-id and therefore aren't intimately linked to the item. if (strlen($item['resource-id'])) { q("DELETE FROM `photo` WHERE `resource-id` = '%s' AND `uid` = %d ", dbesc($item['resource-id']), intval($item['uid'])); // ignore the result } // If item is a link to an event, nuke the event record. if (intval($item['event-id'])) { q("DELETE FROM `event` WHERE `id` = %d AND `uid` = %d", intval($item['event-id']), intval($item['uid'])); // ignore the result } // If item has attachments, drop them foreach (explode(",", $item['attach']) as $attach) { preg_match("|attach/(\\d+)|", $attach, $matches); q("DELETE FROM `attach` WHERE `id` = %d AND `uid` = %d", intval($matches[1]), local_user()); // ignore the result } // clean up item_id and sign meta-data tables /* // Old code - caused very long queries and warning entries in the mysql logfiles: $r = q("DELETE FROM item_id where iid in (select id from item where parent = %d and uid = %d)", intval($item['id']), intval($item['uid']) ); $r = q("DELETE FROM sign where iid in (select id from item where parent = %d and uid = %d)", intval($item['id']), intval($item['uid']) ); */ // The new code splits the queries since the mysql optimizer really has bad problems with subqueries // Creating list of parents $r = q("select id from item where parent = %d and uid = %d", intval($item['id']), intval($item['uid'])); $parentid = ""; foreach ($r as $row) { if ($parentid != "") { $parentid .= ", "; } $parentid .= $row["id"]; } // Now delete them if ($parentid != "") { $r = q("DELETE FROM item_id where iid in (%s)", dbesc($parentid)); $r = q("DELETE FROM sign where iid in (%s)", dbesc($parentid)); } // If it's the parent of a comment thread, kill all the kids if ($item['uri'] == $item['parent-uri']) { $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s', `body` = '' , `title` = ''\n\t\t\t\tWHERE `parent-uri` = '%s' AND `uid` = %d ", dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc($item['parent-uri']), intval($item['uid'])); create_tags_from_itemuri($item['parent-uri'], $item['uid']); create_files_from_itemuri($item['parent-uri'], $item['uid']); delete_thread_uri($item['parent-uri'], $item['uid']); // ignore the result } else { // ensure that last-child is set in case the comment that had it just got wiped. q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d ", dbesc(datetime_convert()), dbesc($item['parent-uri']), intval($item['uid'])); // who is the last child now? $r = q("SELECT `id` FROM `item` WHERE `parent-uri` = '%s' AND `type` != 'activity' AND `deleted` = 0 AND `uid` = %d ORDER BY `edited` DESC LIMIT 1", dbesc($item['parent-uri']), intval($item['uid'])); if (count($r)) { q("UPDATE `item` SET `last-child` = 1 WHERE `id` = %d", intval($r[0]['id'])); } // Add a relayable_retraction signature for Diaspora. store_diaspora_retract_sig($item, $a->user, $a->get_baseurl()); } $drop_id = intval($item['id']); // send the notification upstream/downstream as the case may be proc_run('php', "include/notifier.php", "drop", "{$drop_id}"); if (!$interactive) { return $owner; } goaway($a->get_baseurl() . '/' . $_SESSION['return_url']); //NOTREACHED } else { if (!$interactive) { return 0; } notice(t('Permission denied.') . EOL); goaway($a->get_baseurl() . '/' . $_SESSION['return_url']); //NOTREACHED } }
function drop_item($id, $interactive = true) { $a = get_app(); // locate item to be deleted $r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1", intval($id)); if (!count($r)) { if (!$interactive) { return 0; } notice(t('Item not found.') . EOL); goaway($a->get_baseurl() . '/' . $_SESSION['return_url']); } $item = $r[0]; $owner = $item['uid']; // check if logged in user is either the author or owner of this item if (local_user() == $item['uid'] || remote_user() == $item['contact-id']) { // delete the item $r = q("UPDATE `item` SET `deleted` = 1, `title` = '', `body` = '', `edited` = '%s', `changed` = '%s' WHERE `id` = %d LIMIT 1", dbesc(datetime_convert()), dbesc(datetime_convert()), intval($item['id'])); // clean up categories and tags so they don't end up as orphans $matches = false; $cnt = preg_match_all('/<(.*?)>/', $item['file'], $matches, PREG_SET_ORDER); if ($cnt) { foreach ($matches as $mtch) { file_tag_unsave_file($item['uid'], $item['id'], $mtch[1], true); } } $matches = false; $cnt = preg_match_all('/\\[(.*?)\\]/', $item['file'], $matches, PREG_SET_ORDER); if ($cnt) { foreach ($matches as $mtch) { file_tag_unsave_file($item['uid'], $item['id'], $mtch[1], false); } } // If item is a link to a photo resource, nuke all the associated photos // (visitors will not have photo resources) // This only applies to photos uploaded from the photos page. Photos inserted into a post do not // generate a resource-id and therefore aren't intimately linked to the item. if (strlen($item['resource-id'])) { q("DELETE FROM `photo` WHERE `resource-id` = '%s' AND `uid` = %d ", dbesc($item['resource-id']), intval($item['uid'])); // ignore the result } // If item is a link to an event, nuke the event record. if (intval($item['event-id'])) { q("DELETE FROM `event` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($item['event-id']), intval($item['uid'])); // ignore the result } // clean up item_id and sign meta-data tables $r = q("DELETE FROM item_id where iid in (select id from item where parent = %d and uid = %d)", intval($item['id']), intval($item['uid'])); $r = q("DELETE FROM sign where iid in (select id from item where parent = %d and uid = %d)", intval($item['id']), intval($item['uid'])); // If it's the parent of a comment thread, kill all the kids if ($item['uri'] == $item['parent-uri']) { $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s', `body` = '' , `title` = ''\n\t\t\t\tWHERE `parent-uri` = '%s' AND `uid` = %d ", dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc($item['parent-uri']), intval($item['uid'])); // ignore the result } else { // ensure that last-child is set in case the comment that had it just got wiped. q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d ", dbesc(datetime_convert()), dbesc($item['parent-uri']), intval($item['uid'])); // who is the last child now? $r = q("SELECT `id` FROM `item` WHERE `parent-uri` = '%s' AND `type` != 'activity' AND `deleted` = 0 AND `uid` = %d ORDER BY `edited` DESC LIMIT 1", dbesc($item['parent-uri']), intval($item['uid'])); if (count($r)) { q("UPDATE `item` SET `last-child` = 1 WHERE `id` = %d LIMIT 1", intval($r[0]['id'])); } // Add a relayable_retraction signature for Diaspora. Note that we can't add a target_author_signature // if the comment was deleted by a remote user. That should be ok, because if a remote user is deleting // the comment, that means we're the home of the post, and Diaspora will only // check the parent_author_signature of retractions that it doesn't have to relay further // // I don't think this function gets called for an "unlike," but I'll check anyway $signed_text = $item['guid'] . ';' . ($item['verb'] === ACTIVITY_LIKE ? 'Like' : 'Comment'); if (local_user() == $item['uid']) { $handle = $a->user['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(), '://') + 3); $authorsig = base64_encode(rsa_sign($signed_text, $a->user['prvkey'], 'sha256')); } else { $r = q("SELECT `nick`, `url` FROM `contact` WHERE `id` = '%d' LIMIT 1", $item['contact-id']); if (count($r)) { // The below handle only works for NETWORK_DFRN. I think that's ok, because this function // only handles DFRN deletes $handle_baseurl_start = strpos($r['url'], '://') + 3; $handle_baseurl_length = strpos($r['url'], '/profile') - $handle_baseurl_start; $handle = $r['nick'] . '@' . substr($r['url'], $handle_baseurl_start, $handle_baseurl_length); $authorsig = ''; } } if (isset($handle)) { q("insert into sign (`retract_iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ", intval($item['id']), dbesc($signed_text), dbesc($authorsig), dbesc($handle)); } } $drop_id = intval($item['id']); // send the notification upstream/downstream as the case may be if (!$interactive) { return $owner; } proc_run('php', "include/notifier.php", "drop", "{$drop_id}"); goaway($a->get_baseurl() . '/' . $_SESSION['return_url']); //NOTREACHED } else { if (!$interactive) { return 0; } notice(t('Permission denied.') . EOL); goaway($a->get_baseurl() . '/' . $_SESSION['return_url']); //NOTREACHED } }