diff options
Diffstat (limited to 'mod/item.php')
-rw-r--r-- | mod/item.php | 266 |
1 files changed, 159 insertions, 107 deletions
diff --git a/mod/item.php b/mod/item.php index 6ea434542..164b345f0 100644 --- a/mod/item.php +++ b/mod/item.php @@ -33,6 +33,8 @@ function item_post(&$a) { $uid = local_user(); + $channel = null; + if(x($_REQUEST,'dropitems')) { require_once('include/items.php'); $arr_drop = explode(',',$_REQUEST['dropitems']); @@ -150,26 +152,21 @@ function item_post(&$a) { // can_comment_on_post() needs info from the following xchan_query xchan_query($r); + $parent_item = $r[0]; $parent = $r[0]['id']; // multi-level threading - preserve the info but re-parent to our single level threading - //if(($parid) && ($parid != $parent)) - $thr_parent = $parent_mid; - -// if($parent_item['contact-id'] && $uid) { -// $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", -// intval($parent_item['contact-id']), -// intval($uid) -// ); -// if(count($r)) -// $parent_contact = $r[0]; -// } + + $thr_parent = $parent_mid; + } + $observer = $a->get_observer(); + if($parent) { logger('mod_item: item_post parent=' . $parent); $can_comment = false; @@ -219,20 +216,22 @@ function item_post(&$a) { $orig_post = $i[0]; } - $channel = null; - if(local_user() && local_user() == $profile_uid) { - $channel = $a->get_channel(); - } - else { - $r = q("SELECT channel.*, account.* FROM channel left join account on channel.channel_account_id = account.account_id - where channel.channel_id = %d LIMIT 1", - intval($profile_uid) - ); - if(count($r)) - $channel = $r[0]; + if(! $channel) { + if(local_user() && local_user() == $profile_uid) { + $channel = $a->get_channel(); + } + else { + // posting as yourself but not necessarily to a channel you control + $r = q("select * from channel left join account on channel_account_id = account_id where channel_id = %d LIMIT 1", + intval($profile_uid) + ); + if($r) + $channel = $r[0]; + } } + if(! $channel) { logger("mod_item: no channel."); if(x($_REQUEST,'return')) @@ -260,11 +259,17 @@ function item_post(&$a) { } + + if($orig_post) { - $str_group_allow = $orig_post['allow_gid']; - $str_contact_allow = $orig_post['allow_cid']; - $str_group_deny = $orig_post['deny_gid']; - $str_contact_deny = $orig_post['deny_cid']; + $str_group_allow = ((array_key_exists('group_allow',$_REQUEST)) + ? perms2str($_REQUEST['group_allow']) : $orig_post['allow_gid']); + $str_contact_allow = ((array_key_exists('contact_allow',$_REQUEST)) + ? perms2str($_REQUEST['contact_allow']) : $orig_post['allow_cid']); + $str_group_deny = ((array_key_exists('group_deny',$_REQUEST)) + ? perms2str($_REQUEST['group_deny']) : $orig_post['deny_gid']); + $str_contact_deny = ((array_key_exists('contact_deny',$_REQUEST)) + ? perms2str($_REQUEST['contact_deny']) : $orig_post['deny_cid']); $location = $orig_post['location']; $coord = $orig_post['coord']; $verb = $orig_post['verb']; @@ -306,6 +311,7 @@ function item_post(&$a) { $str_contact_deny = perms2str($_REQUEST['contact_deny']); } + $location = notags(trim($_REQUEST['location'])); $coord = notags(trim($_REQUEST['coord'])); $verb = notags(trim($_REQUEST['verb'])); @@ -360,20 +366,18 @@ function item_post(&$a) { } } - - $post_type = notags(trim($_REQUEST['type'])); $mimetype = notags(trim($_REQUEST['mimetype'])); if(! $mimetype) $mimetype = 'text/bbcode'; - // Verify ability to use html or php!!! - if($preview) { $body = z_input_filter($profile_uid,$body,$mimetype); } + // Verify ability to use html or php!!! + $execflag = false; if($mimetype === 'application/x-php') { @@ -496,8 +500,6 @@ function item_post(&$a) { $tagged = array(); - $private_forum = false; - if(count($tags)) { $first_access_tag = true; foreach($tags as $tag) { @@ -516,9 +518,9 @@ function item_post(&$a) { continue; $success = handle_tag($a, $body, $access_tag, $str_tags, (local_user()) ? local_user() : $profile_uid , $tag); - logger('handle_tag: ' . print_r($success,tue), LOGGER_DEBUG); + logger('handle_tag: ' . print_r($success,tue), LOGGER_DATA); if(($access_tag) && (! $parent_item)) { - logger('access_tag: ' . $tag . ' ' . print_r($access_tag,true), LOGGER_DEBUG); + logger('access_tag: ' . $tag . ' ' . print_r($access_tag,true), LOGGER_DATA); if ($first_access_tag) { $str_contact_allow = ''; $str_group_allow = ''; @@ -544,22 +546,12 @@ function item_post(&$a) { 'url' => $success['url'] ); } -// if(is_array($success['contact']) && intval($success['contact']['prv'])) { -// $private_forum = true; -// $private_id = $success['contact']['id']; -// } } } // logger('post_tags: ' . print_r($post_tags,true)); - if(($private_forum) && (! $parent) && (! $private)) { - // we tagged a private forum in a top level post and the message was public. - // Restrict it. - $private = 1; - $str_contact_allow = '<' . $private_id . '>'; - } $attachments = ''; $match = false; @@ -573,7 +565,7 @@ function item_post(&$a) { if($r['success']) { $attachments[] = array( 'href' => $a->get_baseurl() . '/attach/' . $r['data']['hash'], - 'length' => $r['data']['filesize'], + 'length' => $r['data']['filesize'], 'type' => $r['data']['filetype'], 'title' => urlencode($r['data']['filename']), 'revision' => $r['data']['revision'] @@ -601,7 +593,6 @@ function item_post(&$a) { } $item_flags |= ITEM_UNSEEN; -// $item_restrict |= ITEM_VISIBLE; if($post_type === 'wall' || $post_type === 'wall-comment') $item_flags = $item_flags | ITEM_WALL; @@ -652,11 +643,11 @@ function item_post(&$a) { $datarray['owner_xchan'] = (($owner_hash) ? $owner_hash : $owner_xchan['xchan_hash']); $datarray['author_xchan'] = $observer['xchan_hash']; $datarray['created'] = $created; - $datarray['edited'] = datetime_convert(); + $datarray['edited'] = (($orig_post) ? datetime_convert() : $created); $datarray['expires'] = $expires; - $datarray['commented'] = datetime_convert(); - $datarray['received'] = datetime_convert(); - $datarray['changed'] = datetime_convert(); + $datarray['commented'] = (($orig_post) ? datetime_convert() : $created); + $datarray['received'] = (($orig_post) ? datetime_convert() : $created); + $datarray['changed'] = (($orig_post) ? datetime_convert() : $created); $datarray['mid'] = $mid; $datarray['parent_mid'] = $parent_mid; $datarray['mimetype'] = $mimetype; @@ -757,31 +748,12 @@ function item_post(&$a) { $post = item_store($datarray,$execflag); - $post_id = $post['item_id']; if($post_id) { logger('mod_item: saved item ' . $post_id); if($parent) { - - $r = q("UPDATE `item` SET `changed` = '%s' WHERE `parent` = %d ", - dbesc(datetime_convert()), - intval($parent) - ); - - // Inherit ACL's from the parent item. - - $r = q("UPDATE `item` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s', `item_private` = %d - WHERE `id` = %d LIMIT 1", - dbesc($parent_item['allow_cid']), - dbesc($parent_item['allow_gid']), - dbesc($parent_item['deny_cid']), - dbesc($parent_item['deny_gid']), - intval($parent_item['item_private']), - intval($post_id) - ); - if($datarray['owner_xchan'] != $datarray['author_xchan']) { notification(array( 'type' => NOTIFY_COMMENT, @@ -796,7 +768,6 @@ function item_post(&$a) { )); } - } else { $parent = $post_id; @@ -814,25 +785,10 @@ function item_post(&$a) { } } - // fallback so that parent always gets set to non-zero. - - if(! $parent) - $parent = $post_id; - - $r = q("UPDATE `item` SET `parent` = %d, `parent_mid` = '%s', `changed` = '%s' - WHERE `id` = %d LIMIT 1", - intval($parent), - dbesc(($parent == $post_id) ? $mid : $parent_item['mid']), - dbesc(datetime_convert()), - intval($post_id) - ); - // photo comments turn the corresponding item visible to the profile wall // This way we don't see every picture in your new photo album posted to your wall at once. // They will show up as people comment on them. -// fixme set item visible as well - if($parent_item['item_restrict'] & ITEM_HIDDEN) { $r = q("UPDATE `item` SET `item_restrict` = %d WHERE `id` = %d LIMIT 1", intval($parent_item['item_restrict'] - ITEM_HIDDEN), @@ -890,9 +846,40 @@ function item_content(&$a) { require_once('include/security.php'); - if(($a->argc == 3) && ($a->argv[1] === 'drop') && intval($a->argv[2])) { + if((argc() == 3) && (argv(1) === 'drop') && intval(argv(2))) { require_once('include/items.php'); - drop_item($a->argv[2]); + $i = q("select id, uid, author_xchan, owner_xchan, source_xchan, item_restrict from item where id = %d and uid = %d limit 1", + intval(argv(2)), + intval(local_user()) + ); + + if($i) { + $can_delete = false; + $local_delete = false; + if(local_user() && local_user() == $i[0]['uid']) + $local_delete = true; + + $ob_hash = get_observer_hash(); + if($ob_hash && ($ob_hash === $i[0]['author_xchan'] || $ob_hash === $i[0]['owner_xchan'] || $ob_hash === $i[0]['source_xchan'])) + $can_delete = true; + + if(! ($can_delete || $local_delete)) { + notice( t('Permission denied.') . EOL); + return; + } + + // if this is a different page type or it's just a local delete + // but not by the item author or owner, do a simple deletion + + if($i[0]['item_restrict'] || ($local_delete && (! $can_delete))) { + drop_item($i[0]['id']); + } + else { + // complex deletion that needs to propagate and be performed in phases + drop_item($i[0]['id'],true,DROPITEM_PHASE1); + tag_deliver($i[0]['uid'],$i[0]['id']); + } + } } } @@ -942,8 +929,16 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag) { $replaced = true; } if(! $replaced) { + //base tag has the tags name only - $basetag = str_replace('_',' ',substr($tag,1)); + + if((substr($tag,0,7) === '#"') && (substr($tag,-6,6) === '"')) { + $basetag = substr($tag,7); + $basetag = substr($basetag,0,-6); + } + else + $basetag = str_replace('_',' ',substr($tag,1)); + //create text for link $url = $a->get_baseurl() . '/search?tag=' . rawurlencode($basetag); $newtag = '#[zrl=' . $a->get_baseurl() . '/search?tag=' . rawurlencode($basetag) . ']' . $basetag . '[/zrl]'; @@ -962,40 +957,83 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag) { } //is it a person tag? + if(strpos($tag,'@') === 0) { + + // The @! tag will alter permissions $exclusive = ((strpos($tag,'!') === 1) ? true : false); + //is it already replaced? if(strpos($tag,'[zrl=')) return $replaced; - $stat = false; + //get the person's name - $name = substr($tag,(($exclusive) ? 2 : 1)); - $newname = $name; - $alias = ''; + + $name = substr($tag,(($exclusive) ? 2 : 1)); // The name or name fragment we are going to replace + $newname = $name; // a copy that we can mess with $tagcid = 0; + $r = null; + // is it some generated name? + $forum = false; + $trailing_plus_name = false; + + // @channel+ is a forum or network delivery tag + + if(substr($newname,-1,1) === '+') { + $forum = true; + $newname = substr($newname,0,-1); + } + + // Here we're looking for an address book entry as provided by the auto-completer + // of the form something+nnn where nnn is an abook_id or the first chars of xchan_hash + if(strrpos($newname,'+')) { //get the id - $tagcid = intval(substr($newname,strrpos($newname,'+') + 1)); + + if(strrpos($tagcid,' ')) + $tagcid = substr($tagcid,0,strrpos($tagcid,' ')); + + $tagcid = substr($newname,strrpos($newname,'+') + 1); + + if(strlen($tagcid) < 16) + $abook_id = intval($tagcid); //remove the next word from tag's name if(strpos($name,' ')) { $name = substr($name,0,strpos($name,' ')); } - if($tagcid) { // if there was an id + if($abook_id) { // if there was an id // select channel with that id from the logged in user's address book $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_id = %d AND abook_channel = %d LIMIT 1", - intval($tagcid), + intval($abook_id), intval($profile_uid) ); } + else { + $r = q("SELECT * FROM xchan + WHERE xchan_hash like '%s%%' LIMIT 1", + dbesc($tagcid) + ); + } } - else { - $newname = str_replace('_',' ',$name); + if(! $r) { + + // look for matching names in the address book + + // Two ways to deal with spaces - doube quote the name or use underscores + // we see this after input filtering so quotes have been html entity encoded + + if((substr($name,0,6) === '"') && (substr($name,-6,6) === '"')) { + $newname = substr($name,6); + $newname = substr($newname,0,-6); + } + else + $newname = str_replace('_',' ',$name); //select someone from this user's contacts by name $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash @@ -1012,14 +1050,28 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag) { intval($profile_uid) ); } + + if(! $r) { + + // it's possible somebody has a name ending with '+', which we stripped off as a forum indicator + // This is very rare but we want to get it right. + + $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash + WHERE xchan_name = '%s' AND abook_channel = %d LIMIT 1", + dbesc($newname . '+'), + intval($profile_uid) + ); + if($r) + $trailing_plus_name = true; + } } - // $r is set, if someone could be selected + // $r is set if we found something if($r) { $profile = $r[0]['xchan_url']; $newname = $r[0]['xchan_name']; - //add person's id to $access_tag if exclusive + // add the channel's xchan_hash to $access_tag if exclusive if($exclusive) { $access_tag .= 'cid:' . $r[0]['xchan_hash']; } @@ -1044,20 +1096,21 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag) { } $channel = get_app()->get_channel(); if($channel) { - $newtag = '@' . (($exclusive) ? '!' : '') . '[zrl=' . z_root() . '/channel/' . $channel['channel_address'] . ']' . $newname . '[/zrl]'; + $newtag = '@' . (($exclusive) ? '!' : '') . '[zrl=' . z_root() . '/channel/' . $channel['channel_address'] . ']' . $newname . '[/zrl]'; $body = str_replace('@' . (($exclusive) ? '!' : '') . $name, $newtag, $body); } } } } - //if there is an url for this persons profile + // if there is an url for this channel + if(isset($profile)) { $replaced = true; //create profile link $profile = str_replace(',','%2c',$profile); $url = $profile; - $newtag = '@' . (($exclusive) ? '!' : '') . '[zrl=' . $profile . ']' . $newname . '[/zrl]'; + $newtag = '@' . (($exclusive) ? '!' : '') . '[zrl=' . $profile . ']' . $newname . (($forum && ! $trailing_plus_name) ? '+' : '') . '[/zrl]'; $body = str_replace('@' . (($exclusive) ? '!' : '') . $name, $newtag, $body); //append tag to str_tags if(! stristr($str_tags,$newtag)) { @@ -1077,8 +1130,8 @@ function fix_attached_photo_permissions($uid,$xchan_hash,$body, $match = null; // match img and zmg image links - if(preg_match_all("/\[[zi]mg\](.*?)\[\/[zi]mg\]/",$body,$match)) { - $images = $match[1]; + if(preg_match_all("/\[[zi]mg(.*?)\](.*?)\[\/[zi]mg\]/",$body,$match)) { + $images = $match[2]; if($images) { foreach($images as $image) { if(! stristr($image,get_app()->get_baseurl() . '/photo/')) @@ -1102,14 +1155,13 @@ function fix_attached_photo_permissions($uid,$xchan_hash,$body, if($r) { $r = q("UPDATE photo SET allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' - WHERE resource_id = '%s' AND uid = %d AND album = '%s' ", + WHERE resource_id = '%s' AND uid = %d ", dbesc($str_contact_allow), dbesc($str_group_allow), dbesc($str_contact_deny), dbesc($str_group_deny), dbesc($image_uri), - intval($uid), - dbesc( t('Wall Photos')) + intval($uid) ); // also update the linked item (which is probably invisible) |