Merge remote branch 'upstream/master'

Conflicts:
	include/bb2diaspora.php
This commit is contained in:
Michael Vogel 2012-07-13 23:39:51 +02:00
commit bfca7f47ef
282 changed files with 35083 additions and 2632 deletions

View file

@ -143,7 +143,7 @@ class Photo {
public function orient($filename) {
// based off comment on http://php.net/manual/en/function.imagerotate.php
if(! function_exists('exif_read_data'))
if( (! function_exists('exif_read_data')) || ($this->getType() !== 'image/jpeg') )
return;
$exif = exif_read_data($filename);

View file

@ -432,7 +432,7 @@ function probe_url($url, $mode = PROBE_NORMAL) {
intval(local_user())
);
if(count($x) && count($r)) {
$mailbox = construct_mailbox_name($r[0]);
$mailbox = construct_mailbox_name($r[0]);
$password = '';
openssl_private_decrypt(hex2bin($r[0]['pass']),$password,$x[0]['prvkey']);
$mbox = email_connect($mailbox,$r[0]['user'],$password);

View file

@ -7,6 +7,66 @@ require_once("include/html2bbcode.php");
require_once("include/bbcode.php");
require_once("include/markdownify/markdownify.php");
function get_bb_tag_pos($s, $name, $occurance = 1) {
if($occurance < 1)
$occurance = 1;
$start_open = -1;
for($i = 1; $i <= $occurance; $i++) {
if( $start_open !== false)
$start_open = strpos($s, '[' . $name, $start_open + 1); // allow [name= type tags
}
if( $start_open === false)
return false;
$start_equal = strpos($s, '=', $start_open);
$start_close = strpos($s, ']', $start_open);
if( $start_close === false)
return false;
$start_close++;
$end_open = strpos($s, '[/' . $name . ']', $start_close);
if( $end_open === false)
return false;
$res = array( 'start' => array('open' => $start_open, 'close' => $start_close),
'end' => array('open' => $end_open, 'close' => $end_open + strlen('[/' . $name . ']')) );
if( $start_equal !== false)
$res['start']['equal'] = $start_equal + 1;
return $res;
}
function bb_tag_preg_replace($pattern, $replace, $name, $s) {
$string = $s;
$occurance = 1;
$pos = get_bb_tag_pos($string, $name, $occurance);
while($pos !== false && $occurance < 1000) {
$start = substr($string, 0, $pos['start']['open']);
$subject = substr($string, $pos['start']['open'], $pos['end']['close'] - $pos['start']['open']);
$end = substr($string, $pos['end']['close']);
if($end === false)
$end = '';
$subject = preg_replace($pattern, $replace, $subject);
$string = $start . $subject . $end;
$occurance++;
$pos = get_bb_tag_pos($string, $name, $occurance);
}
return $string;
}
// we don't want to support a bbcode specific markdown interpreter
// and the markdown library we have is pretty good, but provides HTML output.
// So we'll use that to convert to HTML, then convert the HTML back to bbcode,
@ -38,20 +98,23 @@ function diaspora2bb($s) {
$s = Markdown($s);
$s = str_replace('&#35;','#',$s);
$s = str_replace("\n",'<br />',$s);
// we seem to have double linebreaks
// $s = str_replace("\n",'<br />',$s);
$s = html2bbcode($s);
// $s = str_replace('&#42;','*',$s);
// protect the recycle symbol from turning into a tag, but without unescaping angles and naked ampersands
$s = str_replace('&#x2672;',html_entity_decode('&#x2672;',ENT_QUOTES,'UTF-8'),$s);
// Convert everything that looks like a link to a link
$s = preg_replace("/([^\]\=]|^)(https?\:\/\/)([a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)/ism", '$1[url=$2$3]$2$3[/url]',$s);
//$s = preg_replace("/([^\]\=]|^)(https?\:\/\/)(vimeo|youtu|www\.youtube|soundcloud)([a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)/ism", '$1[url=$2$3$4]$2$3$4[/url]',$s);
$s = preg_replace("/\[url\=?(.*?)\]https?:\/\/www.youtube.com\/watch\?v\=(.*?)\[\/url\]/ism",'[youtube]$2[/youtube]',$s);
$s = preg_replace("/\[url\=https?:\/\/www.youtube.com\/watch\?v\=(.*?)\].*?\[\/url\]/ism",'[youtube]$1[/youtube]',$s);
$s = preg_replace("/\[url\=?(.*?)\]https?:\/\/vimeo.com\/([0-9]+)(.*?)\[\/url\]/ism",'[vimeo]$2[/vimeo]',$s);
$s = preg_replace("/\[url\=https?:\/\/vimeo.com\/([0-9]+)\](.*?)\[\/url\]/ism",'[vimeo]$1[/vimeo]',$s);
$s = bb_tag_preg_replace("/\[url\=?(.*?)\]https?:\/\/www.youtube.com\/watch\?v\=(.*?)\[\/url\]/ism",'[youtube]$2[/youtube]','url',$s);
$s = bb_tag_preg_replace("/\[url\=https?:\/\/www.youtube.com\/watch\?v\=(.*?)\].*?\[\/url\]/ism",'[youtube]$1[/youtube]','url',$s);
$s = bb_tag_preg_replace("/\[url\=?(.*?)\]https?:\/ \/vimeo.com\/([0-9]+)(.*?)\[\/url\]/ism",'[vimeo]$2[/vimeo]','url',$s);
$s = bb_tag_preg_replace("/\[url\=https?:\/\/vimeo.com\/([0-9]+)\](.*?)\[\/url\]/ism",'[vimeo]$1[/vimeo]','url',$s);
// remove duplicate adjacent code tags
$s = preg_replace("/(\[code\])+(.*?)(\[\/code\])+/ism","[code]$2[/code]", $s);
@ -67,6 +130,12 @@ function stripdcode_br_cb($s) {
}
//////////////////////
// The following "diaspora_ul" and "diaspora_ol" are only appropriate for the
// pre-Markdownify conversion. If Markdownify isn't used, use the non-Markdownify
// versions below
//////////////////////
/*
function diaspora_ul($s) {
// Replace "[*]" followed by any number (including zero) of
// spaces by "* " to match Diaspora's list format
@ -100,32 +169,33 @@ function diaspora_ol($s) {
else
return $s[0];
}
*/
//////////////////////
// Non-Markdownify versions of "diaspora_ol" and "diaspora_ul"
//////////////////////
function diaspora_ul($s) {
// Replace "[\\*]" followed by any number (including zero) of
// spaces by "* " to match Diaspora's list format
return preg_replace("/\[\\\\\*\]( *)/", "* ", $s[1]);
}
function diaspora_ol($s) {
// A hack: Diaspora will create a properly-numbered ordered list even
// if you use '1.' for each element of the list, like:
// 1. First element
// 1. Second element
// 1. Third element
return preg_replace("/\[\\\\\*\]( *)/", "1. ", $s[1]);
}
function bb2diaspora($Text,$preserve_nl = false) {
// bbcode() will convert "[*]" into "<li>" with no closing "</li>"
// Markdownify() is unable to handle these, as it makes each new
// "<li>" into a deeper nested element until it crashes. So pre-format
// the lists as Diaspora lists before sending the $Text to bbcode()
//
// Note that to get nested lists to work for Diaspora, we would need
// to define the closing tag for the list elements. So nested lists
// are going to be flattened out in Diaspora for now
/* $endlessloop = 0;
while ((((strpos($Text, "[/list]") !== false) && (strpos($Text, "[list") !== false)) ||
((strpos($Text, "[/ol]") !== false) && (strpos($Text, "[ol]") !== false)) ||
((strpos($Text, "[/ul]") !== false) && (strpos($Text, "[ul]") !== false))) && (++$endlessloop < 20)) {
$Text = preg_replace_callback("/\[list\](.*?)\[\/list\]/is", 'diaspora_ul', $Text);
$Text = preg_replace_callback("/\[list=1\](.*?)\[\/list\]/is", 'diaspora_ol', $Text);
$Text = preg_replace_callback("/\[list=i\](.*?)\[\/list\]/s",'diaspora_ol', $Text);
$Text = preg_replace_callback("/\[list=I\](.*?)\[\/list\]/s", 'diaspora_ol', $Text);
$Text = preg_replace_callback("/\[list=a\](.*?)\[\/list\]/s", 'diaspora_ol', $Text);
$Text = preg_replace_callback("/\[list=A\](.*?)\[\/list\]/s", 'diaspora_ol', $Text);
$Text = preg_replace_callback("/\[ul\](.*?)\[\/ul\]/is", 'diaspora_ul', $Text);
$Text = preg_replace_callback("/\[ol\](.*?)\[\/ol\]/is", 'diaspora_ol', $Text);
}
*/
// Re-enabling the converter again.
// The bbcode parser now handles youtube-links (and the other stuff) correctly.
// Additionally the html code is now fixed so that lists are now working.
// Convert it to HTML - don't try oembed
$Text = bbcode($Text, $preserve_nl, false);
@ -142,7 +212,9 @@ function bb2diaspora($Text,$preserve_nl = false) {
// Remove all unconverted tags
$Text = strip_tags($Text);
/*
/* Old routine
$ev = bbtoevent($Text);
// Replace any html brackets with HTML Entities to prevent executing HTML or script
@ -225,15 +297,21 @@ function bb2diaspora($Text,$preserve_nl = false) {
$Text = preg_replace("(\[size=(.*?)\](.*?)\[\/size\])is","$2",$Text);
// Check for list text
$Text = preg_replace_callback("/\[list\](.*?)\[\/list\]/is", 'diaspora_ul', $Text);
$Text = preg_replace_callback("/\[ul\](.*?)\[\/ul\]/is", 'diaspora_ul', $Text);
$Text = preg_replace_callback("/\[list=1\](.*?)\[\/list\]/is", 'diaspora_ol', $Text);
$Text = preg_replace_callback("/\[list=i\](.*?)\[\/list\]/s",'diaspora_ol', $Text);
$Text = preg_replace_callback("/\[list=I\](.*?)\[\/list\]/s", 'diaspora_ol', $Text);
$Text = preg_replace_callback("/\[list=a\](.*?)\[\/list\]/s", 'diaspora_ol', $Text);
$Text = preg_replace_callback("/\[list=A\](.*?)\[\/list\]/s", 'diaspora_ol', $Text);
$Text = preg_replace_callback("/\[ol\](.*?)\[\/ol\]/is", 'diaspora_ol', $Text);
// $Text = preg_replace("/\[li\](.*?)\[\/li\]/s", '<li>$1</li>' ,$Text);
$endlessloop = 0;
while ((((strpos($Text, "[/list]") !== false) && (strpos($Text, "[list") !== false)) ||
((strpos($Text, "[/ol]") !== false) && (strpos($Text, "[ol]") !== false)) ||
((strpos($Text, "[/ul]") !== false) && (strpos($Text, "[ul]") !== false)) ||
((strpos($Text, "[/li]") !== false) && (strpos($Text, "[li]") !== false))) && (++$endlessloop < 20)) {
$Text = preg_replace_callback("/\[list\](.*?)\[\/list\]/is", 'diaspora_ul', $Text);
$Text = preg_replace_callback("/\[list=1\](.*?)\[\/list\]/is", 'diaspora_ol', $Text);
$Text = preg_replace_callback("/\[list=i\](.*?)\[\/list\]/s",'diaspora_ol', $Text);
$Text = preg_replace_callback("/\[list=I\](.*?)\[\/list\]/s", 'diaspora_ol', $Text);
$Text = preg_replace_callback("/\[list=a\](.*?)\[\/list\]/s", 'diaspora_ol', $Text);
$Text = preg_replace_callback("/\[list=A\](.*?)\[\/list\]/s", 'diaspora_ol', $Text);
$Text = preg_replace_callback("/\[ul\](.*?)\[\/ul\]/is", 'diaspora_ul', $Text);
$Text = preg_replace_callback("/\[ol\](.*?)\[\/ol\]/is", 'diaspora_ol', $Text);
$Text = preg_replace("/\[li\]( *)(.*?)\[\/li\]/s", '* $2' ,$Text);
}
// Just get rid of table tags since Diaspora doesn't support tables
$Text = preg_replace("/\[th\](.*?)\[\/th\]/s", '$1' ,$Text);
@ -295,12 +373,13 @@ function bb2diaspora($Text,$preserve_nl = false) {
// If we found an event earlier, strip out all the event code and replace with a reformatted version.
if(x($ev,'desc') && x($ev,'start')) {
if(x($ev,'start')) {
$sub = format_event_diaspora($ev);
$Text = preg_replace("/\[event\-description\](.*?)\[\/event\-description\]/is",$sub,$Text);
$Text = preg_replace("/\[event\-start\](.*?)\[\/event\-start\]/is",'',$Text);
$Text = preg_replace("/\[event\-summary\](.*?)\[\/event\-summary\]/is",'',$Text);
$Text = preg_replace("/\[event\-description\](.*?)\[\/event\-description\]/is",'',$Text);
$Text = preg_replace("/\[event\-start\](.*?)\[\/event\-start\]/is",$sub,$Text);
$Text = preg_replace("/\[event\-finish\](.*?)\[\/event\-finish\]/is",'',$Text);
$Text = preg_replace("/\[event\-location\](.*?)\[\/event\-location\]/is",'',$Text);
$Text = preg_replace("/\[event\-adjust\](.*?)\[\/event\-adjust\]/is",'',$Text);
@ -309,6 +388,7 @@ function bb2diaspora($Text,$preserve_nl = false) {
$Text = preg_replace("/\<(.*?)(src|href)=(.*?)\&amp\;(.*?)\>/ism",'<$1$2=$3&$4>',$Text);
$Text = preg_replace_callback('/\[(.*?)\]\((.*?)\)/ism','unescape_underscores_in_links',$Text);
*/
// Remove any leading or trailing whitespace, as this will mess up
@ -336,7 +416,7 @@ function format_event_diaspora($ev) {
$o = 'Friendica event notification:' . "\n";
$o .= '**' . bb2diaspora($ev['desc']) . '**' . "\n";
$o .= '**' . (($ev['summary']) ? bb2diaspora($ev['summary']) : bb2diaspora($ev['desc'])) . '**' . "\n";
$o .= t('Starts:') . ' ' . '['
. (($ev['adjust']) ? day_translate(datetime_convert('UTC', 'UTC',

View file

@ -47,6 +47,67 @@ function bb_unspacefy_and_trim($st) {
return $unspacefied;
}
if(! function_exists('bb_extract_images')) {
function bb_extract_images($body) {
$saved_image = array();
$orig_body = $body;
$new_body = '';
$cnt = 0;
$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;
if(! strcmp(substr($orig_body, $img_start + $img_st_close, 5), 'data:')) {
// This is an embedded image
$saved_image[$cnt] = substr($orig_body, $img_start + $img_st_close, $img_end - ($img_start + $img_st_close));
$new_body = $new_body . substr($orig_body, 0, $img_start) . '[$#saved_image' . $cnt . '#$]';
$cnt++;
}
else
$new_body = $new_body . substr($orig_body, 0, $img_end + strlen('[/img]'));
$orig_body = substr($orig_body, $img_end + strlen('[/img]'));
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);
}
$new_body = $new_body . $orig_body;
return array('body' => $new_body, 'images' => $saved_image);
}}
if(! function_exists('bb_replace_images')) {
function bb_replace_images($body, $images) {
$newbody = $body;
$cnt = 0;
foreach($images as $image) {
// We're depending on the property of 'foreach' (specified on the PHP website) that
// it loops over the array starting from the first element and going sequentially
// to the last element
$newbody = str_replace('[$#saved_image' . $cnt . '#$]', '<img src="' . $image .'" alt="' . t('Image/photo') . '" />', $newbody);
$cnt++;
}
return $newbody;
}}
// BBcode 2 HTML was written by WAY2WEB.net
// extended to work with Mistpark/Friendica - Mike Macgirvin
@ -54,29 +115,21 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
$a = get_app();
// Hide all [noparse] contained bbtags spacefying them
// Hide all [noparse] contained bbtags by spacefying them
// POSSIBLE BUG --> Will the 'preg' functions crash if there's an embedded image?
$Text = preg_replace_callback("/\[noparse\](.*?)\[\/noparse\]/ism", 'bb_spacefy',$Text);
$Text = preg_replace_callback("/\[nobb\](.*?)\[\/nobb\]/ism", 'bb_spacefy',$Text);
$Text = preg_replace_callback("/\[pre\](.*?)\[\/pre\]/ism", 'bb_spacefy',$Text);
// Extract a single private image which uses data url's since preg has issues with
// large data sizes. Stash it away while we do bbcode conversion, and then put it back
// Extract the private images which use data url's since preg has issues with
// large data sizes. Stash them away while we do bbcode conversion, and then put them back
// in after we've done all the regex matching. We cannot use any preg functions to do this.
$saved_image = '';
$img_start = strpos($Text,'[img]data:');
$img_end = strpos($Text,'[/img]');
if($img_start !== false && $img_end !== false && $img_end > $img_start) {
$start_fragment = substr($Text,0,$img_start);
$img_start += strlen('[img]');
$saved_image = substr($Text,$img_start,$img_end - $img_start);
$end_fragment = substr($Text,$img_end + strlen('[/img]'));
// logger('saved_image: ' . $saved_image,LOGGER_DEBUG);
$Text = $start_fragment . '[$#saved_image#$]' . $end_fragment;
}
$extracted = bb_extract_images($Text);
$Text = $extracted['body'];
$saved_image = $extracted['images'];
// If we find any event code, turn it into an event.
// After we're finished processing the bbcode we'll
@ -93,11 +146,19 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
// Convert new line chars to html <br /> tags
$Text = nl2br($Text);
// nlbr seems to be hopelessly messed up
// $Text = nl2br($Text);
// We'll emulate it.
$Text = str_replace("\r\n","\n", $Text);
$Text = str_replace(array("\r","\n"), array('<br />','<br />'), $Text);
if($preserve_nl)
$Text = str_replace(array("\n","\r"), array('',''),$Text);
// Set up the parameters for a URL search string
$URLSearchString = "^\[\]";
// Set up the parameters for a MAIL search string
@ -158,14 +219,14 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
// Check for list text
$Text = str_replace("[*]", "<li>", $Text);
$Text = preg_replace("/\[li\](.*?)\[\/li\]/ism", '<li>$1</li>' ,$Text);
// handle nested lists
$endlessloop = 0;
while ((((strpos($Text, "[/list]") !== false) && (strpos($Text, "[list") !== false)) ||
((strpos($Text, "[/ol]") !== false) && (strpos($Text, "[ol]") !== false)) ||
((strpos($Text, "[/ul]") !== false) && (strpos($Text, "[ul]") !== false))) && (++$endlessloop < 20)) {
((strpos($Text, "[/ul]") !== false) && (strpos($Text, "[ul]") !== false)) ||
((strpos($Text, "[/li]") !== false) && (strpos($Text, "[li]") !== false))) && (++$endlessloop < 20)) {
$Text = preg_replace("/\[list\](.*?)\[\/list\]/ism", '<ul class="listbullet" style="list-style-type: circle;">$1</ul>' ,$Text);
$Text = preg_replace("/\[list=\](.*?)\[\/list\]/ism", '<ul class="listnone" style="list-style-type: none;">$1</ul>' ,$Text);
$Text = preg_replace("/\[list=1\](.*?)\[\/list\]/ism", '<ul class="listdecimal" style="list-style-type: decimal;">$1</ul>' ,$Text);
@ -175,6 +236,7 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
$Text = preg_replace("/\[list=((?-i)A)\](.*?)\[\/list\]/ism", '<ul class="listupperalpha" style="list-style-type: upper-alpha;">$2</ul>' ,$Text);
$Text = preg_replace("/\[ul\](.*?)\[\/ul\]/ism", '<ul class="listbullet" style="list-style-type: circle;">$1</ul>' ,$Text);
$Text = preg_replace("/\[ol\](.*?)\[\/ol\]/ism", '<ul class="listdecimal" style="list-style-type: decimal;">$1</ul>' ,$Text);
$Text = preg_replace("/\[li\](.*?)\[\/li\]/ism", '<li>$1</li>' ,$Text);
}
$Text = preg_replace("/\[th\](.*?)\[\/th\]/sm", '<th>$1</th>' ,$Text);
@ -196,7 +258,7 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
// Declare the format for [code] layout
$Text = preg_replace_callback("/\[code\](.*?)\[\/code\]/ism",'stripcode_br_cb',$Text);
// $Text = preg_replace_callback("/\[code\](.*?)\[\/code\]/ism",'stripcode_br_cb',$Text);
$CodeLayout = '<code>$1</code>';
// Check for [code] text
@ -335,8 +397,9 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
// fix any escaped ampersands that may have been converted into links
$Text = preg_replace("/\<(.*?)(src|href)=(.*?)\&amp\;(.*?)\>/ism",'<$1$2=$3&$4>',$Text);
if(strlen($saved_image))
$Text = str_replace('[$#saved_image#$]','<img src="' . $saved_image .'" alt="' . t('Image/photo') . '" />',$Text);
if($saved_image)
$Text = bb_replace_images($Text, $saved_image);
// Clean up the HTML by loading and saving the HTML with the DOM
// Only do it when it has to be done - for performance reasons

View file

@ -1,30 +1,91 @@
<?php
// Note: the code in 'item_extract_images' and 'item_redir_and_replace_images'
// is identical to the code in mod/message.php for 'item_extract_images' and
// 'item_redir_and_replace_images'
if(! function_exists('item_extract_images')) {
function item_extract_images($body) {
$saved_image = array();
$orig_body = $body;
$new_body = '';
$cnt = 0;
$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;
if(! strcmp(substr($orig_body, $img_start + $img_st_close, 5), 'data:')) {
// This is an embedded image
$saved_image[$cnt] = substr($orig_body, $img_start + $img_st_close, $img_end - ($img_start + $img_st_close));
$new_body = $new_body . substr($orig_body, 0, $img_start) . '[!#saved_image' . $cnt . '#!]';
$cnt++;
}
else
$new_body = $new_body . substr($orig_body, 0, $img_end + strlen('[/img]'));
$orig_body = substr($orig_body, $img_end + strlen('[/img]'));
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);
}
$new_body = $new_body . $orig_body;
return array('body' => $new_body, 'images' => $saved_image);
}}
if(! function_exists('item_redir_and_replace_images')) {
function item_redir_and_replace_images($body, $images, $cid) {
$origbody = $body;
$newbody = '';
for($i = 0; $i < count($images); $i++) {
$search = '/\[url\=(.*?)\]\[!#saved_image' . $i . '#!\]\[\/url\]' . '/is';
$replace = '[url=' . z_path() . '/redir/' . $cid
. '?f=1&url=' . '$1' . '][!#saved_image' . $i . '#!][/url]' ;
$img_end = strpos($origbody, '[!#saved_image' . $i . '#!][/url]') + strlen('[!#saved_image' . $i . '#!][/url]');
$process_part = substr($origbody, 0, $img_end);
$origbody = substr($origbody, $img_end);
$process_part = preg_replace($search, $replace, $process_part);
$newbody = $newbody . $process_part;
}
$newbody = $newbody . $origbody;
$cnt = 0;
foreach($images as $image) {
// We're depending on the property of 'foreach' (specified on the PHP website) that
// it loops over the array starting from the first element and going sequentially
// to the last element
$newbody = str_replace('[!#saved_image' . $cnt . '#!]', '[img]' . $image . '[/img]', $newbody);
$cnt++;
}
return $newbody;
}}
/**
* Render actions localized
*/
function localize_item(&$item){
$Text = $item['body'];
$saved_image = '';
$img_start = strpos($Text,'[img]data:');
$img_end = strpos($Text,'[/img]');
if($img_start !== false && $img_end !== false && $img_end > $img_start) {
$start_fragment = substr($Text,0,$img_start);
$img_start += strlen('[img]');
$saved_image = substr($Text,$img_start,$img_end - $img_start);
$end_fragment = substr($Text,$img_end + strlen('[/img]'));
$Text = $start_fragment . '[!#saved_image#!]' . $end_fragment;
$search = '/\[url\=(.*?)\]\[!#saved_image#!\]\[\/url\]' . '/is';
$replace = '[url=' . z_path() . '/redir/' . $item['contact-id']
. '?f=1&url=' . '$1' . '][!#saved_image#!][/url]' ;
$Text = preg_replace($search,$replace,$Text);
if(strlen($saved_image))
$item['body'] = str_replace('[!#saved_image#!]', '[img]' . $saved_image . '[/img]',$Text);
}
$extracted = item_extract_images($item['body']);
if($extracted['images'])
$item['body'] = item_redir_and_replace_images($extracted['body'], $extracted['images'], $item['contact-id']);
$xmlhead="<"."?xml version='1.0' encoding='UTF-8' ?".">";
if ($item['verb']=== ACTIVITY_LIKE || $item['verb']=== ACTIVITY_DISLIKE){
@ -173,6 +234,7 @@ function localize_item(&$item){
$item['body'] = str_replace($mtch[0],'@[url=' . zrl($mtch[1]). ']',$item['body']);
}
}
// add zrl's to public images
if(preg_match_all('/\[url=(.*?)\/photos\/(.*?)\/image\/(.*?)\]\[img(.*?)\]h(.*?)\[\/img\]\[\/url\]/is',$item['body'],$matches,PREG_SET_ORDER)) {
foreach($matches as $mtch) {
@ -180,6 +242,17 @@ function localize_item(&$item){
}
}
// add sparkle links to appropriate permalinks
$x = stristr($item['plink'],'/display/');
if($x) {
$sparkle = false;
$y = best_link_url($item,$sparkle,true);
if(strstr($y,'/redir/'))
$item['plink'] = $y . '?f=&url=' . $item['plink'];
}
}
@ -546,7 +619,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
}
$likebuttons = '';
$shareable = ((($profile_owner == local_user()) && (! $item['private'] == 1)) ? true : false);
$shareable = ((($profile_owner == local_user()) && ($item['private'] != 1)) ? true : false);
if($page_writeable) {
/* if($toplevelpost) { */

View file

@ -261,39 +261,6 @@ function aes_unencapsulate($data,$prvkey) {
return AES256CBC_decrypt(base64url_decode($data['data']),$k,$i);
}
// This has been superceded.
function zot_encapsulate($data,$envelope,$pubkey) {
$res = aes_encapsulate($data,$pubkey);
return <<< EOT
<?xml version='1.0' encoding='UTF-8'?>
<zot:msg xmlns:zot='http://purl.org/zot/1.0'>
<zot:key>{$res['key']}</zot:key>
<zot:iv>{$res['iv']}</zot:iv>
<zot:env>$s1</zot:env>
<zot:sig key_id="$keyid">$sig</zot:sig>
<zot:alg>AES-256-CBC</zot:alg>
<zot:data type='application/magic-envelope+xml'>{$res['data']}</zot:data>
</zot:msg>
EOT;
}
// so has this
function zot_unencapsulate($data,$prvkey) {
$ret = array();
$c = array();
$x = parse_xml_string($data);
$c = array('key' => $x->key,'iv' => $x->iv,'data' => $x->data);
openssl_private_decrypt(base64url_decode($x->sender),$s,$prvkey);
$ret['sender'] = $s;
$ret['data'] = aes_unencapsulate($x,$prvkey);
return $ret;
}
function new_keypair($bits) {
$openssl_options = array(

View file

@ -285,3 +285,9 @@ function dbesc_array(&$arr) {
array_walk($arr,'dbesc_array_cb');
}
}}
function dba_timer() {
return microtime(true);
}

View file

@ -5,6 +5,7 @@ require_once('include/items.php');
require_once('include/bb2diaspora.php');
require_once('include/contact_selectors.php');
require_once('include/queue_fn.php');
require_once('include/lock.php');
function diaspora_dispatch_public($msg) {
@ -60,10 +61,10 @@ function diaspora_dispatch($importer,$msg) {
$ret = diaspora_request($importer,$xmlbase->request);
}
elseif($xmlbase->status_message) {
$ret = diaspora_post($importer,$xmlbase->status_message);
$ret = diaspora_post($importer,$xmlbase->status_message,$msg);
}
elseif($xmlbase->profile) {
$ret = diaspora_profile($importer,$xmlbase->profile);
$ret = diaspora_profile($importer,$xmlbase->profile,$msg);
}
elseif($xmlbase->comment) {
$ret = diaspora_comment($importer,$xmlbase->comment,$msg);
@ -72,10 +73,10 @@ function diaspora_dispatch($importer,$msg) {
$ret = diaspora_like($importer,$xmlbase->like,$msg);
}
elseif($xmlbase->asphoto) {
$ret = diaspora_asphoto($importer,$xmlbase->asphoto);
$ret = diaspora_asphoto($importer,$xmlbase->asphoto,$msg);
}
elseif($xmlbase->reshare) {
$ret = diaspora_reshare($importer,$xmlbase->reshare);
$ret = diaspora_reshare($importer,$xmlbase->reshare,$msg);
}
elseif($xmlbase->retraction) {
$ret = diaspora_retraction($importer,$xmlbase->retraction,$msg);
@ -113,27 +114,93 @@ function diaspora_get_contact_by_handle($uid,$handle) {
}
function find_diaspora_person_by_handle($handle) {
$person = false;
$update = false;
$r = q("select * from fcontact where network = '%s' and addr = '%s' limit 1",
dbesc(NETWORK_DIASPORA),
dbesc($handle)
);
if(count($r)) {
logger('find_diaspora_person_by handle: in cache ' . print_r($r,true), LOGGER_DEBUG);
// update record occasionally so it doesn't get stale
$d = strtotime($r[0]['updated'] . ' +00:00');
if($d > strtotime('now - 14 days'))
return $r[0];
$update = true;
}
logger('find_diaspora_person_by_handle: refresh',LOGGER_DEBUG);
require_once('include/Scrape.php');
$r = probe_url($handle, PROBE_DIASPORA);
if((count($r)) && ($r['network'] === NETWORK_DIASPORA)) {
add_fcontact($r,$update);
return ($r);
}
return false;
$got_lock = false;
$endlessloop = 0;
$maxloops = 10;
do {
$r = q("select * from fcontact where network = '%s' and addr = '%s' limit 1",
dbesc(NETWORK_DIASPORA),
dbesc($handle)
);
if(count($r)) {
$person = $r[0];
logger('find_diaspora_person_by handle: in cache ' . print_r($r,true), LOGGER_DEBUG);
// update record occasionally so it doesn't get stale
$d = strtotime($person['updated'] . ' +00:00');
if($d < strtotime('now - 14 days'))
$update = true;
}
// FETCHING PERSON INFORMATION FROM REMOTE SERVER
//
// If the person isn't in our 'fcontact' table, or if he/she is but
// his/her information hasn't been updated for more than 14 days, then
// we want to fetch the person's information from the remote server.
//
// Note that $person isn't changed by this block of code unless the
// person's information has been successfully fetched from the remote
// server. So if $person was 'false' to begin with (because he/she wasn't
// in the local cache), it'll stay false, and if $person held the local
// cache information to begin with, it'll keep that information. That way
// if there's a problem with the remote fetch, we can at least use our
// cached information--it's better than nothing.
if((! $person) || ($update)) {
// Lock the function to prevent race conditions if multiple items
// come in at the same time from a person who doesn't exist in
// fcontact
//
// Don't loop forever. On the last loop, try to create the contact
// whether the function is locked or not. Maybe the locking thread
// has died or something. At any rate, a duplicate in 'fcontact'
// is a much smaller problem than a deadlocked thread
$got_lock = lock_function('find_diaspora_person_by_handle', false);
if(($endlessloop + 1) >= $maxloops)
$got_lock = true;
if($got_lock) {
logger('find_diaspora_person_by_handle: create or refresh', LOGGER_DEBUG);
require_once('include/Scrape.php');
$r = probe_url($handle, PROBE_DIASPORA);
// Note that Friendica contacts can return a "Diaspora person"
// if Diaspora connectivity is enabled on their server
if((count($r)) && ($r['network'] === NETWORK_DIASPORA)) {
add_fcontact($r,$update);
$person = ($r);
}
unlock_function('find_diaspora_person_by_handle');
}
else {
logger('find_diaspora_person_by_handle: couldn\'t lock function', LOGGER_DEBUG);
if(! $person)
block_on_function_lock('find_diaspora_person_by_handle');
}
}
} while((! $person) && (! $got_lock) && (++$endlessloop < $maxloops));
// We need to try again if the person wasn't in 'fcontact' but the function was locked.
// The fact that the function was locked may mean that another process was creating the
// person's record. It could also mean another process was creating or updating an unrelated
// person.
//
// At any rate, we need to keep trying until we've either got the person or had a chance to
// try to fetch his/her remote information. But we don't want to block on locking the
// function, because if the other process is creating the record, then when we acquire the lock
// we'll dive right into creating another, duplicate record. We DO want to at least wait
// until the lock is released, so we don't flood the database with requests.
//
// If the person was in the 'fcontact' table, don't try again. It's not worth the time, since
// we do have some information for the person
return $person;
}
@ -654,12 +721,17 @@ function diaspora_post_allow($importer,$contact) {
}
function diaspora_post($importer,$xml) {
function diaspora_post($importer,$xml,$msg) {
$a = get_app();
$guid = notags(unxmlify($xml->guid));
$diaspora_handle = notags(unxmlify($xml->diaspora_handle));
if($diaspora_handle != $msg['author']) {
logger('diaspora_post: Potential forgery. Message handle is not the same as envelope sender.');
return 202;
}
$contact = diaspora_get_contact_by_handle($importer['uid'],$diaspora_handle);
if(! $contact)
return;
@ -770,7 +842,7 @@ function diaspora_post($importer,$xml) {
}
function diaspora_reshare($importer,$xml) {
function diaspora_reshare($importer,$xml,$msg) {
logger('diaspora_reshare: init: ' . print_r($xml,true));
@ -779,6 +851,11 @@ function diaspora_reshare($importer,$xml) {
$diaspora_handle = notags(unxmlify($xml->diaspora_handle));
if($diaspora_handle != $msg['author']) {
logger('diaspora_post: Potential forgery. Message handle is not the same as envelope sender.');
return 202;
}
$contact = diaspora_get_contact_by_handle($importer['uid'],$diaspora_handle);
if(! $contact)
return;
@ -844,7 +921,7 @@ function diaspora_reshare($importer,$xml) {
else
$details = $orig_author;
$prefix = '&#x2672; ' . $details . "\n";
$prefix = html_entity_decode("&#x2672; ", ENT_QUOTES, 'UTF-8') . $details . "\n";
// allocate a guid on our system - we aren't fixing any collisions.
@ -924,13 +1001,18 @@ function diaspora_reshare($importer,$xml) {
}
function diaspora_asphoto($importer,$xml) {
function diaspora_asphoto($importer,$xml,$msg) {
logger('diaspora_asphoto called');
$a = get_app();
$guid = notags(unxmlify($xml->guid));
$diaspora_handle = notags(unxmlify($xml->diaspora_handle));
if($diaspora_handle != $msg['author']) {
logger('diaspora_post: Potential forgery. Message handle is not the same as envelope sender.');
return 202;
}
$contact = diaspora_get_contact_by_handle($importer['uid'],$diaspora_handle);
if(! $contact)
return;
@ -1154,6 +1236,7 @@ function diaspora_comment($importer,$xml,$msg) {
$datarray['uid'] = $importer['uid'];
$datarray['contact-id'] = $contact['id'];
$datarray['type'] = 'remote-comment';
$datarray['wall'] = $parent_item['wall'];
$datarray['gravity'] = GRAVITY_COMMENT;
$datarray['guid'] = $guid;
@ -1190,7 +1273,7 @@ function diaspora_comment($importer,$xml,$msg) {
if(($parent_item['origin']) && (! $parent_author_signature)) {
q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
intval($message_id),
dbesc($author_signed_data),
dbesc($signed_data),
dbesc(base64_encode($author_signature)),
dbesc($diaspora_handle)
);
@ -1591,8 +1674,8 @@ function diaspora_like($importer,$xml,$msg) {
// likes on comments not supported here and likes on photos not supported by Diaspora
if($target_type !== 'Post')
return;
// if($target_type !== 'Post')
// return;
$contact = diaspora_get_contact_by_handle($importer['uid'],$msg['author']);
if(! $contact) {
@ -1773,7 +1856,7 @@ EOT;
if(! $parent_author_signature) {
q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
intval($message_id),
dbesc($author_signed_data),
dbesc($signed_data),
dbesc(base64_encode($author_signature)),
dbesc($diaspora_handle)
);
@ -1923,11 +2006,17 @@ function diaspora_signed_retraction($importer,$xml,$msg) {
// NOTREACHED
}
function diaspora_profile($importer,$xml) {
function diaspora_profile($importer,$xml,$msg) {
$a = get_app();
$diaspora_handle = notags(unxmlify($xml->diaspora_handle));
if($diaspora_handle != $msg['author']) {
logger('diaspora_post: Potential forgery. Message handle is not the same as envelope sender.');
return 202;
}
$contact = diaspora_get_contact_by_handle($importer['uid'],$diaspora_handle);
if(! $contact)
return;
@ -2165,22 +2254,30 @@ function diaspora_send_followup($item,$owner,$contact,$public_batch = false) {
$myaddr = $owner['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3);
// $theiraddr = $contact['addr'];
// The first item in the `item` table with the parent id is the parent. However, MySQL doesn't always
// return the items ordered by `item`.`id`, in which case the wrong item is chosen as the parent.
// The only item with `parent` and `id` as the parent id is the parent item.
$p = q("select guid from item where parent = %d and id = %d limit 1",
intval($item['parent']),
intval($item['parent'])
);
if($item['thr-parent']) {
$p = q("select guid, type, uri, `parent-uri` from item where uri = '%s' limit 1",
dbesc($item['thr-parent'])
);
}
else {
// The first item in the `item` table with the parent id is the parent. However, MySQL doesn't always
// return the items ordered by `item`.`id`, in which case the wrong item is chosen as the parent.
// The only item with `parent` and `id` as the parent id is the parent item.
$p = q("select guid, type, uri, `parent-uri` from item where parent = %d and id = %d limit 1",
intval($item['parent']),
intval($item['parent'])
);
}
if(count($p))
$parent_guid = $p[0]['guid'];
$parent = $p[0];
else
return;
if($item['verb'] === ACTIVITY_LIKE) {
$tpl = get_markup_template('diaspora_like.tpl');
$like = true;
$target_type = 'Post';
$target_type = ( $parent['uri'] === $parent['parent-uri'] ? 'Post' : 'Comment');
// $target_type = (strpos($parent['type'], 'comment') ? 'Comment' : 'Post');
// $positive = (($item['deleted']) ? 'false' : 'true');
$positive = 'true';
@ -2197,15 +2294,15 @@ function diaspora_send_followup($item,$owner,$contact,$public_batch = false) {
// sign it
if($like)
$signed_text = $item['guid'] . ';' . $target_type . ';' . $parent_guid . ';' . $positive . ';' . $myaddr;
$signed_text = $item['guid'] . ';' . $target_type . ';' . $parent['guid'] . ';' . $positive . ';' . $myaddr;
else
$signed_text = $item['guid'] . ';' . $parent_guid . ';' . $text . ';' . $myaddr;
$signed_text = $item['guid'] . ';' . $parent['guid'] . ';' . $text . ';' . $myaddr;
$authorsig = base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256'));
$msg = replace_macros($tpl,array(
'$guid' => xmlify($item['guid']),
'$parent_guid' => xmlify($parent_guid),
'$parent_guid' => xmlify($parent['guid']),
'$target_type' =>xmlify($target_type),
'$authorsig' => xmlify($authorsig),
'$body' => xmlify($text),
@ -2233,15 +2330,22 @@ function diaspora_send_relay($item,$owner,$contact,$public_batch = false) {
$text = html_entity_decode(bb2diaspora($body));
// The first item in the `item` table with the parent id is the parent. However, MySQL doesn't always
// return the items ordered by `item`.`id`, in which case the wrong item is chosen as the parent.
// The only item with `parent` and `id` as the parent id is the parent item.
$p = q("select guid from item where parent = %d and id = %d limit 1",
intval($item['parent']),
intval($item['parent'])
);
if($item['thr-parent']) {
$p = q("select guid, type, uri, `parent-uri` from item where uri = '%s' limit 1",
dbesc($item['thr-parent'])
);
}
else {
// The first item in the `item` table with the parent id is the parent. However, MySQL doesn't always
// return the items ordered by `item`.`id`, in which case the wrong item is chosen as the parent.
// The only item with `parent` and `id` as the parent id is the parent item.
$p = q("select guid, type, uri, `parent-uri` from item where parent = %d and id = %d limit 1",
intval($item['parent']),
intval($item['parent'])
);
}
if(count($p))
$parent_guid = $p[0]['guid'];
$parent = $p[0];
else
return;
@ -2259,7 +2363,8 @@ function diaspora_send_relay($item,$owner,$contact,$public_batch = false) {
elseif($item['verb'] === ACTIVITY_LIKE) {
$like = true;
$target_type = 'Post';
$target_type = ( $parent['uri'] === $parent['parent-uri'] ? 'Post' : 'Comment');
// $target_type = (strpos($parent['type'], 'comment') ? 'Comment' : 'Post');
// $positive = (($item['deleted']) ? 'false' : 'true');
$positive = 'true';
@ -2294,9 +2399,9 @@ function diaspora_send_relay($item,$owner,$contact,$public_batch = false) {
if($relay_retract)
$sender_signed_text = $item['guid'] . ';' . $target_type;
elseif($like)
$sender_signed_text = $item['guid'] . ';' . $target_type . ';' . $parent_guid . ';' . $positive . ';' . $handle;
$sender_signed_text = $item['guid'] . ';' . $target_type . ';' . $parent['guid'] . ';' . $positive . ';' . $handle;
else
$sender_signed_text = $item['guid'] . ';' . $parent_guid . ';' . $text . ';' . $handle;
$sender_signed_text = $item['guid'] . ';' . $parent['guid'] . ';' . $text . ';' . $handle;
// Sign the relayable with the top-level owner's signature
//
@ -2313,7 +2418,7 @@ function diaspora_send_relay($item,$owner,$contact,$public_batch = false) {
$msg = replace_macros($tpl,array(
'$guid' => xmlify($item['guid']),
'$parent_guid' => xmlify($parent_guid),
'$parent_guid' => xmlify($parent['guid']),
'$target_type' =>xmlify($target_type),
'$authorsig' => xmlify($authorsig),
'$parentsig' => xmlify($parentauthorsig),
@ -2429,7 +2534,7 @@ function diaspora_send_mail($item,$owner,$contact) {
}
function diaspora_transmit($owner,$contact,$slap,$public_batch) {
function diaspora_transmit($owner,$contact,$slap,$public_batch,$queue_run=false) {
$enabled = intval(get_config('system','diaspora_enabled'));
if(! $enabled) {
@ -2446,7 +2551,7 @@ function diaspora_transmit($owner,$contact,$slap,$public_batch) {
logger('diaspora_transmit: ' . $logid . ' ' . $dest_url);
if(was_recently_delayed($contact['id'])) {
if( (! $queue_run) && (was_recently_delayed($contact['id'])) ) {
$return_code = 0;
}
else {

View file

@ -54,6 +54,20 @@ function notification($params) {
$parent_id = $params['parent'];
// Check to see if there was already a tag notify for this post.
// If so don't create a second notification
$p = null;
$p = q("select id from notify where type = %d and link = '%s' and uid = %d limit 1",
intval(NOTIFY_TAGSELF),
dbesc($params['link']),
intval($params['uid'])
);
if($p and count($p)) {
pop_lang();
return;
}
// if it's a post figure out who's post it is.
@ -110,9 +124,9 @@ function notification($params) {
$preamble = sprintf( t('%1$s posted to your profile wall at %2$s') , $params['source_name'], $sitename);
$epreamble = sprintf( t('%1$s posted to [url=%2s]your wall[/url]') ,
$epreamble = sprintf( t('%1$s posted to [url=%2$s]your wall[/url]') ,
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]',
$itemlink);
$params['link']);
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf( $sitelink, $siteurl );

View file

@ -124,7 +124,7 @@ function html2bbcode($message)
$node->nodeValue = str_replace("\n", "\r", $node->nodeValue);
$message = $doc->saveHTML();
$message = str_replace(array("\n<", ">\n", "\r", "\n", "\xC3\x82\xC2\xA0"), array("<", ">", "<br>", " ", ""), $message);
$message = str_replace(array("\n<", ">\n", "\r", "\n", "\xC3\x82\xC2\xA0"), array("<", ">", "<br />", " ", ""), $message);
$message = preg_replace('= [\s]*=i', " ", $message);
@$doc->loadHTML($message);

View file

@ -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,7 +280,99 @@ 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) {
@ -442,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
@ -757,6 +850,12 @@ function item_store($arr,$force_parent = false) {
if((strpos($arr['body'],'<') !== false) || (strpos($arr['body'],'>') !== false))
$arr['body'] = strip_tags($arr['body']);
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());
@ -825,7 +924,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']),
@ -2304,7 +2403,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()),
@ -2313,7 +2413,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()),
@ -3119,20 +3220,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);
@ -3150,14 +3264,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) {
@ -3172,15 +3278,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);
}
@ -3524,7 +3660,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');
@ -3583,7 +3721,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

75
include/lock.php Normal file
View file

@ -0,0 +1,75 @@
<?php
// Provide some ability to lock a PHP function so that multiple processes
// can't run the function concurrently
if(! function_exists('lock_function')) {
function lock_function($fn_name, $block = true, $wait_sec = 2, $timeout = 30) {
if( $wait_sec == 0 )
$wait_sec = 2; // don't let the user pick a value that's likely to crash the system
$got_lock = false;
$start = time();
do {
q("LOCK TABLE locks WRITE");
$r = q("SELECT locked FROM locks WHERE name = '%s' LIMIT 1",
dbesc($fn_name)
);
if((count($r)) && (! $r[0]['locked'])) {
q("UPDATE locks SET locked = 1 WHERE name = '%s' LIMIT 1",
dbesc($fn_name)
);
$got_lock = true;
}
elseif(! $r) { // the Boolean value for count($r) should be equivalent to the Boolean value of $r
q("INSERT INTO locks ( name, locked ) VALUES ( '%s', 1 )",
dbesc($fn_name)
);
$got_lock = true;
}
q("UNLOCK TABLES");
if(($block) && (! $got_lock))
sleep($wait_sec);
} while(($block) && (! $got_lock) && ((time() - $start) < $timeout));
logger('lock_function: function ' . $fn_name . ' with blocking = ' . $block . ' got_lock = ' . $got_lock . ' time = ' . (time() - $start), LOGGER_DEBUG);
return $got_lock;
}}
if(! function_exists('block_on_function_lock')) {
function block_on_function_lock($fn_name, $wait_sec = 2, $timeout = 30) {
if( $wait_sec == 0 )
$wait_sec = 2; // don't let the user pick a value that's likely to crash the system
$start = time();
do {
$r = q("SELECT locked FROM locks WHERE name = '%s' LIMIT 1",
dbesc($fn_name)
);
if(count($r) && $r[0]['locked'])
sleep($wait_sec);
} while(count($r) && $r[0]['locked'] && ((time() - $start) < $timeout));
return;
}}
if(! function_exists('unlock_function')) {
function unlock_function($fn_name) {
$r = q("UPDATE locks SET locked = 0 WHERE name = '%s' LIMIT 1",
dbesc($fn_name)
);
logger('unlock_function: released lock for function ' . $fn_name, LOGGER_DEBUG);
return;
}}

View file

@ -162,6 +162,7 @@ function nav(&$a) {
$tpl = get_markup_template('nav.tpl');
$a->page['nav'] .= replace_macros($tpl, array(
'$baseurl' => $a->get_baseurl(),
'$langselector' => lang_selector(),
'$sitelocation' => $sitelocation,
'$nav' => $nav,

View file

@ -605,6 +605,9 @@ function validate_url(&$url) {
if(! function_exists('validate_email')) {
function validate_email($addr) {
if(get_config('system','disable_email_validation'))
return true;
if(! strpos($addr,'@'))
return false;
$h = substr($addr,strpos($addr,'@') + 1);

View file

@ -161,7 +161,7 @@ function queue_run($argv, $argc){
case NETWORK_DIASPORA:
if($contact['notify']) {
logger('queue: diaspora_delivery: item ' . $q_item['id'] . ' for ' . $contact['name']);
$deliver_status = diaspora_transmit($owner,$contact,$data,$public);
$deliver_status = diaspora_transmit($owner,$contact,$data,$public,true);
if($deliver_status == (-1))
update_queue_time($q_item['id']);

0
include/security.php Executable file → Normal file
View file

View file

@ -656,6 +656,10 @@ function search($s,$id='search-box',$url='/search',$save = false) {
if(! function_exists('valid_email')) {
function valid_email($x){
if(get_config('system','disable_email_validation'))
return true;
if(preg_match('/^[_a-zA-Z0-9\-\+]+(\.[_a-zA-Z0-9\-\+]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)+$/',$x))
return true;
return false;
@ -1533,7 +1537,6 @@ function undo_post_tagging($s) {
function fix_mce_lf($s) {
$s = str_replace("\r\n","\n",$s);
$s = str_replace("\n\n","\n",$s);
return $s;
}

View file

@ -99,11 +99,11 @@ function create_user($arr) {
if(! allowed_email($email))
$result['message'] .= t('Your email domain is not among those allowed on this site.') . EOL;
$result['message'] .= t('Your email domain is not among those allowed on this site.') . EOL;
if((! valid_email($email)) || (! validate_email($email)))
$result['message'] .= t('Not a valid email address.') . EOL;
// Disallow somebody creating an account using openid that uses the admin email address,
// since openid bypasses email verification. We'll allow it if there is not yet an admin account.