diff options
author | mrjive <mrjive@mrjive.it> | 2015-11-11 16:51:48 +0100 |
---|---|---|
committer | mrjive <mrjive@mrjive.it> | 2015-11-11 16:51:48 +0100 |
commit | 53a796afcc0cff6f9e3f51457df4506a43db1945 (patch) | |
tree | a2366c48e0dae047b052283cc44284224369c8cd /include | |
parent | a4c3058f845a1c38d06b2201a10700c5f878366d (diff) | |
parent | bc7c0ed844711e81c4bc642e3024849195a48421 (diff) | |
download | volse-hubzilla-53a796afcc0cff6f9e3f51457df4506a43db1945.tar.gz volse-hubzilla-53a796afcc0cff6f9e3f51457df4506a43db1945.tar.bz2 volse-hubzilla-53a796afcc0cff6f9e3f51457df4506a43db1945.zip |
Merge pull request #8 from redmatrix/master
get fresh code from HZ base
Diffstat (limited to 'include')
-rw-r--r-- | include/Contact.php | 5 | ||||
-rw-r--r-- | include/ItemObject.php | 1 | ||||
-rw-r--r-- | include/RedDAV/RedDirectory.php | 23 | ||||
-rw-r--r-- | include/RedDAV/RedFile.php | 12 | ||||
-rw-r--r-- | include/acl_selectors.php | 2 | ||||
-rw-r--r-- | include/api.php | 159 | ||||
-rw-r--r-- | include/api_auth.php | 95 | ||||
-rw-r--r-- | include/attach.php | 27 | ||||
-rw-r--r-- | include/auth.php | 1 | ||||
-rw-r--r-- | include/bb2diaspora.php | 16 | ||||
-rw-r--r-- | include/bbcode.php | 12 | ||||
-rw-r--r-- | include/conversation.php | 11 | ||||
-rw-r--r-- | include/dir_fns.php | 18 | ||||
-rw-r--r-- | include/identity.php | 13 | ||||
-rwxr-xr-x | include/items.php | 16 | ||||
-rw-r--r-- | include/network.php | 22 | ||||
-rw-r--r-- | include/notifier.php | 2 | ||||
-rw-r--r-- | include/photo/photo_driver.php | 22 | ||||
-rw-r--r-- | include/photo/photo_gd.php | 2 | ||||
-rw-r--r-- | include/photos.php | 25 | ||||
-rw-r--r-- | include/text.php | 23 | ||||
-rw-r--r-- | include/widgets.php | 2 | ||||
-rw-r--r-- | include/zot.php | 56 |
23 files changed, 379 insertions, 186 deletions
diff --git a/include/Contact.php b/include/Contact.php index 8e22c608e..3bd5f9936 100644 --- a/include/Contact.php +++ b/include/Contact.php @@ -292,7 +292,8 @@ function channel_remove($channel_id, $local = true, $unset_session=true) { intval($channel_id) ); - + logger('deleting hublocs',LOGGER_DEBUG); + $r = q("update hubloc set hubloc_deleted = 1 where hubloc_hash = '%s'", dbesc($channel['channel_hash']) ); @@ -349,6 +350,8 @@ function channel_remove($channel_id, $local = true, $unset_session=true) { } + logger('deleting hublocs',LOGGER_DEBUG); + $r = q("update hubloc set hubloc_deleted = 1 where hubloc_hash = '%s' and hubloc_url = '%s' ", dbesc($channel['channel_hash']), dbesc(z_root()) diff --git a/include/ItemObject.php b/include/ItemObject.php index c5c2cb2e6..34500efb9 100644 --- a/include/ItemObject.php +++ b/include/ItemObject.php @@ -263,6 +263,7 @@ class Item extends BaseObject { localize_item($item); + $body = prepare_body($item,true); // $viewthread (below) is only valid in list mode. If this is a channel page, build the thread viewing link diff --git a/include/RedDAV/RedDirectory.php b/include/RedDAV/RedDirectory.php index 507fde46f..8d8af5bd3 100644 --- a/include/RedDAV/RedDirectory.php +++ b/include/RedDAV/RedDirectory.php @@ -251,7 +251,7 @@ class RedDirectory extends DAV\Node implements DAV\ICollection, DAV\IQuota { intval($filesize), intval(0), intval($is_photo), - dbesc($this->os_path . '/' . $hash), + dbesc($f), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc($allow_cid), @@ -363,6 +363,27 @@ class RedDirectory extends DAV\Node implements DAV\ICollection, DAV\IQuota { } /** + * @brief delete directory + */ + + public function delete() { + logger('delete file ' . basename($this->red_path), LOGGER_DEBUG); + + if ((! $this->auth->owner_id) || (! perm_is_allowed($this->auth->owner_id, $this->auth->observer, 'write_storage'))) { + throw new DAV\Exception\Forbidden('Permission denied.'); + } + + if ($this->auth->owner_id !== $this->auth->channel_id) { + if (($this->auth->observer !== $this->data['creator']) || intval($this->data['is_dir'])) { + throw new DAV\Exception\Forbidden('Permission denied.'); + } + } + + attach_delete($this->auth->owner_id, $this->folder_hash); + } + + + /** * @brief Checks if a child exists. * * @param string $name diff --git a/include/RedDAV/RedFile.php b/include/RedDAV/RedFile.php index ec6871a69..3283a6e88 100644 --- a/include/RedDAV/RedFile.php +++ b/include/RedDAV/RedFile.php @@ -126,7 +126,11 @@ class RedFile extends DAV\Node implements DAV\IFile { } } $fname = dbunescbin($d[0]['data']); - $f = 'store/' . $this->auth->owner_nick . '/' . (($fname) ? $fname : ''); + if(strpos($fname,'store') === false) + $f = 'store/' . $this->auth->owner_nick . '/' . $fname ; + else + $f = $fname; + // @todo check return value and set $size directly @file_put_contents($f, $data); $size = @filesize($f); @@ -226,7 +230,11 @@ class RedFile extends DAV\Node implements DAV\IFile { } if (intval($r[0]['os_storage'])) { - $f = 'store/' . $this->auth->owner_nick . '/' . (($this->os_path) ? $this->os_path . '/' : '') . dbunescbin($r[0]['data']); + $x = dbunescbin($r[0]['data']); + if(strpos($x,'store') === false) + $f = 'store/' . $this->auth->owner_nick . '/' . (($this->os_path) ? $this->os_path . '/' : '') . $x; + else + $f = $x; return fopen($f, 'rb'); } return dbunescbin($r[0]['data']); diff --git a/include/acl_selectors.php b/include/acl_selectors.php index cb2266473..4d44ec12e 100644 --- a/include/acl_selectors.php +++ b/include/acl_selectors.php @@ -231,6 +231,7 @@ function populate_acl($defaults = null,$show_jotnets = true) { $jotnets = ''; if($show_jotnets) { +logger('jot_networks'); call_hooks('jot_networks', $jotnets); } @@ -243,6 +244,7 @@ function populate_acl($defaults = null,$show_jotnets = true) { '$allowgid' => json_encode($allow_gid), '$denycid' => json_encode($deny_cid), '$denygid' => json_encode($deny_gid), + '$jnetModalTitle' => t('Other networks and post services'), '$jotnets' => $jotnets, '$aclModalTitle' => t('Permissions'), '$aclModalDismiss' => t('Close') diff --git a/include/api.php b/include/api.php index 16dbb569b..24176884c 100644 --- a/include/api.php +++ b/include/api.php @@ -66,95 +66,6 @@ require_once('include/attach.php'); 'auth'=>$auth); } - /** - * Simple HTTP Login - */ - - function api_login(&$a){ - // login with oauth - try { - $oauth = new FKOAuth1(); - $req = OAuthRequest::from_request(); - list($consumer,$token) = $oauth->verify_request($req); -// list($consumer,$token) = $oauth->verify_request(OAuthRequest::from_request()); - if (!is_null($token)){ - $oauth->loginUser($token->uid); - - $a->set_oauth_key($consumer->key); - - call_hooks('logged_in', $a->user); - return; - } - echo __file__.__line__.__function__."<pre>"; -// var_dump($consumer, $token); - die(); - } - catch(Exception $e) { - logger(__file__.__line__.__function__."\n".$e); - } - - - // workaround for HTTP-auth in CGI mode - if(x($_SERVER,'REDIRECT_REMOTE_USER')) { - $userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"],6)) ; - if(strlen($userpass)) { - list($name, $password) = explode(':', $userpass); - $_SERVER['PHP_AUTH_USER'] = $name; - $_SERVER['PHP_AUTH_PW'] = $password; - } - } - - if(x($_SERVER,'HTTP_AUTHORIZATION')) { - $userpass = base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"],6)) ; - if(strlen($userpass)) { - list($name, $password) = explode(':', $userpass); - $_SERVER['PHP_AUTH_USER'] = $name; - $_SERVER['PHP_AUTH_PW'] = $password; - } - } - - - if (!isset($_SERVER['PHP_AUTH_USER'])) { - logger('API_login: ' . print_r($_SERVER,true), LOGGER_DEBUG); - header('WWW-Authenticate: Basic realm="Red"'); - header('HTTP/1.0 401 Unauthorized'); - die('This api requires login'); - } - - // process normal login request - require_once('include/auth.php'); - $channel_login = 0; - $record = account_verify_password($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW']); - if(! $record) { - $r = q("select * from channel where channel_address = '%s' limit 1", - dbesc($_SERVER['PHP_AUTH_USER']) - ); - if ($r) { - $x = q("select * from account where account_id = %d limit 1", - intval($r[0]['channel_account_id']) - ); - if ($x) { - $record = account_verify_password($x[0]['account_email'],$_SERVER['PHP_AUTH_PW']); - if($record) - $channel_login = $r[0]['channel_id']; - } - } - if(! $record) { - logger('API_login failure: ' . print_r($_SERVER,true), LOGGER_DEBUG); - header('WWW-Authenticate: Basic realm="Red"'); - header('HTTP/1.0 401 Unauthorized'); - die('This api requires login'); - } - } - - require_once('include/security.php'); - authenticate_success($record); - - if($channel_login) - change_channel($channel_login); - - $_SESSION['allow_api'] = true; - } /************************** * MAIN API ENTRY POINT * @@ -627,6 +538,71 @@ require_once('include/attach.php'); api_register_func('api/red/files','api_attach_list', true); + + + + function api_file_meta(&$a,$type) { + if (api_user()===false) return false; + if(! $_REQUEST['file_id']) return false; + $r = q("select * from attach where uid = %d and hash = '%s' limit 1", + intval(api_user()), + dbesc($_REQUEST['file_id']) + ); + if($r) { + unset($r[0]['data']); + $ret = array('attach' => $r[0]); + json_return_and_die($ret); + } + killme(); + } + + api_register_func('api/red/filemeta', 'api_file_meta', true); + + + function api_file_data(&$a,$type) { + if (api_user()===false) return false; + if(! $_REQUEST['file_id']) return false; + $start = (($_REQUEST['start']) ? intval($_REQUEST['start']) : 0); + $length = (($_REQUEST['length']) ? intval($_REQUEST['length']) : 0); + + $r = q("select * from attach where uid = %d and hash = '%s' limit 1", + intval(api_user()), + dbesc($_REQUEST['file_id']) + ); + if($r) { + $ptr = $r[0]; + if($length === 0) + $length = intval($ptr['filesize']); + + if($ptr['is_dir']) + $ptr['data'] = ''; + elseif(! intval($r[0]['os_storage'])) { + $ptr['start'] = $start; + $x = substr(dbunescbin($ptr['data'],$start,$length)); + $ptr['length'] = strlen($x); + $ptr['data'] = base64_encode($x); + } + else { + $fp = fopen(dbunescbin($ptr['data']),'r'); + if($fp) { + $seek = fseek($fp,$start,SEEK_SET); + $x = fread($fp,$length); + $ptr['start'] = $start; + $ptr['length'] = strlen($x); + $ptr['data'] = base64_encode($x); + } + } + + $ret = array('attach' => $ptr); + json_return_and_die($ret); + } + killme(); + } + + api_register_func('api/red/filedata', 'api_file_data', true); + + + function api_file_detail(&$a,$type) { if (api_user()===false) return false; if(! $_REQUEST['file_id']) return false; @@ -826,6 +802,7 @@ require_once('include/attach.php'); require_once('include/html2bbcode.php'); $txt = requestdata('htmlstatus'); + if((strpos($txt,'<') !== false) || (strpos($txt,'>') !== false)) { $txt = html2bb_video($txt); @@ -837,9 +814,10 @@ require_once('include/attach.php'); $purifier = new HTMLPurifier($config); $txt = $purifier->purify($txt); - $_REQUEST['body'] = html2bbcode($txt); } + $_REQUEST['body'] = html2bbcode($txt); + } else $_REQUEST['body'] = requestdata('status'); @@ -2348,6 +2326,7 @@ logger('Req: ' . var_export($req,true)); api_register_func('api/oauth/request_token', 'api_oauth_request_token', false); api_register_func('api/oauth/access_token', 'api_oauth_access_token', false); + /* Not implemented by now: statuses/retweets_of_me diff --git a/include/api_auth.php b/include/api_auth.php new file mode 100644 index 000000000..ee9db3f55 --- /dev/null +++ b/include/api_auth.php @@ -0,0 +1,95 @@ +<?php /** @file */ + +require_once("oauth.php"); + + +/** + * Simple HTTP Login + */ + +function api_login(&$a){ + // login with oauth + try { + $oauth = new FKOAuth1(); + $req = OAuthRequest::from_request(); + + list($consumer,$token) = $oauth->verify_request($req); + + if (!is_null($token)){ + $oauth->loginUser($token->uid); + + $a->set_oauth_key($consumer->key); + + call_hooks('logged_in', $a->user); + return; + } + echo __file__.__line__.__function__."<pre>"; +// var_dump($consumer, $token); + die(); + } + catch(Exception $e) { + logger(__file__.__line__.__function__."\n".$e); + } + + + // workaround for HTTP-auth in CGI mode + if(x($_SERVER,'REDIRECT_REMOTE_USER')) { + $userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"],6)) ; + if(strlen($userpass)) { + list($name, $password) = explode(':', $userpass); + $_SERVER['PHP_AUTH_USER'] = $name; + $_SERVER['PHP_AUTH_PW'] = $password; + } + } + + if(x($_SERVER,'HTTP_AUTHORIZATION')) { + $userpass = base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"],6)) ; + if(strlen($userpass)) { + list($name, $password) = explode(':', $userpass); + $_SERVER['PHP_AUTH_USER'] = $name; + $_SERVER['PHP_AUTH_PW'] = $password; + } + } + + + if (!isset($_SERVER['PHP_AUTH_USER'])) { + logger('API_login: ' . print_r($_SERVER,true), LOGGER_DEBUG); + header('WWW-Authenticate: Basic realm="Red"'); + header('HTTP/1.0 401 Unauthorized'); + die('This api requires login'); + } + + // process normal login request + require_once('include/auth.php'); + $channel_login = 0; + $record = account_verify_password($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW']); + if(! $record) { + $r = q("select * from channel where channel_address = '%s' limit 1", + dbesc($_SERVER['PHP_AUTH_USER']) + ); + if ($r) { + $x = q("select * from account where account_id = %d limit 1", + intval($r[0]['channel_account_id']) + ); + if ($x) { + $record = account_verify_password($x[0]['account_email'],$_SERVER['PHP_AUTH_PW']); + if($record) + $channel_login = $r[0]['channel_id']; + } + } + if(! $record) { + logger('API_login failure: ' . print_r($_SERVER,true), LOGGER_DEBUG); + header('WWW-Authenticate: Basic realm="Red"'); + header('HTTP/1.0 401 Unauthorized'); + die('This api requires login'); + } + } + + require_once('include/security.php'); + authenticate_success($record); + + if($channel_login) + change_channel($channel_login); + + $_SESSION['allow_api'] = true; +} diff --git a/include/attach.php b/include/attach.php index f5d2c69b6..36b971712 100644 --- a/include/attach.php +++ b/include/attach.php @@ -64,7 +64,10 @@ function z_mime_content_type($filename) { 'wav' => 'audio/wav', 'qt' => 'video/quicktime', 'mov' => 'video/quicktime', - 'ogg' => 'application/ogg', + 'ogg' => 'audio/ogg', + 'ogv' => 'video/ogg', + 'ogx' => 'application/ogg', + 'flac' => 'audio/flac', 'opus' => 'audio/ogg', 'webm' => 'video/webm', // 'webm' => 'audio/webm', @@ -105,9 +108,9 @@ function z_mime_content_type($filename) { 'oth' => 'application/vnd.oasis.opendocument.text-web' ); - $dot = strpos($filename, '.'); - if ($dot !== false) { - $ext = strtolower(substr($filename, $dot + 1)); + $last_dot = strrpos($filename, '.'); + if ($last_dot !== false) { + $ext = strtolower(substr($filename, $last_dot + 1)); if (array_key_exists($ext, $mime_types)) { return $mime_types[$ext]; } @@ -719,7 +722,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { intval($filesize), intval(1), intval($is_photo), - dbesc($os_relpath), + dbesc($os_basepath . $os_relpath), dbesc($created), intval($existing_id), intval($channel_id) @@ -739,7 +742,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { intval($x[0]['revision'] + 1), intval(1), intval($is_photo), - dbesc($os_relpath), + dbesc($os_basepath . $os_relpath), dbesc($created), dbesc($created), dbesc($x[0]['allow_cid']), @@ -780,7 +783,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { intval(0), intval(1), intval($is_photo), - dbesc($os_relpath), + dbesc($os_basepath . $os_relpath), dbesc($created), dbesc($created), dbesc(($arr && array_key_exists('allow_cid',$arr)) ? $arr['allow_cid'] : $str_contact_allow), @@ -1267,9 +1270,13 @@ function attach_delete($channel_id, $resource, $is_photo = 0) { ); if($y) { - $f = 'store/' . $channel_address . '/' . $y[0]['data']; - if(is_dir($y[0]['data'])) - @rmdir($y[0]['data']); + if(strpos($y[0]['data'],'store') === false) + $f = 'store/' . $channel_address . '/' . $y[0]['data']; + else + $f = $y[0]['data']; + + if(is_dir($f)) + @rmdir($f); elseif(file_exists($f)) unlink($f); } diff --git a/include/auth.php b/include/auth.php index 643894e32..4f0c4c928 100644 --- a/include/auth.php +++ b/include/auth.php @@ -9,6 +9,7 @@ * Also provides a function for OpenID identiy matching. */ +require_once('include/api_auth.php'); require_once('include/security.php'); /** diff --git a/include/bb2diaspora.php b/include/bb2diaspora.php index d10ed57eb..1be7caa19 100644 --- a/include/bb2diaspora.php +++ b/include/bb2diaspora.php @@ -162,10 +162,10 @@ function diaspora2bb($s, $use_zrl = false) { } //$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 = 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); + $s = bb_tag_preg_replace("/\[url\=?(.*?)\]https?:\/\/www.youtube.com\/watch\?v\=(.*?)\[\/url\]/ism",'[embed]https://www.youtube.com/watch?v=$2[/embed]','url',$s); + $s = bb_tag_preg_replace("/\[url\=https?:\/\/www.youtube.com\/watch\?v\=(.*?)\].*?\[\/url\]/ism",'[embed]https://www.youtube.com/watch?v=$1[/embed]','url',$s); + $s = bb_tag_preg_replace("/\[url\=?(.*?)\]https?:\/ \/vimeo.com\/([0-9]+)(.*?)\[\/url\]/ism",'[embed]https://vimeo.com/$2[/embed]','url',$s); + $s = bb_tag_preg_replace("/\[url\=https?:\/\/vimeo.com\/([0-9]+)\](.*?)\[\/url\]/ism",'[embed]https://vimeo.com/$1[/embed]','url',$s); // remove duplicate adjacent code tags $s = preg_replace("/(\[code\])+(.*?)(\[\/code\])+/ism","[code]$2[/code]", $s); @@ -309,9 +309,8 @@ function bb2diaspora_itembody($item, $force_update = false) { $is_photo = (($item['obj_type'] == ACTIVITY_OBJ_PHOTO) ? true : false); if($is_photo) { $object = json_decode($item['object'],true); - if($object['link'][2]) { - $photo_bb = '[zrl=' . rawurldecode($object['id']) . ']' . '[zmg=' . $object['link'][2]['width'] . 'x' . $object['link'][2]['height'] . ']' . rawurldecode($object['link'][2]['href']) . '[/zmg]' . '[/zrl]'; - $item['body'] = (($item['body']) ? $photo_bb . $item['body'] : $photo_bb); + if($object['bbcode']) { + $item['body'] = (($item['body']) ? $object['bbcode'] . "\r\n" . $item['body'] : $object['bbcode']); } } @@ -441,6 +440,9 @@ function bb2diaspora($Text,$preserve_nl = false, $fordiaspora = true) { // So take off the angle brackets of any such URL $Text = preg_replace("/<http(.*?)>/is", "http$1", $Text); + // Remove empty zrl links + $Text = preg_replace("/\[zrl\=\].*?\[\/zrl\]/is", "", $Text); + // Remove all unconverted tags $Text = strip_tags($Text); diff --git a/include/bbcode.php b/include/bbcode.php index 1092c08a3..05802aa57 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -28,7 +28,7 @@ function tryzrlaudio($match) { if($zrl) $link = zid($link); - return '<audio src="' . str_replace(' ','%20',$link) . '" controls="controls"><a href="' . str_replace(' ','%20',$link) . '">' . $link . '</a></audio>'; + return '<audio src="' . str_replace(' ','%20',$link) . '" controls="controls" preload="none"><a href="' . str_replace(' ','%20',$link) . '">' . $link . '</a></audio>'; } function tryzrlvideo($match) { @@ -37,7 +37,7 @@ function tryzrlvideo($match) { if($zrl) $link = zid($link); - return '<video controls="controls" src="' . str_replace(' ','%20',$link) . '" style="width:100%; max-width:' . get_app()->videowidth . 'px"><a href="' . str_replace(' ','%20',$link) . '">' . $link . '</a></video>'; + return '<video controls="controls" preload="none" src="' . str_replace(' ','%20',$link) . '" style="width:100%; max-width:' . get_app()->videowidth . 'px"><a href="' . str_replace(' ','%20',$link) . '">' . $link . '</a></video>'; } // [noparse][i]italic[/i][/noparse] turns into @@ -599,6 +599,7 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false) $Text = preg_replace("/\[mail\=([$MAILSearchString]*)\](.*?)\[\/mail\]/", '<a href="mailto:$1" target="_newwin" >$2</a>', $Text); } + // leave open the posibility of [map=something] // this is replaced in prepare_body() which has knowledge of the item location @@ -983,7 +984,12 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false) $Text = preg_replace('/\[\&\;([#a-z0-9]+)\;\]/', '&$1;', $Text); // fix any escaped ampersands that may have been converted into links - $Text = preg_replace("/\<(.*?)(src|href)=(.*?)\&\;(.*?)\>/ism", '<$1$2=$3&$4>', $Text); + + if(strpos($Text,'&') !== false) + $Text = preg_replace("/\<(.*?)(src|href)=(.*?)\&\;(.*?)\>/ism", '<$1$2=$3&$4>', $Text); + + // This is subtle - it's an XSS filter. It only accepts links with a protocol scheme and where + // the scheme begins with z (zhttp), h (http(s)), f (ftp), m (mailto), and named anchors. $Text = preg_replace("/\<(.*?)(src|href)=\"[^zhfm#](.*?)\>/ism", '<$1$2="">', $Text); diff --git a/include/conversation.php b/include/conversation.php index c2d9641ba..c278dcf12 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -681,7 +681,6 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $ $body = prepare_body($item,true); - $is_photo = ((($item['resource_type'] == 'photo') && (feature_enabled($profile_owner,'large_photos'))) ? true : false); $has_tags = (($body['tags'] || $body['categories'] || $body['mentions'] || $body['attachments'] || $body['folders']) ? true : false); $tmp_item = array( @@ -698,6 +697,7 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $ 'thumb' => $profile_avatar, 'title' => $item['title'], 'body' => $body['html'], + 'photo' => $body['photo'], 'tags' => $body['tags'], 'categories' => $body['categories'], 'mentions' => $body['mentions'], @@ -738,7 +738,6 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $ 'previewing' => $previewing, 'wait' => t('Please wait'), 'thread_level' => 1, - 'is_photo' => $is_photo, 'has_tags' => $has_tags, ); @@ -918,6 +917,9 @@ function item_photo_menu($item){ if($item['parent'] == $item['id'] && $channel && ($channel_hash != $item['author_xchan'])) { $sub_link = 'javascript:dosubthread(' . $item['id'] . '); return false;'; } + if($channel) { + $unsub_link = 'javascript:dounsubthread(' . $item['id'] . '); return false;'; + } } $profile_link = chanlink_hash($item['author_xchan']); @@ -942,6 +944,7 @@ function item_photo_menu($item){ $menu = Array( t("View Source") => $vsrc_link, t("Follow Thread") => $sub_link, + t("Stop Following") => $unsub_link, t("View Status") => $status_link, t("View Profile") => $profile_link, t("View Photos") => $photos_link, @@ -1021,8 +1024,8 @@ function builtin_activity_puller($item, &$conv_responses) { if((activity_match($item['verb'], $verb)) && ($item['id'] != $item['parent'])) { $name = (($item['author']['xchan_name']) ? $item['author']['xchan_name'] : t('Unknown')); - $url = (($item['author']['xchan_url']) - ? '<a href="' . chanlink_url($item['author']['xchan_url']) . '">' . $name . '</a>' + $url = (($item['author']['xchan_url'] && $item['author']['xchan_photo_s']) + ? '<a href="' . chanlink_url($item['author']['xchan_url']) . '">' . '<img class="response-photo" src="' . zid($item['author']['xchan_photo_s']) . ' alt="' . urlencode($name) . '" /> ' . $name . '</a>' : '<a href="#" class="disabled">' . $name . '</a>' ); diff --git a/include/dir_fns.php b/include/dir_fns.php index ecc5f6d96..398f43d00 100644 --- a/include/dir_fns.php +++ b/include/dir_fns.php @@ -15,6 +15,19 @@ function find_upstream_directory($dirmode) { global $DIRECTORY_FALLBACK_SERVERS; $preferred = get_config('system','directory_server'); + + // Thwart attempts to use a private directory + + if(($preferred) && ($prefered != z_root())) { + $r = q("select * from site where site_url = '%s' limit 1", + dbesc($preferred) + ); + if(($r) && ($r[0]['site_flags'] & DIRECTORY_MODE_STADALONE)) { + $preferred = ''; + } + } + + if (! $preferred) { /* @@ -190,8 +203,9 @@ function sync_directories($dirmode) { intval($r[0]['site_valid']) ); - $r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and site_type = %d ", - intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY), + $r = q("select * from site where site_flags in (%d, %d) and site_url != '%s' and site_type = %d ", + intval(DIRECTORY_MODE_PRIMARY), + intval(DIRECTORY_MODE_SECONDARY), dbesc(z_root()), intval(SITE_TYPE_ZOT) ); diff --git a/include/identity.php b/include/identity.php index 0c4a9df45..21d919508 100644 --- a/include/identity.php +++ b/include/identity.php @@ -904,19 +904,6 @@ function profile_load(&$a, $nickname, $profile = '') { } /** - * @brief - * - * @param App &$a - * @param boolean $connect - */ -function profile_create_sidebar(&$a, $connect = true) { - - $block = (((get_config('system', 'block_public')) && (! local_channel()) && (! remote_channel())) ? true : false); - - $a->set_widget('profile', profile_sidebar($a->profile, $block, $connect)); -} - -/** * @brief Formats a profile for display in the sidebar. * * It is very difficult to templatise the HTML completely diff --git a/include/items.php b/include/items.php index 08be981e7..3e4805212 100755 --- a/include/items.php +++ b/include/items.php @@ -2837,6 +2837,8 @@ function store_diaspora_comment_sig($datarray, $channel, $parent_item, $post_id, function send_status_notifications($post_id,$item) { $notify = false; + $unfollowed = false; + $parent = 0; $r = q("select channel_hash from channel where channel_id = %d limit 1", @@ -2864,6 +2866,14 @@ function send_status_notifications($post_id,$item) { foreach($x as $xx) { if($xx['author_xchan'] === $r[0]['channel_hash']) { $notify = true; + + // check for an unfollow thread activity - we should probably decode the obj and check the id + // but it will be extremely rare for this to be wrong. + + if(($xx['verb'] === ACTIVITY_UNFOLLOW) + && ($xx['obj_type'] === ACTIVITY_OBJ_NOTE || $xx['obj_type'] === ACTIVITY_OBJ_PHOTO) + && ($xx['parent'] != $xx['id'])) + $unfollowed = true; } if($xx['id'] == $xx['parent']) { $parent = $xx['parent']; @@ -2871,6 +2881,9 @@ function send_status_notifications($post_id,$item) { } } + if($unfollowed) + return; + $link = get_app()->get_baseurl() . '/display/' . $item['mid']; $y = q("select id from notify where link = '%s' and uid = %d limit 1", @@ -3455,6 +3468,7 @@ function post_is_importable($item,$abook) { $text = prepare_text($item['body'],$item['mimetype']); $text = html2plain($text); + $lang = null; if((strpos($abook['abook_incl'],'lang=') !== false) || (strpos($abook['abook_excl'],'lang=') !== false)) { @@ -4792,7 +4806,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C if($arr['mid']) $sql_options .= " and parent_mid = '" . dbesc($arr['mid']) . "' "; - $sql_extra = " AND item.parent IN ( SELECT parent FROM item WHERE item_thread_top = 1 $sql_options ) "; + $sql_extra = " AND item.parent IN ( SELECT parent FROM item WHERE item_thread_top = 1 $sql_options $item_normal ) "; if($arr['since_id']) $sql_extra .= " and item.id > " . $since_id . " "; diff --git a/include/network.php b/include/network.php index c67c019ef..65599bd05 100644 --- a/include/network.php +++ b/include/network.php @@ -526,28 +526,6 @@ function allowed_email($email) { -function avatar_img($email) { - - $avatar = array(); - $a = get_app(); - - $avatar['size'] = 300; - $avatar['email'] = $email; - $avatar['url'] = ''; - $avatar['success'] = false; - - call_hooks('avatar_lookup', $avatar); - - if (! $avatar['success']) - $avatar['url'] = $a->get_baseurl() . '/' . get_default_profile_photo(); - - logger('Avatar: ' . $avatar['email'] . ' ' . $avatar['url'], LOGGER_DEBUG); - - return $avatar['url']; -} - - - function parse_xml_string($s,$strict = true) { if($strict) { if(! strstr($s,'<?xml')) diff --git a/include/notifier.php b/include/notifier.php index 0b29146c1..34a527e15 100644 --- a/include/notifier.php +++ b/include/notifier.php @@ -675,7 +675,7 @@ function notifier_run($argv, $argc){ dbesc(json_encode($encoded_item)) ); // only create delivery reports for normal undeleted items - if(array_key_exists('postopts',$target_item) && (! $target_item['item_deleted'])) { + if(is_array($target_item) && array_key_exists('postopts',$target_item) && (! $target_item['item_deleted'])) { q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_result, dreport_time, dreport_xchan, dreport_queue ) values ( '%s','%s','%s','%s','%s','%s','%s' ) ", dbesc($target_item['mid']), dbesc($hub['hubloc_host']), diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php index 32b9bd302..285cbc8fb 100644 --- a/include/photo/photo_driver.php +++ b/include/photo/photo_driver.php @@ -546,11 +546,18 @@ function guess_image_type($filename, $headers = '') { $ext = pathinfo($filename, PATHINFO_EXTENSION); $ph = photo_factory(''); $types = $ph->supportedTypes(); - $type = "image/jpeg"; foreach ($types as $m=>$e){ if ($ext==$e) $type = $m; } } + + if(is_null($type)) { + $size = getimagesize($filename); + $ph = photo_factory(''); + $types = $ph->supportedTypes(); + $type = ((array_key_exists($size['mime'], $types)) ? $size['mime'] : 'image/jpeg'); + } + } logger('Photo: guess_image_type: type='.$type, LOGGER_DEBUG); return $type; @@ -586,16 +593,12 @@ function import_xchan_photo($photo,$xchan,$thing = false) { if($photo) { $filename = basename($photo); - $type = guess_image_type($photo); - - if(! $type) - $type = 'image/jpeg'; - $result = z_fetch_url($photo,true); if($result['success']) { $img_str = $result['body']; + $type = guess_image_type($photo, $result['header']); $h = explode("\n",$result['header']); if($h) { @@ -731,6 +734,11 @@ function import_channel_photo($photo,$type,$aid,$uid) { $photo_failure = true; } - return(($photo_failure)? false : true); + //return(($photo_failure)? false : true); + + if($photo_failure) + return false; + else + return $hash; } diff --git a/include/photo/photo_gd.php b/include/photo/photo_gd.php index fa1f700e9..2ac7287e4 100644 --- a/include/photo/photo_gd.php +++ b/include/photo/photo_gd.php @@ -137,4 +137,4 @@ class photo_gd extends photo_driver { return $string; } -}
\ No newline at end of file +} diff --git a/include/photos.php b/include/photos.php index a8619c372..c7360a956 100644 --- a/include/photos.php +++ b/include/photos.php @@ -292,18 +292,19 @@ function photo_upload($channel, $observer, $args) { $tag = (($r2) ? '[zmg=' . $width . 'x' . $height . ']' : '[zmg]'); } + $body = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash . ']' + . $tag . z_root() . "/photo/{$photo_hash}-{$scale}." . $ph->getExt() . '[/zmg]' + . '[/zrl]'; + // Create item object $object = array( 'type' => ACTIVITY_OBJ_PHOTO, 'title' => $title, 'id' => rawurlencode(z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash), - 'link' => $link + 'link' => $link, + 'bbcode' => $body ); - $body = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash . ']' - . $tag . z_root() . "/photo/{$photo_hash}-{$scale}." . $ph->getExt() . '[/zmg]' - . '[/zrl]'; - // Create item container if($args['item']) { foreach($args['item'] as $i) { @@ -378,6 +379,20 @@ function photo_upload($channel, $observer, $args) { $arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $arr['mid']; $arr['body'] = (($object) ? $args['body'] : $body . "\r\n" . $args['body']); + + // this one is tricky because the item and the photo have the same permissions, those of the photo. + // Use the channel read_stream permissions to get the correct public_policy for the item and recalculate the + // private flag accordingly. This may cause subtle bugs due to custom permissions roles. We want to use + // public policy when federating items to other sites, but should probably ignore them when accessing the item + // in the photos pages - using the photos permissions instead. We need the public policy to keep the photo + // linked item from leaking into the feed when somebody has a channel with read_stream restrictions. + + $arr['public_policy'] = map_scope($channel['channel_r_stream'],true); + if($arr['public_policy']) + $arr['item_private'] = 1; + + + $result = item_store($arr); $item_id = $result['item_id']; diff --git a/include/text.php b/include/text.php index c30be77b8..edaa8dcd3 100644 --- a/include/text.php +++ b/include/text.php @@ -872,15 +872,17 @@ function searchbox($s,$id='search-box',$url='/search',$save = false) { )); } +function valid_email_regex($x){ + if(preg_match('/^[_a-zA-Z0-9\-\+]+(\.[_a-zA-Z0-9\-\+]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)+$/',$x)) + return true; + return false; +} 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; + return valid_email_regex($x); } /** @@ -912,8 +914,17 @@ function sslify($s) { if (strpos(z_root(),'https:') === false) return $s; + // By default we'll only sslify img tags because media files will probably choke. + // You can set sslify_everything if you want - but it will likely white-screen if it hits your php memory limit. + // The downside is that http: media files will likely be blocked by your browser + // Complain to your browser maker + + $allow = get_config('system','sslify_everything'); + + $pattern = (($allow) ? "/\<(.*?)src=\"(http\:.*?)\"(.*?)\>/" : "/\<img(.*?)src=\"(http\:.*?)\"(.*?)\>/" ); + $matches = null; - $cnt = preg_match_all("/\<(.*?)src=\"(http\:.*?)\"(.*?)\>/",$s,$matches,PREG_SET_ORDER); + $cnt = preg_match_all($pattern,$s,$matches,PREG_SET_ORDER); if ($cnt) { foreach ($matches as $match) { $filename = basename( parse_url($match[2], PHP_URL_PATH) ); @@ -1224,7 +1235,7 @@ function theme_attachments(&$item) { if($label == ' ') $label = t('Unknown Attachment'); - $title = t('Attachment') . ' - ' . (($r['length']) ? userReadableSize($r['length']) : t('Size Unknown')); + $title = t('Size') . ' ' . (($r['length']) ? userReadableSize($r['length']) : t('unknown')); require_once('include/identity.php'); if(is_foreigner($item['author_xchan'])) diff --git a/include/widgets.php b/include/widgets.php index 3e6fdb04c..0f61a04a0 100644 --- a/include/widgets.php +++ b/include/widgets.php @@ -642,7 +642,7 @@ function widget_conversations($arr) { 'subject' => (($rr['seen']) ? $rr['title'] : '<strong>' . $rr['title'] . '</strong>'), 'delete' => t('Delete conversation'), 'body' => $rr['body'], - 'date' => datetime_convert('UTC',date_default_timezone_get(),$rr['created'], t('D, d M Y - g:i A')), + 'date' => datetime_convert('UTC',date_default_timezone_get(),$rr['created'], 'c'), 'seen' => $rr['seen'], 'selected' => ((argv(2)) ? (argv(2) == $rr['id']) : ($r[0]['id'] == $rr['id'])) ); diff --git a/include/zot.php b/include/zot.php index 793eb6b39..d5d68f72c 100644 --- a/include/zot.php +++ b/include/zot.php @@ -117,7 +117,8 @@ function zot_build_packet($channel, $type = 'notify', $recipients = null, $remot 'guid' => $channel['channel_guid'], 'guid_sig' => base64url_encode(rsa_sign($channel['channel_guid'],$channel['channel_prvkey'])), 'url' => z_root(), - 'url_sig' => base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey'])) + 'url_sig' => base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey'])), + 'sitekey' => get_config('system','pubkey') ), 'callback' => '/post', 'version' => ZOT_REVISION @@ -569,11 +570,12 @@ function zot_gethub($arr,$multiple = false) { } $limit = (($multiple) ? '' : ' limit 1 '); - + $sitekey = ((array_key_exists('sitekey',$arr) && $arr['sitekey']) ? " and hubloc_sitekey = '" . protect_sprintf($arr['sitekey']) . "' " : ''); + $r = q("select * from hubloc where hubloc_guid = '%s' and hubloc_guid_sig = '%s' and hubloc_url = '%s' and hubloc_url_sig = '%s' - $limit", + $sitekey $limit", dbesc($arr['guid']), dbesc($arr['guid_sig']), dbesc($arr['url']), @@ -814,7 +816,34 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { if ($local) { $ph = z_fetch_url($arr['photo'], true); if ($ph['success']) { - import_channel_photo($ph['body'], $arr['photo_mimetype'], $local[0]['channel_account_id'],$local[0]['channel_id']); + + $hash = import_channel_photo($ph['body'], $arr['photo_mimetype'], $local[0]['channel_account_id'], $local[0]['channel_id']); + + if($hash) { + // unless proven otherwise + $is_default_profile = 1; + + $profile = q("select is_default from profile where aid = %d and uid = %d limit 1", + intval($local[0]['channel_account_id']), + intval($local[0]['channel_id']) + ); + if($profile) { + if(! intval($profile[0]['is_default'])) + $is_default_profile = 0; + } + + // If setting for the default profile, unset the profile photo flag from any other photos I own + if($is_default_profile) { + q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d AND resource_id != '%s' AND aid = %d AND uid = %d", + intval(PHOTO_NORMAL), + intval(PHOTO_PROFILE), + dbesc($hash), + intval($local[0]['channel_account_id']), + intval($local[0]['channel_id']) + ); + } + } + // reset the names in case they got messed up when we had a bug in this function $photos = array( z_root() . '/photo/profile/l/' . $local[0]['channel_id'], @@ -2337,16 +2366,16 @@ function sync_locations($sender, $arr, $absolute = false) { $changed = true; } } - if((intval($r[0]['hubloc_deleted']) && (! $location['deleted'])) - || ((! (intval($r[0]['hubloc_deleted']))) && ($location['deleted']))) { + if(intval($r[0]['hubloc_deleted']) && (! intval($location['deleted']))) { $n = q("update hubloc set hubloc_deleted = 0, hubloc_updated = '%s' where hubloc_id = %d", dbesc(datetime_convert()), intval($r[0]['hubloc_id']) ); - $what .= 'delete_hub '; + $what .= 'undelete_hub '; $changed = true; } - elseif((! intval($r[0]['hubloc_deleted'])) && ($location['deleted'])) { + elseif((! intval($r[0]['hubloc_deleted'])) && (intval($location['deleted']))) { + logger('deleting hubloc: ' . $r[0]['hubloc_addr']); $n = q("update hubloc set hubloc_deleted = 1, hubloc_updated = '%s' where hubloc_id = %d", dbesc(datetime_convert()), intval($r[0]['hubloc_id']) @@ -2401,7 +2430,7 @@ function sync_locations($sender, $arr, $absolute = false) { if($absolute && $xisting) { foreach($xisting as $x) { if(! array_key_exists('updated',$x)) { - logger('sync_locations: deleting unreferenced hub location ' . $x['hubloc_url']); + logger('sync_locations: deleting unreferenced hub location ' . $x['hubloc_addr']); $r = q("update hubloc set hubloc_deleted = 1, hubloc_updated = '%s' where hubloc_id = %d", dbesc(datetime_convert()), intval($x['hubloc_id']) @@ -2437,6 +2466,13 @@ function zot_encode_locations($channel) { if($x && count($x)) { foreach($x as $hub) { + + // if this is a local channel that has been deleted, the hubloc is no good - make sure it is marked deleted + // so that nobody tries to use it. + + if(intval($channel['channel_removed']) && $hub['hubloc_url'] === z_root()) + $hub['hubloc_deleted'] = 1; + $ret[] = array( 'host' => $hub['hubloc_host'], 'address' => $hub['hubloc_addr'], @@ -3709,6 +3745,8 @@ function zotinfo($arr) { $ret['public_forum'] = $public_forum; if($deleted) $ret['deleted'] = $deleted; + if(intval($e['channel_removed'])) + $ret['deleted_locally'] = true; // premium or other channel desiring some contact with potential followers before connecting. // This is a template - %s will be replaced with the follow_url we discover for the return channel. |