diff options
author | Wave <wave72@users.noreply.github.com> | 2015-11-25 09:39:44 +0100 |
---|---|---|
committer | Wave <wave72@users.noreply.github.com> | 2015-11-25 09:39:44 +0100 |
commit | 2de65ab39fc704fd8b7abcf9003ee98e3ffb1cc3 (patch) | |
tree | 783f90531c93f498609fb1dbd0e199ca65bb2cc0 /include | |
parent | e785b723aad51d4f7202dbbb24a0e2245428cb5b (diff) | |
parent | 0559db9cf81267c34ca014fef1aebe1cf31de2ab (diff) | |
download | volse-hubzilla-2de65ab39fc704fd8b7abcf9003ee98e3ffb1cc3.tar.gz volse-hubzilla-2de65ab39fc704fd8b7abcf9003ee98e3ffb1cc3.tar.bz2 volse-hubzilla-2de65ab39fc704fd8b7abcf9003ee98e3ffb1cc3.zip |
Merge pull request #3 from redmatrix/master
Update branch
Diffstat (limited to 'include')
-rw-r--r-- | include/ItemObject.php | 15 | ||||
-rw-r--r-- | include/RedDAV/RedDirectory.php | 21 | ||||
-rw-r--r-- | include/RedDAV/RedFile.php | 2 | ||||
-rw-r--r-- | include/acl_selectors.php | 2 | ||||
-rw-r--r-- | include/api.php | 98 | ||||
-rw-r--r-- | include/api_auth.php | 95 | ||||
-rw-r--r-- | include/auth.php | 1 | ||||
-rw-r--r-- | include/bbcode.php | 32 | ||||
-rw-r--r-- | include/conversation.php | 13 | ||||
-rw-r--r-- | include/datetime.php | 27 | ||||
-rwxr-xr-x | include/dba/dba_driver.php | 2 | ||||
-rw-r--r-- | include/deliver.php | 12 | ||||
-rw-r--r-- | include/dir_fns.php | 13 | ||||
-rw-r--r-- | include/enotify.php | 3 | ||||
-rw-r--r-- | include/features.php | 1 | ||||
-rw-r--r-- | include/identity.php | 27 | ||||
-rw-r--r-- | include/import.php | 8 | ||||
-rwxr-xr-x | include/items.php | 28 | ||||
-rw-r--r-- | include/network.php | 47 | ||||
-rw-r--r-- | include/notifier.php | 2 | ||||
-rw-r--r-- | include/photo/photo_driver.php | 11 | ||||
-rw-r--r-- | include/system_unavailable.php | 3 | ||||
-rw-r--r-- | include/taxonomy.php | 21 | ||||
-rw-r--r-- | include/text.php | 37 | ||||
-rw-r--r-- | include/widgets.php | 114 | ||||
-rw-r--r-- | include/zot.php | 23 |
26 files changed, 445 insertions, 213 deletions
diff --git a/include/ItemObject.php b/include/ItemObject.php index 34500efb9..512e12838 100644 --- a/include/ItemObject.php +++ b/include/ItemObject.php @@ -258,6 +258,15 @@ class Item extends BaseObject { if ($shareable) $share = array( t('Share This'), t('share')); + $dreport = ''; + + $keep_reports = intval(get_config('system','expire_delivery_reports')); + if($keep_reports === 0) + $keep_reports = 30; + + if(strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC',"now - $keep_reports days")) > 0) + $dreport = t('Delivery Report'); + if(strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC','now - 12 hours')) > 0) $indent .= ' shiny'; @@ -277,6 +286,10 @@ class Item extends BaseObject { $comment_count_txt = sprintf( tt('%d comment','%d comments',$total_children),$total_children ); $list_unseen_txt = (($unseen_comments) ? sprintf('%d unseen',$unseen_comments) : ''); + + + + $children = $this->get_children(); $has_tags = (($body['tags'] || $body['categories'] || $body['mentions'] || $body['attachments'] || $body['folders']) ? true : false); @@ -309,7 +322,7 @@ class Item extends BaseObject { 'vwall' => t('via Wall-To-Wall:'), 'profile_url' => $profile_link, 'item_photo_menu' => item_photo_menu($item), - 'dreport' => t('Delivery Report'), + 'dreport' => $dreport, 'name' => $profile_name, 'thumb' => $profile_avatar, 'osparkle' => $osparkle, diff --git a/include/RedDAV/RedDirectory.php b/include/RedDAV/RedDirectory.php index 87bdf8f13..8d8af5bd3 100644 --- a/include/RedDAV/RedDirectory.php +++ b/include/RedDAV/RedDirectory.php @@ -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 2bc3f40e5..3283a6e88 100644 --- a/include/RedDAV/RedFile.php +++ b/include/RedDAV/RedFile.php @@ -127,7 +127,7 @@ class RedFile extends DAV\Node implements DAV\IFile { } $fname = dbunescbin($d[0]['data']); if(strpos($fname,'store') === false) - $f = 'store/' . $this->auth->owner_nick . '/' . (($fname) ? $fname : ''); + $f = 'store/' . $this->auth->owner_nick . '/' . $fname ; else $f = $fname; 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 b51bcc5f0..f279b2aa3 100644 --- a/include/api.php +++ b/include/api.php @@ -9,6 +9,7 @@ require_once('include/security.php'); require_once('include/photos.php'); require_once('include/items.php'); require_once('include/attach.php'); +require_once('include/api_auth.php'); /* * @@ -66,96 +67,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); - - 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 * @@ -831,6 +742,8 @@ require_once('include/attach.php'); } $user_info = api_get_user($a); +// logger('status_with_media: ' . print_r($_REQUEST,true), LOGGER_DEBUG); + $_REQUEST['type'] = 'wall'; $_REQUEST['profile_uid'] = api_user(); $_REQUEST['api_source'] = true; @@ -998,7 +911,7 @@ require_once('include/attach.php'); function red_item(&$a, $type) { if (api_user() === false) { - logger('api_red_item_new: no user'); + logger('api_red_item_full: no user'); return false; } @@ -2285,7 +2198,7 @@ require_once('include/attach.php'); } } - $id = send_message($recipient['id'], $_POST['text'], $sub, $replyto); + $id = send_message(api_user(),$recipient['guid'], $_POST['text'], $sub, $replyto); if ($id>-1) { $r = q("SELECT * FROM `mail` WHERE id=%d", intval($id)); @@ -2416,6 +2329,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/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/bbcode.php b/include/bbcode.php index 05802aa57..a8372d728 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -570,7 +570,7 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false) $urlchars = '[a-zA-Z0-9\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\+\,\@]'; if (strpos($Text,'http') !== false) { - $Text = preg_replace("/([^\]\='".'"'."\/]|^|\#\^)(https?\:\/\/$urlchars+)/ism", '$1<a href="$2" target="_newwin" >$2</a>', $Text); + $Text = preg_replace("/([^\]\='".'"'."\/]|^|\#\^)(https?\:\/\/$urlchars+)/ism", '$1<a href="$2" target="_blank" >$2</a>', $Text); } if (strpos($Text,'[/share]') !== false) { @@ -582,21 +582,21 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false) } } if (strpos($Text,'[/url]') !== false) { - $Text = preg_replace("/\#\^\[url\]([$URLSearchString]*)\[\/url\]/ism", '<span class="bookmark-identifier">#^</span><a class="bookmark" href="$1" target="_newwin" >$1</a>', $Text); - $Text = preg_replace("/\#\^\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '<span class="bookmark-identifier">#^</span><a class="bookmark" href="$1" target="_newwin" >$2</a>', $Text); - $Text = preg_replace("/\[url\]([$URLSearchString]*)\[\/url\]/ism", '<a href="$1" target="_newwin" >$1</a>', $Text); - $Text = preg_replace("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '<a href="$1" target="_newwin" >$2</a>', $Text); + $Text = preg_replace("/\#\^\[url\]([$URLSearchString]*)\[\/url\]/ism", '<span class="bookmark-identifier">#^</span><a class="bookmark" href="$1" target="_blank" >$1</a>', $Text); + $Text = preg_replace("/\#\^\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '<span class="bookmark-identifier">#^</span><a class="bookmark" href="$1" target="_blank" >$2</a>', $Text); + $Text = preg_replace("/\[url\]([$URLSearchString]*)\[\/url\]/ism", '<a href="$1" target="_blank" >$1</a>', $Text); + $Text = preg_replace("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '<a href="$1" target="_blank" >$2</a>', $Text); } if (strpos($Text,'[/zrl]') !== false) { - $Text = preg_replace("/\#\^\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" target="_newwin" >$1</a>', $Text); - $Text = preg_replace("/\#\^\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" target="_newwin" >$2</a>', $Text); - $Text = preg_replace("/\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '<a class="zrl" href="$1" target="_newwin" >$1</a>', $Text); - $Text = preg_replace("/\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<a class="zrl" href="$1" target="_newwin" >$2</a>', $Text); + $Text = preg_replace("/\#\^\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" target="_blank" >$1</a>', $Text); + $Text = preg_replace("/\#\^\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" target="_blank" >$2</a>', $Text); + $Text = preg_replace("/\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '<a class="zrl" href="$1" target="_blank" >$1</a>', $Text); + $Text = preg_replace("/\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<a class="zrl" href="$1" target="_blank" >$2</a>', $Text); } // Perform MAIL Search if (strpos($Text,'[/mail]') !== false) { - $Text = preg_replace("/\[mail\]([$MAILSearchString]*)\[\/mail\]/", '<a href="mailto:$1" target="_newwin" >$1</a>', $Text); - $Text = preg_replace("/\[mail\=([$MAILSearchString]*)\](.*?)\[\/mail\]/", '<a href="mailto:$1" target="_newwin" >$2</a>', $Text); + $Text = preg_replace("/\[mail\]([$MAILSearchString]*)\[\/mail\]/", '<a href="mailto:$1" target="_blank" >$1</a>', $Text); + $Text = preg_replace("/\[mail\=([$MAILSearchString]*)\](.*?)\[\/mail\]/", '<a href="mailto:$1" target="_blank" >$2</a>', $Text); } @@ -886,17 +886,17 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false) // if video couldn't be embedded, link to it instead. if (strpos($Text,'[/video]') !== false) { - $Text = preg_replace("/\[video\](.*?)\[\/video\]/", '<a href="$1" target="_newwin" >$1</a>', $Text); + $Text = preg_replace("/\[video\](.*?)\[\/video\]/", '<a href="$1" target="_blank" >$1</a>', $Text); } if (strpos($Text,'[/audio]') !== false) { - $Text = preg_replace("/\[audio\](.*?)\[\/audio\]/", '<a href="$1" target="_newwin" >$1</a>', $Text); + $Text = preg_replace("/\[audio\](.*?)\[\/audio\]/", '<a href="$1" target="_blank" >$1</a>', $Text); } if (strpos($Text,'[/zvideo]') !== false) { - $Text = preg_replace("/\[zvideo\](.*?)\[\/zvideo\]/", '<a class="zid" href="$1" target="_newwin" >$1</a>', $Text); + $Text = preg_replace("/\[zvideo\](.*?)\[\/zvideo\]/", '<a class="zid" href="$1" target="_blank" >$1</a>', $Text); } if (strpos($Text,'[/zaudio]') !== false) { - $Text = preg_replace("/\[zaudio\](.*?)\[\/zaudio\]/", '<a class="zid" href="$1" target="_newwin" >$1</a>', $Text); + $Text = preg_replace("/\[zaudio\](.*?)\[\/zaudio\]/", '<a class="zid" href="$1" target="_blank" >$1</a>', $Text); } if ($tryoembed){ @@ -905,7 +905,7 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false) } } else { if (strpos($Text,'[/iframe]') !== false) { - $Text = preg_replace("/\[iframe\](.*?)\[\/iframe\]/ism", '<a href="$1" target="_newwin" >$1</a>', $Text); + $Text = preg_replace("/\[iframe\](.*?)\[\/iframe\]/ism", '<a href="$1" target="_blank" >$1</a>', $Text); } } diff --git a/include/conversation.php b/include/conversation.php index a5fe573cd..2c447acbc 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -674,7 +674,7 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $ $unverified = ''; // $tags=array(); -// $terms = get_terms_oftype($item['term'],array(TERM_HASHTAG,TERM_MENTION,TERM_UNKNOWN)); +// $terms = get_terms_oftype($item['term'],array(TERM_HASHTAG,TERM_MENTION,TERM_UNKNOWN,TERM_COMMUNITYTAG)); // if(count($terms)) // foreach($terms as $tag) // $tags[] = format_term_for_display($tag); @@ -944,7 +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("Unfollow Thread") => $unsub_link, t("View Status") => $status_link, t("View Profile") => $profile_link, t("View Photos") => $photos_link, @@ -1024,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="dropdown-menu-img-xs" src="' . zid($item['author']['xchan_photo_s']) . '" alt="' . urlencode($name) . '" />' . $name . '</a>' : '<a href="#" class="disabled">' . $name . '</a>' ); @@ -1089,6 +1089,11 @@ function format_like($cnt, $arr, $type, $id) { return $o; } +/** + * This is our general purpose content editor. + * It was once nicknamed "jot" and you may see references to "jot" littered throughout the code. + * They are referring to the content editor or components thereof. + */ function status_editor($a, $x, $popup = false) { diff --git a/include/datetime.php b/include/datetime.php index b0167edb2..f7df70a36 100644 --- a/include/datetime.php +++ b/include/datetime.php @@ -153,7 +153,7 @@ function dob($dob) { * id and name of datetimepicker (defaults to "datetimepicker") */ function datesel($format, $min, $max, $default, $id = 'datepicker') { - return datetimesel($format, $min, $max, $default, $id,true, false, '', ''); + return datetimesel($format, $min, $max, $default, '', $id,true, false, '', ''); } /** @@ -168,7 +168,7 @@ function datesel($format, $min, $max, $default, $id = 'datepicker') { * id and name of datetimepicker (defaults to "timepicker") */ function timesel($format, $h, $m, $id='timepicker') { - return datetimesel($format,new DateTime(),new DateTime(),new DateTime("$h:$m"),$id,false,true); + return datetimesel($format,new DateTime(),new DateTime(),new DateTime("$h:$m"),'', $id,false,true); } /** @@ -198,7 +198,7 @@ function timesel($format, $h, $m, $id='timepicker') { * @todo Once browser support is better this could probably be replaced with * native HTML5 date picker. */ -function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pickdate = true, $picktime = true, $minfrom = '', $maxfrom = '', $required = false) { +function datetimesel($format, $min, $max, $default, $label, $id = 'datetimepicker', $pickdate = true, $picktime = true, $minfrom = '', $maxfrom = '', $required = false, $first_day = 0) { $o = ''; $dateformat = ''; @@ -207,11 +207,11 @@ function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pic if($pickdate && $picktime) $dateformat .= ' '; if($picktime) $dateformat .= 'H:i'; - $minjs = $min ? ",minDate: new Date({$min->getTimestamp()}*1000), yearStart: " . $min->format('Y') : ''; - $maxjs = $max ? ",maxDate: new Date({$max->getTimestamp()}*1000), yearEnd: " . $max->format('Y') : ''; + $minjs = $min->getTimestamp() ? ",minDate: new Date({$min->getTimestamp()}*1000), yearStart: " . $min->format('Y') : ''; + $maxjs = $max->getTimestamp() ? ",maxDate: new Date({$max->getTimestamp()}*1000), yearEnd: " . $max->format('Y') : ''; - $input_text = $default ? 'value="' . date($dateformat, $default->getTimestamp()) . '"' : ''; - $defaultdatejs = $default ? ",defaultDate: new Date({$default->getTimestamp()}*1000)" : ''; + $input_text = $default->getTimestamp() ? date($dateformat, $default->getTimestamp()) : ''; + $defaultdatejs = $default->getTimestamp() ? ",defaultDate: new Date({$default->getTimestamp()}*1000)" : ''; $pickers = ''; if(!$pickdate) $pickers .= ',datepicker: false'; @@ -219,10 +219,10 @@ function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pic $extra_js = ''; if($minfrom != '') - $extra_js .= "\$('#$minfrom').data('xdsoft_datetimepicker').setOptions({onChangeDateTime: function (currentDateTime) { \$('#$id').data('xdsoft_datetimepicker').setOptions({minDate: currentDateTime})}})"; + $extra_js .= "\$('#id_$minfrom').data('xdsoft_datetimepicker').setOptions({onChangeDateTime: function (currentDateTime) { \$('#id_$id').data('xdsoft_datetimepicker').setOptions({minDate: currentDateTime})}})"; if($maxfrom != '') - $extra_js .= "\$('#$maxfrom').data('xdsoft_datetimepicker').setOptions({onChangeDateTime: function (currentDateTime) { \$('#$id').data('xdsoft_datetimepicker').setOptions({maxDate: currentDateTime})}})"; + $extra_js .= "\$('#id_$maxfrom').data('xdsoft_datetimepicker').setOptions({onChangeDateTime: function (currentDateTime) { \$('#id_$id').data('xdsoft_datetimepicker').setOptions({maxDate: currentDateTime})}})"; $readable_format = $dateformat; $readable_format = str_replace('Y','yyyy',$readable_format); @@ -231,10 +231,11 @@ function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pic $readable_format = str_replace('H','HH',$readable_format); $readable_format = str_replace('i','MM',$readable_format); - $o .= "<div class='date'><input type='text' placeholder='$readable_format' name='$id' id='$id' $input_text />"; - $o .= (($required) ? '<span class="required" title="' . t('Required') . '" >*</span>' : ''); - $o .= '</div>'; - $o .= "<script type='text/javascript'>\$(function () {var picker = \$('#$id').datetimepicker({step:5,format:'$dateformat' $minjs $maxjs $pickers $defaultdatejs}); $extra_js})</script>"; + $tpl = get_markup_template('field_input.tpl'); + $o .= replace_macros($tpl,array( + '$field' => array($id, $label, $input_text, (($required) ? t('Required') : ''), (($required) ? '*' : ''), 'placeholder="' . $readable_format . '"'), + )); + $o .= "<script>\$(function () {var picker = \$('#id_$id').datetimepicker({step:5,format:'$dateformat' $minjs $maxjs $pickers $defaultdatejs,dayOfWeekStart:$first_day}); $extra_js})</script>"; return $o; } diff --git a/include/dba/dba_driver.php b/include/dba/dba_driver.php index 708d8e709..1fb3d5c00 100755 --- a/include/dba/dba_driver.php +++ b/include/dba/dba_driver.php @@ -137,7 +137,7 @@ abstract class dba_driver { } if(strlen($server) && ($server !== 'localhost') && ($server !== '127.0.0.1')) { - if(! dns_get_record($server, DNS_A + DNS_CNAME + DNS_PTR)) { + if((! dns_get_record($server, DNS_A + DNS_CNAME + DNS_PTR)) && (! filter_var($server, FILTER_VALIDATE_IP))) { $this->error = sprintf( t('Cannot locate DNS info for database server \'%s\''), $server); $this->connected = false; $this->db = null; diff --git a/include/deliver.php b/include/deliver.php index 11c1b249e..de93e316e 100644 --- a/include/deliver.php +++ b/include/deliver.php @@ -107,15 +107,10 @@ function deliver_run($argv, $argc) { $notify = json_decode($r[0]['outq_notify'],true); - // Check if this is a conversation request packet. It won't have outq_msg - // but will be an encrypted packet - so will need to be handed off to - // web delivery rather than processed inline. + // Messages without an outq_msg will need to go via the web, even if it's a + // local delivery. This includes conversation requests and refresh packets. - $sendtoweb = false; - if(array_key_exists('iv',$notify) && (! $r[0]['outq_msg'])) - $sendtoweb = true; - - if(($r[0]['outq_posturl'] === z_root() . '/post') && (! $sendtoweb)) { + if(($r[0]['outq_posturl'] === z_root() . '/post') && ($r[0]['outq_msg'])) { logger('deliver: local delivery', LOGGER_DEBUG); // local delivery // we should probably batch these and save a few delivery processes @@ -166,6 +161,7 @@ function deliver_run($argv, $argc) { } else { logger('deliver: remote zot delivery failed to ' . $r[0]['outq_posturl']); + logger('deliver: remote zot delivery fail data: ' . print_r($result,true), LOGGER_DATA); $y = q("update outq set outq_updated = '%s' where outq_hash = '%s'", dbesc(datetime_convert()), dbesc($argv[$x]) diff --git a/include/dir_fns.php b/include/dir_fns.php index e5f0e1e2b..b9f221bd1 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) && ($preferred != 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) { /* diff --git a/include/enotify.php b/include/enotify.php index bbddcdd14..c9b6e0463 100644 --- a/include/enotify.php +++ b/include/enotify.php @@ -152,6 +152,8 @@ function notification($params) { // $private = $p[0]['item_private']; $parent_id = $p[0]['id']; + $parent_item = $p[0]; + //$possess_desc = str_replace('<!item_type!>',$possess_desc); // "a post" @@ -358,6 +360,7 @@ function notification($params) { $datarray['uid'] = $recip['channel_id']; $datarray['link'] = $itemlink; $datarray['parent'] = $parent_mid; + $datarray['parent_item'] = $parent_item; $datarray['type'] = $params['type']; $datarray['verb'] = $params['verb']; $datarray['otype'] = $params['otype']; diff --git a/include/features.php b/include/features.php index 74ae7b3d7..4e962b00e 100644 --- a/include/features.php +++ b/include/features.php @@ -60,6 +60,7 @@ function get_features() { array('content_encrypt', t('Even More Encryption'), t('Allow optional encryption of content end-to-end with a shared secret key'),false), array('consensus_tools', t('Enable Voting Tools'), t('Provide a class of post which others can vote on'),false), array('delayed_posting', t('Delayed Posting'), t('Allow posts to be published at a later date'),false), + array('suppress_duplicates', t('Suppress Duplicate Posts/Comments'), t('Prevent posts with identical content to be published with less than two minutes in between submissions.'),true), ), diff --git a/include/identity.php b/include/identity.php index 0c4a9df45..95ade3b28 100644 --- a/include/identity.php +++ b/include/identity.php @@ -710,7 +710,8 @@ function identity_export_year($channel_id,$year,$month = 0) { else $maxdate = datetime_convert('UTC','UTC',$year+1 . '-01-01 00:00:00'); - $r = q("select * from item where item_wall = 1 and item_deleted = 0 and uid = %d and created >= '%s' and created < '%s' and resource_type = '' order by created", + $r = q("select * from item where ( item_wall = 1 or item_type != %d ) and item_deleted = 0 and uid = %d and created >= '%s' and created < '%s' and resource_type = '' order by created", + intval(ITEM_TYPE_POST), intval($channel_id), dbesc($mindate), dbesc($maxdate) @@ -904,19 +905,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 @@ -1702,3 +1690,14 @@ function get_channel_default_perms($uid) { return 0; } + + +function profiles_build_sync($channel_id) { + + $r = q("select * from profile where uid = %d", + intval($channel_id) + ); + if($r) { + build_sync_packet($channel_id,array('profile' => $r)); + } +} diff --git a/include/import.php b/include/import.php index 0fd1ab2a5..ffaea6c1a 100644 --- a/include/import.php +++ b/include/import.php @@ -2,7 +2,7 @@ require_once('include/menu.php'); -function import_channel($channel) { +function import_channel($channel, $account_id) { if(! array_key_exists('channel_system',$channel)) { $channel['channel_system'] = (($channel['channel_pageflags'] & 0x1000) ? 1 : 0); @@ -48,7 +48,7 @@ function import_channel($channel) { } unset($channel['channel_id']); - $channel['channel_account_id'] = get_account_id(); + $channel['channel_account_id'] = $account_id; $channel['channel_primary'] = (($seize) ? 1 : 0); if($channel['channel_pageflags'] & PAGE_ALLOWCODE) { @@ -72,7 +72,7 @@ function import_channel($channel) { } $r = q("select * from channel where channel_account_id = %d and channel_guid = '%s' limit 1", - intval(get_account_id()), + intval($account_id), $channel['channel_guid'] // Already dbesc'd ); if(! $r) { @@ -83,7 +83,7 @@ function import_channel($channel) { // reset $channel = $r[0]; - set_default_login_identity(get_account_id(),$channel['channel_id'],false); + set_default_login_identity($account_id,$channel['channel_id'],false); logger('import step 1'); $_SESSION['import_step'] = 1; ref_session_write(session_id(), serialize($_SESSION)); diff --git a/include/items.php b/include/items.php index 3e4805212..7d349c631 100755 --- a/include/items.php +++ b/include/items.php @@ -1408,7 +1408,7 @@ function encode_item_xchan($xchan) { function encode_item_terms($terms,$mirror = false) { $ret = array(); - $allowed_export_terms = array( TERM_UNKNOWN, TERM_HASHTAG, TERM_MENTION, TERM_CATEGORY, TERM_BOOKMARK ); + $allowed_export_terms = array( TERM_UNKNOWN, TERM_HASHTAG, TERM_MENTION, TERM_CATEGORY, TERM_BOOKMARK, TERM_COMMUNITYTAG ); if($mirror) { $allowed_export_terms[] = TERM_PCATEGORY; @@ -1432,7 +1432,7 @@ function encode_item_terms($terms,$mirror = false) { * @return string */ function termtype($t) { - $types = array('unknown','hashtag','mention','category','private_category','file','search','thing','bookmark'); + $types = array('unknown','hashtag','mention','category','private_category','file','search','thing','bookmark', 'hierarchy', 'communitytag'); return(($types[$t]) ? $types[$t] : 'unknown'); } @@ -1478,6 +1478,9 @@ function decode_tags($t) { case 'bookmark': $tag['type'] = TERM_BOOKMARK; break; + case 'communitytag': + $tag['type'] = TERM_COMMUNITYTAG; + break; default: case 'unknown': $tag['type'] = TERM_UNKNOWN; @@ -2962,9 +2965,12 @@ function tag_deliver($uid, $item_id) { if(($item['source_xchan']) && intval($item['item_uplink']) && intval($item['item_thread_top']) && ($item['edited'] != $item['created'])) { + // this is an update (edit) to a post which was already processed by us and has a second delivery chain // Just start the second delivery chain to deliver the updated post - proc_run('php','include/notifier.php','tgroup',$item['id']); + // after resetting ownership and permission bits + + start_delivery_chain($u[0], $item, $item_id, 0); return; } @@ -3029,7 +3035,7 @@ function tag_deliver($uid, $item_id) { if(is_array($j_obj['link'])) $taglink = get_rel_link($j_obj['link'],'alternate'); - store_item_tag($u[0]['channel_id'],$p[0]['id'],TERM_OBJ_POST,TERM_HASHTAG,$j_obj['title'],$j_obj['id']); + store_item_tag($u[0]['channel_id'],$p[0]['id'],TERM_OBJ_POST,TERM_COMMUNITYTAG,$j_obj['title'],$j_obj['id']); $x = q("update item set edited = '%s', received = '%s', changed = '%s' where mid = '%s' and uid = %d", dbesc(datetime_convert()), dbesc(datetime_convert()), @@ -3181,7 +3187,7 @@ function tag_deliver($uid, $item_id) { } if((! $mention) && (! $union)) { - logger('tag_deliver: no mention and no union.'); + logger('tag_deliver: no mention for ' . $u[0]['channel_name'] . ' and no union.'); return; } @@ -3434,7 +3440,7 @@ function check_item_source($uid, $item) { foreach($words as $word) { if(substr($word,0,1) === '#' && $tags) { foreach($tags as $t) - if(($t['type'] == TERM_HASHTAG) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*'))) + if((($t['type'] == TERM_HASHTAG) || ($t['type'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*'))) return true; } elseif((strpos($word,'/') === 0) && preg_match($word,$text)) @@ -3487,7 +3493,7 @@ function post_is_importable($item,$abook) { continue; if(substr($word,0,1) === '#' && $tags) { foreach($tags as $t) - if(($t['type'] == TERM_HASHTAG) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*'))) + if((($t['type'] == TERM_HASHTAG) || ($t['type'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*'))) return false; } elseif((strpos($word,'/') === 0) && preg_match($word,$text)) @@ -3508,7 +3514,7 @@ function post_is_importable($item,$abook) { continue; if(substr($word,0,1) === '#' && $tags) { foreach($tags as $t) - if(($t['type'] == TERM_HASHTAG) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*'))) + if((($t['type'] == TERM_HASHTAG) || ($t['type'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*'))) return true; } elseif((strpos($word,'/') === 0) && preg_match($word,$text)) @@ -4159,12 +4165,12 @@ function enumerate_permissions($obj) { function item_getfeedtags($item) { - $terms = get_terms_oftype($item['term'],array(TERM_HASHTAG,TERM_MENTION)); + $terms = get_terms_oftype($item['term'],array(TERM_HASHTAG,TERM_MENTION,TERM_COMMUNITYTAG)); $ret = array(); if(count($terms)) { foreach($terms as $term) { - if($term['type'] == TERM_HASHTAG) + if(($term['type'] == TERM_HASHTAG) || ($term['type'] == TERM_COMMUNITYTAG)) $ret[] = array('#',$term['url'],$term['term']); else $ret[] = array('@',$term['url'],$term['term']); @@ -4872,7 +4878,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C if($arr['search']) { if(strpos($arr['search'],'#') === 0) - $sql_extra .= term_query('item',substr($arr['search'],1),TERM_HASHTAG); + $sql_extra .= term_query('item',substr($arr['search'],1),TERM_HASHTAG,TERM_COMMUNITYTAG); else $sql_extra .= sprintf(" AND item.body like '%s' ", dbesc(protect_sprintf('%' . $arr['search'] . '%')) diff --git a/include/network.php b/include/network.php index c67c019ef..026f5ee0a 100644 --- a/include/network.php +++ b/include/network.php @@ -320,17 +320,18 @@ function xml_status($st, $message = '') { killme(); } + + /** - * @brief Send HTTP status header and exit. + * @brief Send HTTP status header * * @param int $val * integer HTTP status result value * @param string $msg * optional message - * @returns (does not return, process is terminated) + * @returns nil */ -function http_status_exit($val, $msg = '') { - +function http_status($val, $msg = '') { if ($val >= 400) $msg = (($msg) ? $msg : 'Error'); if ($val >= 200 && $val < 300) @@ -338,10 +339,26 @@ function http_status_exit($val, $msg = '') { logger('http_status_exit ' . $val . ' ' . $msg); header($_SERVER['SERVER_PROTOCOL'] . ' ' . $val . ' ' . $msg); +} + + + +/** + * @brief Send HTTP status header and exit. + * + * @param int $val + * integer HTTP status result value + * @param string $msg + * optional message + * @returns (does not return, process is terminated) + */ +function http_status_exit($val, $msg = '') { + http_status($val, $msg); killme(); } + // convert an XML document to a normalised, case-corrected array // used by webfinger @@ -526,28 +543,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 34a527e15..b7830285a 100644 --- a/include/notifier.php +++ b/include/notifier.php @@ -101,7 +101,7 @@ function notifier_run($argv, $argc){ $dead_hubs = array(); $dh = q("select site_url from site where site_dead = 1"); - if(dh) { + if($dh) { foreach($dh as $dead) { $dead_hubs[] = $dead['site_url']; } diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php index 285cbc8fb..0de3b9c97 100644 --- a/include/photo/photo_driver.php +++ b/include/photo/photo_driver.php @@ -3,6 +3,17 @@ function photo_factory($data, $type = null) { $ph = null; + + $unsupported_types = array( + 'image/bmp', + 'image/vnd.microsoft.icon', + 'image/tiff', + 'image/svg+xml' + ); + + if($type && in_array(strtolower($type),$unsupported_types)) + return null; + $ignore_imagick = get_config('system', 'ignore_imagick'); if(class_exists('Imagick') && !$ignore_imagick) { diff --git a/include/system_unavailable.php b/include/system_unavailable.php index dfe7c5e6b..4e0e6717b 100644 --- a/include/system_unavailable.php +++ b/include/system_unavailable.php @@ -1,6 +1,9 @@ <?php /** @file */ +require_once("include/network.php"); + function system_down() { +http_status(503, 'Service Unavailable'); echo <<< EOT <html> <head><title>System Unavailable</title></head> diff --git a/include/taxonomy.php b/include/taxonomy.php index e68b9659f..b396d53f1 100644 --- a/include/taxonomy.php +++ b/include/taxonomy.php @@ -26,12 +26,21 @@ function file_tag_file_query($table,$s,$type = 'file') { ); } -function term_query($table,$s,$type = TERM_UNKNOWN) { +function term_query($table,$s,$type = TERM_UNKNOWN, $type2 = '') { - return sprintf(" AND " . (($table) ? dbesc($table) . '.' : '') . "id in (select term.oid from term where term.type = %d and term.term = '%s' and term.uid = " . (($table) ? dbesc($table) . '.' : '') . "uid ) ", - intval($type), - protect_sprintf(dbesc($s)) - ); + if($type2) { + return sprintf(" AND " . (($table) ? dbesc($table) . '.' : '') . "id in (select term.oid from term where term.type in (%d, %d) and term.term = '%s' and term.uid = " . (($table) ? dbesc($table) . '.' : '') . "uid ) ", + intval($type), + intval($type2), + protect_sprintf(dbesc($s)) + ); + } + else { + return sprintf(" AND " . (($table) ? dbesc($table) . '.' : '') . "id in (select term.oid from term where term.type = %d and term.term = '%s' and term.uid = " . (($table) ? dbesc($table) . '.' : '') . "uid ) ", + intval($type), + protect_sprintf(dbesc($s)) + ); + } } @@ -84,7 +93,7 @@ function get_terms_oftype($arr,$type) { function format_term_for_display($term) { $s = ''; - if($term['type'] == TERM_HASHTAG) + if(($term['type'] == TERM_HASHTAG) || ($term['type'] == TERM_COMMUNITYTAG)) $s .= '#'; elseif($term['type'] == TERM_MENTION) $s .= '@'; diff --git a/include/text.php b/include/text.php index c2573da0c..eb9171b40 100644 --- a/include/text.php +++ b/include/text.php @@ -94,6 +94,8 @@ function z_input_filter($channel_id,$s,$type = 'text/bbcode') { return escape_tags($s); if($type == 'text/plain') return escape_tags($s); + if($type == 'application/x-pdl') + return escape_tags($s); $a = get_app(); if($a->is_sys) { @@ -529,11 +531,12 @@ function attribute_contains($attr, $s) { * LOGGER_DATA and LOGGER_ALL. * * Since PHP5.4 we get the file, function and line automatically where the logger - * was caleld, so no need to add it to the message anymore. + * was called, so no need to add it to the message anymore. * * @param string $msg Message to log * @param int $level A log level. */ + function logger($msg, $level = 0) { // turn off logger in install mode global $a; @@ -555,7 +558,13 @@ function logger($msg, $level = 0) { $where = basename($stack[0]['file']) . ':' . $stack[0]['line'] . ':' . $stack[1]['function'] . ': '; } - @file_put_contents($logfile, datetime_convert() . ':' . session_id() . ' ' . $where . $msg . PHP_EOL, FILE_APPEND); + $s = datetime_convert() . ':' . session_id() . ' ' . $where . $msg . PHP_EOL; + $pluginfo = array('filename' => $logfile, 'loglevel' => $level, 'message' => $s,'logged' => false); + + call_hooks('logger',$pluginfo); + + if(! $pluginfo['logged']) + @file_put_contents($pluginfo['filename'], $pluginfo['message'], FILE_APPEND); } /** @@ -872,15 +881,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); } /** @@ -1287,7 +1298,7 @@ function format_categories(&$item,$writeable) { function format_hashtags(&$item) { $s = ''; - $terms = get_terms_oftype($item['term'], TERM_HASHTAG); + $terms = get_terms_oftype($item['term'], array(TERM_HASHTAG,TERM_COMMUNITYTAG)); if($terms) { foreach($terms as $t) { $term = htmlspecialchars($t['term'], ENT_COMPAT, 'UTF-8', false) ; @@ -1392,13 +1403,13 @@ function prepare_body(&$item,$attach = false) { // if original photo width is <= 640px prepend it to item body if($object['link'][0]['width'] && $object['link'][0]['width'] <= 640) { - $s = '<div class="inline-photo-item-wrapper"><a href="' . zid(rawurldecode($object['id'])) . '" target="_newwin"><img class="inline-photo-item" style="max-width:' . $object['link'][0]['width'] . 'px; width:100%; height:auto;" src="' . zid(rawurldecode($object['link'][0]['href'])) . '"></a></div>' . $s; + $s = '<div class="inline-photo-item-wrapper"><a href="' . zid(rawurldecode($object['id'])) . '" target="_blank"><img class="inline-photo-item" style="max-width:' . $object['link'][0]['width'] . 'px; width:100%; height:auto;" src="' . zid(rawurldecode($object['link'][0]['href'])) . '"></a></div>' . $s; } // if original photo width is > 640px make it a cover photo if($object['link'][0]['width'] && $object['link'][0]['width'] > 640) { $scale = ((($object['link'][1]['width'] == 1024) || ($object['link'][1]['height'] == 1024)) ? 1 : 0); - $photo = '<a href="' . zid(rawurldecode($object['id'])) . '" target="_newwin"><img style="max-width:' . $object['link'][$scale]['width'] . 'px; width:100%; height:auto;" src="' . zid(rawurldecode($object['link'][$scale]['href'])) . '"></a>'; + $photo = '<a href="' . zid(rawurldecode($object['id'])) . '" target="_blank"><img style="max-width:' . $object['link'][$scale]['width'] . 'px; width:100%; height:auto;" src="' . zid(rawurldecode($object['link'][$scale]['href'])) . '"></a>'; } } @@ -1515,6 +1526,11 @@ function prepare_text($text, $content_type = 'text/bbcode', $cache = false) { $s = Markdown($text); break; + + case 'application/x-pdl'; + $s = escape_tags($text); + break; + // No security checking is done here at display time - so we need to verify // that the author is allowed to use PHP before storing. We also cannot allow // importation of PHP text bodies from other sites. Therefore this content @@ -1679,7 +1695,8 @@ function mimetype_select($channel_id, $current = 'text/bbcode') { 'text/bbcode', 'text/html', 'text/markdown', - 'text/plain' + 'text/plain', + 'application/x-pdl' ); $a = get_app(); diff --git a/include/widgets.php b/include/widgets.php index 0f61a04a0..a3f7444ec 100644 --- a/include/widgets.php +++ b/include/widgets.php @@ -7,6 +7,7 @@ require_once('include/dir_fns.php'); require_once('include/contact_widgets.php'); +require_once('include/attach.php'); function widget_profile($args) { @@ -661,6 +662,20 @@ function widget_conversations($arr) { return $o; } +function widget_eventsmenu($arr) { + if (! local_channel()) + return; + + return replace_macros(get_markup_template('events_side.tpl'), array( + '$title' => t('Events Menu'), + '$day' => t('Day View'), + '$week' => t('Week View'), + '$month' => t('Month View'), + '$export' => t('Export'), + '$upload' => t('Import'), + '$submit' => t('Submit') + )); +} function widget_design_tools($arr) { $a = get_app(); @@ -1221,3 +1236,102 @@ function widget_admin($arr) { return $o; } + + + +function widget_album($args) { + + $owner_uid = get_app()->profile_uid; + $sql_extra = permissions_sql($owner_uid); + + + if(! perm_is_allowed($owner_uid,get_observer_hash(),'view_storage')) + return ''; + + if($args['album']) + $album = $args['album']; + if($args['title']) + $title = $args['title']; + + /** + * This may return incorrect permissions if you have multiple directories of the same name. + * It is a limitation of the photo table using a name for a photo album instead of a folder hash + */ + + if($album) { + $x = q("select hash from attach where filename = '%s' and uid = %d limit 1", + dbesc($album), + intval($owner_uid) + ); + if($x) { + $y = attach_can_view_folder($owner_uid,get_observer_hash(),$x[0]['hash']); + if(! $y) + return ''; + } + } + + $order = 'DESC'; + + $r = q("SELECT p.resource_id, p.id, p.filename, p.type, p.scale, p.description, p.created FROM photo p INNER JOIN + (SELECT resource_id, max(scale) scale FROM photo WHERE uid = %d AND album = '%s' AND scale <= 4 AND photo_usage IN ( %d, %d ) $sql_extra GROUP BY resource_id) ph + ON (p.resource_id = ph.resource_id AND p.scale = ph.scale) + ORDER BY created $order ", + intval($owner_uid), + dbesc($album), + intval(PHOTO_NORMAL), + intval(PHOTO_PROFILE) + ); + + //edit album name + $album_edit = null; + + + $photos = array(); + if($r) { + $twist = 'rotright'; + foreach($r as $rr) { + + if($twist == 'rotright') + $twist = 'rotleft'; + else + $twist = 'rotright'; + + $ext = $phototypes[$rr['type']]; + + $imgalt_e = $rr['filename']; + $desc_e = $rr['description']; + + $imagelink = (z_root() . '/photos/' . get_app()->profile['channel_address'] . '/image/' . $rr['resource_id']); + + + $photos[] = array( + 'id' => $rr['id'], + 'twist' => ' ' . $twist . rand(2,4), + 'link' => $imagelink, + 'title' => t('View Photo'), + 'src' => z_root() . '/photo/' . $rr['resource_id'] . '-' . $rr['scale'] . '.' .$ext, + 'alt' => $imgalt_e, + 'desc'=> $desc_e, + 'ext' => $ext, + 'hash'=> $rr['resource_id'], + 'unknown' => t('Unknown') + ); + } + } + + + $tpl = get_markup_template('photo_album.tpl'); + $o .= replace_macros($tpl, array( + '$photos' => $photos, + '$album' => (($title) ? $title : $album), + '$album_edit' => array(t('Edit Album'), $album_edit), + '$can_post' => false, + '$upload' => array(t('Upload'), z_root() . '/photos/' . get_app()->profile['channel_address'] . '/upload/' . bin2hex($album)), + '$order' => false, + '$upload_form' => $upload_form, + '$usage' => $usage_message + )); + + return $o; +} + diff --git a/include/zot.php b/include/zot.php index d5d68f72c..2366c1d2d 100644 --- a/include/zot.php +++ b/include/zot.php @@ -745,8 +745,8 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { || ($r[0]['xchan_follow'] != $arr['follow_url']) || ($r[0]['xchan_connpage'] != $arr['connect_url']) || ($r[0]['xchan_url'] != $arr['url']) - || $hidden_changed || adult_changed || deleted_changed || $pubforum_changed ) { - $r = q("update xchan set xchan_name = '%s', xchan_name_date = '%s', xchan_connurl = '%s', xchan_follow = '%s', + || $hidden_changed || $adult_changed || $deleted_changed || $pubforum_changed ) { + $rup = q("update xchan set xchan_name = '%s', xchan_name_date = '%s', xchan_connurl = '%s', xchan_follow = '%s', xchan_connpage = '%s', xchan_hidden = %d, xchan_selfcensored = %d, xchan_deleted = %d, xchan_pubforum = %d, xchan_addr = '%s', xchan_url = '%s' where xchan_hash = '%s'", dbesc(($arr['name']) ? $arr['name'] : '-'), @@ -763,8 +763,8 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { dbesc($xchan_hash) ); - logger('import_xchan: existing: ' . print_r($r[0],true), LOGGER_DATA); - logger('import_xchan: new: ' . print_r($arr,true), LOGGER_DATA); + logger('import_xchan: update: existing: ' . print_r($r[0],true), LOGGER_DATA); + logger('import_xchan: update: new: ' . print_r($arr,true), LOGGER_DATA); $what .= 'xchan '; $changed = true; } @@ -1933,11 +1933,12 @@ function remove_community_tag($sender, $arr, $uid) { return; } - q("delete from term where uid = %d and oid = %d and otype = %d and type = %d and term = '%s' and url = '%s'", + q("delete from term where uid = %d and oid = %d and otype = %d and type in ( %d, %d ) and term = '%s' and url = '%s'", intval($uid), intval($r[0]['id']), intval(TERM_OBJ_POST), intval(TERM_HASHTAG), + intval(TERM_COMMUNITYTAG), dbesc($i['object']['title']), dbesc(get_rel_link($i['object']['link'],'alternate')) ); @@ -3949,6 +3950,10 @@ function delivery_report_is_storable($dr) { if(! $c) return false; + + + + // is the recipient one of our connections, or do we want to store every report? $r = explode(' ', $dr['recipient']); @@ -3957,6 +3962,14 @@ function delivery_report_is_storable($dr) { if($pcf) return true; + // We always add ourself as a recipient to private and relayed posts + // So if a remote site says they can't find us, that's no big surprise + // and just creates a lot of extra report noise + + if(($dr['location'] !== z_root()) && ($dr['sender'] === $rxchan) && ($dr['status'] === 'recipient_not_found')) + return false; + + $r = q("select abook_id from abook where abook_xchan = '%s' and abook_channel = %d limit 1", dbesc($rxchan), intval($c[0]['channel_id']) |