X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=include%2Fitems.php;h=b933804fd9fc54e0aab475ebd16a954134306ef3;hb=082ad499c6bceadb2a1bc5127229bd0f86ee3895;hp=7d51261db94c3535bd06b0cc6da25afdd07a1eb5;hpb=32f5d4e04abdb52080c6e88e29b1d6c7ce89e6b9;p=friendica.git diff --git a/include/items.php b/include/items.php index 7d51261db9..b933804fd9 100755 --- a/include/items.php +++ b/include/items.php @@ -4,6 +4,8 @@ require_once('include/bbcode.php'); require_once('include/oembed.php'); require_once('include/salmon.php'); require_once('include/crypto.php'); +require_once('include/Photo.php'); + function get_feed_for(&$a, $dfrn_id, $owner_nick, $last_update, $direction = 0) { @@ -278,8 +280,123 @@ function construct_activity_target($item) { } return ''; -} +} + +/* limit_body_size() + * + * The purpose of this function is to apply system message length limits to + * imported messages without including any embedded photos in the length + */ +if(! function_exists('limit_body_size')) { +function limit_body_size($body) { + + logger('limit_body_size: start', LOGGER_DEBUG); + + $maxlen = get_max_import_size(); + + // If the length of the body, including the embedded images, is smaller + // than the maximum, then don't waste time looking for the images + if($maxlen && (strlen($body) > $maxlen)) { + + logger('limit_body_size: the total body length exceeds the limit', LOGGER_DEBUG); + + $orig_body = $body; + $new_body = ''; + $textlen = 0; + $max_found = false; + + $img_start = strpos($orig_body, '[img'); + $img_st_close = ($img_start !== false ? strpos(substr($orig_body, $img_start), ']') : false); + $img_end = ($img_start !== false ? strpos(substr($orig_body, $img_start), '[/img]') : false); + while(($img_st_close !== false) && ($img_end !== false)) { + + $img_st_close++; // make it point to AFTER the closing bracket + $img_end += $img_start; + $img_end += strlen('[/img]'); + + if(! strcmp(substr($orig_body, $img_start + $img_st_close, 5), 'data:')) { + // This is an embedded image + + if( ($textlen + $img_start) > $maxlen ) { + if($textlen < $maxlen) { + logger('limit_body_size: the limit happens before an embedded image', LOGGER_DEBUG); + $new_body = $new_body . substr($orig_body, 0, $maxlen - $textlen); + $textlen = $maxlen; + } + } + else { + $new_body = $new_body . substr($orig_body, 0, $img_start); + $textlen += $img_start; + } + + $new_body = $new_body . substr($orig_body, $img_start, $img_end - $img_start); + } + else { + + if( ($textlen + $img_end) > $maxlen ) { + if($textlen < $maxlen) { + logger('limit_body_size: the limit happens before the end of a non-embedded image', LOGGER_DEBUG); + $new_body = $new_body . substr($orig_body, 0, $maxlen - $textlen); + $textlen = $maxlen; + } + } + else { + $new_body = $new_body . substr($orig_body, 0, $img_end); + $textlen += $img_end; + } + } + $orig_body = substr($orig_body, $img_end); + + if($orig_body === false) // in case the body ends on a closing image tag + $orig_body = ''; + + $img_start = strpos($orig_body, '[img'); + $img_st_close = ($img_start !== false ? strpos(substr($orig_body, $img_start), ']') : false); + $img_end = ($img_start !== false ? strpos(substr($orig_body, $img_start), '[/img]') : false); + } + + if( ($textlen + strlen($orig_body)) > $maxlen) { + if($textlen < $maxlen) { + logger('limit_body_size: the limit happens after the end of the last image', LOGGER_DEBUG); + $new_body = $new_body . substr($orig_body, 0, $maxlen - $textlen); + $textlen = $maxlen; + } + } + else { + logger('limit_body_size: the text size with embedded images extracted did not violate the limit', LOGGER_DEBUG); + $new_body = $new_body . $orig_body; + $textlen += strlen($orig_body); + } + + return $new_body; + } + else + return $body; +}} +function title_is_body($title, $body) { + + $title = strip_tags($title); + $title = trim($title); + $title = str_replace(array("\n", "\r", "\t", " "), array("","","",""), $title); + + $body = strip_tags($body); + $body = trim($body); + $body = str_replace(array("\n", "\r", "\t", " "), array("","","",""), $body); + + if (strlen($title) < strlen($body)) + $body = substr($body, 0, strlen($title)); + + if (($title != $body) and (substr($title, -3) == "...")) { + $pos = strrpos($title, "..."); + if ($pos > 0) { + $title = substr($title, 0, $pos); + $body = substr($body, 0, $pos); + } + } + + return($title == $body); +} @@ -306,6 +423,11 @@ function get_atom_elements($feed,$item) { $res['body'] = unxmlify($item->get_content()); $res['plink'] = unxmlify($item->get_link(0)); + // removing the content of the title if its identically to the body + // This helps with auto generated titles e.g. from tumblr + if (title_is_body($res["title"], $res["body"])) + $res['title'] = ""; + if($res['plink']) $base_url = implode('/', array_slice(explode('/',$res['plink']),0,3)); else @@ -324,7 +446,7 @@ function get_atom_elements($feed,$item) { $res['author-avatar'] = unxmlify($link['attribs']['']['href']); } } - } + } $rawactor = $item->get_item_tags(NAMESPACE_ACTIVITY, 'actor'); @@ -356,7 +478,7 @@ function get_atom_elements($feed,$item) { $res['author-avatar'] = unxmlify($link['attribs']['']['href']); } } - } + } $rawactor = $feed->get_feed_tags(NAMESPACE_ACTIVITY, 'subject'); @@ -381,7 +503,7 @@ function get_atom_elements($feed,$item) { $res['app'] = strip_tags(unxmlify($apps[0]['attribs']['']['source'])); if($res['app'] === 'web') $res['app'] = 'OStatus'; - } + } // base64 encoded json structure representing Diaspora signature @@ -414,9 +536,8 @@ function get_atom_elements($feed,$item) { $res['body'] = notags(base64url_decode($res['body'])); } - $maxlen = get_max_import_size(); - if($maxlen && (strlen($res['body']) > $maxlen)) - $res['body'] = substr($res['body'],0, $maxlen); + + $res['body'] = limit_body_size($res['body']); // It isn't certain at this point whether our content is plaintext or html and we'd be foolish to trust // the content type. Our own network only emits text normally, though it might have been converted to @@ -466,8 +587,8 @@ function get_atom_elements($feed,$item) { $res['last-child'] = 0; $private = $item->get_item_tags(NAMESPACE_DFRN,'private'); - if($private && $private[0]['data'] == 1) - $res['private'] = 1; + if($private && intval($private[0]['data']) > 0) + $res['private'] = intval($private[0]['data']); else $res['private'] = 0; @@ -525,7 +646,7 @@ function get_atom_elements($feed,$item) { foreach($base as $link) { if(!x($res, 'owner-avatar') || !$res['owner-avatar']) { - if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar') + if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar') $res['owner-avatar'] = unxmlify($link['attribs']['']['href']); } } @@ -665,10 +786,41 @@ function get_atom_elements($feed,$item) { $res['target'] .= '' . "\n"; } + // This is some experimental stuff. By now retweets are shown with "RT:" + // But: There is data so that the message could be shown similar to native retweets + // There is some better way to parse this array - but it didn't worked for me. + $child = $item->feed->data["child"][SIMPLEPIE_NAMESPACE_ATOM_10]["feed"][0]["child"][SIMPLEPIE_NAMESPACE_ATOM_10]["entry"][0]["child"]["http://activitystrea.ms/spec/1.0/"][object][0]["child"]; + if (is_array($child)) { + $message = $child["http://activitystrea.ms/spec/1.0/"]["object"][0]["child"][SIMPLEPIE_NAMESPACE_ATOM_10]["content"][0]["data"]; + $author = $child[SIMPLEPIE_NAMESPACE_ATOM_10]["author"][0]["child"][SIMPLEPIE_NAMESPACE_ATOM_10]; + $uri = $author["uri"][0]["data"]; + $name = $author["name"][0]["data"]; + $avatar = @array_shift($author["link"][2]["attribs"]); + $avatar = $avatar["href"]; + + if (($name != "") and ($uri != "") and ($avatar != "") and ($message != "")) { + $res["owner-name"] = $res["author-name"]; + $res["owner-link"] = $res["author-link"]; + $res["owner-avatar"] = $res["author-avatar"]; + + $res["author-name"] = $name; + $res["author-link"] = $uri; + $res["author-avatar"] = $avatar; + + $res["body"] = html2bbcode($message); + } + } + $arr = array('feed' => $feed, 'item' => $item, 'result' => $res); call_hooks('parse_atom', $arr); + //if (($res["title"] != "") or (strpos($res["body"], "RT @") > 0)) { + //if (strpos($res["body"], "RT @") !== false) { + // $debugfile = tempnam("/home/ike/log", "item-res2-"); + // file_put_contents($debugfile, serialize($arr)); + //} + return $res; } @@ -724,6 +876,14 @@ function item_store($arr,$force_parent = false) { $arr['body'] = strip_tags($arr['body']); + if (version_compare(PHP_VERSION, '5.3.0', '>=')) { + require_once('Text/LanguageDetect.php'); + $naked_body = preg_replace('/\[(.+?)\]/','',$arr['body']); + $l = new Text_LanguageDetect; + $lng = $l->detectConfidence($naked_body); + $arr['postopts'] = (($lng['language']) ? 'lang=' . $lng['language'] . ';' . $lng['confidence'] : ''); + } + $arr['wall'] = ((x($arr,'wall')) ? intval($arr['wall']) : 0); $arr['uri'] = ((x($arr,'uri')) ? notags(trim($arr['uri'])) : random_string()); $arr['extid'] = ((x($arr,'extid')) ? notags(trim($arr['extid'])) : ''); @@ -791,7 +951,7 @@ function item_store($arr,$force_parent = false) { if($r[0]['uri'] != $r[0]['parent-uri']) { $arr['thr-parent'] = $arr['parent-uri']; $arr['parent-uri'] = $r[0]['parent-uri']; - $z = q("SELECT `id` FROM `item` WHERE `uri` = '%s' AND `parent-uri` = '%s' AND `uid` = %d + $z = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `parent-uri` = '%s' AND `uid` = %d ORDER BY `id` ASC LIMIT 1", dbesc($r[0]['parent-uri']), dbesc($r[0]['parent-uri']), @@ -814,7 +974,7 @@ function item_store($arr,$force_parent = false) { // email correspondents to be private even if the overall thread is not. if($r[0]['private']) - $arr['private'] = 1; + $arr['private'] = $r[0]['private']; // Edge case. We host a public forum that was originally posted to privately. // The original author commented, but as this is a comment, the permissions @@ -1457,11 +1617,12 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) * */ - $bdtext = t('Birthday:') . ' [url=' . $contact['url'] . ']' . $contact['name'] . '[/url]' ; + $bdtext = sprintf( t('%s\'s birthday'), $contact['name']); + $bdtext2 = sprintf( t('Happy Birthday %s'), ' [url=' . $contact['url'] . ']' . $contact['name'] . '[/url]' ) ; - $r = q("INSERT INTO `event` (`uid`,`cid`,`created`,`edited`,`start`,`finish`,`desc`,`type`) - VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s' ) ", + $r = q("INSERT INTO `event` (`uid`,`cid`,`created`,`edited`,`start`,`finish`,`summary`,`desc`,`type`) + VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ", intval($contact['uid']), intval($contact['id']), dbesc(datetime_convert()), @@ -1469,6 +1630,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) dbesc(datetime_convert('UTC','UTC', $birthday)), dbesc(datetime_convert('UTC','UTC', $birthday . ' + 1 day ')), dbesc($bdtext), + dbesc($bdtext2), dbesc('birthday') ); @@ -1614,7 +1776,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) // Now process the feed - if($feed->get_item_quantity()) { + if($feed->get_item_quantity()) { logger('consume_feed: feed item count = ' . $feed->get_item_quantity()); @@ -1627,7 +1789,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) foreach($items as $item) { - $is_reply = false; + $is_reply = false; $item_id = $item->get_id(); $rawthread = $item->get_item_tags( NAMESPACE_THREAD,'in-reply-to'); if(isset($rawthread[0]['attribs']['']['ref'])) { @@ -1641,11 +1803,10 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) continue; // Have we seen it? If not, import it. - + $item_id = $item->get_id(); $datarray = get_atom_elements($feed,$item); - if((! x($datarray,'author-name')) && ($contact['network'] != NETWORK_DFRN)) $datarray['author-name'] = $contact['name']; if((! x($datarray,'author-link')) && ($contact['network'] != NETWORK_DFRN)) @@ -1658,6 +1819,21 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) continue; } + $force_parent = false; + if($contact['network'] === NETWORK_OSTATUS || stristr($contact['url'],'twitter.com')) { + if($contact['network'] === NETWORK_OSTATUS) + $force_parent = true; + if(strlen($datarray['title'])) + unset($datarray['title']); + $r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d", + dbesc(datetime_convert()), + dbesc($parent_uri), + intval($importer['uid']) + ); + $datarray['last-child'] = 1; + } + + $r = q("SELECT `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($item_id), intval($importer['uid']) @@ -1701,19 +1877,6 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) continue; } - $force_parent = false; - if($contact['network'] === NETWORK_OSTATUS || stristr($contact['url'],'twitter.com')) { - if($contact['network'] === NETWORK_OSTATUS) - $force_parent = true; - if(strlen($datarray['title'])) - unset($datarray['title']); - $r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d", - dbesc(datetime_convert()), - dbesc($parent_uri), - intval($importer['uid']) - ); - $datarray['last-child'] = 1; - } if(($contact['network'] === NETWORK_FEED) || (! strlen($contact['notify']))) { // one way feed - no remote comment ability @@ -1726,7 +1889,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) $datarray['type'] = 'activity'; $datarray['gravity'] = GRAVITY_LIKE; // only one like or dislike per person - $r = q("select id from item where uid = %d and `contact-id` = %d and verb ='%s' and deleted = 0 and (`parent-uri` = '%s' OR `thr_parent` = '%s') limit 1", + $r = q("select id from item where uid = %d and `contact-id` = %d and verb ='%s' and deleted = 0 and (`parent-uri` = '%s' OR `thr-parent` = '%s') limit 1", intval($datarray['uid']), intval($datarray['contact-id']), dbesc($datarray['verb']), @@ -1811,6 +1974,13 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) } } + if($contact['network'] === NETWORK_OSTATUS || stristr($contact['url'],'twitter.com')) { + if(strlen($datarray['title'])) + unset($datarray['title']); + $datarray['last-child'] = 1; + } + + $r = q("SELECT `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($item_id), intval($importer['uid']) @@ -1873,24 +2043,23 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) if(! is_array($contact)) return; - if($contact['network'] === NETWORK_OSTATUS || stristr($contact['url'],'twitter.com')) { - if(strlen($datarray['title'])) - unset($datarray['title']); - $datarray['last-child'] = 1; - } if(($contact['network'] === NETWORK_FEED) || (! strlen($contact['notify']))) { // one way feed - no remote comment ability $datarray['last-child'] = 0; } if($contact['network'] === NETWORK_FEED) - $datarray['private'] = 1; + $datarray['private'] = 2; // This is my contact on another system, but it's really me. // Turn this into a wall post. - if($contact['remote_self']) + if($contact['remote_self']) { $datarray['wall'] = 1; + if($contact['network'] === NETWORK_FEED) { + $datarray['private'] = 0; + } + } $datarray['parent-uri'] = $item_id; $datarray['uid'] = $importer['uid']; @@ -2148,6 +2317,67 @@ function local_delivery($importer,$data) { } if($deleted) { + // check for relayed deletes to our conversation + + $is_reply = false; + $r = q("select * from item where uri = '%s' and uid = %d limit 1", + dbesc($uri), + intval($importer['importer_uid']) + ); + if(count($r)) { + $parent_uri = $r[0]['parent-uri']; + if($r[0]['id'] != $r[0]['parent']) + $is_reply = true; + } + + if($is_reply) { + $community = false; + + if($importer['page-flags'] == PAGE_COMMUNITY || $importer['page-flags'] == PAGE_PRVGROUP ) { + $sql_extra = ''; + $community = true; + logger('local_delivery: possible community delete'); + } + else + $sql_extra = " and contact.self = 1 and item.wall = 1 "; + + // was the top-level post for this reply written by somebody on this site? + // Specifically, the recipient? + + $is_a_remote_delete = false; + + $r = q("select `item`.`id`, `item`.`uri`, `item`.`tag`, `item`.`forum_mode`,`item`.`origin`,`item`.`wall`, + `contact`.`name`, `contact`.`url`, `contact`.`thumb` from `item` + LEFT JOIN `contact` ON `contact`.`id` = `item`.`contact-id` + WHERE `item`.`uri` = '%s' AND (`item`.`parent-uri` = '%s' or `item`.`thr-parent` = '%s') + AND `item`.`uid` = %d + $sql_extra + LIMIT 1", + dbesc($parent_uri), + dbesc($parent_uri), + dbesc($parent_uri), + intval($importer['importer_uid']) + ); + if($r && count($r)) + $is_a_remote_delete = true; + + // Does this have the characteristics of a community or private group comment? + // If it's a reply to a wall post on a community/prvgroup page it's a + // valid community comment. Also forum_mode makes it valid for sure. + // If neither, it's not. + + if($is_a_remote_delete && $community) { + if((! $r[0]['forum_mode']) && (! $r[0]['wall'])) { + $is_a_remote_delete = false; + logger('local_delivery: not a community delete'); + } + } + + if($is_a_remote_delete) { + logger('local_delivery: received remote delete'); + } + } + $r = q("SELECT `item`.*, `contact`.`self` FROM `item` left join contact on `item`.`contact-id` = `contact`.`id` WHERE `uri` = '%s' AND `item`.`uid` = %d AND `contact-id` = %d AND NOT `item`.`file` LIKE '%%[%%' LIMIT 1", dbesc($uri), @@ -2200,7 +2430,8 @@ function local_delivery($importer,$data) { } if($item['uri'] == $item['parent-uri']) { - $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s' + $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s', + `body` = '', `title` = '' WHERE `parent-uri` = '%s' AND `uid` = %d", dbesc($when), dbesc(datetime_convert()), @@ -2209,7 +2440,8 @@ function local_delivery($importer,$data) { ); } else { - $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s' + $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s', + `body` = '', `title` = '' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($when), dbesc(datetime_convert()), @@ -2235,7 +2467,11 @@ function local_delivery($importer,$data) { ); } } - } + // if this is a relayed delete, propagate it to other recipients + + if($is_a_remote_delete) + proc_run('php',"include/notifier.php","drop",$item['id']); + } } } } @@ -2964,7 +3200,7 @@ function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) { $o .= '' . xmlify($item['coord']) . '' . "\r\n"; if(($item['private']) || strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid'])) - $o .= '1' . "\r\n"; + $o .= '' . (($item['private']) ? $item['private'] : 1) . '' . "\r\n"; if($item['extid']) $o .= '' . xmlify($item['extid']) . '' . "\r\n"; @@ -3011,20 +3247,33 @@ function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) { return $o; } -function fix_private_photos($s,$uid, $item = null, $cid = 0) { +function fix_private_photos($s, $uid, $item = null, $cid = 0) { $a = get_app(); logger('fix_private_photos', LOGGER_DEBUG); $site = substr($a->get_baseurl(),strpos($a->get_baseurl(),'://')); - if(preg_match("/\[img(.*?)\](.*?)\[\/img\]/is",$s,$matches)) { - $image = $matches[2]; + $orig_body = $s; + $new_body = ''; + + $img_start = strpos($orig_body, '[img'); + $img_st_close = ($img_start !== false ? strpos(substr($orig_body, $img_start), ']') : false); + $img_len = ($img_start !== false ? strpos(substr($orig_body, $img_start + $img_st_close + 1), '[/img]') : false); + while( ($img_st_close !== false) && ($img_len !== false) ) { + + $img_st_close++; // make it point to AFTER the closing bracket + $image = substr($orig_body, $img_start + $img_st_close, $img_len); + logger('fix_private_photos: found photo ' . $image, LOGGER_DEBUG); + + if(stristr($image , $site . '/photo/')) { + // Only embed locally hosted photos $replace = false; $i = basename($image); $i = str_replace(array('.jpg','.png'),array('',''),$i); $x = strpos($i,'-'); + if($x) { $res = substr($i,$x+1); $i = substr($i,0,$x); @@ -3042,14 +3291,6 @@ function fix_private_photos($s,$uid, $item = null, $cid = 0) { // 3. Otherwise, if we have an item, see if the item permissions match the photo // permissions, regardless of order but first check to see if they're an exact // match to save some processing overhead. - - // Currently we only embed one private photo per message so as not to hit import - // size limits at the receiving end. - - // To embed multiples, we would need to parse out the embedded photos on message - // receipt and limit size based only on the text component. Would also need to - // ignore all photos during bbcode translation and item localisation, as these - // will hit internal regex backtrace limits. if(has_permissions($r[0])) { if($cid) { @@ -3064,15 +3305,45 @@ function fix_private_photos($s,$uid, $item = null, $cid = 0) { } } if($replace) { + $data = $r[0]['data']; + $type = $r[0]['type']; + + // If a custom width and height were specified, apply before embedding + if(preg_match("/\[img\=([0-9]*)x([0-9]*)\]/is", substr($orig_body, $img_start, $img_st_close), $match)) { + logger('fix_private_photos: scaling photo', LOGGER_DEBUG); + + $width = intval($match[1]); + $height = intval($match[2]); + + $ph = new Photo($data, $type); + if($ph->is_valid()) { + $ph->scaleImage(max($width, $height)); + $data = $ph->imageString(); + $type = $ph->getType(); + } + } + logger('fix_private_photos: replacing photo', LOGGER_DEBUG); - $s = str_replace($image, 'data:' . $r[0]['type'] . ';base64,' . base64_encode($r[0]['data']), $s); - logger('fix_private_photos: replaced: ' . $s, LOGGER_DATA); + $image = 'data:' . $type . ';base64,' . base64_encode($data); + logger('fix_private_photos: replaced: ' . $image, LOGGER_DATA); } } } } + + $new_body = $new_body . substr($orig_body, 0, $img_start + $img_st_close) . $image . '[/img]'; + $orig_body = substr($orig_body, $img_start + $img_st_close + $img_len + strlen('[/img]')); + if($orig_body === false) + $orig_body = ''; + + $img_start = strpos($orig_body, '[img'); + $img_st_close = ($img_start !== false ? strpos(substr($orig_body, $img_start), ']') : false); + $img_len = ($img_start !== false ? strpos(substr($orig_body, $img_start + $img_st_close + 1), '[/img]') : false); } - return($s); + + $new_body = $new_body . $orig_body; + + return($new_body); } @@ -3416,7 +3687,9 @@ function posted_dates($uid,$wall) { $dnow = substr($dthen,0,8) . '28'; $ret = array(); - while($dnow >= $dthen) { + // Starting with the current month, get the first and last days of every + // month down to and including the month of the first post + while(substr($dnow, 0, 7) >= substr($dthen, 0, 7)) { $dstart = substr($dnow,0,8) . '01'; $dend = substr($dnow,0,8) . get_dim(intval($dnow),intval(substr($dnow,5))); $start_month = datetime_convert('','',$dstart,'Y-m-d'); @@ -3450,7 +3723,6 @@ function posted_date_widget($url,$uid,$wall) { return $o; } - function store_diaspora_retract_sig($item, $user, $baseurl) { // 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 @@ -3476,7 +3748,7 @@ function store_diaspora_retract_sig($item, $user, $baseurl) { } else { $r = q("SELECT `nick`, `url` FROM `contact` WHERE `id` = '%d' LIMIT 1", - $item['contact-id'] + $item['contact-id'] // If this function gets called, drop_item() has already checked remote_user() == $item['contact-id'] ); if(count($r)) { // The below handle only works for NETWORK_DFRN. I think that's ok, because this function