Merge branch 'master' into tres

Conflicts:
	include/Contact.php
	include/ItemObject.php
	include/api.php
	include/attach.php
	include/diaspora.php
	include/dir_fns.php
	include/enotify.php
	include/event.php
	include/expire.php
	include/items.php
	include/notifier.php
	include/notify.php
	include/photos.php
	include/taxonomy.php
	include/text.php
	include/widgets.php
	include/zot.php
	mod/admin.php
	mod/channel.php
	mod/dirsearch.php
	mod/display.php
	mod/editwebpage.php
	mod/events.php
	mod/home.php
	mod/item.php
	mod/manage.php
	mod/mood.php
	mod/network.php
	mod/page.php
	mod/photos.php
	mod/ping.php
	mod/post.php
	mod/thing.php
	mod/viewsrc.php
	view/css/mod_events.css
This commit is contained in:
friendica
2015-04-23 19:49:41 -07:00
1727 changed files with 56838 additions and 208980 deletions

View File

@@ -1,11 +1,10 @@
<?php
require_once 'boot.php';
/**
* Interface for template engines
*/
interface ITemplateEngine {
public function replace_macros($s,$v);
public function get_markup_template($file, $root='');
}
<?php
require_once 'boot.php';
/**
* @brief Interface for template engines.
*/
interface ITemplateEngine {
public function replace_macros($s, $v);
public function get_markup_template($file, $root='');
}

View File

@@ -177,7 +177,7 @@ function reflect_photo_callback($matches) {
'resource_id' => str_replace('-','',$hash),
'filename' => $hash . '.jpg',
'type' => 'image/jpeg',
'not_visible' => true
'visible' => false
)
);

View File

@@ -134,6 +134,39 @@ class Item extends BaseObject {
$profile_name = $item['author']['xchan_name'];
$location = format_location($item);
$isevent = false;
$attend = null;
$canvote = false;
// process action responses - e.g. like/dislike/attend/agree/whatever
$response_verbs = array('like');
if(feature_enabled($conv->get_profile_owner(),'dislike'))
$response_verbs[] = 'dislike';
if($item['obj_type'] === ACTIVITY_OBJ_EVENT) {
$response_verbs[] = 'attendyes';
$response_verbs[] = 'attendno';
$response_verbs[] = 'attendmaybe';
if($this->is_commentable()) {
$isevent = true;
$attend = array( t('I will attend'), t('I will not attend'), t('I might attend'));
}
}
$consensus = (($item['item_flags'] & ITEM_CONSENSUS) ? true : false);
if($consensus) {
$response_verbs[] = 'agree';
$response_verbs[] = 'disagree';
$response_verbs[] = 'abstain';
if($this->is_commentable()) {
$conlabels = array( t('I agree'), t('I disagree'), t('I abstain'));
$canvote = true;
}
}
if(! feature_enabled($conv->get_profile_owner(),'dislike'))
unset($conv_responses['dislike']);
$responses = get_responses($conv_responses,$response_verbs,$this,$item);
$like_count = ((x($conv_responses['like'],$item['mid'])) ? $conv_responses['like'][$item['mid']] : '');
$like_list = ((x($conv_responses['like'],$item['mid'])) ? $conv_responses['like'][$item['mid'] . '-l'] : '');
@@ -253,6 +286,11 @@ class Item extends BaseObject {
'body' => $body,
'text' => strip_tags($body),
'id' => $this->get_id(),
'isevent' => $isevent,
'attend' => $attend,
'consensus' => $consensus,
'conlabels' => $conlabels,
'canvote' => $canvote,
'linktitle' => sprintf( t('View %s\'s profile - %s'), $profile_name, $item['author']['xchan_addr']),
'olinktitle' => sprintf( t('View %s\'s profile - %s'), $this->get_owner_name(), $item['owner']['xchan_addr']),
'llink' => $item['llink'],
@@ -271,7 +309,7 @@ class Item extends BaseObject {
'title_tosource' => get_pconfig($conv->get_profile_owner(),'system','title_tosource'),
'ago' => relative_date($item['created']),
'app' => $item['app'],
'str_app' => sprintf( t(' from %s'), $item['app']),
'str_app' => sprintf( t('from %s'), $item['app']),
'isotime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'c'),
'localtime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'r'),
'editedtime' => (($item['edited'] != $item['created']) ? sprintf( t('last edited: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['edited'], 'r')) : ''),
@@ -307,6 +345,7 @@ class Item extends BaseObject {
'comment_count_txt' => $comment_count_txt,
'list_unseen_txt' => $list_unseen_txt,
'markseen' => t('Mark all seen'),
'responses' => $responses,
'like_count' => $like_count,
'like_list' => $like_list,
'like_list_part' => $like_list_part,
@@ -569,7 +608,7 @@ class Item extends BaseObject {
if((! visible_activity($child->data)) || array_key_exists('author_blocked',$child->data)) {
continue;
}
if($child->data['item_unseen'])
if(intval($child->data['item_unseen']))
$total ++;
}
}
@@ -633,7 +672,7 @@ class Item extends BaseObject {
'$edquote' => t('Quote'),
'$edcode' => t('Code'),
'$edimg' => t('Image'),
'$edurl' => t('Link'),
'$edurl' => t('Insert Link'),
'$edvideo' => t('Video'),
'$preview' => t('Preview'), // ((feature_enabled($conv->get_profile_owner(),'preview')) ? t('Preview') : ''),
'$indent' => $indent,

View File

@@ -95,6 +95,7 @@ class RedBrowser extends DAV\Browser\Plugin {
'{DAV:}getlastmodified',
), 1);
$parent = $this->server->tree->getNodeForPath($path);
$parentpath = array();
@@ -167,6 +168,7 @@ class RedBrowser extends DAV\Browser\Plugin {
$fullPath = DAV\URLUtil::encodePath('/' . trim($this->server->getBaseUri() . ($path ? $path . '/' : '') . $name, '/'));
$displayName = isset($file[200]['{DAV:}displayname']) ? $file[200]['{DAV:}displayname'] : $name;
$displayName = $this->escapeHTML($displayName);
@@ -269,18 +271,19 @@ class RedBrowser extends DAV\Browser\Plugin {
'$nick' => $this->auth->getCurrentUser()
));
get_app()->page['content'] = $html;
load_pdl(get_app());
$a = get_app();
$a->page['content'] = $html;
load_pdl($a);
$theme_info_file = "view/theme/" . current_theme() . "/php/theme.php";
if (file_exists($theme_info_file)){
require_once($theme_info_file);
if (function_exists(str_replace('-', '_', current_theme()) . '_init')) {
$func = str_replace('-', '_', current_theme()) . '_init';
$func(get_app());
$func($a);
}
}
construct_page(get_app());
construct_page($a);
}
/**

View File

@@ -49,6 +49,7 @@ class RedDirectory extends DAV\Node implements DAV\ICollection, DAV\IQuota {
* @param RedBasicAuth &$auth_plugin
*/
public function __construct($ext_path, &$auth_plugin) {
// $ext_path = urldecode($ext_path);
//logger('directory ' . $ext_path, LOGGER_DATA);
$this->ext_path = $ext_path;
// remove "/cloud" from the beginning of the path

View File

@@ -80,7 +80,8 @@ class RedFile extends DAV\Node implements DAV\IFile {
$newName = str_replace('/', '%2F', $newName);
$r = q("UPDATE attach SET filename = '%s' WHERE hash = '%s' AND id = %d",
dbesc($this->data['filename']),
dbesc($newName),
dbesc($this->data['hash']),
intval($this->data['id'])
);
}

View File

@@ -1,4 +1,8 @@
<?php /** @file */
<?php
/**
* @file include/account.php
* @brief Somme account related functions.
*/
require_once('include/config.php');
require_once('include/network.php');
@@ -43,15 +47,14 @@ function check_account_email($email) {
function check_account_password($password) {
$result = array('error' => false, 'message' => '');
// The only validation we perform by default is pure Javascript to
// The only validation we perform by default is pure Javascript to
// check minimum length and that both entered passwords match.
// Use hooked functions to perform complexity requirement checks.
// Use hooked functions to perform complexity requirement checks.
$arr = array('password' => $password, 'result' => $result);
call_hooks('check_account_password', $arr);
return $arr['result'];
}
function check_account_invite($invite_code) {
@@ -75,7 +78,6 @@ function check_account_invite($invite_code) {
call_hooks('check_account_invite', $arr);
return $arr['result'];
}
function check_account_admin($arr) {
@@ -109,7 +111,7 @@ function create_account($arr) {
$flags = ((x($arr,'account_flags')) ? intval($arr['account_flags']) : ACCOUNT_OK);
$roles = ((x($arr,'account_roles')) ? intval($arr['account_roles']) : 0 );
$expires = ((x($arr,'expires')) ? intval($arr['expires']) : NULL_DATE);
$default_service_class = get_config('system','default_service_class');
if($default_service_class === false)
@@ -132,16 +134,16 @@ function create_account($arr) {
// allow the admin_email account to be admin, but only if it's the first account.
$c = account_total();
if(($c === 0) && (check_account_admin($arr)))
if (($c === 0) && (check_account_admin($arr)))
$roles |= ACCOUNT_ROLE_ADMIN;
// Ensure that there is a host keypair.
// Ensure that there is a host keypair.
if((! get_config('system','pubkey')) && (! get_config('system','prvkey'))) {
$hostkey = new_keypair(4096);
set_config('system','pubkey',$hostkey['pubkey']);
set_config('system','prvkey',$hostkey['prvkey']);
}
if ((! get_config('system', 'pubkey')) && (! get_config('system', 'prvkey'))) {
$hostkey = new_keypair(4096);
set_config('system', 'pubkey', $hostkey['pubkey']);
set_config('system', 'prvkey', $hostkey['prvkey']);
}
$invite_result = check_account_invite($invite_code);
if($invite_result['error']) {
@@ -180,7 +182,6 @@ function create_account($arr) {
dbesc($roles),
dbesc($expires),
dbesc($default_service_class)
);
if(! $r) {
logger('create_account: DB INSERT failed.');
@@ -195,7 +196,7 @@ function create_account($arr) {
if($r && count($r)) {
$result['account'] = $r[0];
}
else {
else {
logger('create_account: could not retrieve newly created account');
}
@@ -215,8 +216,8 @@ function create_account($arr) {
$result['success'] = true;
$result['email'] = $email;
$result['password'] = $password;
return $result;
return $result;
}
@@ -255,7 +256,6 @@ function verify_email_address($arr) {
logger('send_reg_approval_email: failed to ' . $admin['email'] . 'account_id: ' . $arr['account']['account_id']);
return $res;
}
@@ -292,7 +292,6 @@ function send_reg_approval_email($arr) {
$details = (($ip) ? $ip . ' [' . gethostbyaddr($ip) . ']' : '[unknown or stealth IP]');
$delivered = 0;
foreach($admins as $admin) {
@@ -346,11 +345,14 @@ function send_verification_email($email,$password) {
return($res ? true : false);
}
/**
* @brief Allows a user registration.
*
* @param string $hash
* @return array|boolean
*/
function user_allow($hash) {
$a = get_app();
$ret = array('success' => false);
$register = q("SELECT * FROM `register` WHERE `hash` = '%s' LIMIT 1",
@@ -363,7 +365,7 @@ function user_allow($hash) {
$account = q("SELECT * FROM account WHERE account_id = %d LIMIT 1",
intval($register[0]['uid'])
);
if(! $account)
return $ret;
@@ -381,7 +383,7 @@ function user_allow($hash) {
intval(ACCOUNT_PENDING),
intval($register[0]['uid'])
);
push_lang($register[0]['language']);
$email_tpl = get_intltext_template("register_open_eml.tpl");
@@ -402,18 +404,23 @@ function user_allow($hash) {
pop_lang();
if($res) {
if ($res) {
info( t('Account approved.') . EOL );
return true;
}
}
}
// This does not have to go through user_remove() and save the nickname
// permanently against re-registration, as the person was not yet
// allowed to have friends on this system
/**
* @brief Denies a user registration.
*
* This does not have to go through user_remove() and save the nickname
* permanently against re-registration, as the person was not yet
* allowed to have friends on this system
*
* @param string $hash
* @return boolean
*/
function user_deny($hash) {
$register = q("SELECT * FROM register WHERE hash = '%s' LIMIT 1",
@@ -426,7 +433,7 @@ function user_deny($hash) {
$account = q("SELECT account_id, account_email FROM account WHERE account_id = %d LIMIT 1",
intval($register[0]['uid'])
);
if(! $account)
return false;
@@ -438,15 +445,14 @@ function user_deny($hash) {
dbesc($register[0]['id'])
);
notice( sprintf(t('Registration revoked for %s'), $account[0]['account_email']) . EOL);
return true;
}
function user_approve($hash) {
$a = get_app();
$ret = array('success' => false);
$register = q("SELECT * FROM `register` WHERE `hash` = '%s' and password = 'verify' LIMIT 1",
@@ -459,7 +465,7 @@ function user_approve($hash) {
$account = q("SELECT * FROM account WHERE account_id = %d LIMIT 1",
intval($register[0]['uid'])
);
if(! $account)
return $ret;
@@ -482,21 +488,16 @@ function user_approve($hash) {
intval(ACCOUNT_UNVERIFIED),
intval($register[0]['uid'])
);
info( t('Account verified. Please login.') . EOL );
return true;
}
/**
* @function downgrade_accounts()
* Checks for accounts that have past their expiration date.
* @brief Checks for accounts that have past their expiration date.
*
* If the account has a service class which is not the site default,
* the service class is reset to the site default and expiration reset to never.
* If the account has no service class it is expired and subsequently disabled.
@@ -506,8 +507,6 @@ function user_approve($hash) {
* not the job of this function, but this can be implemented by plugin if desired.
* Default behaviour is to stop allowing additional resources to be consumed.
*/
function downgrade_accounts() {
$r = q("select * from account where not ( account_flags & %d )>0
@@ -523,9 +522,7 @@ function downgrade_accounts() {
$basic = get_config('system','default_service_class');
foreach($r as $rr) {
if(($basic) && ($rr['account_service_class']) && ($rr['account_service_class'] != $basic)) {
$x = q("UPDATE account set account_service_class = '%s', account_expires = '%s'
where account_id = %d",
@@ -550,74 +547,98 @@ function downgrade_accounts() {
}
/**
* @brief Check service_class restrictions.
*
* If there are no service_classes defined, everything is allowed.
* If $usage is supplied, we check against a maximum count and return true if
* the current usage is less than the subscriber plan allows. Otherwise we
* return boolean true or false if the property is allowed (or not) in this
* subscriber plan. An unset property for this service plan means the property
* is allowed, so it is only necessary to provide negative properties for each
* plan, or what the subscriber is not allowed to do.
*
* Like account_service_class_allows() but queries directly by account rather
* than channel. Service classes are set for accounts, so we look up the
* account for the channel and fetch the service class restrictions of the
* account.
*
* @see account_service_class_allows() if you have a channel_id already
* @see service_class_fetch()
*
* @param int $uid The channel_id to check
* @param string $property The service class property to check for
* @param string|boolean $usage (optional) The value to check against
* @return boolean
*/
function service_class_allows($uid, $property, $usage = false) {
$limit = service_class_fetch($uid, $property);
// check service_class restrictions. If there are no service_classes defined, everything is allowed.
// if $usage is supplied, we check against a maximum count and return true if the current usage is
// less than the subscriber plan allows. Otherwise we return boolean true or false if the property
// is allowed (or not) in this subscriber plan. An unset property for this service plan means
// the property is allowed, so it is only necessary to provide negative properties for each plan,
// or what the subscriber is not allowed to do.
if($limit === false)
return true; // No service class set => everything is allowed
function service_class_allows($uid,$property,$usage = false) {
$a = get_app();
if($uid == local_channel()) {
$service_class = $a->account['account_service_class'];
}
else {
$r = q("select account_service_class as service_class
from channel c, account a
where c.channel_account_id=a.account_id and c.channel_id= %d limit 1",
intval($uid)
);
if($r !== false and count($r)) {
$service_class = $r[0]['service_class'];
}
}
if(! x($service_class))
return true; // everything is allowed
$arr = get_config('service_class',$service_class);
if(! is_array($arr) || (! count($arr)))
return true;
if($usage === false)
return ((x($arr[$property])) ? (bool) $arr[$property] : true);
else {
if(! array_key_exists($property,$arr))
return true;
return (((intval($usage)) < intval($arr[$property])) ? true : false);
if($usage === false) {
// We use negative values for not allowed properties in a subscriber plan
return ((x($limit)) ? (bool) $limit : true);
} else {
return (((intval($usage)) < intval($limit)) ? true : false);
}
}
// like service_class_allows but queries by account rather than channel
function account_service_class_allows($aid,$property,$usage = false) {
$a = get_app();
$r = q("select account_service_class as service_class from account where account_id = %d limit 1",
intval($aid)
);
if($r !== false and count($r)) {
$service_class = $r[0]['service_class'];
}
/**
* @brief Check service class restrictions by account.
*
* If there are no service_classes defined, everything is allowed.
* If $usage is supplied, we check against a maximum count and return true if
* the current usage is less than the subscriber plan allows. Otherwise we
* return boolean true or false if the property is allowed (or not) in this
* subscriber plan. An unset property for this service plan means the property
* is allowed, so it is only necessary to provide negative properties for each
* plan, or what the subscriber is not allowed to do.
*
* Like service_class_allows() but queries directly by account rather than channel.
*
* @see service_class_allows() if you have a channel_id instead of an account_id
* @see account_service_class_fetch()
*
* @param int $aid The account_id to check
* @param string $property The service class property to check for
* @param int|boolean $usage (optional) The value to check against
* @return boolean
*/
function account_service_class_allows($aid, $property, $usage = false) {
if(! x($service_class))
return true; // everything is allowed
$limit = account_service_class_fetch($aid, $property);
$arr = get_config('service_class',$service_class);
if(! is_array($arr) || (! count($arr)))
return true;
if($limit === false)
return true; // No service class is set => everything is allowed
if($usage === false)
return ((x($arr[$property])) ? (bool) $arr[$property] : true);
else {
if(! array_key_exists($property,$arr))
return true;
return (((intval($usage)) < intval($arr[$property])) ? true : false);
if($usage === false) {
// We use negative values for not allowed properties in a subscriber plan
return ((x($limit)) ? (bool) $limit : true);
} else {
return (((intval($usage)) < intval($limit)) ? true : false);
}
}
function service_class_fetch($uid,$property) {
/**
* @brief Queries a service class value for a channel and property.
*
* Service classes are set for accounts, so look up the account for this channel
* and fetch the service classe of the account.
*
* If no service class is available it returns false and everything should be
* allowed.
*
* @see account_service_class_fetch()
*
* @param int $uid The channel_id to query
* @param string $property The service property name to check for
* @return boolean|int
*
* @todo Should we merge this with account_service_class_fetch()?
*/
function service_class_fetch($uid, $property) {
$a = get_app();
if($uid == local_channel()) {
$service_class = $a->account['account_service_class'];
@@ -635,17 +656,27 @@ function service_class_fetch($uid,$property) {
if(! x($service_class))
return false; // everything is allowed
$arr = get_config('service_class',$service_class);
$arr = get_config('service_class', $service_class);
if(! is_array($arr) || (! count($arr)))
return false;
return((array_key_exists($property,$arr)) ? $arr[$property] : false);
return((array_key_exists($property, $arr)) ? $arr[$property] : false);
}
// like service_class_fetch but queries by account rather than channel
function account_service_class_fetch($aid,$property) {
/**
* @brief Queries a service class value for an account and property.
*
* Like service_class_fetch() but queries by account rather than channel.
*
* @see service_class_fetch() if you have channel_id.
* @see account_service_class_allows()
*
* @param int $aid The account_id to query
* @param string $property The service property name to check for
* @return boolean|int
*/
function account_service_class_fetch($aid, $property) {
$r = q("select account_service_class as service_class from account where account_id = %d limit 1",
intval($aid)
@@ -657,17 +688,17 @@ function account_service_class_fetch($aid,$property) {
if(! x($service_class))
return false; // everything is allowed
$arr = get_config('service_class',$service_class);
$arr = get_config('service_class', $service_class);
if(! is_array($arr) || (! count($arr)))
return false;
return((array_key_exists($property,$arr)) ? $arr[$property] : false);
return((array_key_exists($property, $arr)) ? $arr[$property] : false);
}
function upgrade_link($bbcode = false) {
$l = get_config('service_class','upgrade_link');
$l = get_config('service_class', 'upgrade_link');
if(! $l)
return '';
if($bbcode)
@@ -685,4 +716,4 @@ function upgrade_message($bbcode = false) {
function upgrade_bool_message($bbcode = false) {
$x = upgrade_link($bbcode);
return t('This action is not available under your subscription plan.') . (($x) ? ' ' . $x : '') ;
}
}

View File

@@ -267,40 +267,46 @@ require_once('include/items.php');
* Returns user info array.
*/
function api_get_user(&$a, $contact_id = Null){
function api_get_user(&$a, $contact_id = null, $contact_xchan = null){
global $called_api;
$user = null;
$extra_query = "";
if(!is_null($contact_id)){
$user=$contact_id;
$extra_query = " AND abook_id = %d ";
if(! is_null($contact_xchan)) {
$user = local_channel();
$extra_query = " and abook_xchan = '" . dbesc($contact_xchan) . "' ";
}
if(is_null($user) && x($_GET, 'user_id')) {
$user = intval($_GET['user_id']);
$extra_query = " AND abook_id = %d ";
}
if(is_null($user) && x($_GET, 'screen_name')) {
$user = dbesc($_GET['screen_name']);
$extra_query = " AND xchan_addr like '%s@%%' ";
if (api_user()!==false)
$extra_query .= " AND abook_channel = ".intval(api_user());
}
if (is_null($user) && argc() > (count($called_api)-1)){
$argid = count($called_api);
list($user, $null) = explode(".",argv($argid));
if(is_numeric($user)){
$user = intval($user);
else {
if(!is_null($contact_id)){
$user=$contact_id;
$extra_query = " AND abook_id = %d ";
} else {
$user = dbesc($user);
}
if(is_null($user) && x($_GET, 'user_id')) {
$user = intval($_GET['user_id']);
$extra_query = " AND abook_id = %d ";
}
if(is_null($user) && x($_GET, 'screen_name')) {
$user = dbesc($_GET['screen_name']);
$extra_query = " AND xchan_addr like '%s@%%' ";
if (api_user() !== false)
if (api_user()!==false)
$extra_query .= " AND abook_channel = ".intval(api_user());
}
if (is_null($user) && argc() > (count($called_api)-1) && (strstr($a->cmd,'/users'))){
$argid = count($called_api);
list($xx, $null) = explode(".",argv($argid));
if(is_numeric($xx)){
$user = intval($xx);
$extra_query = " AND abook_id = %d ";
} else {
$user = dbesc($xx);
$extra_query = " AND xchan_addr like '%s@%%' ";
if (api_user() !== false)
$extra_query .= " AND abook_channel = ".intval(api_user());
}
}
}
if (! $user) {
@@ -316,11 +322,13 @@ require_once('include/items.php');
logger('api_user: ' . $extra_query . ', user: ' . $user);
// user info
$uinfo = q("SELECT * from abook left join xchan on abook_xchan = xchan_hash
WHERE 1
$extra_query",
$user
);
if (count($uinfo)==0) {
return False;
}
@@ -392,7 +400,7 @@ require_once('include/items.php');
'utc_offset' => "+00:00",
'time_zone' => 'UTC', //$uinfo[0]['timezone'],
'geo_enabled' => false,
'statuses_count' => intval($countitms), #XXX: fix me
'statuses_count' => intval($countitms), //#XXX: fix me
'lang' => get_app()->language,
'description' => (($profile) ? $profile[0]['pdesc'] : ''),
'followers_count' => intval($countfollowers),
@@ -408,11 +416,16 @@ require_once('include/items.php');
'profile_background_tile' => false,
'profile_use_background_image' => false,
'notifications' => false,
'following' => '', #XXX: fix me
'verified' => true, #XXX: fix me
'status' => array()
'following' => '', // #XXX: fix me
'verified' => true // #XXX: fix me
);
$x = api_get_status($uinfo[0]['xchan_hash']);
if($x)
$ret['status'] = $x;
// logger('api_get_user: ' . print_r($ret,true));
return $ret;
}
@@ -444,12 +457,12 @@ require_once('include/items.php');
'description' => '',
'profile_image_url' => $item['author']['xchan_photo_m'],
'url' => $item['author']['xchan_url'],
'protected' => false, #
'protected' => false,
'followers_count' => 0,
'friends_count' => 0,
'created_at' => '',
'favourites_count' => 0,
'utc_offset' => 0, #XXX: fix me
'utc_offset' => 0, // #XXX: fix me
'time_zone' => '', //$uinfo[0]['timezone'],
'statuses_count' => 0,
'following' => 1,
@@ -458,7 +471,7 @@ require_once('include/items.php');
'uid' => 0,
'contact_url' => 0,
'geo_enabled' => false,
'lang' => 'en', #XXX: fix me
'lang' => 'en', // #XXX: fix me
'contributors_enabled' => false,
'follow_request_sent' => false,
'profile_background_color' => 'cfe8f6',
@@ -469,9 +482,8 @@ require_once('include/items.php');
'profile_background_image_url' => '',
'profile_background_tile' => false,
'profile_use_background_image' => false,
'verified' => true, #XXX: fix me
'followers' => '', #XXX: fix me
'status' => array()
'verified' => true, // #XXX: fix me
'followers' => '' // #XXX: fix me
);
return $ret;
@@ -620,10 +632,14 @@ require_once('include/items.php');
function api_red_xchan(&$a,$type) {
logger('api_xchan');
if(api_user() === false)
return false;
logger('api_xchan');
require_once('include/hubloc.php');
if($_SERVER['request_method'] === 'POST') {
if($_SERVER['REQUEST_METHOD'] === 'POST') {
$r = xchan_store($_REQUEST);
}
$r = xchan_fetch($_REQUEST);
@@ -661,8 +677,9 @@ require_once('include/items.php');
$a->argv[1] = $user_info['screen_name'];
$_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo
require_once('mod/wall_upload.php');
$posted = wall_upload_post($a);
$_FILES['userfile'] = $_FILES['media'];
require_once('mod/wall_attach.php');
$posted = wall_attach_post($a);
//now that we have the img url in bbcode we can add it to the status and insert the wall item.
$_REQUEST['body']=$txt."\n\n".$posted;
@@ -725,6 +742,16 @@ require_once('include/items.php');
else
$_REQUEST['parent_mid'] = $parent;
if($_REQUEST['namespace'] && $parent) {
$x = q("select iid from item_id where service = '%s' and sid = '%s' limit 1",
dbesc($_REQUEST['namespace']),
dbesc($parent)
);
if($x) {
$_REQUEST['parent'] = $x[0]['iid'];
}
}
if(requestdata('lat') && requestdata('long'))
$_REQUEST['coord'] = sprintf("%s %s",requestdata('lat'),requestdata('long'));
@@ -739,8 +766,8 @@ require_once('include/items.php');
$_FILES['userfile'] = $_FILES['media'];
// upload the image if we have one
$_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo
require_once('mod/wall_upload.php');
$media = wall_upload_post($a);
require_once('mod/wall_attach.php');
$media = wall_attach_post($a);
if(strlen($media)>0)
$_REQUEST['body'] .= "\n\n".$media;
}
@@ -791,13 +818,65 @@ require_once('include/items.php');
api_register_func('api/red/item/new','red_item_new', true);
function api_get_status($xchan_hash) {
require_once('include/security.php');
$lastwall = q("SELECT * from item where
item_private = 0 and item_restrict = 0
and author_xchan = '%s'
and allow_cid = '' and allow_gid = '' and deny_cid = '' and deny_gid = ''
and verb = '%s'
order by created desc limit 1",
dbesc($xchan_hash),
dbesc(ACTIVITY_POST)
);
if($lastwall){
$lastwall = $lastwall[0];
$in_reply_to_status_id = '';
$in_reply_to_user_id = '';
$in_reply_to_screen_name = '';
if($lastwall['author_xchan'] != $lastwall['owner_xchan']) {
$w = q("select * from abook left join xchan on abook_xchan = xchan_hash where
xchan_hash = '%s' limit 1",
dbesc($lastwall['owner_xchan'])
);
if($w) {
$in_reply_to_user_id = $w[0]['abook_id'];
$in_reply_to_screen_name = substr($w[0]['xchan_addr'],0,strpos($w[0]['xchan_addr'],'@'));
}
}
if ($lastwall['parent']!=$lastwall['id']) {
$in_reply_to_status_id=$lastwall['thr_parent'];
if(! $in_reply_to_user_id) {
$in_reply_to_user_id = $user_info['id'];
$in_reply_to_screen_name = $user_info['screen_name'];
}
}
unobscure($lastwall);
$status_info = array(
'text' => html2plain(prepare_text($lastwall['body'],$lastwall['mimetype']), 0),
'truncated' => false,
'created_at' => api_date($lastwall['created']),
'in_reply_to_status_id' => $in_reply_to_status_id,
'source' => (($lastwall['app']) ? $lastwall['app'] : 'web'),
'id' => ($lastwall['id']),
'in_reply_to_user_id' => $in_reply_to_user_id,
'in_reply_to_screen_name' => $in_reply_to_screen_name,
'geo' => '',
'favorited' => false,
'coordinates' => $lastwall['coord'],
'place' => $lastwall['location'],
'contributors' => ''
);
}
return $status_info;
}
function api_status_show(&$a, $type){
$user_info = api_get_user($a);
@@ -806,12 +885,11 @@ require_once('include/items.php');
require_once('include/security.php');
$lastwall = q("SELECT * from item where 1
and item_private = 0 and item_restrict = 0
$lastwall = q("SELECT * from item where
item_private = 0 and item_restrict = 0
and author_xchan = '%s'
and allow_cid = '' and allow_gid = '' and deny_cid = '' and deny_gid = ''
and verb = '%s'
and uid in ( " . stream_perms_api_uids() . " )
order by created desc limit 1",
dbesc($user_info['guid']),
dbesc(ACTIVITY_POST)
@@ -885,7 +963,6 @@ require_once('include/items.php');
and author_xchan = '%s'
and allow_cid = '' and allow_gid = '' and deny_cid = '' and deny_gid = ''
and verb = '%s'
and uid in ( " . stream_perms_api_uids() . " )
order by created desc limit 1",
dbesc($user_info['guid']),
dbesc(ACTIVITY_POST)
@@ -1031,8 +1108,8 @@ require_once('include/items.php');
if (api_user()===false) return false;
$user_info = api_get_user($a);
// get last newtork messages
$sys = get_sys_channel();
// params
$count = (x($_REQUEST,'count')?$_REQUEST['count']:20);
@@ -1054,7 +1131,7 @@ require_once('include/items.php');
and allow_cid = '' and allow_gid = ''
and deny_cid = '' and deny_gid = ''
and item_private = 0
and uid in ( " . stream_perms_api_uids() . " )
and uid = " . $sys['channel_id'] . "
$sql_extra
AND id > %d group by mid
order by received desc LIMIT %d OFFSET %d ",
@@ -1401,58 +1478,155 @@ require_once('include/items.php');
api_register_func('api/statuses/user_timeline','api_statuses_user_timeline', true);
/**
* Star/unstar an item
* param: id : id of the item
*
* api v1 : https://web.archive.org/web/20131019055350/https://dev.twitter.com/docs/api/1/post/favorites/create/%3Aid
*/
function api_favorites_create_destroy(&$a, $type){
logger('favorites_create_destroy');
if (api_user()===false)
return false;
$action = str_replace(".".$type,"",argv(2));
if (argc() > 3) {
$itemid = intval(argv(3));
} else {
$itemid = intval($_REQUEST['id']);
}
$item = q("SELECT * FROM item WHERE id = %d AND uid = %d",
intval($itemid),
intval(api_user())
);
if (! $item)
return false;
switch($action){
case "create":
$flags = $item[0]['item_flags'] | ITEM_STARRED;
break;
case "destroy":
$flags = $item[0]['item_flags'] | (~ ITEM_STARRED);
break;
default:
return false;
}
$r = q("UPDATE item SET item_flags = %d where id = %d and uid = %d",
intval($flags),
intval($itemid),
intval(api_user())
);
if(! $r)
return false;
$item = q("SELECT * FROM item WHERE id = %d AND uid = %d",
intval($itemid),
intval(api_user())
);
xchan_query($item,true);
$user_info = api_get_user($a);
$rets = api_format_items($item,$user_info);
$ret = $rets[0];
$data = array('$status' => $ret);
switch($type){
case "atom":
case "rss":
$data = api_rss_extra($a, $data, $user_info);
}
return api_apply_template("status", $type, $data);
}
api_register_func('api/favorites/create', 'api_favorites_create_destroy', true);
api_register_func('api/favorites/destroy', 'api_favorites_create_destroy', true);
function api_favorites(&$a, $type){
if (api_user()===false) return false;
if (api_user()===false)
return false;
$user_info = api_get_user($a);
// in friendica starred item are private
// return favorites only for self
logger('api_favorites: self:' . $user_info['self']);
if ($user_info['self']==0) {
$ret = array();
} else {
// params
$count = (x($_REQUEST,'count')?$_REQUEST['count']:20);
$page = (x($_REQUEST,'page')?$_REQUEST['page']-1:0);
if($page < 0)
$page = 0;
$since_id = (x($_REQUEST,'since_id')?$_REQUEST['since_id']:0);
$max_id = (x($_REQUEST,'max_id')?$_REQUEST['max_id']:0);
$exclude_replies = (x($_REQUEST,'exclude_replies')?1:0);
$start = $page*$count;
// params
$count = (x($_GET,'count')?$_GET['count']:20);
$page = (x($_REQUEST,'page')?$_REQUEST['page']-1:0);
if ($page<0) $page=0;
//$include_entities = (x($_REQUEST,'include_entities')?$_REQUEST['include_entities']:false);
$start = $page*$count;
$r = q("SELECT `item`.*, `item`.`id` AS `item_id`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
`contact`.`network`, `contact`.`thumb`, `contact`.`dfrn_id`, `contact`.`self`,
`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
FROM `item`, `contact`
WHERE `item`.`uid` = %d
AND `item`.`visible` = 1 and `item`.`moderated` = 0 AND `item`.`deleted` = 0
AND `item`.`starred` = 1
AND `contact`.`id` = `item`.`contact-id`
AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
$sql_extra
ORDER BY `item`.`received` DESC LIMIT %d ,%d ",
intval($user_info['uid']),
intval($start), intval($count)
);
$ret = api_format_items($r,$user_info);
$sql_extra = '';
if ($max_id > 0)
$sql_extra .= ' AND `item`.`id` <= '.intval($max_id);
if ($exclude_replies > 0)
$sql_extra .= ' AND `item`.`parent` = `item`.`id`';
if (api_user() != $user_info['uid']) {
$observer = get_app()->get_observer();
require_once('include/permissions.php');
if(! perm_is_allowed($user_info['uid'],(($observer) ? $observer['xchan_hash'] : ''),'view_stream'))
return '';
$sql_extra .= " and item_private = 0 ";
}
$r = q("SELECT * from item WHERE uid = %d and item_restrict = 0
and ( item_flags & %d ) > 0 $sql_extra
AND id > %d
ORDER BY received DESC LIMIT %d ,%d ",
intval($user_info['uid']),
intval(ITEM_STARRED),
intval($since_id),
intval($start),
intval($count)
);
xchan_query($r,true);
$ret = api_format_items($r,$user_info);
$data = array('$statuses' => $ret);
switch($type){
case "atom":
case "rss":
$data = api_rss_extra($a, $data, $user_info);
break;
case "as":
$as = api_format_as($a, $ret, $user_info);
$as['title'] = $a->config['sitename']." Home Timeline";
$as['link']['url'] = $a->get_baseurl()."/".$user_info["screen_name"]."/all";
return($as);
break;
}
return api_apply_template("timeline", $type, $data);
}
api_register_func('api/favorites','api_favorites', true);
function api_format_as($a, $ret, $user_info) {
$as = array();
@@ -1518,7 +1692,7 @@ require_once('include/items.php');
return($as);
}
function api_format_messages($item, $recipient, $sender) {
function api_format_message($item, $recipient, $sender) {
// standard meta information
$ret = array(
'id' => $item['id'],
@@ -1530,7 +1704,7 @@ require_once('include/items.php');
'recipient_screen_name' => $recipient['screen_name'],
'recipient' => $recipient,
);
unobscure($item);
unobscure_mail($item);
//don't send title to regular StatusNET requests to avoid confusing these apps
if (x($_GET, 'getText')) {
$ret['title'] = $item['title'] ;
@@ -1568,6 +1742,8 @@ require_once('include/items.php');
localize_item($item);
$status_user = (($item['author_xchan']==$user_info['guid'])?$user_info: api_item_get_user($a,$item));
if(array_key_exists('status',$status_user))
unset($status_user['status']);
if($item['parent'] != $item['id']) {
$r = q("select id from item where parent= %d and id < %d order by id desc limit 1",
@@ -1893,7 +2069,7 @@ require_once('include/items.php');
if ($id>-1) {
$r = q("SELECT * FROM `mail` WHERE id=%d", intval($id));
$ret = api_format_messages($r[0], $recipient, $sender);
$ret = api_format_message($r[0], $recipient, $sender);
} else {
$ret = array("error"=>$id);
@@ -1947,18 +2123,16 @@ require_once('include/items.php');
$ret = Array();
if($r) {
foreach($r as $item) {
if ($box == "inbox" || $item['from-url'] != $profile_url){
$recipient = $user_info;
// fixme to lookup recipient
$sender = api_get_user($a);
}
elseif ($box == "sentbox" || $item['from-url'] != $profile_url){
// fixme to lookup recipient
$recipient = api_get_user($a);
if ($item['from_xchan'] == $channel['channel_hash']) {
$sender = $user_info;
$recipient = api_get_user($a, null, $item['to_xchan']);
}
else {
$sender = api_get_user($a, null, $item['from_xchan']);
$recipient = $user_info;
}
$ret[]=api_format_messages($item, $recipient, $sender);
$ret[]=api_format_message($item, $recipient, $sender);
}
}
@@ -2024,9 +2198,6 @@ logger('Req: ' . var_export($req,true));
/*
Not implemented by now:
favorites
favorites/create
favorites/destroy
statuses/retweets_of_me
friendships/create
friendships/destroy

View File

@@ -1,10 +1,10 @@
<?php
/** @file
/**
* @file include/attach.php
*
* @brief File/attach API with the potential for revision control.
*
* TODO: a filesystem storage abstraction which maintains security (and 'data' contains a system filename
* @TODO: a filesystem storage abstraction which maintains security (and 'data' contains a system filename
* which is inaccessible from the web). This could get around PHP storage limits and store videos and larger
* items, using fread or OS methods or native code to read/write or chunk it through.
* Also an 'append' option to the storage function might be a useful addition.
@@ -15,10 +15,10 @@ require_once('include/security.php');
/**
* @brief Guess the mimetype from file ending.
*
*
* This function takes a file name and guess the mimetype from the
* filename extension.
*
*
* @param $filename a string filename
* @return string The mimetype according to a file ending.
*/
@@ -65,10 +65,10 @@ function z_mime_content_type($filename) {
'mov' => 'video/quicktime',
'ogg' => 'application/ogg',
'opus' => 'audio/ogg',
'webm' => 'audio/webm',
'webm' => 'video/webm',
'mp4' => 'audio/mp4',
// 'webm' => 'audio/webm',
'mp4' => 'video/mp4',
// 'mp4' => 'audio/mp4',
// adobe
'pdf' => 'application/pdf',
@@ -117,23 +117,22 @@ function z_mime_content_type($filename) {
/**
* @brief Count files/attachments.
*
*
* @param $channel_id
* @param $observer
* @param $hash (optional)
* @param $filename (optional)
* @param $filetype (optional)
* @return array
* $ret['success'] boolean
* $ret['results'] amount of found results, or false
* $ret['message'] string with error messages if any
*
* @param int $channel_id
* @param string $observer
* @param string $hash (optional)
* @param string $filename (optional)
* @param string $filetype (optional)
* @return assoziative array with:
* * \e boolean \b success
* * \e int|boolean \b results amount of found results, or false
* * \e string \b message with error messages if any
*/
function attach_count_files($channel_id, $observer, $hash = '', $filename = '', $filetype = '') {
$ret = array('success' => false);
if(! perm_is_allowed($channel_id,$observer, 'read_storage')) {
if(! perm_is_allowed($channel_id, $observer, 'read_storage')) {
$ret['message'] = t('Permission denied.');
return $ret;
}
@@ -219,8 +218,9 @@ function attach_list_files($channel_id, $observer, $hash = '', $filename = '', $
*
* This could exhaust memory so most useful only when immediately sending the data.
*
* @param $hash
* @param $rev
* @param string $hash
* @param int $rev Revision
* @return array
*/
function attach_by_hash($hash, $rev = 0) {
@@ -234,7 +234,6 @@ function attach_by_hash($hash, $rev = 0) {
elseif($rev)
$sql_extra = " and revision = " . intval($rev) . " ";
$r = q("SELECT uid FROM attach WHERE hash = '%s' $sql_extra LIMIT 1",
dbesc($hash)
);
@@ -270,12 +269,16 @@ function attach_by_hash($hash, $rev = 0) {
/**
* @brief Find an attachment by hash and revision.
*
*
* Returns the entire attach structure excluding data.
*
*
* @see attach_by_hash()
* @param $hash
* @param $ref
* @param $rev revision default 0
* @return array Everything except data.
* * \e boolean \b success boolean true or false
* * \e string \b message (optional) only when success is false
* * \e array \b data array of attach DB entry without data component
*/
function attach_by_hash_nodata($hash, $rev = 0) {
@@ -318,6 +321,7 @@ function attach_by_hash_nodata($hash, $rev = 0) {
$ret['success'] = true;
$ret['data'] = $r[0];
return $ret;
}
@@ -361,6 +365,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
$existing_size = 0;
if($options === 'replace') {
/** @BUG $replace is undefined here */
$x = q("select id, hash, filesize from attach where id = %d and uid = %d limit 1",
intval($replace),
intval($channel_id)
@@ -373,7 +378,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
$existing_size = intval($x[0]['filesize']);
$hash = $x[0]['hash'];
}
if($options === 'revise' || $options === 'update') {
$sql_options = " order by revision desc ";
if($options === 'update' && $arr && array_key_exists('revision',$arr))
@@ -513,22 +518,24 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
}
/**
* Read a virtual directory and return contents, checking permissions of all parent components.
* @function z_readdir
* @brief Read a virtual directory and return contents.
*
* Also checking permissions of all parent components.
*
* @param integer $channel_id
* @param string $observer_hash hash of current observer
* @param string $pathname
* @param string $parent_hash (optional)
*
* @returns array $ret
* $ret['success'] = boolean true or false
* $ret['message'] = error message if success is false
* $ret['data'] = array of attach DB entries without data component
* @return array $ret
* * \e boolean \b success boolean true or false
* * \e string \b message error message if success is false
* * \e array \b data array of attach DB entries without data component
*/
function z_readdir($channel_id, $observer_hash, $pathname, $parent_hash = '') {
$ret = array('success' => false);
if(! perm_is_allowed($r[0]['uid'], get_observer_hash(), 'view_storage')) {
if(! perm_is_allowed($channel_id, get_observer_hash(), 'view_storage')) {
$ret['message'] = t('Permission denied.');
return $ret;
}
@@ -553,7 +560,7 @@ function z_readdir($channel_id, $observer_hash, $pathname, $parent_hash = '') {
}
else
$paths = array($pathname);
$r = q("select id, aid, uid, hash, creator, filename, filetype, filesize, revision, folder, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where id = %d and folder = '%s' and filename = '%s' and (flags & %d )>0 " . permissions_sql($channel_id),
intval($channel_id),
dbesc($parent_hash),
@@ -571,24 +578,22 @@ function z_readdir($channel_id, $observer_hash, $pathname, $parent_hash = '') {
}
/**
* @function attach_mkdir($channel,$observer_hash,$arr);
*
* @brief Create directory.
*
* @param array $channel channel array of owner
* @param string $observer_hash hash of current observer
* @param array $arr parameter array to fulfil request
* Required:
* $arr['filename']
* $arr['folder'] // hash of parent directory, empty string for root directory
* Optional:
* $arr['hash'] // precumputed hash for this node
* $arr['allow_cid']
* $arr['allow_gid']
* $arr['deny_cid']
* $arr['deny_gid']
* - Required:
* * \e string \b filename
* * \e string \b folder hash of parent directory, empty string for root directory
* - Optional:
* * \e string \b hash precumputed hash for this node
* * \e tring \b allow_cid
* * \e string \b allow_gid
* * \e string \b deny_cid
* * \e string \b deny_gid
* @return array
*/
function attach_mkdir($channel, $observer_hash, $arr = null) {
$ret = array('success' => false);
@@ -698,7 +703,7 @@ function attach_mkdir($channel, $observer_hash, $arr = null) {
);
}
else {
logger('attach_mkdir: ' . mkdir . ' ' . $path . 'failed.');
logger('attach_mkdir: ' . mkdir . ' ' . $path . ' failed.');
$ret['message'] = t('mkdir failed.');
}
}
@@ -712,13 +717,13 @@ function attach_mkdir($channel, $observer_hash, $arr = null) {
/**
* @brief Changes permissions of a file.
*
* @param $channel_id
* @param $resource
* @param $allow_cid
* @param $allow_gid
* @param $deny_cid
* @param $deny_gid
* @param $recurse
* @param int $channel_id
* @param array $resource
* @param string $allow_cid
* @param string $allow_gid
* @param string $deny_cid
* @param string $deny_gid
* @param boolean $recurse (optional) default false
*/
function attach_change_permissions($channel_id, $resource, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $recurse = false) {
@@ -807,8 +812,8 @@ function attach_delete($channel_id, $resource) {
if($y) {
$f = 'store/' . $channel_address . '/' . $y[0]['data'];
if(is_dir($f))
@rmdir($f);
if(is_dir($y[0]['data']))
@rmdir($y[0]['data']);
elseif(file_exists($f))
unlink($f);
}
@@ -827,18 +832,19 @@ function attach_delete($channel_id, $resource) {
intval($channel_id)
);
file_activity($channel_id, $object, $allow_cid='', $allow_gid='', $deny_cid='', $deny_gid='', 'update', $no_activity=false);
file_activity($channel_id, $object, $object['allow_cid'], $object['allow_gid'], $object['deny_cid'], $object['deny_gid'], 'update', $notify=0);
}
/**
* @brief Returns path to file in cloud/.
* This function cannot be used with mod/dav as it always returns a path valid under mod/cloud
*
* @param array
* $arr[uid] int the channels uid
* $arr[folder] string
* $arr[filename]] string
*
* @warning This function cannot be used with mod/dav as it always returns a
* path valid under mod/cloud.
*
* @param array $arr assoziative array with:
* * \e int \b uid the channel's uid
* * \e string \b folder
* * \e string \b filename
* @return string
* path to the file in cloud/
*/
@@ -895,6 +901,7 @@ function get_cloudpath($arr) {
* @return string with the full folder path
*/
function get_parent_cloudpath($channel_id, $channel_name, $attachHash) {
$parentFullPath = '';
// build directory tree
$parentHash = $attachHash;
do {
@@ -933,9 +940,9 @@ function find_folder_hash_by_attach_hash($channel_id, $attachHash) {
/**
* @brief Returns the filename of an attachment in a given channel.
*
* @param mixed $channel_id
* @param int $channel_id
* The id of the channel
* @param mixed $attachHash
* @param string $attachHash
* The hash of the attachment
* @return string
* The filename of the attachment
@@ -949,6 +956,7 @@ function find_filename_by_hash($channel_id, $attachHash) {
if ($r) {
$filename = $r[0]['filename'];
}
return $filename;
}
@@ -961,10 +969,23 @@ function pipe_streams($in, $out) {
$size = 0;
while (!feof($in))
$size += fwrite($out, fread($in, 8192));
return $size;
}
function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $verb, $no_activity) {
/**
* @brief Activity for files.
*
* @param int $channel_id
* @param array $object
* @param string $allow_cid
* @param string $allow_gid
* @param string $deny_cid
* @param string $deny_gid
* @param string $verb
* @param boolean $no_activity
*/
function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $verb, $notify) {
require_once('include/items.php');
@@ -974,6 +995,15 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid,
if(!$object)
return;
//turn strings into arrays
$arr_allow_cid = expand_acl($allow_cid);
$arr_allow_gid = expand_acl($allow_gid);
$arr_deny_cid = expand_acl($deny_cid);
$arr_deny_gid = expand_acl($deny_gid);
//filter out receivers which do not have permission to view filestorage
$arr_allow_cid = check_list_permissions($channel_id, $arr_allow_cid, 'view_storage');
$is_dir = (($object['flags'] & ATTACH_FLAG_DIR) ? true : false);
//do not send activity for folders for now
@@ -985,13 +1015,16 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid,
$folder_hash = $object['folder'];
$r_perms = recursive_activity_recipients($allow_cid, $allow_gid, $deny_cid, $deny_gid, $folder_hash);
$r_perms = recursive_activity_recipients($arr_allow_cid, $arr_allow_gid, $arr_deny_cid, $arr_deny_gid, $folder_hash);
$allow_cid = perms2str($r_perms['allow_cid']);
$allow_gid = perms2str($r_perms['allow_gid']);
$deny_cid = perms2str($r_perms['deny_cid']);
$deny_gid = perms2str($r_perms['deny_gid']);
//split up returned perms
$arr_allow_cid = $r_perms['allow_cid'];
$arr_allow_gid = $r_perms['allow_gid'];
$arr_deny_cid = $r_perms['deny_cid'];
$arr_deny_gid = $r_perms['deny_gid'];
//filter out receivers which do not have permission to view filestorage
$arr_allow_cid = check_list_permissions($channel_id, $arr_allow_cid, 'view_storage');
}
$mid = item_message_id();
@@ -1004,13 +1037,12 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid,
$objtype = ACTIVITY_OBJ_FILE;
$private = (($allow_cid || $allow_gid || $deny_cid || $deny_gid) ? 1 : 0);
$private = (($arr_allow_cid[0] || $arr_allow_gid[0] || $arr_deny_cid[0] || $arr_deny_gid[0]) ? 1 : 0);
$jsonobject = json_encode($object);
//check if item for this object exists
$y = q("SELECT * FROM item WHERE verb = '%s' AND obj_type = '%s' AND resource_id = '%s' AND uid = %d LIMIT 1",
$y = q("SELECT mid FROM item WHERE verb = '%s' AND obj_type = '%s' AND resource_id = '%s' AND uid = %d LIMIT 1",
dbesc(ACTIVITY_POST),
dbesc($objtype),
dbesc($object['hash']),
@@ -1034,6 +1066,12 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid,
if($update && $verb == 'post' ) {
//send update activity and create a new one
//updates should be sent to everybody with recursive perms and all eventual former allowed members ($object['allow_cid'] etc.).
$u_arr_allow_cid = array_unique(array_merge($arr_allow_cid, expand_acl($object['allow_cid'])));
$u_arr_allow_gid = array_unique(array_merge($arr_allow_gid, expand_acl($object['allow_gid'])));
$u_arr_deny_cid = array_unique(array_merge($arr_deny_cid, expand_acl($object['deny_cid'])));
$u_arr_deny_gid = array_unique(array_merge($arr_deny_gid, expand_acl($object['deny_gid'])));
$u_mid = item_message_id();
$arr['aid'] = get_account_id();
@@ -1068,10 +1106,9 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid,
$update = false;
//notice( t('File activity updated') . EOL);
}
if($no_activity) {
if(! $notify) {
return;
}
@@ -1087,10 +1124,10 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid,
$arr['author_xchan'] = $poster['xchan_hash'];
$arr['owner_xchan'] = $poster['xchan_hash'];
$arr['title'] = '';
$arr['allow_cid'] = $allow_cid;
$arr['allow_gid'] = $allow_gid;
$arr['deny_cid'] = $deny_cid;
$arr['deny_gid'] = $deny_gid;
$arr['allow_cid'] = perms2str($arr_allow_cid);
$arr['allow_gid'] = perms2str($arr_allow_gid);
$arr['deny_cid'] = perms2str($arr_deny_cid);
$arr['deny_gid'] = perms2str($arr_deny_gid);
$arr['item_hidden'] = 1;
$arr['item_private'] = $private;
$arr['verb'] = (($update) ? ACTIVITY_UPDATE : ACTIVITY_POST);
@@ -1112,12 +1149,18 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid,
//(($verb === 'post') ? notice( t('File activity posted') . EOL) : notice( t('File activity dropped') . EOL));
return;
}
/**
* @brief Create file activity object
*
* @param int $channel_id
* @param string $hash
* @param string $cloudpath
*/
function get_file_activity_object($channel_id, $hash, $cloudpath) {
$x = q("SELECT creator, filename, filetype, filesize, revision, folder, flags, created, edited FROM attach WHERE uid = %d AND hash = '%s' LIMIT 1",
$x = q("SELECT creator, filename, filetype, filesize, revision, folder, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid FROM attach WHERE uid = %d AND hash = '%s' LIMIT 1",
intval($channel_id),
dbesc($hash)
);
@@ -1146,20 +1189,36 @@ function get_file_activity_object($channel_id, $hash, $cloudpath) {
'folder' => $x[0]['folder'],
'flags' => $x[0]['flags'],
'created' => $x[0]['created'],
'edited' => $x[0]['edited']
'edited' => $x[0]['edited'],
'allow_cid' => $x[0]['allow_cid'],
'allow_gid' => $x[0]['allow_gid'],
'deny_cid' => $x[0]['deny_cid'],
'deny_gid' => $x[0]['deny_gid']
);
return $object;
return $object;
}
function recursive_activity_recipients($allow_cid, $allow_gid, $deny_cid, $deny_gid, $folder_hash) {
/**
* @brief Returns array of channels which have recursive permission for a file
*
* @param $arr_allow_cid
* @param $arr_allow_gid
* @param $arr_deny_cid
* @param $arr_deny_gid
* @param $folder_hash
*/
function recursive_activity_recipients($arr_allow_cid, $arr_allow_gid, $arr_deny_cid, $arr_deny_gid, $folder_hash) {
$ret = array();
$parent_arr = array();
$poster = get_app()->get_observer();
$arr_allow_cid = expand_acl($allow_cid);
$arr_allow_gid = expand_acl($allow_gid);
$arr_deny_cid = expand_acl($deny_cid);
$arr_deny_gid = expand_acl($deny_gid);
//turn allow_gid into allow_cid's
foreach($arr_allow_gid as $gid) {
$in_group = in_group($gid);
$arr_allow_cid = array_unique(array_merge($arr_allow_cid, $in_group));
}
$count = 0;
while($folder_hash) {
@@ -1173,8 +1232,10 @@ function recursive_activity_recipients($allow_cid, $allow_gid, $deny_cid, $deny_
$parent_arr['allow_cid'][] = expand_acl($x[0]['allow_cid']);
$parent_arr['allow_gid'][] = expand_acl($x[0]['allow_gid']);
//TODO: should find a much better solution for the allow_cid <-> allow_gid problem.
//Do not use allow_gid for now. Instead lookup the members of the group directly and add them to allow_cid.
/**
* @TODO should find a much better solution for the allow_cid <-> allow_gid problem.
* Do not use allow_gid for now. Instead lookup the members of the group directly and add them to allow_cid.
* */
if($parent_arr['allow_gid']) {
foreach($parent_arr['allow_gid'][$count] as $gid) {
$in_group = in_group($gid);
@@ -1186,11 +1247,9 @@ function recursive_activity_recipients($allow_cid, $allow_gid, $deny_cid, $deny_
$parent_arr['deny_gid'][] = expand_acl($x[0]['deny_gid']);
$count++;
}
$folder_hash = $x[0]['folder'];
}
//if none of the parent folders is private just return file perms
@@ -1258,11 +1317,18 @@ function recursive_activity_recipients($allow_cid, $allow_gid, $deny_cid, $deny_
}
return $ret;
}
/**
* @brief Returns members of a group
*
* @param $group_id
*/
function in_group($group_id) {
//TODO: make these two queries one with a join.
$group_members = array();
/** @TODO make these two queries one with a join. */
$x = q("SELECT id FROM groups WHERE hash = '%s'",
dbesc($group_id)
);

View File

@@ -29,7 +29,8 @@ function nuke_session() {
unset($_SESSION['mobile_theme']);
unset($_SESSION['show_mobile']);
unset($_SESSION['page_flags']);
unset($_SESSION['submanage']);
unset($_SESSION['delegate']);
unset($_SESSION['delegate_channel']);
unset($_SESSION['my_url']);
unset($_SESSION['my_address']);
unset($_SESSION['addr']);

View File

@@ -1,4 +1,8 @@
<?php /** @file */
<?php
/**
* @file include/bb2diaspora.php
* @brief Some functions for BB conversions for Diaspora protocol.
*/
require_once("include/oembed.php");
require_once("include/event.php");
@@ -107,14 +111,19 @@ function diaspora_mention_callback($matches) {
}
// 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,
// and then clean up a few Diaspora specific constructs.
function diaspora2bb($s,$use_zrl = false) {
/**
* @brief
*
* 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,
* and then clean up a few Diaspora specific constructs.
*
* @param string $s
* @param boolean $use_zrl default false
* @return string
*/
function diaspora2bb($s, $use_zrl = false) {
$s = str_replace("&#xD;","\r",$s);
$s = str_replace("&#xD;\n&gt;","",$s);
@@ -150,7 +159,6 @@ function diaspora2bb($s,$use_zrl = false) {
}
else {
$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);
@@ -217,18 +225,33 @@ function diaspora_ol($s) {
//////////////////////
// Non-Markdownify versions of "diaspora_ol" and "diaspora_ul"
//////////////////////
/**
* @brief
*
* Replace "[\\*]" followed by any number (including zero) of
* spaces by "* " to match Diaspora's list format.
*
* @param string $s
* @return string
*/
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]);
}
/**
* @brief
*
* A hack: Diaspora will create a properly-numbered ordered list even
* if you use '1.' for each element of the list, like:
* \code
* 1. First element
* 1. Second element
* 1. Third element
* \endcode
* @param string $s
* @return string
*/
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]);
}
@@ -240,8 +263,8 @@ function bb2dmention_callback($match) {
if($r)
return '@{' . $match[3] . ' ; ' . $r[0]['xchan_addr'] . '}';
return '@' . $match[3];
return '@' . $match[3];
}
@@ -272,14 +295,15 @@ function bb2diaspora_itemwallwall(&$item) {
}
// $item['author'] might cause a surprise further down the line if it wasn't expected to be here.
if(! $author_exists)
$unset($item['author']);
if(! $author_exists)
unset($item['author']);
}
function bb2diaspora_itembody($item,$force_update = false) {
function bb2diaspora_itembody($item, $force_update = false) {
$matches = array();
if(($item['diaspora_meta']) && (! $force_update)) {
$diaspora_meta = json_decode($item['diaspora_meta'],true);
@@ -295,8 +319,6 @@ function bb2diaspora_itembody($item,$force_update = false) {
logger('bb2diaspora_itembody: cached ');
$newitem = $item;
$newitem['body'] = $meta['body'];
// this won't work - the post is now in markdown
// bb2diaspora_itemwallwall($newitem);
return $newitem['body'];
}
}
@@ -317,7 +339,8 @@ function bb2diaspora_itembody($item,$force_update = false) {
bb2diaspora_itemwallwall($newitem);
$body = preg_replace('/\#\^http/i', 'http', $newitem['body']);
$title = $newitem['title'];
$body = preg_replace('/\#\^http/i', 'http', $newitem['body']);
// protect tags and mentions from hijacking
@@ -345,8 +368,8 @@ function bb2diaspora_itembody($item,$force_update = false) {
$body = "## " . $title . "\n\n" . $body;
if($item['attach']) {
$cnt = preg_match_all('/href=\"(.*?)\"(.*?)title=\"(.*?)\"/ism',$item['attach'],$matches,PREG_SET_ORDER);
if(cnt) {
$cnt = preg_match_all('/href=\"(.*?)\"(.*?)title=\"(.*?)\"/ism', $item['attach'], $matches, PREG_SET_ORDER);
if($cnt) {
$body .= "\n" . t('Attachments:') . "\n";
foreach($matches as $mtch) {
$body .= '[' . $mtch[3] . '](' . $mtch[1] . ')' . "\n";
@@ -357,7 +380,6 @@ function bb2diaspora_itembody($item,$force_update = false) {
// logger('bb2diaspora_itembody : ' . $body, LOGGER_DATA);
return html_entity_decode($body);
}
function bb2diaspora($Text,$preserve_nl = false, $fordiaspora = true) {
@@ -366,7 +388,7 @@ function bb2diaspora($Text,$preserve_nl = false, $fordiaspora = true) {
// 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.
/**
/*
* Transform #tags, strip off the [url] and replace spaces with underscore
*/
$Text = preg_replace_callback('/#\[([zu])rl\=(\w+.*?)\](\w+.*?)\[\/[(zu)]rl\]/i', create_function('$match',
@@ -452,5 +474,6 @@ function format_event_diaspora($ev) {
. "\n";
$o .= "\n";
return $o;
}

View File

@@ -1,28 +1,33 @@
<?php /** @file */
<?php
/**
* @file include/bbcode.php
* @brief BBCode related functions for parsing, etc.
*/
require_once("include/oembed.php");
require_once('include/oembed.php');
require_once('include/event.php');
require_once('include/zot.php');
require_once('include/hubloc.php');
function tryoembed($match) {
$url = ((count($match)==2)?$match[1]:$match[2]);
$url = ((count($match) == 2) ? $match[1] : $match[2]);
$o = oembed_fetch_url($url);
if ($o->type=="error") return $match[0];
if ($o->type == 'error')
return $match[0];
$html = oembed_format_object($o);
return $html;
}
function tryzrlaudio($match) {
$link = $match[1];
$zrl = is_matrix_url($link);
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"><a href="' . str_replace(' ','%20',$link) . '">' . $link . '</a></audio>';
}
function tryzrlvideo($match) {
@@ -30,8 +35,8 @@ function tryzrlvideo($match) {
$zrl = is_matrix_url($link);
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" 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
@@ -39,11 +44,12 @@ function tryzrlvideo($match) {
// to hide them from parser.
function bb_spacefy($st) {
$whole_match = $st[0];
$captured = $st[1];
$spacefied = preg_replace("/\[(.*?)\]/", "[ $1 ]", $captured);
$new_str = str_replace($captured, $spacefied, $whole_match);
return $new_str;
$whole_match = $st[0];
$captured = $st[1];
$spacefied = preg_replace("/\[(.*?)\]/", "[ $1 ]", $captured);
$new_str = str_replace($captured, $spacefied, $whole_match);
return $new_str;
}
// The previously spacefied [noparse][ i ]italic[ /i ][/noparse],
@@ -51,10 +57,11 @@ function bb_spacefy($st) {
// returning [i]italic[/i]
function bb_unspacefy_and_trim($st) {
$whole_match = $st[0];
$captured = $st[1];
$unspacefied = preg_replace("/\[ (.*?)\ ]/", "[$1]", $captured);
return $unspacefied;
//$whole_match = $st[0];
$captured = $st[1];
$unspacefied = preg_replace("/\[ (.*?)\ ]/", "[$1]", $captured);
return $unspacefied;
}
@@ -103,8 +110,8 @@ function bb_extract_images($body) {
function bb_replace_images($body, $images) {
$newbody = $body;
$cnt = 0;
if(! $images)
return $newbody;
@@ -119,10 +126,15 @@ function bb_replace_images($body, $images) {
return $newbody;
}
/**
* @brief Parses crypt BBCode.
*
* @param array $match
* @return string HTML code
*/
function bb_parse_crypt($match) {
$matches = array();
$attributes = $match[1];
$algorithm = "";
@@ -137,7 +149,6 @@ function bb_parse_crypt($match) {
$hint = "";
preg_match("/hint='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
$hint = $matches[1];
@@ -147,36 +158,42 @@ function bb_parse_crypt($match) {
$x = random_string();
$Text = '<br/><div id="' . $x . '"><img src="' . z_root() . '/images/lock_icon.gif" onclick="red_decrypt(\'' . $algorithm . '\',\'' . $hint . '\',\'' . $match[2] . '\',\'#' . $x . '\');" alt="' . t('Encrypted content') . '" title="' . t('Encrypted content') . '" /></div><br />';
$Text = '<br /><div id="' . $x . '"><img src="' . z_root() . '/images/lock_icon.gif" onclick="red_decrypt(\'' . $algorithm . '\',\'' . $hint . '\',\'' . $match[2] . '\',\'#' . $x . '\');" alt="' . t('Encrypted content') . '" title="' . t('Encrypted content') . '" /></div><br />';
return $Text;
}
function bb_parse_app($match) {
require_once('include/apps.php');
$app = app_decode($match[1]);
if($app)
if ($app)
return app_render($app);
}
function bb_parse_element($match) {
$j = json_decode(base64url_decode($match[1]),true);
if($j) {
if ($j) {
$o = EOL . '<a href="#" onclick="importElement(\'' . $match[1] . '\'); return false;" >' . t('Install design element: ') . $j['pagetitle'] . '</a>' . EOL;
}
return $o;
}
/**
* @brief Returns an QR-code image from a value given in $match[1].
*
* @param array $match
* @return string HTML img with QR-code of $match[1]
*/
function bb_qr($match) {
return '<img class="zrl" src="' . z_root() . '/photo/qr?f=&qr=' . urlencode($match[1]) . '" alt="' . t('QR code') . '" title="' . htmlspecialchars($match[1],ENT_QUOTES,'UTF-8') . '" />';
}
}
function bb_ShareAttributes($match) {
$matches = array();
$attributes = $match[1];
$author = "";
@@ -204,13 +221,14 @@ function bb_ShareAttributes($match) {
if ($matches[1] != "")
$posted = $matches[1];
// message_id is never used, do we still need it?
$message_id = "";
preg_match("/message_id='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
$message_id = $matches[1];
// FIXME - this should really be a wall-item-ago so it will get updated on the client
/** @FIXME - this should really be a wall-item-ago so it will get updated on the client */
$reldate = (($posted) ? relative_date($posted) : '');
$headline = '<div class="shared_container"> <div class="shared_header">';
@@ -230,24 +248,30 @@ function bb_ShareAttributes($match) {
$text = $headline . '<div class="reshared-content">' . trim($match[2]) . '</div></div>';
return($text);
return $text;
}
function bb_location($match) {
// not yet implemented
}
function bbiframe($match) {
/**
* @brief Returns an iframe from $match[1].
*
* @param array $match
* @return string HTML iframe with content of $match[1]
*/
function bb_iframe($match) {
$a = get_app();
$sandbox = ((strpos($match[1],get_app()->get_hostname())) ? ' sandbox="allow-scripts" ' : '');
$sandbox = ((strpos($match[1], $a->get_hostname())) ? ' sandbox="allow-scripts" ' : '');
return '<iframe ' . $sandbox . ' src="' . $match[1] . '" width="' . $a->videowidth . '" height="' . $a->videoheight . '"><a href="' . $match[1] . '">' . $match[1] . '</a></iframe>';
}
function bb_ShareAttributesSimple($match) {
$matches = array();
$attributes = $match[1];
$author = "";
@@ -268,16 +292,16 @@ function bb_ShareAttributesSimple($match) {
if ($matches[1] != "")
$profile = $matches[1];
$text = "<br />".html_entity_decode("&#x2672; ", ENT_QUOTES, 'UTF-8').' <a href="'.$profile.'">'.$author."</a>: div class=\"reshared-content\">" .$match[2]."</div>";
$text = '<br />' . html_entity_decode("&#x2672; ", ENT_QUOTES, 'UTF-8') . ' <a href="' . $profile . '">' . $author . '</a>: div class="reshared-content">' . $match[2] . '</div>';
return($text);
}
function rpost_callback($match) {
if ($match[2]) {
return str_replace($match[0],get_rpost_path(get_app()->get_observer()) . '&title=' . urlencode($match[2]) . '&body=' . urlencode($match[3]),$match[0]);
return str_replace($match[0], get_rpost_path(get_app()->get_observer()) . '&title=' . urlencode($match[2]) . '&body=' . urlencode($match[3]), $match[0]);
} else {
return str_replace($match[0],get_rpost_path(get_app()->get_observer()) . '&body=' . urlencode($match[3]),$match[0]);
return str_replace($match[0], get_rpost_path(get_app()->get_observer()) . '&body=' . urlencode($match[3]), $match[0]);
}
}
@@ -291,46 +315,59 @@ function bb_map_location($match) {
return str_replace($match[0],'<div class="map" >' . generate_named_map($match[1]) . '</div>', $match[0]);
}
function bb_opentag($match) {
$rnd = mt_rand();
return "<br /><div onclick=\"openClose('opendiv-" . $rnd . "');return false;\" class=\"fakelink\">" . $match[1] . "</div><div id=\"opendiv-" . $rnd . "\" style=\"display: none;\">" . $match[2] . "</div>";
}
/**
* @brief Sanitize style properties from BBCode to HTML.
*
* @param array $input
* @return string A HTML span tag with the styles.
*/
function bb_sanitize_style($input) {
//whitelist property limits (0 = no limitation)
$w = array( // color properties
"color" => 0,
"background-color" => 0,
// whitelist array: property => limits (0 = no limitation)
$w = array(
// color properties
"color" => 0,
"background-color" => 0,
// box properties
"padding" => array("px"=>100, "%"=>0, "em"=>2, "ex"=>2, "mm"=>0, "cm"=>0, "in"=>0, "pt"=>0, "pc"=>0),
"margin" => array("px"=>100, "%"=>0, "em"=>2, "ex"=>2, "mm"=>0, "cm"=>0, "in"=>0, "pt"=>0, "pc"=>0),
"border" => array("px"=>100, "%"=>0, "em"=>2, "ex"=>2, "mm"=>0, "cm"=>0, "in"=>0, "pt"=>0, "pc"=>0),
"float" => 0,
"clear" => 0,
"padding" => array("px"=>100, "%"=>0, "em"=>2, "ex"=>2, "mm"=>0, "cm"=>0, "in"=>0, "pt"=>0, "pc"=>0),
"margin" => array("px"=>100, "%"=>0, "em"=>2, "ex"=>2, "mm"=>0, "cm"=>0, "in"=>0, "pt"=>0, "pc"=>0),
"border" => array("px"=>100, "%"=>0, "em"=>2, "ex"=>2, "mm"=>0, "cm"=>0, "in"=>0, "pt"=>0, "pc"=>0),
"float" => 0,
"clear" => 0,
// text properties
"text-decoration" => 0,
"text-decoration" => 0,
);
$css = array();
$css_string = $input[1];
$a = explode(';',$css_string);
$a = explode(';', $css_string);
foreach($a as $parts){
list($k, $v) = explode(':', $parts);
$css[ trim($k) ] = trim($v);
$css[ trim($k) ] = trim($v);
}
// sanitize properties
$b = array_merge(array_diff_key($css, $w), array_diff_key($w, $css));
$css = array_diff_key($css, $b);
$css_string_san = '';
foreach($css as $key => $value) {
if($w[$key] != null) {
foreach($w[$key] as $limit_key => $limit_value) {
foreach ($css as $key => $value) {
if ($w[$key] != null) {
foreach ($w[$key] as $limit_key => $limit_value) {
//sanitize values
if(strpos($value, $limit_key)) {
if (strpos($value, $limit_key)) {
$value = preg_replace_callback(
"/(\S.*?)$limit_key/ism",
function($match) use($limit_value, $limit_key) {
if($match[1] > $limit_value) {
if ($match[1] > $limit_value) {
return $limit_value . $limit_key;
} else {
return $match[1] . $limit_key;
return $match[1] . $limit_key;
}
},
$value
@@ -340,19 +377,20 @@ function bb_sanitize_style($input) {
}
$css_string_san .= $key . ":" . $value ."; ";
}
return "<span style=\"" . $css_string_san . "\">" . $input[2] . "</span>";
return '<span style="' . $css_string_san . '">' . $input[2] . '</span>';
}
// BBcode 2 HTML was written by WAY2WEB.net
// extended to work with Mistpark/Friendica/Red - Mike Macgirvin
function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
function bbcode($Text, $preserve_nl = false, $tryoembed = true) {
$a = get_app();
// Move all spaces out of the tags
// Move all spaces out of the tags
// ....Uhm why?
// This is basically doing a trim() on the stuff in between tags, but it messes up
// This is basically doing a trim() on the stuff in between tags, but it messes up
// carefully crafted bbcode and especially other pre-formatted code.
// Commenting out until we come up with a use case where it's needed. Then let's try and
// special case rather than a heavy-handed approach like this.
@@ -393,7 +431,7 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
$Text = preg_replace("/\[observer\=0\](.*?)\[\/observer\]/ism", '$1', $Text);
$Text = preg_replace("/\[rpost(=.*?)?\](.*?)\[\/rpost\]/ism", '', $Text);
}
}
}
$channel = $a->get_channel();
if (strpos($Text,'[/channel]') !== false) {
@@ -404,7 +442,7 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
$Text = preg_replace("/\[channel\=1\].*?\[\/channel\]/ism", '', $Text);
$Text = preg_replace("/\[channel\=0\](.*?)\[\/channel\]/ism", '$1', $Text);
}
}
}
$x = bb_extract_images($Text);
@@ -413,14 +451,14 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
$Text = str_replace(array('[baseurl]','[sitename]'),array(z_root(),get_config('system','sitename')),$Text);
// Replace any html brackets with HTML Entities to prevent executing HTML or script
// Don't use strip_tags here because it breaks [url] search by replacing & with amp
$Text = str_replace("<", "&lt;", $Text);
$Text = str_replace(">", "&gt;", $Text);
// Convert new line chars to html <br /> tags
// nlbr seems to be hopelessly messed up
@@ -428,14 +466,14 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
// We'll emulate it.
$Text = str_replace("\r\n","\n", $Text);
$Text = str_replace(array("\r","\n"), array('<br />','<br />'), $Text);
$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);
if ($preserve_nl)
$Text = str_replace(array("\n", "\r"), array('', ''), $Text);
$Text = str_replace(array("\t"," "),array("&nbsp;&nbsp;&nbsp;&nbsp;","&nbsp;&nbsp;"),$Text);
$Text = str_replace(array("\t", " "), array("&nbsp;&nbsp;&nbsp;&nbsp;", "&nbsp;&nbsp;"), $Text);
// Set up the parameters for a URL search string
$URLSearchString = "^\[\]";
@@ -452,56 +490,53 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
$Text = str_replace('[observer.url]',$observer['xchan_url'], $Text);
$Text = str_replace('[observer.name]',$s1 . $observer['xchan_name'] . $s2, $Text);
$Text = str_replace('[observer.address]',$s1 . $observer['xchan_addr'] . $s2, $Text);
$Text = str_replace('[observer.webname]',$s1 . substr($observer['xchan_addr'],0,strpos($observer['xchan_addr'],'@')) . $s2, $Text);
$Text = str_replace('[observer.photo]',$s1 . '[zmg]'.$observer['xchan_photo_l'].'[/zmg]' . $s2, $Text);
$Text = str_replace('[observer.webname]', substr($observer['xchan_addr'],0,strpos($observer['xchan_addr'],'@')), $Text);
$Text = str_replace('[observer.photo]',$s1 . '[zmg]'.$observer['xchan_photo_l'].'[/zmg]' . $s2, $Text);
} else {
$Text = str_replace('[observer.baseurl]', '', $Text);
$Text = str_replace('[observer.url]','', $Text);
$Text = str_replace('[observer.name]','', $Text);
$Text = str_replace('[observer.address]','', $Text);
$Text = str_replace('[observer.webname]','',$Text);
$Text = str_replace('[observer.photo]','', $Text);
$Text = str_replace('[observer.photo]','', $Text);
}
// Perform URL Search
$urlchars = '[a-zA-Z0-9\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\+\,]';
$urlchars = '[a-zA-Z0-9\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\+\,\@]';
if (strpos($Text,'http') !== false) {
$Text = preg_replace("/([^\]\='".'"'."]|^)(https?\:\/\/$urlchars+)/ism", '$1<a href="$2" >$2</a>', $Text);
$Text = preg_replace("/([^\]\='".'"'."\/]|^|\#\^)(https?\:\/\/$urlchars+)/ism", '$1<a href="$2" >$2</a>', $Text);
}
if (strpos($Text,'[/qr]') !== false) {
$Text = preg_replace_callback("/\[qr\](.*?)\[\/qr\]/ism","bb_qr",$Text);
$Text = preg_replace_callback("/\[qr\](.*?)\[\/qr\]/ism", 'bb_qr', $Text);
}
if (strpos($Text,'[/share]') !== false) {
$Text = preg_replace_callback("/\[share(.*?)\](.*?)\[\/share\]/ism","bb_ShareAttributes",$Text);
$Text = preg_replace_callback("/\[share(.*?)\](.*?)\[\/share\]/ism", 'bb_ShareAttributes', $Text);
}
if($tryoembed) {
if (strpos($Text,'[/url]') !== false) {
$Text = preg_replace_callback("/\[url\]([$URLSearchString]*)\[\/url\]/ism",'tryoembed',$Text);
$Text = preg_replace_callback("/\[url\]([$URLSearchString]*)\[\/url\]/ism", 'tryoembed', $Text);
}
}
}
if (strpos($Text,'[/url]') !== false) {
$Text = preg_replace("/\#\^\[url\]([$URLSearchString]*)\[\/url\]/ism", '<span class="bookmark-identifier">#^</span><a class="bookmark" href="$1" >$1</a>', $Text);
$Text = preg_replace("/\#\^\[url\]([$URLSearchString]*)\[\/url\]/ism", '<span class="bookmark-identifier">#^</span><a class="bookmark" href="$1" >$1</a>', $Text);
$Text = preg_replace("/\#\^\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '<span class="bookmark-identifier">#^</span><a class="bookmark" href="$1" >$2</a>', $Text);
$Text = preg_replace("/\[url\]([$URLSearchString]*)\[\/url\]/ism", '<a href="$1" >$1</a>', $Text);
$Text = preg_replace("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '<a href="$1" >$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" >$1</a>', $Text);
$Text = preg_replace("/\#\^\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" >$2</a>', $Text);
$Text = preg_replace("/\#\^\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" >$1</a>', $Text);
$Text = preg_replace("/\#\^\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" >$2</a>', $Text);
$Text = preg_replace("/\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '<a class="zrl" href="$1" >$1</a>', $Text);
$Text = preg_replace("/\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<a class="zrl" href="$1" >$2</a>', $Text);
}
}
// Perform MAIL Search
if (strpos($Text,'[/mail]') !== false) {
if (strpos($Text,'[/mail]') !== false) {
$Text = preg_replace("/\[mail\]([$MAILSearchString]*)\[\/mail\]/", '<a href="mailto:$1">$1</a>', $Text);
$Text = preg_replace("/\[mail\=([$MAILSearchString]*)\](.*?)\[\/mail\]/", '<a href="mailto:$1">$2</a>', $Text);
}
@@ -509,54 +544,52 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
// leave open the posibility of [map=something]
// this is replaced in prepare_body() which has knowledge of the item location
if (strpos($Text,'[/map]') !== false) {
$Text = preg_replace_callback("/\[map\](.*?)\[\/map\]/ism",'bb_map_location',$Text);
if (strpos($Text,'[/map]') !== false) {
$Text = preg_replace_callback("/\[map\](.*?)\[\/map\]/ism", 'bb_map_location', $Text);
}
if (strpos($Text,'[map=') !== false) {
$Text = preg_replace_callback("/\[map=(.*?)\]/ism",'bb_map_coords',$Text);
if (strpos($Text,'[map=') !== false) {
$Text = preg_replace_callback("/\[map=(.*?)\]/ism", 'bb_map_coords', $Text);
}
if (strpos($Text,'[map]') !== false) {
if (strpos($Text,'[map]') !== false) {
$Text = preg_replace("/\[map\]/", '<div class="map"></div>', $Text);
}
// Check for bold text
if (strpos($Text,'[b]') !== false) {
$Text = preg_replace("(\[b\](.*?)\[\/b\])ism",'<strong>$1</strong>',$Text);
if (strpos($Text,'[b]') !== false) {
$Text = preg_replace("(\[b\](.*?)\[\/b\])ism", '<strong>$1</strong>', $Text);
}
// Check for Italics text
if (strpos($Text,'[i]') !== false) {
$Text = preg_replace("(\[i\](.*?)\[\/i\])ism",'<em>$1</em>',$Text);
if (strpos($Text,'[i]') !== false) {
$Text = preg_replace("(\[i\](.*?)\[\/i\])ism", '<em>$1</em>', $Text);
}
// Check for Underline text
if (strpos($Text,'[u]') !== false) {
$Text = preg_replace("(\[u\](.*?)\[\/u\])ism",'<u>$1</u>',$Text);
if (strpos($Text,'[u]') !== false) {
$Text = preg_replace("(\[u\](.*?)\[\/u\])ism", '<u>$1</u>', $Text);
}
// Check for strike-through text
if (strpos($Text,'[s]') !== false) {
$Text = preg_replace("(\[s\](.*?)\[\/s\])ism",'<strike>$1</strike>',$Text);
$Text = preg_replace("(\[s\](.*?)\[\/s\])ism", '<strike>$1</strike>', $Text);
}
// Check for over-line text
if (strpos($Text,'[o]') !== false) {
$Text = preg_replace("(\[o\](.*?)\[\/o\])ism",'<span class="overline">$1</span>',$Text);
if (strpos($Text,'[o]') !== false) {
$Text = preg_replace("(\[o\](.*?)\[\/o\])ism", '<span class="overline">$1</span>', $Text);
}
if (strpos($Text,'[sup]') !== false) {
$Text = preg_replace("(\[sup\](.*?)\[\/sup\])ism",'<sup>$1</sup>',$Text);
if (strpos($Text,'[sup]') !== false) {
$Text = preg_replace("(\[sup\](.*?)\[\/sup\])ism", '<sup>$1</sup>', $Text);
}
if (strpos($Text,'[sub]') !== false) {
$Text = preg_replace("(\[sub\](.*?)\[\/sub\])ism",'<sub>$1</sub>',$Text);
if (strpos($Text,'[sub]') !== false) {
$Text = preg_replace("(\[sub\](.*?)\[\/sub\])ism", '<sub>$1</sub>', $Text);
}
// Check for colored text
if (strpos($Text,'[/color]') !== false) {
$Text = preg_replace("(\[color=(.*?)\](.*?)\[\/color\])ism","<span style=\"color: $1;\">$2</span>",$Text);
if (strpos($Text,'[/color]') !== false) {
$Text = preg_replace("(\[color=(.*?)\](.*?)\[\/color\])ism", "<span style=\"color: $1;\">$2</span>", $Text);
}
// Check for sized text
// [size=50] --> font-size: 50px (with the unit).
if (strpos($Text,'[/size]') !== false) {
$Text = preg_replace("(\[size=(\d*?)\](.*?)\[\/size\])ism","<span style=\"font-size: $1px;\">$2</span>",$Text);
$Text = preg_replace("(\[size=(.*?)\](.*?)\[\/size\])ism","<span style=\"font-size: $1;\">$2</span>",$Text);
// [size=50] --> font-size: 50px (with the unit).
if (strpos($Text,'[/size]') !== false) {
$Text = preg_replace("(\[size=(\d*?)\](.*?)\[\/size\])ism", "<span style=\"font-size: $1px;\">$2</span>", $Text);
$Text = preg_replace("(\[size=(.*?)\](.*?)\[\/size\])ism", "<span style=\"font-size: $1;\">$2</span>", $Text);
}
// Check for h1
if (strpos($Text,'[h1]') !== false) {
@@ -582,13 +615,17 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
if (strpos($Text,'[h6]') !== false) {
$Text = preg_replace("(\[h6\](.*?)\[\/h6\])ism",'<h6>$1</h6>',$Text);
}
// Check for table of content
// Check for table of content without params
if (strpos($Text,'[toc]') !== false) {
$Text = preg_replace("/\[toc\]/ism",'<ul id="toc"></ul>',$Text);
}
// Check for table of content with params
if (strpos($Text,'[toc') !== false) {
$Text = preg_replace("/\[toc([^\]]+?)\]/ism",'<ul$1></ul>',$Text);
}
// Check for centered text
if (strpos($Text,'[/center]') !== false) {
$Text = preg_replace("(\[center\](.*?)\[\/center\])ism","<div style=\"text-align:center;\">$1</div>",$Text);
if (strpos($Text,'[/center]') !== false) {
$Text = preg_replace("(\[center\](.*?)\[\/center\])ism", "<div style=\"text-align:center;\">$1</div>", $Text);
}
// Check for list text
$Text = str_replace("[*]", "<li>", $Text);
@@ -597,51 +634,54 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
$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("/\[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);
$Text = preg_replace("/\[list=((?-i)i)\](.*?)\[\/list\]/ism",'<ul class="listlowerroman" style="list-style-type: lower-roman;">$2</ul>' ,$Text);
$Text = preg_replace("/\[list=((?-i)I)\](.*?)\[\/list\]/ism", '<ul class="listupperroman" style="list-style-type: upper-roman;">$2</ul>' ,$Text);
$Text = preg_replace("/\[list=((?-i)a)\](.*?)\[\/list\]/ism", '<ul class="listloweralpha" style="list-style-type: lower-alpha;">$2</ul>' ,$Text);
$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);
((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("/\[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);
$Text = preg_replace("/\[list=((?-i)i)\](.*?)\[\/list\]/ism",'<ul class="listlowerroman" style="list-style-type: lower-roman;">$2</ul>', $Text);
$Text = preg_replace("/\[list=((?-i)I)\](.*?)\[\/list\]/ism", '<ul class="listupperroman" style="list-style-type: upper-roman;">$2</ul>', $Text);
$Text = preg_replace("/\[list=((?-i)a)\](.*?)\[\/list\]/ism", '<ul class="listloweralpha" style="list-style-type: lower-alpha;">$2</ul>', $Text);
$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);
}
if (strpos($Text,'[th]') !== false) {
$Text = preg_replace("/\[th\](.*?)\[\/th\]/sm", '<th>$1</th>' ,$Text);
if (strpos($Text,'[th]') !== false) {
$Text = preg_replace("/\[th\](.*?)\[\/th\]/sm", '<th>$1</th>', $Text);
}
if (strpos($Text,'[td]') !== false) {
$Text = preg_replace("/\[td\](.*?)\[\/td\]/sm", '<td>$1</td>' ,$Text);
$Text = preg_replace("/\[td\](.*?)\[\/td\]/sm", '<td>$1</td>', $Text);
}
if (strpos($Text,'[tr]') !== false) {
$Text = preg_replace("/\[tr\](.*?)\[\/tr\]/sm", '<tr>$1</tr>' ,$Text);
if (strpos($Text,'[tr]') !== false) {
$Text = preg_replace("/\[tr\](.*?)\[\/tr\]/sm", '<tr>$1</tr>', $Text);
}
if (strpos($Text,'[/table]') !== false) {
$Text = preg_replace("/\[table\](.*?)\[\/table\]/sm", '<table>$1</table>' ,$Text);
$Text = preg_replace("/\[table border=1\](.*?)\[\/table\]/sm", '<table border="1" >$1</table>' ,$Text);
$Text = preg_replace("/\[table border=0\](.*?)\[\/table\]/sm", '<table border="0" >$1</table>' ,$Text);
if (strpos($Text,'[/table]') !== false) {
$Text = preg_replace("/\[table\](.*?)\[\/table\]/sm", '<table>$1</table>', $Text);
$Text = preg_replace("/\[table border=1\](.*?)\[\/table\]/sm", '<table border="1" >$1</table>', $Text);
$Text = preg_replace("/\[table border=0\](.*?)\[\/table\]/sm", '<table border="0" >$1</table>', $Text);
}
$Text = str_replace('[hr]','<hr />', $Text);
$Text = str_replace('</tr><br /><tr>', "</tr>\n<tr>", $Text);
$Text = str_replace('[hr]', '<hr />', $Text);
// This is actually executed in prepare_body()
$Text = str_replace('[nosmile]','',$Text);
$Text = str_replace('[nosmile]', '', $Text);
// Check for font change text
if (strpos($Text,'[/font]') !== false) {
$Text = preg_replace("/\[font=(.*?)\](.*?)\[\/font\]/sm","<span style=\"font-family: $1;\">$2</span>",$Text);
if (strpos($Text,'[/font]') !== false) {
$Text = preg_replace("/\[font=(.*?)\](.*?)\[\/font\]/sm", "<span style=\"font-family: $1;\">$2</span>", $Text);
}
// Declare the format for [code] layout
// Declare the format for [code] layout
$CodeLayout = '<code>$1</code>';
// Check for [code] text
if (strpos($Text,'[code]') !== false) {
$Text = preg_replace("/\[code\](.*?)\[\/code\]/ism","$CodeLayout", $Text);
if (strpos($Text,'[code]') !== false) {
$Text = preg_replace("/\[code\](.*?)\[\/code\]/ism", "$CodeLayout", $Text);
}
// Declare the format for [spoiler] layout
$SpoilerLayout = '<blockquote class="spoiler">$1</blockquote>';
@@ -649,7 +689,7 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
// handle nested quotes
$endlessloop = 0;
while ((strpos($Text, "[/spoiler]") !== false) and (strpos($Text, "[spoiler]") !== false) and (++$endlessloop < 20))
$Text = preg_replace("/\[spoiler\](.*?)\[\/spoiler\]/ism","$SpoilerLayout", $Text);
$Text = preg_replace("/\[spoiler\](.*?)\[\/spoiler\]/ism", "$SpoilerLayout", $Text);
// Check for [spoiler=Author] text
@@ -662,6 +702,13 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
"<br /><strong class=".'"spoiler"'.">" . $t_wrote . "</strong><blockquote class=".'"spoiler"'.">$2</blockquote>",
$Text);
$endlessloop = 0;
while ((strpos($Text, "[/open]")!== false) and (strpos($Text, "[open=") !== false) and (++$endlessloop < 20)) {
$Text = preg_replace_callback("/\[open=(.*?)\](.*?)\[\/open\]/ism", 'bb_opentag', $Text);
}
// Declare the format for [quote] layout
$QuoteLayout = '<blockquote>$1</blockquote>';
@@ -669,7 +716,7 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
// handle nested quotes
$endlessloop = 0;
while ((strpos($Text, "[/quote]") !== false) and (strpos($Text, "[quote]") !== false) and (++$endlessloop < 20))
$Text = preg_replace("/\[quote\](.*?)\[\/quote\]/ism","$QuoteLayout", $Text);
$Text = preg_replace("/\[quote\](.*?)\[\/quote\]/ism", "$QuoteLayout", $Text);
// Check for [quote=Author] text
@@ -733,9 +780,9 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
}
// crypt
if (strpos($Text,'[/crypt]') !== false) {
if (strpos($Text,'[/crypt]') !== false) {
$x = random_string();
$Text = preg_replace("/\[crypt\](.*?)\[\/crypt\]/ism",'<br/><div id="' . $x . '"><img src="' .$a->get_baseurl() . '/images/lock_icon.gif" onclick="red_decrypt(\'rot13\',\'\',\'$1\',\'#' . $x . '\');" alt="' . t('Encrypted content') . '" title="' . t('Encrypted content') . '" /><br /></div>', $Text);
$Text = preg_replace("/\[crypt\](.*?)\[\/crypt\]/ism",'<br /><div id="' . $x . '"><img src="' .$a->get_baseurl() . '/images/lock_icon.gif" onclick="red_decrypt(\'rot13\',\'\',\'$1\',\'#' . $x . '\');" alt="' . t('Encrypted content') . '" title="' . t('Encrypted content') . '" /><br /></div>', $Text);
$Text = preg_replace_callback("/\[crypt (.*?)\](.*?)\[\/crypt\]/ism", 'bb_parse_crypt', $Text);
}
@@ -747,24 +794,35 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
$Text = preg_replace_callback("/\[element\](.*?)\[\/element\]/ism",'bb_parse_element', $Text);
}
// html5 video and audio
if (strpos($Text,'[/video]') !== false) {
$Text = preg_replace_callback("/\[video\](.*?\.(ogg|ogv|oga|ogm|webm|mp4))\[\/video\]/ism", 'tryzrlvideo', $Text);
if (strpos($Text,'[/video]') !== false) {
$Text = preg_replace_callback("/\[video\](.*?\.(ogg|ogv|oga|ogm|webm|mp4|mpeg|mpg))\[\/video\]/ism", 'tryzrlvideo', $Text);
}
if (strpos($Text,'[/audio]') !== false) {
if (strpos($Text,'[/audio]') !== false) {
$Text = preg_replace_callback("/\[audio\](.*?\.(ogg|ogv|oga|ogm|webm|mp4|mp3|opus))\[\/audio\]/ism", 'tryzrlaudio', $Text);
}
if (strpos($Text,'[/zvideo]') !== false) {
$Text = preg_replace_callback("/\[zvideo\](.*?\.(ogg|ogv|oga|ogm|webm|mp4|mpeg|mpg))\[\/zvideo\]/ism", 'tryzrlvideo', $Text);
}
if (strpos($Text,'[/zaudio]') !== false) {
$Text = preg_replace_callback("/\[zaudio\](.*?\.(ogg|ogv|oga|ogm|webm|mp4|mp3|opus))\[\/zaudio\]/ism", 'tryzrlaudio', $Text);
}
// Try to Oembed
if ($tryoembed) {
if (strpos($Text,'[/video]') !== false) {
if (strpos($Text,'[/video]') !== false) {
$Text = preg_replace_callback("/\[video\](.*?)\[\/video\]/ism", 'tryoembed', $Text);
}
if (strpos($Text,'[/audio]') !== false) {
$Text = preg_replace_callback("/\[audio\](.*?)\[\/audio\]/ism", 'tryoembed', $Text);
}
if (strpos($Text,'[/zvideo]') !== false) {
$Text = preg_replace_callback("/\[zvideo\](.*?)\[\/zvideo\]/ism", 'tryoembed', $Text);
}
if (strpos($Text,'[/zaudio]') !== false) {
$Text = preg_replace_callback("/\[zaudio\](.*?)\[\/zaudio\]/ism", 'tryoembed', $Text);
}
}
// if video couldn't be embedded, link to it instead.
@@ -775,43 +833,47 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
$Text = preg_replace("/\[audio\](.*?)\[\/audio\]/", '<a href="$1">$1</a>', $Text);
}
if (strpos($Text,'[/zvideo]') !== false) {
$Text = preg_replace("/\[zvideo\](.*?)\[\/zvideo\]/", '<a class="zid" href="$1">$1</a>', $Text);
}
if (strpos($Text,'[/zaudio]') !== false) {
$Text = preg_replace("/\[zaudio\](.*?)\[\/zaudio\]/", '<a class="zid" href="$1">$1</a>', $Text);
}
if ($tryoembed){
if (strpos($Text,'[/iframe]') !== false) {
$Text = preg_replace_callback("/\[iframe\](.*?)\[\/iframe\]/ism", 'bbiframe', $Text);
$Text = preg_replace_callback("/\[iframe\](.*?)\[\/iframe\]/ism", 'bb_iframe', $Text);
}
}
else {
} else {
if (strpos($Text,'[/iframe]') !== false) {
$Text = preg_replace("/\[iframe\](.*?)\[\/iframe\]/ism", '<a href="$1">$1</a>', $Text);
}
}
// Youtube extensions
if (strpos($Text,'[youtube]') !== false) {
if ($tryoembed) {
$Text = preg_replace_callback("/\[youtube\](https?:\/\/www.youtube.com\/watch\?v\=.*?)\[\/youtube\]/ism", 'tryoembed', $Text);
$Text = preg_replace_callback("/\[youtube\](www.youtube.com\/watch\?v\=.*?)\[\/youtube\]/ism", 'tryoembed', $Text);
$Text = preg_replace_callback("/\[youtube\](https?:\/\/youtu.be\/.*?)\[\/youtube\]/ism",'tryoembed',$Text);
$Text = preg_replace_callback("/\[youtube\](https?:\/\/www.youtube.com\/watch\?v\=.*?)\[\/youtube\]/ism", 'tryoembed', $Text);
$Text = preg_replace_callback("/\[youtube\](www.youtube.com\/watch\?v\=.*?)\[\/youtube\]/ism", 'tryoembed', $Text);
$Text = preg_replace_callback("/\[youtube\](https?:\/\/youtu.be\/.*?)\[\/youtube\]/ism", 'tryoembed', $Text);
}
$Text = preg_replace("/\[youtube\]https?:\/\/www.youtube.com\/watch\?v\=(.*?)\[\/youtube\]/ism",'[youtube]$1[/youtube]',$Text);
$Text = preg_replace("/\[youtube\]https?:\/\/www.youtube.com\/embed\/(.*?)\[\/youtube\]/ism",'[youtube]$1[/youtube]',$Text);
$Text = preg_replace("/\[youtube\]https?:\/\/youtu.be\/(.*?)\[\/youtube\]/ism",'[youtube]$1[/youtube]',$Text);
$Text = preg_replace("/\[youtube\]https?:\/\/www.youtube.com\/watch\?v\=(.*?)\[\/youtube\]/ism", '[youtube]$1[/youtube]', $Text);
$Text = preg_replace("/\[youtube\]https?:\/\/www.youtube.com\/embed\/(.*?)\[\/youtube\]/ism", '[youtube]$1[/youtube]', $Text);
$Text = preg_replace("/\[youtube\]https?:\/\/youtu.be\/(.*?)\[\/youtube\]/ism", '[youtube]$1[/youtube]', $Text);
if ($tryoembed)
$Text = preg_replace("/\[youtube\]([A-Za-z0-9\-_=]+)(.*?)\[\/youtube\]/ism", '<iframe width="' . $a->videowidth . '" height="' . $a->videoheight . '" src="http://www.youtube.com/embed/$1" frameborder="0" ></iframe>', $Text);
else
$Text = preg_replace("/\[youtube\]([A-Za-z0-9\-_=]+)(.*?)\[\/youtube\]/ism", '<iframe width="' . $a->videowidth . '" height="' . $a->videoheight . '" src="http://www.youtube.com/embed/$1" frameborder="0"></iframe>', $Text);
else
$Text = preg_replace("/\[youtube\]([A-Za-z0-9\-_=]+)(.*?)\[\/youtube\]/ism", "http://www.youtube.com/watch?v=$1", $Text);
}
if (strpos($Text,'[vimeo]') !== false) {
if ($tryoembed) {
$Text = preg_replace_callback("/\[vimeo\](https?:\/\/player.vimeo.com\/video\/[0-9]+).*?\[\/vimeo\]/ism",'tryoembed',$Text);
$Text = preg_replace_callback("/\[vimeo\](https?:\/\/vimeo.com\/[0-9]+).*?\[\/vimeo\]/ism",'tryoembed',$Text);
$Text = preg_replace_callback("/\[vimeo\](https?:\/\/player.vimeo.com\/video\/[0-9]+).*?\[\/vimeo\]/ism", 'tryoembed', $Text);
$Text = preg_replace_callback("/\[vimeo\](https?:\/\/vimeo.com\/[0-9]+).*?\[\/vimeo\]/ism", 'tryoembed', $Text);
}
$Text = preg_replace("/\[vimeo\]https?:\/\/player.vimeo.com\/video\/([0-9]+)(.*?)\[\/vimeo\]/ism",'[vimeo]$1[/vimeo]',$Text);
$Text = preg_replace("/\[vimeo\]https?:\/\/vimeo.com\/([0-9]+)(.*?)\[\/vimeo\]/ism",'[vimeo]$1[/vimeo]',$Text);
$Text = preg_replace("/\[vimeo\]https?:\/\/player.vimeo.com\/video\/([0-9]+)(.*?)\[\/vimeo\]/ism", '[vimeo]$1[/vimeo]', $Text);
$Text = preg_replace("/\[vimeo\]https?:\/\/vimeo.com\/([0-9]+)(.*?)\[\/vimeo\]/ism", '[vimeo]$1[/vimeo]', $Text);
if ($tryoembed)
$Text = preg_replace("/\[vimeo\]([0-9]+)(.*?)\[\/vimeo\]/ism", '<iframe width="' . $a->videowidth . '" height="' . $a->videoheight . '" src="http://player.vimeo.com/video/$1" frameborder="0" ></iframe>', $Text);
@@ -830,7 +892,7 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
// Summary (e.g. title) is required, earlier revisions only required description (in addition to
// start which is always required). Allow desc with a missing summary for compatibility.
if((x($ev,'desc') || x($ev,'summary')) && x($ev,'start')) {
if ((x($ev,'desc') || x($ev,'summary')) && x($ev,'start')) {
$sub = format_event_html($ev);
$Text = preg_replace("/\[event\-summary\](.*?)\[\/event\-summary\]/ism",'',$Text);
@@ -844,26 +906,25 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
// Unhide all [noparse] contained bbtags unspacefying them
// and triming the [noparse] tag.
if (strpos($Text,'[noparse]') !== false) {
$Text = preg_replace_callback("/\[noparse\](.*?)\[\/noparse\]/ism", 'bb_unspacefy_and_trim',$Text);
$Text = preg_replace_callback("/\[noparse\](.*?)\[\/noparse\]/ism", 'bb_unspacefy_and_trim', $Text);
}
if (strpos($Text,'[nobb]') !== false) {
$Text = preg_replace_callback("/\[nobb\](.*?)\[\/nobb\]/ism", 'bb_unspacefy_and_trim',$Text);
$Text = preg_replace_callback("/\[nobb\](.*?)\[\/nobb\]/ism", 'bb_unspacefy_and_trim', $Text);
}
if (strpos($Text,'[pre]') !== false) {
$Text = preg_replace_callback("/\[pre\](.*?)\[\/pre\]/ism", 'bb_unspacefy_and_trim',$Text);
$Text = preg_replace_callback("/\[pre\](.*?)\[\/pre\]/ism", 'bb_unspacefy_and_trim', $Text);
}
$Text = preg_replace('/\[\&amp\;([#a-z0-9]+)\;\]/','&$1;',$Text);
$Text = preg_replace('/\[\&amp\;([#a-z0-9]+)\;\]/', '&$1;', $Text);
// fix any escaped ampersands that may have been converted into links
$Text = preg_replace("/\<(.*?)(src|href)=(.*?)\&amp\;(.*?)\>/ism",'<$1$2=$3&$4>',$Text);
$Text = preg_replace("/\<(.*?)(src|href)=(.*?)\&amp\;(.*?)\>/ism", '<$1$2=$3&$4>', $Text);
$Text = preg_replace("/\<(.*?)(src|href)=\"[^hfm#](.*?)\>/ism",'<$1$2="">',$Text);
$Text = preg_replace("/\<(.*?)(src|href)=\"[^zhfm#](.*?)\>/ism", '<$1$2="">', $Text);
$Text = bb_replace_images($Text,$saved_images);
$Text = bb_replace_images($Text, $saved_images);
call_hooks('bbcode',$Text);
call_hooks('bbcode', $Text);
return $Text;
}

View File

@@ -9,7 +9,7 @@ function bookmark_add($channel,$sender,$taxonomy,$private,$opts = null) {
$ischat = false;
if(is_array($opts)) {
$menu_id = ((x($opts,'menu_id')) ? intval($opt['menu_id']) : 0);
$menu_id = ((x($opts,'menu_id')) ? intval($opts['menu_id']) : 0);
$menu_name = ((x($opts,'menu_name')) ? escape_tags($opts['menu_name']) : '');
$ischat = ((x($opts,'ischat')) ? intval($opts['ischat']) : 0);
}

View File

@@ -1,7 +1,20 @@
<?php /** @file */
<?php
/**
* @file include/chat.php
* @brief Chat related functions.
*/
function chatroom_create($channel,$arr) {
/**
* @brief Creates a chatroom.
*
* @param array $channel
* @param array $arr
* @return An associative array containing:
* - success: A boolean
* - message: (optional) A string
*/
function chatroom_create($channel, $arr) {
$ret = array('success' => false);
@@ -24,14 +37,14 @@ function chatroom_create($channel,$arr) {
intval($channel['channel_account_id'])
);
if($r)
$limit = service_class_fetch($channel_id,'chatrooms');
$limit = service_class_fetch($channel['channel_id'], 'chatrooms');
if(($r) && ($limit !== false) && ($r[0]['total'] >= $limit)) {
$ret['message'] = upgrade_message();
return $ret;
}
if(($r) && ($limit !== false) && ($r[0]['total'] >= $limit)) {
$ret['message'] = upgrade_message();
return $ret;
}
if(! array_key_exists('expire',$arr))
if(! array_key_exists('expire', $arr))
$arr['expire'] = 120; // minutes, e.g. 2 hours
$created = datetime_convert();
@@ -60,6 +73,7 @@ function chatroom_create($channel,$arr) {
function chatroom_destroy($channel,$arr) {
$ret = array('success' => false);
if(intval($arr['cr_id']))
$sql_extra = " and cr_id = " . intval($arr['cr_id']) . " ";
elseif(trim($arr['cr_name']))
@@ -72,7 +86,7 @@ function chatroom_destroy($channel,$arr) {
$r = q("select * from chatroom where cr_uid = %d $sql_extra limit 1",
intval($channel['channel_id'])
);
if(! $r) {
if(! $r) {
$ret['message'] = t('Invalid room specifier.');
return $ret;
}
@@ -88,12 +102,13 @@ function chatroom_destroy($channel,$arr) {
intval($r[0]['cr_id'])
);
}
$ret['success'] = true;
return $ret;
}
function chatroom_enter($observer_xchan,$room_id,$status,$client) {
function chatroom_enter($observer_xchan, $room_id, $status, $client) {
if(! $room_id || ! $observer_xchan)
return;
@@ -117,7 +132,7 @@ function chatroom_enter($observer_xchan,$room_id,$status,$client) {
return false;
}
$limit = service_class_fetch($r[0]['cr_uid'],'chatters_inroom');
$limit = service_class_fetch($r[0]['cr_uid'], 'chatters_inroom');
if($limit !== false) {
$y = q("select count(*) as total from chatpresence where cp_room = %d",
intval($room_id)
@@ -157,12 +172,12 @@ function chatroom_enter($observer_xchan,$room_id,$status,$client) {
dbesc($status),
dbesc($client)
);
return $r;
}
function chatroom_leave($observer_xchan,$room_id,$client) {
function chatroom_leave($observer_xchan, $room_id, $client) {
if(! $room_id || ! $observer_xchan)
return;
@@ -208,7 +223,7 @@ function chatroom_list_count($uid) {
* It is the caller's responsibility to enter the room.
*/
function chat_message($uid,$room_id,$xchan,$text) {
function chat_message($uid, $room_id, $xchan, $text) {
$ret = array('success' => false);
@@ -230,14 +245,14 @@ function chat_message($uid,$room_id,$xchan,$text) {
'chat_text' => $text
);
call_hooks('chat_message',$arr);
call_hooks('chat_message', $arr);
$x = q("insert into chat ( chat_room, chat_xchan, created, chat_text )
values( %d, '%s', '%s', '%s' )",
intval($room_id),
dbesc($xchan),
dbesc(datetime_convert()),
dbesc($arr['chat_text'])
dbesc($arr['chat_text'])
);
$ret['success'] = true;

View File

@@ -15,23 +15,22 @@ require_once('include/widgets.php');
// page layout from the given description
function pdl_selector($uid,$current="") {
function pdl_selector($uid, $current="") {
$o = '';
$sql_extra = item_permissions_sql($uid);
$r = q("select item_id.*, mid from item_id left join item on iid = item.id where item_id.uid = %d and item_id.uid = item.uid and service = 'PDL' order by sid asc",
intval($owner)
$r = q("select item_id.*, mid from item_id left join item on iid = item.id where item_id.uid = %d and item_id.uid = item.uid and service = 'PDL' $sql_extra order by sid asc",
intval($uid)
);
$arr = array('channel_id' => $uid, 'current' => $current, 'entries' => $r);
call_hooks('pdl_selector',$arr);
$entries = $arr['entries'];
$current = $arr['current'];
$o .= "<select name=\"pdl_select\" id=\"pdl_select\" size=\"1\" >";
$current = $arr['current'];
$o .= '<select name="pdl_select" id="pdl_select" size="1">';
$entries[] = array('title' => t('Default'), 'mid' => '');
foreach($entries as $selection) {
$selected = (($selection == $current) ? ' selected="selected" ' : '');
@@ -40,109 +39,131 @@ function pdl_selector($uid,$current="") {
$o .= '</select>';
return $o;
}
}
function comanche_parser(&$a,$s) {
function comanche_parser(&$a, $s, $pass = 0) {
$matches = array();
$cnt = preg_match_all("/\[comment\](.*?)\[\/comment\]/ism", $s, $matches, PREG_SET_ORDER);
if($cnt) {
foreach($matches as $mtch) {
$s = str_replace($mtch[0],'',$s);
$s = str_replace($mtch[0], '', $s);
}
}
$cnt = preg_match("/\[layout\](.*?)\[\/layout\]/ism", $s, $matches);
if($cnt)
$a->page['template'] = trim($matches[1]);
if($pass == 0) {
$cnt = preg_match("/\[layout\](.*?)\[\/layout\]/ism", $s, $matches);
if($cnt)
$a->page['template'] = trim($matches[1]);
$cnt = preg_match("/\[template=(.*?)\](.*?)\[\/template\]/ism", $s, $matches);
if($cnt) {
$a->page['template'] = trim($matches[2]);
$a->page['template_style'] = trim($matches[2]) . '_' . $matches[1];
}
$cnt = preg_match("/\[template\](.*?)\[\/template\]/ism", $s, $matches);
if($cnt) {
$a->page['template'] = trim($matches[1]);
}
$cnt = preg_match("/\[theme=(.*?)\](.*?)\[\/theme\]/ism", $s, $matches);
if($cnt) {
$a->layout['schema'] = trim($matches[1]);
$a->layout['theme'] = trim($matches[2]);
}
$cnt = preg_match("/\[theme\](.*?)\[\/theme\]/ism", $s, $matches);
if($cnt)
$a->layout['theme'] = trim($matches[1]);
$cnt = preg_match_all("/\[region=(.*?)\](.*?)\[\/region\]/ism", $s, $matches, PREG_SET_ORDER);
if($cnt) {
foreach($matches as $mtch) {
$a->layout['region_' . $mtch[1]] = comanche_region($a,$mtch[2]);
$cnt = preg_match("/\[template=(.*?)\](.*?)\[\/template\]/ism", $s, $matches);
if($cnt) {
$a->page['template'] = trim($matches[2]);
$a->page['template_style'] = trim($matches[2]) . '_' . $matches[1];
}
}
$cnt = preg_match_all("/\[webpage\](.*?)\[\/webpage\]/ism", $s, $matches, PREG_SET_ORDER);
if($cnt) {
// only the last webpage definition is used if there is more than one
foreach($matches as $mtch) {
$a->layout['webpage'] = comanche_webpage($a,$mtch[1]);
$cnt = preg_match("/\[template\](.*?)\[\/template\]/ism", $s, $matches);
if($cnt) {
$a->page['template'] = trim($matches[1]);
}
$cnt = preg_match("/\[theme=(.*?)\](.*?)\[\/theme\]/ism", $s, $matches);
if($cnt) {
$a->layout['schema'] = trim($matches[1]);
$a->layout['theme'] = trim($matches[2]);
}
$cnt = preg_match("/\[theme\](.*?)\[\/theme\]/ism", $s, $matches);
if($cnt)
$a->layout['theme'] = trim($matches[1]);
$cnt = preg_match_all("/\[webpage\](.*?)\[\/webpage\]/ism", $s, $matches, PREG_SET_ORDER);
if($cnt) {
// only the last webpage definition is used if there is more than one
foreach($matches as $mtch) {
$a->layout['webpage'] = comanche_webpage($a,$mtch[1]);
}
}
}
else {
$cnt = preg_match_all("/\[region=(.*?)\](.*?)\[\/region\]/ism", $s, $matches, PREG_SET_ORDER);
if($cnt) {
foreach($matches as $mtch) {
$a->layout['region_' . $mtch[1]] = comanche_region($a,$mtch[2]);
}
}
}
}
function comanche_menu($name,$class = '') {
function comanche_menu($name, $class = '') {
$channel_id = comanche_get_channel_id();
if($channel_id) {
$m = menu_fetch($name,$channel_id,get_observer_hash());
return menu_render($m,$class);
$m = menu_fetch($name,$channel_id, get_observer_hash());
return menu_render($m, $class);
}
}
function comanche_replace_region($match) {
$a = get_app();
if(array_key_exists($match[1],$a->page)) {
if (array_key_exists($match[1], $a->page)) {
return $a->page[$match[1]];
}
}
/**
* @function comanche_get_channel_id()
* Returns the channel_id of the profile owner of the page, or the local_channel if there is no profile owner.
* Otherwise returns 0
*/
* @brief Returns the channel_id of the profile owner of the page.
*
* Returns the channel_id of the profile owner of the page, or the local_channel
* if there is no profile owner. Otherwise returns 0.
*
* @return channel_id
*/
function comanche_get_channel_id() {
$channel_id = ((is_array(get_app()->profile)) ? get_app()->profile['profile_uid'] : 0);
if((! $channel_id) && (local_channel()))
if ((! $channel_id) && (local_channel()))
$channel_id = local_channel();
return $channel_id;
}
function comanche_block($name) {
function comanche_block($s) {
$var = array();
$matches = array();
$name = $s;
$cnt = preg_match_all("/\[var=(.*?)\](.*?)\[\/var\]/ism", $s, $matches, PREG_SET_ORDER);
if($cnt) {
foreach($matches as $mtch) {
$var[$mtch[1]] = $mtch[2];
$name = str_replace($mtch[0], '', $name);
}
}
$o = '';
$channel_id = comanche_get_channel_id();
if($channel_id) {
$o = '';
$r = q("select * from item inner join item_id on iid = item.id and item_id.uid = item.uid and item.uid = %d and service = 'BUILDBLOCK' and sid = '%s' limit 1",
intval($channel_id),
dbesc($name)
);
if($r) {
$o = '<div class="widget bblock">';
$o .= (($var['wrap'] == 'none') ? '' : '<div class="bblock">');
if($r[0]['title'])
$o .= '<h3>' . $r[0]['title'] . '</h3>';
$o .= prepare_text($r[0]['body'],$r[0]['mimetype']);
$o .= '</div>';
$o .= prepare_text($r[0]['body'], $r[0]['mimetype']);
$o .= (($var['wrap'] == 'none') ? '' : '</div>');
}
}
return $o;
}
@@ -154,8 +175,9 @@ function comanche_block($name) {
// of what template and webpage options we might desire.
function comanche_webpage(&$a,$s) {
$ret = array();
$matches = array();
$cnt = preg_match_all("/\[authored\](.*?)\[\/authored\]/ism", $s, $matches, PREG_SET_ORDER);
if($cnt) {
foreach($matches as $mtch) {
@@ -166,32 +188,37 @@ function comanche_webpage(&$a,$s) {
}
// Widgets will have to get any operational arguments from the session,
// the global app environment, or config storage until we implement argument passing
function comanche_widget($name,$text) {
$a = get_app();
/**
* Widgets will have to get any operational arguments from the session, the
* global app environment, or config storage until we implement argument passing
*
* @param string $name
* @param string $text
*/
function comanche_widget($name, $text) {
$vars = array();
$matches = array();
$cnt = preg_match_all("/\[var=(.*?)\](.*?)\[\/var\]/ism", $text, $matches, PREG_SET_ORDER);
if($cnt) {
foreach($matches as $mtch) {
if ($cnt) {
foreach ($matches as $mtch) {
$vars[$mtch[1]] = $mtch[2];
}
}
$func = 'widget_' . trim($name);
if(function_exists($func))
if (function_exists($func))
return $func($vars);
}
function comanche_region(&$a,$s) {
function comanche_region(&$a, $s) {
$matches = array();
$cnt = preg_match_all("/\[menu\](.*?)\[\/menu\]/ism", $s, $matches, PREG_SET_ORDER);
if($cnt) {
foreach($matches as $mtch) {
$s = str_replace($mtch[0],comanche_menu(trim($mtch[1])),$s);
$s = str_replace($mtch[0], comanche_menu(trim($mtch[1])), $s);
}
}
@@ -244,7 +271,3 @@ function register_page_template($arr) {
get_app()->page_layouts[$arr['template']] = array($arr['variant']);
return;
}

View File

@@ -3,8 +3,7 @@
* @file include/config.php
* @brief Arbitrary configuration storage.
*
* Note:
* Please do not store booleans - convert to 0/1 integer values
* @note Please do not store booleans - convert to 0/1 integer values.
* The get_?config() functions return boolean false for keys that are unset,
* and this could lead to subtle bugs.
*
@@ -18,19 +17,20 @@
* - <b>pconfig</b> is used for channel specific configurations and takes a
* <i>channel_id</i> as identifier. It stores for example which features are
* enabled per channel. The storage is of size MEDIUMTEXT.
* @code $var = get_pconfig(local_channel(), 'category', 'key');@endcode
* @code{.php} $var = get_pconfig(local_channel(), 'category', 'key');@endcode
* - <b>xconfig</b> is the same as pconfig, except that it uses <i>xchan</i> as
* an identifier. This is for example for people who do not have a local account.
* The storage is of size MEDIUMTEXT.
* @code $observer = $a->get_observer_hash();
* @code{.php}
* $observer = $a->get_observer_hash();
* if ($observer) {
* $var = get_xconfig($observer, 'category', 'key');
* }@endcode
*
* - get_config() and set_config() can also be done through the command line tool
* @ref util/config
* @ref util/config.md "util/config"
* - get_pconfig() and set_pconfig() can also be done through the command line tool
* @ref util/pconfig and takes a channel_id as first argument.
* @ref util/pconfig.md "util/pconfig" and takes a channel_id as first argument.
*
*/
@@ -123,7 +123,7 @@ function get_config_from_storage($family, $key) {
*
* Stores a config value ($value) in the category ($family) under the key ($key).
*
* Please do not store booleans - convert to 0/1 integer values!
* @note Please do not store booleans - convert to 0/1 integer values!
*
* @param string $family
* The category of the configuration value
@@ -272,14 +272,16 @@ function get_pconfig($uid, $family, $key, $instore = false) {
* Stores a config value ($value) in the category ($family) under the key ($key)
* for the channel_id $uid.
*
* Please do not store booleans - convert to 0/1 integer values!
* @note Please do not store booleans - convert to 0/1 integer values!
*
* @param string $uid
* The channel_id
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to query
* The configuration key to set
* @param string $value
* The value to store
* @return mixed Stored $value or false
*/
function set_pconfig($uid, $family, $key, $value) {
@@ -315,6 +317,7 @@ function set_pconfig($uid, $family, $key, $value) {
);
if($ret)
return $value;
return $ret;
}
@@ -339,6 +342,7 @@ function set_pconfig($uid, $family, $key, $value) {
if($ret)
return $value;
return $ret;
}
@@ -360,13 +364,14 @@ function del_pconfig($uid, $family, $key) {
global $a;
$ret = false;
if(x($a->config[$uid][$family], $key))
if (x($a->config[$uid][$family], $key))
unset($a->config[$uid][$family][$key]);
$ret = q("DELETE FROM pconfig WHERE uid = %d AND cat = '%s' AND k = '%s'",
intval($uid),
dbesc($family),
dbesc($key)
);
return $ret;
}
@@ -448,7 +453,7 @@ function get_xconfig($xchan, $family, $key) {
* Stores a config value ($value) in the category ($family) under the key ($key)
* for the observer's $xchan hash.
*
* Please do not store booleans - convert to 0/1 integer values!
* @note Please do not store booleans - convert to 0/1 integer values!
*
* @param string $xchan
* The observer's hash
@@ -456,6 +461,8 @@ function get_xconfig($xchan, $family, $key) {
* The category of the configuration value
* @param string $key
* The configuration key to set
* @param string $value
* The value to store
* @return mixed Stored $value or false
*/
function set_xconfig($xchan, $family, $key, $value) {

File diff suppressed because it is too large Load Diff

View File

@@ -300,7 +300,6 @@ function salmon_key($pubkey) {
// used in Friendica 'RINO'. This function is messy and should be retired.
if(! function_exists('aes_decrypt')) {
function aes_decrypt($val,$ky)
{
$key="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
@@ -310,10 +309,10 @@ function aes_decrypt($val,$ky)
$enc = MCRYPT_RIJNDAEL_128;
$dec = @mcrypt_decrypt($enc, $key, $val, $mode, @mcrypt_create_iv( @mcrypt_get_iv_size($enc, $mode), MCRYPT_DEV_URANDOM ) );
return rtrim($dec,(( ord(substr($dec,strlen($dec)-1,1))>=0 and ord(substr($dec, strlen($dec)-1,1))<=16)? chr(ord( substr($dec,strlen($dec)-1,1))):null));
}}
}
if(! function_exists('aes_encrypt')) {
function aes_encrypt($val,$ky)
{
$key="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
@@ -323,6 +322,14 @@ function aes_encrypt($val,$ky)
$enc=MCRYPT_RIJNDAEL_128;
$val=str_pad($val, (16*(floor(strlen($val) / 16)+(strlen($val) % 16==0?2:1))), chr(16-(strlen($val) % 16)));
return mcrypt_encrypt($enc, $key, $val, $mode, mcrypt_create_iv( mcrypt_get_iv_size($enc, $mode), MCRYPT_DEV_URANDOM));
}}
}
function z_obscure($s) {
return json_encode(crypto_encapsulate($s,get_config('system','pubkey')));
}
function z_unobscure($s) {
if(strpos($s,"{\"") !== 0)
return $s;
return crypto_unencapsulate(json_decode($s,true),get_config('system','prvkey'));
}

View File

@@ -1,54 +1,71 @@
<?php /** @file */
// two-level sort for timezones.
<?php
/**
* @file include/datetime.php
* @brief Some functions for date and time related tasks.
*/
/**
* @brief Two-level sort for timezones.
*
* @param string $a
* @param string $b
* @return number
*/
function timezone_cmp($a, $b) {
if(strstr($a,'/') && strstr($b,'/')) {
if ( t($a) == t($b)) return 0;
return ( t($a) < t($b)) ? -1 : 1;
}
if(strstr($a,'/')) return -1;
if(strstr($b,'/')) return 1;
if (strstr($a,'/')) return -1;
if (strstr($b,'/')) return 1;
if ( t($a) == t($b)) return 0;
return ( t($a) < t($b)) ? -1 : 1;
}
// Return timezones grouped (primarily) by continent
/**
* @brief Return timezones grouped (primarily) by continent.
*
* @return array
*/
function get_timezones( ){
$timezone_identifiers = DateTimeZone::listIdentifiers();
usort($timezone_identifiers, 'timezone_cmp');
$continent = '';
$continents = array();
foreach($timezone_identifiers as $value) {
foreach ($timezone_identifiers as $value) {
$ex = explode("/", $value);
if(count($ex) > 1) {
if (count($ex) > 1) {
$continent = t($ex[0]);
if(count($ex) > 2)
$city = substr($value,strpos($value,'/')+1);
if (count($ex) > 2)
$city = substr($value, strpos($value, '/')+1);
else
$city = $ex[1];
}
else {
} else {
$city = $ex[0];
$continent = t('Miscellaneous');
}
$city = str_replace('_', ' ', t($city));
if(!x($continents,$ex[0])) $continents[$ex[0]] = array();
if (!x($continents, $ex[0])) $continents[$ex[0]] = array();
$continents[$continent][$value] = $city;
}
return $continents;
}
// General purpose date parse/convert function.
// $from = source timezone
// $to = dest timezone
// $s = some parseable date/time string
// $fmt = output format
/**
* @brief General purpose date parse/convert function.
*
* @param string $from source timezone
* @param string $to dest timezone
* @param string $s some parseable date/time string
* @param string $fmt output format recognised from php's DateTime class
* http://www.php.net/manual/en/datetime.format.php
* @return string
*/
function datetime_convert($from = 'UTC', $to = 'UTC', $s = 'now', $fmt = "Y-m-d H:i:s") {
// Defaults to UTC if nothing is set, but throws an exception if set to empty string.
@@ -68,44 +85,46 @@ function datetime_convert($from = 'UTC', $to = 'UTC', $s = 'now', $fmt = "Y-m-d
if(substr($s,0,10) == '0000-00-00') {
$d = new DateTime($s . ' + 32 days', new DateTimeZone('UTC'));
return str_replace('1','0',$d->format($fmt));
return str_replace('1', '0', $d->format($fmt));
}
try {
$from_obj = new DateTimeZone($from);
}
catch(Exception $e) {
} catch(Exception $e) {
$from_obj = new DateTimeZone('UTC');
}
try {
$d = new DateTime($s, $from_obj);
}
catch(Exception $e) {
} catch(Exception $e) {
logger('datetime_convert: exception: ' . $e->getMessage());
$d = new DateTime('now', $from_obj);
}
try {
$to_obj = new DateTimeZone($to);
}
catch(Exception $e) {
} catch(Exception $e) {
$to_obj = new DateTimeZone('UTC');
}
$d->setTimeZone($to_obj);
return($d->format($fmt));
}
// wrapper for date selector, tailored for use in birthday fields
/**
* @brief Wrapper for date selector, tailored for use in birthday fields.
*
* @param string $dob Date of Birth
* @return string
*/
function dob($dob) {
list($year,$month,$day) = sscanf($dob,'%4d-%2d-%2d');
$f = get_config('system','birthday_input_format');
if(! $f)
list($year, $month, $day) = sscanf($dob, '%4d-%2d-%2d');
$f = get_config('system', 'birthday_input_format');
if (! $f)
$f = 'ymd';
if($dob === '0000-00-00')
if ($dob === '0000-00-00')
$value = '';
else
$value = (($year) ? datetime_convert('UTC','UTC',$dob,'Y-m-d') : datetime_convert('UTC','UTC',$dob,'m-d'));
@@ -120,7 +139,6 @@ function dob($dob) {
return $o;
}
/**
* returns a date selector
* @param $format
@@ -135,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, '', '');
}
/**
@@ -154,7 +172,8 @@ function timesel($format, $h, $m, $id='timepicker') {
}
/**
* returns a datetime selector
* @brief Returns a datetime selector.
*
* @param $format
* format string, e.g. 'ymd' or 'mdy'. Not currently supported
* @param $min
@@ -163,21 +182,25 @@ function timesel($format, $h, $m, $id='timepicker') {
* unix timestap of maximum date
* @param $default
* unix timestamp of default date
* @param $id
* @param string $id
* id and name of datetimepicker (defaults to "datetimepicker")
* @param $pickdate
* @param boolean $pickdate
* true to show date picker (default)
* @param $picktime
* @param boolean $picktime
* true to show time picker (default)
* @param $minfrom
* set minimum date from picker with id $minfrom (none by default)
* @param $maxfrom
* set maximum date from picker with id $maxfrom (none by default)
* @param boolean $required default false
* @return string Parsed HTML output.
*
* @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) {
// Once browser support is better this could probably be replaced with native HTML5 date picker
$o = '';
function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pickdate = true, $picktime = true, $minfrom = '', $maxfrom = '', $required = false) {
$o = '';
$dateformat = '';
if($pickdate) $dateformat .= 'Y-m-d';
@@ -186,7 +209,7 @@ function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pic
$minjs = $min ? ",minDate: new Date({$min->getTimestamp()}*1000), yearStart: " . $min->format('Y') : '';
$maxjs = $max ? ",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)" : '';
@@ -212,31 +235,39 @@ function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pic
$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>";
return $o;
}
// implements "3 seconds ago" etc.
// based on $posted_date, (UTC).
// Results relative to current timezone
// Limited to range of timestamps
/**
* @brief Returns a relative date string.
*
* Implements "3 seconds ago" etc.
* Based on $posted_date, (UTC).
* Results relative to current timezone.
* Limited to range of timestamps.
*
* @param string $posted_date
* @param string $format (optional) parsed with sprintf()
* <tt>%1$d %2$s ago</tt>, e.g. 22 hours ago, 1 minute ago
* @return string with relative date
*/
function relative_date($posted_date, $format = null) {
function relative_date($posted_date,$format = null) {
$localtime = datetime_convert('UTC',date_default_timezone_get(),$posted_date);
$localtime = datetime_convert('UTC', date_default_timezone_get(), $posted_date);
$abs = strtotime($localtime);
if (is_null($posted_date) || $posted_date === NULL_DATE || $abs === False) {
return t('never');
if (is_null($posted_date) || $posted_date === NULL_DATE || $abs === false) {
return t('never');
}
$etime = time() - $abs;
if ($etime < 1) {
return t('less than a second ago');
}
$a = array( 12 * 30 * 24 * 60 * 60 => array( t('year'), t('years')),
30 * 24 * 60 * 60 => array( t('month'), t('months')),
7 * 24 * 60 * 60 => array( t('week'), t('weeks')),
@@ -245,231 +276,256 @@ function relative_date($posted_date,$format = null) {
60 => array( t('minute'), t('minutes')),
1 => array( t('second'), t('seconds'))
);
foreach ($a as $secs => $str) {
$d = $etime / $secs;
if ($d >= 1) {
$r = round($d);
// translators - e.g. 22 hours ago, 1 minute ago
if(! $format)
$format = t('%1$d %2$s ago');
return sprintf( $format,$r, (($r == 1) ? $str[0] : $str[1]));
}
}
if (! $format)
$format = t('%1$d %2$s ago', 'e.g. 22 hours ago, 1 minute ago');
return sprintf($format, $r, (($r == 1) ? $str[0] : $str[1]));
}
}
}
// Returns age in years, given a date of birth,
// the timezone of the person whose date of birth is provided,
// and the timezone of the person viewing the result.
// Why? Bear with me. Let's say I live in Mittagong, Australia, and my
// birthday is on New Year's. You live in San Bruno, California.
// When exactly are you going to see my age increase?
// A: 5:00 AM Dec 31 San Bruno time. That's precisely when I start
// celebrating and become a year older. If you wish me happy birthday
// on January 1 (San Bruno time), you'll be a day late.
function age($dob,$owner_tz = '',$viewer_tz = '') {
if(! intval($dob))
/**
* @brief Returns timezone correct age in years.
*
* Returns the age in years, given a date of birth, the timezone of the person
* whose date of birth is provided, and the timezone of the person viewing the
* result.
*
* Why? Bear with me. Let's say I live in Mittagong, Australia, and my birthday
* is on New Year's. You live in San Bruno, California.
* When exactly are you going to see my age increase?
*
* A: 5:00 AM Dec 31 San Bruno time. That's precisely when I start celebrating
* and become a year older. If you wish me happy birthday on January 1
* (San Bruno time), you'll be a day late.
*
* @param string $dob Date of Birth
* @param string $owner_tz (optional) timezone of the person of interest
* @param string $viewer_tz (optional) timezone of the person viewing
* @return number
*/
function age($dob, $owner_tz = '', $viewer_tz = '') {
if (! intval($dob))
return 0;
if(! $owner_tz)
if (! $owner_tz)
$owner_tz = date_default_timezone_get();
if(! $viewer_tz)
if (! $viewer_tz)
$viewer_tz = date_default_timezone_get();
$birthdate = datetime_convert('UTC',$owner_tz,$dob . ' 00:00:00+00:00','Y-m-d');
list($year,$month,$day) = explode("-",$birthdate);
$year_diff = datetime_convert('UTC',$viewer_tz,'now','Y') - $year;
$curr_month = datetime_convert('UTC',$viewer_tz,'now','m');
$curr_day = datetime_convert('UTC',$viewer_tz,'now','d');
$birthdate = datetime_convert('UTC', $owner_tz, $dob . ' 00:00:00+00:00','Y-m-d');
list($year,$month,$day) = explode("-", $birthdate);
$year_diff = datetime_convert('UTC', $viewer_tz, 'now', 'Y') - $year;
$curr_month = datetime_convert('UTC', $viewer_tz, 'now', 'm');
$curr_day = datetime_convert('UTC', $viewer_tz, 'now', 'd');
if(($curr_month < $month) || (($curr_month == $month) && ($curr_day < $day)))
if (($curr_month < $month) || (($curr_month == $month) && ($curr_day < $day)))
$year_diff--;
return $year_diff;
}
/**
* @brief Get days of a month in a given year.
*
* Returns number of days in the month of the given year.
* $m = 1 is 'January' to match human usage.
*
* @param int $y year
* @param int $m month (1=January, 12=December)
* @return int number of days in the given month
*/
function get_dim($y, $m) {
$dim = array( 0,
31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31
);
if ($m != 2)
return $dim[$m];
// Get days in month
// get_dim($year, $month);
// returns number of days.
// $month[1] = 'January';
// to match human usage.
if (((($y % 4) == 0) && (($y % 100) != 0)) || (($y % 400) == 0))
return 29;
function get_dim($y,$m) {
$dim = array( 0,
31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31);
if($m != 2)
return $dim[$m];
if(((($y % 4) == 0) && (($y % 100) != 0)) || (($y % 400) == 0))
return 29;
return $dim[2];
return $dim[2];
}
/**
* @brief Returns the first day in month for a given month, year.
*
* Months start at 1.
*
* @param int $y Year
* @param int $m Month (1=January, 12=December)
* @return day 0 = Sunday through 6 = Saturday
*/
function get_first_dim($y, $m) {
$d = sprintf('%04d-%02d-01 00:00', intval($y), intval($m));
// Returns the first day in month for a given month, year
// get_first_dim($year,$month)
// returns 0 = Sunday through 6 = Saturday
// Months start at 1.
function get_first_dim($y,$m) {
$d = sprintf('%04d-%02d-01 00:00', intval($y), intval($m));
return datetime_convert('UTC','UTC',$d,'w');
return datetime_convert('UTC', 'UTC', $d, 'w');
}
// output a calendar for the given month, year.
// if $links are provided (array), e.g. $links[12] => 'http://mylink' ,
// date 12 will be linked appropriately. Today's date is also noted by
// altering td class.
// Months count from 1.
// TODO: provide (prev,next) links, define class variations for different size calendars
function cal($y = 0,$m = 0, $links = false, $class='') {
/**
* @brief Output a calendar for the given month, year.
*
* If $links are provided (array), e.g. $links[12] => 'http://mylink' ,
* date 12 will be linked appropriately. Today's date is also noted by
* altering td class.
* Months count from 1.
*
* @param number $y Year
* @param number $m Month
* @param string $links (default false)
* @param string $class
* @return string
*
* @todo provide (prev,next) links, define class variations for different size calendars
*/
function cal($y = 0, $m = 0, $links = false, $class='') {
// month table - start at 1 to match human usage.
$mtab = array(' ',
'January','February','March',
'April','May','June',
'July','August','September',
'October','November','December'
);
'January','February','March',
'April','May','June',
'July','August','September',
'October','November','December'
);
$thisyear = datetime_convert('UTC',date_default_timezone_get(),'now','Y');
$thismonth = datetime_convert('UTC',date_default_timezone_get(),'now','m');
if(! $y)
if (! $y)
$y = $thisyear;
if(! $m)
if (! $m)
$m = intval($thismonth);
$dn = array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
$f = get_first_dim($y,$m);
$l = get_dim($y,$m);
$d = 1;
$dow = 0;
$started = false;
$dn = array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
$f = get_first_dim($y, $m);
$l = get_dim($y, $m);
$d = 1;
$dow = 0;
$started = false;
if(($y == $thisyear) && ($m == $thismonth))
$tddate = intval(datetime_convert('UTC',date_default_timezone_get(),'now','j'));
if (($y == $thisyear) && ($m == $thismonth))
$tddate = intval(datetime_convert('UTC',date_default_timezone_get(),'now','j'));
$str_month = day_translate($mtab[$m]);
$o = '<table class="calendar' . $class . '">';
$o .= "<caption>$str_month $y</caption><tr>";
for($a = 0; $a < 7; $a ++)
$o .= '<th>' . mb_substr(day_translate($dn[$a]),0,3,'UTF-8') . '</th>';
$o .= '</tr><tr>';
$o = '<table class="calendar' . $class . '">';
$o .= "<caption>$str_month $y</caption><tr>";
for ($a = 0; $a < 7; $a ++)
$o .= '<th>' . mb_substr(day_translate($dn[$a]),0,3,'UTF-8') . '</th>';
while($d <= $l) {
if(($dow == $f) && (! $started))
$started = true;
$today = (((isset($tddate)) && ($tddate == $d)) ? "class=\"today\" " : '');
$o .= "<td $today>";
$day = str_replace(' ','&nbsp;',sprintf('%2.2d', $d));
if($started) {
if(is_array($links) && isset($links[$d]))
$o .= "<a href=\"{$links[$d]}\">$day</a>";
else
$o .= $day;
$d ++;
}
else
$o .= '&nbsp;';
$o .= '</td>';
$dow ++;
if(($dow == 7) && ($d <= $l)) {
$dow = 0;
$o .= '</tr><tr>';
}
}
if($dow)
for($a = $dow; $a < 7; $a ++)
$o .= '<td>&nbsp;</td>';
$o .= '</tr></table>'."\r\n";
return $o;
$o .= '</tr><tr>';
while ($d <= $l) {
if (($dow == $f) && (! $started))
$started = true;
$today = (((isset($tddate)) && ($tddate == $d)) ? "class=\"today\" " : '');
$o .= "<td $today>";
$day = str_replace(' ','&nbsp;',sprintf('%2.2d', $d));
if ($started) {
if (is_array($links) && isset($links[$d]))
$o .= "<a href=\"{$links[$d]}\">$day</a>";
else
$o .= $day;
$d ++;
} else {
$o .= '&nbsp;';
}
$o .= '</td>';
$dow ++;
if (($dow == 7) && ($d <= $l)) {
$dow = 0;
$o .= '</tr><tr>';
}
}
if ($dow)
for ($a = $dow; $a < 7; $a ++)
$o .= '<td>&nbsp;</td>';
$o .= '</tr></table>'."\r\n";
return $o;
}
/**
* Return the next birthday, converted from the owner's timezone to UTC.
* @brief Return the next birthday, converted from the owner's timezone to UTC.
*
* This makes it globally portable.
* If the provided birthday lacks a month and or day, return an empty string.
* A missing year is acceptable.
*
* @param string $dob Date of Birth
* @param string $tz Timezone
* @param string $format
* @return string
*/
function z_birthday($dob, $tz, $format="Y-m-d H:i:s") {
function z_birthday($dob,$tz,$format="Y-m-d H:i:s") {
if(! strlen($tz))
if (! strlen($tz))
$tz = 'UTC';
$birthday = '';
$tmp_dob = substr($dob,5);
$tmp_d = substr($dob,8);
if(intval($tmp_dob) && intval($tmp_d)) {
if (intval($tmp_dob) && intval($tmp_d)) {
$y = datetime_convert($tz,$tz,'now','Y');
$bd = $y . '-' . $tmp_dob . ' 00:00';
$t_dob = strtotime($bd);
$now = strtotime(datetime_convert($tz,$tz,'now'));
if($t_dob < $now)
if ($t_dob < $now)
$bd = $y + 1 . '-' . $tmp_dob . ' 00:00';
$birthday = datetime_convert($tz,'UTC',$bd,$format);
}
return $birthday;
}
/**
* @brief Create a birthday event for any connections with a birthday in the next 1-2 weeks.
*
* Create a birthday event for any connections with a birthday in the next 1-2 weeks.
* Update the year so that we don't create another event until next year.
*
*/
function update_birthdays() {
require_once('include/event.php');
require_once('include/permissions.php');
$r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash
$r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_dob > %s + interval %s and abook_dob < %s + interval %s",
db_utcnow(), db_quoteinterval('7 day'),
db_utcnow(), db_quoteinterval('14 day')
);
if($r) {
foreach($r as $rr) {
if(! perm_is_allowed($rr['abook_channel'],$rr['xchan_hash'],'send_stream'))
);
if ($r) {
foreach ($r as $rr) {
if (! perm_is_allowed($rr['abook_channel'], $rr['xchan_hash'], 'send_stream'))
continue;
$ev = array();
$ev['uid'] = $rr['abook_channel'];
$ev['account'] = $rr['abook_account'];
$ev['event_xchan'] = $rr['xchan_hash'];
$ev['start'] = datetime_convert('UTC','UTC', $rr['abook_dob']);
$ev['finish'] = datetime_convert('UTC','UTC', $rr['abook_dob'] . ' + 1 day ');
$ev['start'] = datetime_convert('UTC', 'UTC', $rr['abook_dob']);
$ev['finish'] = datetime_convert('UTC', 'UTC', $rr['abook_dob'] . ' + 1 day ');
$ev['adjust'] = 1;
$ev['summary'] = sprintf( t('%1$s\'s birthday'), $rr['xchan_name']);
$ev['description'] = sprintf( t('Happy Birthday %1$s'),
$ev['summary'] = sprintf( t('%1$s\'s birthday'), $rr['xchan_name']);
$ev['description'] = sprintf( t('Happy Birthday %1$s'),
'[zrl=' . $rr['xchan_url'] . ']' . $rr['xchan_name'] . '[/zrl]') ;
$ev['type'] = 'birthday';
$z = event_store_event($ev);
if($z) {
$item_id = event_store_item($ev,$z);
if ($z) {
$item_id = event_store_item($ev, $z);
q("update abook set abook_dob = '%s' where abook_id = %d",
dbesc(intval($rr['abook_dob']) + 1 . substr($rr['abook_dob'],4)),
dbesc(intval($rr['abook_dob']) + 1 . substr($rr['abook_dob'], 4)),
intval($rr['abook_id'])
);
}

View File

@@ -24,7 +24,6 @@
function dba_factory($server, $port,$user,$pass,$db,$dbtype,$install = false) {
$dba = null;
$dbtype = intval($dbtype);
if($dbtype == DBTYPE_POSTGRES) {
@@ -59,7 +58,7 @@ abstract class dba_driver {
const INSTALL_SCRIPT='install/schema_mysql.sql';
const NULL_DATE = '0000-00-00 00:00:00';
const UTC_NOW = 'UTC_TIMESTAMP()';
protected $debug = 0;
protected $db;
public $connected = false;
@@ -121,11 +120,11 @@ abstract class dba_driver {
function get_null_date() {
return static::NULL_DATE;
}
function get_install_script() {
return static::INSTALL_SCRIPT;
}
function utcnow() {
return static::UTC_NOW;
}
@@ -145,6 +144,7 @@ abstract class dba_driver {
return false;
}
}
return true;
}
@@ -166,19 +166,19 @@ abstract class dba_driver {
function quote_interval($txt) {
return $txt;
}
function optimize_table($table) {
q('OPTIMIZE TABLE '.$table);
}
function concat($fld, $sep) {
return 'GROUP_CONCAT(DISTINCT '.$fld.' SEPARATOR \''.$sep.'\')';
}
function escapebin($str) {
return $this->escape($str);
}
function unescapebin($str) {
return $str;
}
@@ -193,6 +193,7 @@ function printable($s) {
$s = str_replace("\x00",'.',$s);
if(x($_SERVER,'SERVER_NAME'))
$s = escape_tags($s);
return $s;
}
@@ -252,7 +253,7 @@ function db_quoteinterval($txt) {
function dbesc_identifier($str) {
global $db;
return $db->escape_identifier($txt);
return $db->escape_identifier($str);
}
function db_utcnow() {
@@ -349,6 +350,7 @@ function dbesc_array_cb(&$item, $key) {
$item = '0001-01-01 00:00:00';
else if($item == '0001-01-01 00:00:00' && ACTIVE_DBTYPE == DBTYPE_MYSQL)
$item = '0000-00-00 00:00:00';
$item = dbesc($item);
}
}
@@ -382,8 +384,7 @@ function db_getfunc($f) {
$f = strtolower($f);
if(isset($lookup[$f]) && isset($lookup[$f][ACTIVE_DBTYPE]))
return $lookup[$f][ACTIVE_DBTYPE];
logger('Unable to abstract DB function "'. $f . '" for dbtype ' . ACTIVE_DBTYPE, LOGGER_DEBUG);
return $f;
}

View File

@@ -20,6 +20,32 @@ function deliver_run($argv, $argc) {
dbesc($argv[$x])
);
if($r) {
/**
* Check to see if we have any recent communications with this hub (in the last month).
* If not, reduce the outq_priority.
*/
$h = parse_url($r[0]['outq_posturl']);
if($h) {
$base = $h['scheme'] . '://' . $h['host'] . (($h['port']) ? ':' . $h['port'] : '');
if($base !== z_root()) {
$y = q("select site_update from site where site_url = '%s' ",
dbesc($base)
);
if($y && $y[0]['site_update'] < datetime_convert('UTC','UTC','now - 1 month')) {
q("update outq set outq_priority = %d where outq_hash = '%s'",
intval($r[0]['outq_priority'] + 10),
dbesc($r[0]['outq_hash'])
);
logger('immediate delivery deferred for site ' . $base);
continue;
}
}
}
// "post" queue driver - used for diaspora and friendica-over-diaspora communications.
if($r[0]['outq_driver'] === 'post') {
$result = z_post_url($r[0]['outq_posturl'],$r[0]['outq_msg']);
if($result['success'] && $result['return_code'] < 300) {
@@ -74,9 +100,11 @@ function deliver_run($argv, $argc) {
logger('deliver: dest: ' . $r[0]['outq_posturl'], LOGGER_DEBUG);
$result = zot_zot($r[0]['outq_posturl'],$r[0]['outq_notify']);
if($result['success']) {
logger('deliver: remote zot delivery succeeded to ' . $r[0]['outq_posturl']);
zot_process_response($r[0]['outq_posturl'],$result, $r[0]);
}
else {
logger('deliver: remote zot delivery failed to ' . $r[0]['outq_posturl']);
$y = q("update outq set outq_updated = '%s' where outq_hash = '%s'",
dbesc(datetime_convert()),
dbesc($argv[$x])

View File

@@ -698,6 +698,57 @@ function diaspora_request($importer,$xml) {
return;
}
//FIXME
/*
if(feature_enabled($channel['channel_id'],'premium_channel')) {
$myaddr = $importer['channel_address'] . '@' . get_app()->get_hostname();
$cnv = random_string();
$mid = random_string();
$msg = t('You have started sharing with a Redmatrix premium channel.');
$msg .= t('Redmatrix premium channels are not available for sharing with Diaspora members. This sharing request has been blocked.') . "\r";
$msg .= t('Please do not reply to this message, as this channel is not sharing with you and any reply will not be seen by the recipient.') . "\r";
$created = datetime_convert('UTC','UTC',$item['created'],'Y-m-d H:i:s \U\T\C');
$signed_text = $mid . ';' . $cnv . ';' . $msg . ';'
. $created . ';' . $myaddr . ';' . $cnv;
$sig = base64_encode(rsa_sign($signed_text,$importer['channel_prvkey'],'sha256'));
$conv = array(
'guid' => xmlify($cnv),
'subject' => xmlify(t('Sharing request failed.')),
'created_at' => xmlify($created),
'diaspora_handle' => xmlify($myaddr),
'participant_handles' => xmlify($myaddr . ';' . $sender_handle)
);
$msg = array(
'guid' => xmlify($mid),
'parent_guid' => xmlify($cnv),
'parent_author_signature' => xmlify($sig),
'author_signature' => xmlify($sig),
'text' => xmlify($msg),
'created_at' => xmlify($created),
'diaspora_handle' => xmlify($myaddr),
'conversation_guid' => xmlify($cnv)
);
$conv['messages'] = array($msg);
$tpl = get_markup_template('diaspora_conversation.tpl');
$xmsg = replace_macros($tpl, array('$conv' => $conv));
$slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($xmsg,$importer,$ret,$importer['channel_prvkey'],$ret['xchan_pubkey'],false)));
diaspora_transmit($importer,$ret,$slap,false);
return;
}
*/
// End FIXME
$role = get_pconfig($channel['channel_id'],'system','permissions_role');
if($role) {
$x = get_role_perms($role);
@@ -709,13 +760,19 @@ function diaspora_request($importer,$xml) {
$their_perms = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK|PERMS_W_STREAM|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT|PERMS_R_STORAGE|PERMS_R_PAGES;
$closeness = get_pconfig($importer['channel_id'],'system','new_abook_closeness');
if($closeness === false)
$closeness = 80;
$r = q("insert into abook ( abook_account, abook_channel, abook_xchan, abook_my_perms, abook_their_perms, abook_closeness, abook_rating, abook_created, abook_updated, abook_connected, abook_dob, abook_flags) values ( %d, %d, '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', %d )",
intval($importer['channel_account_id']),
intval($importer['channel_id']),
dbesc($ret['xchan_hash']),
intval($default_perms),
intval($their_perms),
intval(99),
intval($closeness),
intval(0),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
@@ -799,11 +856,6 @@ function diaspora_post($importer,$xml,$msg) {
}
if((! $importer['system']) && (! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'send_stream'))) {
logger('diaspora_post: Ignoring this author.');
return 202;
}
$search_guid = ((strlen($guid) == 64) ? $guid . '%' : $guid);
$r = q("SELECT id FROM item WHERE uid = %d AND mid like '%s' LIMIT 1",
@@ -827,6 +879,12 @@ function diaspora_post($importer,$xml,$msg) {
$body = scale_external_images($body);
}
$maxlen = get_max_import_size();
if($maxlen && mb_strlen($body) > $maxlen) {
$body = mb_substr($body,0,$maxlen,'UTF-8');
logger('message length exceeds max_import_size: truncated');
}
//WTF? FIXME
// Add OEmbed and other information to the body
@@ -835,34 +893,21 @@ function diaspora_post($importer,$xml,$msg) {
$datarray = array();
$tags = get_tags($body);
// Look for tags and linkify them
$results = linkify_tags(get_app(), $body, $importer['channel_id'], true);
$datarray['term'] = array();
if(count($tags)) {
$datarray['term'] = array();
foreach($tags as $tag) {
if(strpos($tag,'#') === 0) {
if((strpos($tag,'[url=')) || (strpos($tag,'[zrl')))
continue;
// don't link tags that are already embedded in links
if(preg_match('/\[(.*?)' . preg_quote($tag,'/') . '(.*?)\]/',$body))
continue;
if(preg_match('/\[(.*?)\]\((.*?)' . preg_quote($tag,'/') . '(.*?)\)/',$body))
continue;
$basetag = str_replace('_',' ',substr($tag,1));
$body = str_replace($tag,'#[url=' . $a->get_baseurl() . '/search?tag=' . rawurlencode($basetag) . ']' . $basetag . '[/url]',$body);
if($results) {
foreach($results as $result) {
$success = $result['success'];
if($success['replaced']) {
$datarray['term'][] = array(
'uid' => $importer['channel_id'],
'type' => TERM_HASHTAG,
'type' => $success['termtype'],
'otype' => TERM_OBJ_POST,
'term' => $basetag,
'url' => z_root() . '/search?tag=' . rawurlencode($basetag)
'term' => $success['term'],
'url' => $success['url']
);
}
}
@@ -897,6 +942,8 @@ function diaspora_post($importer,$xml,$msg) {
}
$plink = service_plink($contact,$guid);
@@ -920,6 +967,13 @@ function diaspora_post($importer,$xml,$msg) {
$datarray['item_unseen'] = 1;
$datarray['item_thread_top'] = 1;
$tgroup = tgroup_check($importer['channel_id'],$datarray);
if((! $importer['system']) && (! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'send_stream')) && (! $tgroup)) {
logger('diaspora_post: Ignoring this author.');
return 202;
}
$result = item_store($datarray);
return;
@@ -986,11 +1040,6 @@ function diaspora_reshare($importer,$xml,$msg) {
if(! $contact)
return;
if((! $importer['system']) && (! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'send_stream'))) {
logger('diaspora_reshare: Ignoring this author: ' . $diaspora_handle . ' ' . print_r($xml,true));
return 202;
}
$search_guid = ((strlen($guid) == 64) ? $guid . '%' : $guid);
$r = q("SELECT id FROM item WHERE uid = %d AND mid like '%s' LIMIT 1",
intval($importer['channel_id']),
@@ -1040,10 +1089,12 @@ function diaspora_reshare($importer,$xml,$msg) {
//return;
}
//if(! $body) {
// logger('diaspora_reshare: empty body: source= ' . $x);
// return;
//}
$maxlen = get_max_import_size();
if($maxlen && mb_strlen($body) > $maxlen) {
$body = mb_substr($body,0,$maxlen,'UTF-8');
logger('message length exceeds max_import_size: truncated');
}
$person = find_diaspora_person_by_handle($orig_author);
@@ -1053,56 +1104,33 @@ function diaspora_reshare($importer,$xml,$msg) {
$orig_author_photo = $person['xchan_photo_m'];
}
$newbody = "[share author='" . urlencode($orig_author_name)
. "' profile='" . $orig_author_link
. "' avatar='" . $orig_author_photo
. "' link='" . $orig_url
. "' posted='" . datetime_convert('UTC','UTC',unxmlify($source_xml->post->status_message->created_at))
. "' message_id='" . unxmlify($source_xml->post->status_message->guid)
. "']" . $body . "[/share]";
$created = unxmlify($xml->created_at);
$private = ((unxmlify($xml->public) == 'false') ? 1 : 0);
$datarray = array();
$str_tags = '';
// Look for tags and linkify them
$results = linkify_tags(get_app(), $body, $importer['channel_id'], true);
$tags = get_tags($newbody);
if(count($tags)) {
$datarray['term'] = array();
foreach($tags as $tag) {
if(strpos($tag,'#') === 0) {
if((strpos($tag,'[url=')) || (strpos($tag,'[zrl')))
continue;
// don't link tags that are already embedded in links
if(preg_match('/\[(.*?)' . preg_quote($tag,'/') . '(.*?)\]/',$newbody))
continue;
if(preg_match('/\[(.*?)\]\((.*?)' . preg_quote($tag,'/') . '(.*?)\)/',$newbody))
continue;
$basetag = str_replace('_',' ',substr($tag,1));
$newbody = str_replace($tag,'#[url=' . $a->get_baseurl() . '/search?tag=' . rawurlencode($basetag) . ']' . $basetag . '[/url]',$newbody);
$datarray['term'] = array();
if($results) {
foreach($results as $result) {
$success = $result['success'];
if($success['replaced']) {
$datarray['term'][] = array(
'uid' => $importer['channel_id'],
'type' => TERM_HASHTAG,
'type' => $success['termtype'],
'otype' => TERM_OBJ_POST,
'term' => $basetag,
'url' => z_root() . '/search?tag=' . rawurlencode($basetag)
'term' => $success['term'],
'url' => $success['url']
);
}
}
}
$cnt = preg_match_all('/@\[url=(.*?)\](.*?)\[\/url\]/ism',$newbody,$matches,PREG_SET_ORDER);
$cnt = preg_match_all('/@\[url=(.*?)\](.*?)\[\/url\]/ism',$body,$matches,PREG_SET_ORDER);
if($cnt) {
foreach($matches as $mtch) {
$datarray['term'][] = array(
@@ -1115,6 +1143,34 @@ function diaspora_reshare($importer,$xml,$msg) {
}
}
$cnt = preg_match_all('/@\[zrl=(.*?)\](.*?)\[\/zrl\]/ism',$body,$matches,PREG_SET_ORDER);
if($cnt) {
foreach($matches as $mtch) {
// don't include plustags in the term
$term = ((substr($mtch[2],-1,1) === '+') ? substr($mtch[2],0,-1) : $mtch[2]);
$datarray['term'][] = array(
'uid' => $importer['channel_id'],
'type' => TERM_MENTION,
'otype' => TERM_OBJ_POST,
'term' => $term,
'url' => $mtch[1]
);
}
}
$newbody = "[share author='" . urlencode($orig_author_name)
. "' profile='" . $orig_author_link
. "' avatar='" . $orig_author_photo
. "' link='" . $orig_url
. "' posted='" . datetime_convert('UTC','UTC',unxmlify($source_xml->post->status_message->created_at))
. "' message_id='" . unxmlify($source_xml->post->status_message->guid)
. "']" . $body . "[/share]";
$plink = service_plink($contact,$guid);
$datarray['uid'] = $importer['channel_id'];
@@ -1129,6 +1185,15 @@ function diaspora_reshare($importer,$xml,$msg) {
$datarray['app'] = 'Diaspora';
$tgroup = tgroup_check($importer['channel_id'],$datarray);
if((! $importer['system']) && (! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'send_stream')) && (! $tgroup)) {
logger('diaspora_post: Ignoring this author.');
return 202;
}
$result = item_store($datarray);
return;
@@ -1257,17 +1322,40 @@ function diaspora_comment($importer,$xml,$msg) {
return;
}
if((! $importer['system']) && (! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'post_comments'))) {
logger('diaspora_comment: Ignoring this author.');
return 202;
}
$pubcomment = get_pconfig($importer['channel_id'],'system','diaspora_public_comments');
// by default comments on public posts are allowed from anybody on Diaspora. That is their policy.
// Once this setting is set to something we'll track your preference and it will over-ride the default.
if($pubcomment === false)
$pubcomment = 1;
// Friendica is currently truncating guids at 64 chars
$search_guid = $parent_guid;
if(strlen($parent_guid) == 64)
$search_guid = $parent_guid . '%';
$r = q("SELECT * FROM item WHERE uid = %d AND mid LIKE '%s' LIMIT 1",
intval($importer['channel_id']),
dbesc($search_guid)
);
if(! $r) {
logger('diaspora_comment: parent item not found: parent: ' . $parent_guid . ' item: ' . $guid);
return;
}
$parent_item = $r[0];
if(intval($parent_item['item_private']))
$pubcomment = 0;
$search_guid = $guid;
if(strlen($guid) == 64)
$search_guid = $guid . '%';
$r = q("SELECT * FROM item WHERE uid = %d AND mid like '%s' LIMIT 1",
intval($importer['channel_id']),
dbesc($search_guid)
@@ -1277,20 +1365,6 @@ function diaspora_comment($importer,$xml,$msg) {
return;
}
$search_guid = $parent_guid;
if(strlen($parent_guid) == 64)
$search_guid = $parent_guid . '%';
$r = q("SELECT * FROM item WHERE uid = %d AND mid LIKE '%s' LIMIT 1",
intval($importer['channel_id']),
dbesc($search_guid)
);
if(! $r) {
logger('diaspora_comment: parent item not found: parent: ' . $parent_guid . ' item: ' . $guid);
return;
}
$parent_item = $r[0];
/* How Diaspora performs comment signature checking:
@@ -1326,6 +1400,12 @@ function diaspora_comment($importer,$xml,$msg) {
// our post, so he/she must be a contact of ours and his/her public key
// should be in $msg['key']
if($importer['system']) {
// don't relay to the sys channel
logger('diaspora_comment: relay to sys channel blocked.');
return;
}
$author_signature = base64_decode($author_signature);
if(! rsa_verify($signed_data,$author_signature,$key,'sha256')) {
@@ -1354,35 +1434,32 @@ function diaspora_comment($importer,$xml,$msg) {
$body = diaspora2bb($text);
$maxlen = get_max_import_size();
if($maxlen && mb_strlen($body) > $maxlen) {
$body = mb_substr($body,0,$maxlen,'UTF-8');
logger('message length exceeds max_import_size: truncated');
}
$datarray = array();
$tags = get_tags($body);
// Look for tags and linkify them
$results = linkify_tags(get_app(), $body, $importer['channel_id'], true);
if(count($tags)) {
$datarray['term'] = array();
foreach($tags as $tag) {
if(strpos($tag,'#') === 0) {
if((strpos($tag,'[url=')) || (strpos($tag,'[zrl')))
continue;
// don't link tags that are already embedded in links
if(preg_match('/\[(.*?)' . preg_quote($tag,'/') . '(.*?)\]/',$body))
continue;
if(preg_match('/\[(.*?)\]\((.*?)' . preg_quote($tag,'/') . '(.*?)\)/',$body))
continue;
$basetag = str_replace('_',' ',substr($tag,1));
$body = str_replace($tag,'#[url=' . $a->get_baseurl() . '/search?tag=' . rawurlencode($basetag) . ']' . $basetag . '[/url]',$body);
$datarray['term'] = array();
if($results) {
foreach($results as $result) {
$success = $result['success'];
if($success['replaced']) {
$datarray['term'][] = array(
'uid' => $importer['channel_id'],
'type' => TERM_HASHTAG,
'type' => $success['termtype'],
'otype' => TERM_OBJ_POST,
'term' => $basetag,
'url' => z_root() . '/search?tag=' . rawurlencode($basetag)
'term' => $success['term'],
'url' => $success['url']
);
}
}
@@ -1401,6 +1478,21 @@ function diaspora_comment($importer,$xml,$msg) {
}
}
$cnt = preg_match_all('/@\[zrl=(.*?)\](.*?)\[\/zrl\]/ism',$body,$matches,PREG_SET_ORDER);
if($cnt) {
foreach($matches as $mtch) {
// don't include plustags in the term
$term = ((substr($mtch[2],-1,1) === '+') ? substr($mtch[2],0,-1) : $mtch[2]);
$datarray['term'][] = array(
'uid' => $importer['channel_id'],
'type' => TERM_MENTION,
'otype' => TERM_OBJ_POST,
'term' => $term,
'url' => $mtch[1]
);
}
}
$datarray['uid'] = $importer['channel_id'];
$datarray['verb'] = ACTIVITY_POST;
$datarray['mid'] = $guid;
@@ -1432,6 +1524,22 @@ function diaspora_comment($importer,$xml,$msg) {
$datarray['diaspora_meta'] = json_encode(crypto_encapsulate(json_encode($x),$key));
}
// So basically if something arrives at the sys channel it's by definition public and we allow it.
// If $pubcomment and the parent was public, we allow it.
// In all other cases, honour the permissions for this Diaspora connection
$tgroup = tgroup_check($importer['channel_id'],$datarray);
if((! $importer['system']) && (! $pubcomment) && (! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'post_comments')) && (! $tgroup)) {
logger('diaspora_comment: Ignoring this author.');
return 202;
}
$result = item_store($datarray);
if($result && $result['success'])
@@ -1540,6 +1648,15 @@ function diaspora_conversation($importer,$xml,$msg) {
$body = diaspora2bb($msg_text);
$maxlen = get_max_import_size();
if($maxlen && mb_strlen($body) > $maxlen) {
$body = mb_substr($body,0,$maxlen,'UTF-8');
logger('message length exceeds max_import_size: truncated');
}
$author_signed_data = $msg_guid . ';' . $msg_parent_guid . ';' . $msg_text . ';' . unxmlify($mesg->created_at) . ';' . $msg_diaspora_handle . ';' . $msg_conversation_guid;
$author_signature = base64_decode($msg_author_signature);
@@ -1677,6 +1794,17 @@ function diaspora_message($importer,$xml,$msg) {
$subject = $conversation['subject'];
$body = diaspora2bb($msg_text);
$maxlen = get_max_import_size();
if($maxlen && mb_strlen($body) > $maxlen) {
$body = mb_substr($body,0,$maxlen,'UTF-8');
logger('message length exceeds max_import_size: truncated');
}
$message_id = $msg_diaspora_handle . ':' . $msg_guid;
$author_signed_data = $msg_guid . ';' . $msg_parent_guid . ';' . $msg_text . ';' . unxmlify($xml->created_at) . ';' . $msg_diaspora_handle . ';' . $msg_conversation_guid;

View File

@@ -1,14 +1,23 @@
<?php /** @file */
<?php
/**
* @file include/dir_fns.php
*/
require_once('include/permissions.php');
/**
* @brief
*
* @param int $dirmode
* @return array
*/
function find_upstream_directory($dirmode) {
global $DIRECTORY_FALLBACK_SERVERS;
$preferred = get_config('system','directory_server');
if(! $preferred) {
if (! $preferred) {
/**
/*
* No directory has yet been set. For most sites, pick one at random
* from our list of directory servers. However, if we're a directory
* server ourself, point at the local instance
@@ -18,41 +27,40 @@ function find_upstream_directory($dirmode) {
*/
$dirmode = intval(get_config('system','directory_mode'));
if($dirmode == DIRECTORY_MODE_NORMAL) {
if ($dirmode == DIRECTORY_MODE_NORMAL) {
$toss = mt_rand(0,count($DIRECTORY_FALLBACK_SERVERS));
$preferred = $DIRECTORY_FALLBACK_SERVERS[$toss];
set_config('system','directory_server',$preferred);
}
else{
} else{
set_config('system','directory_server',z_root());
}
}
return array('url' => $preferred);
}
/**
* Directories may come and go over time. We will need to check that our
* directory server is still valid occasionally, and reset to something that
* is if our directory has gone offline for any reason
*/
function check_upstream_directory() {
/**
* Directories may come and go over time. We will need to check that our
* directory server is still valid occasionally, and reset to something that
* is if our directory has gone offline for any reason
*/
$directory = get_config('system','directory_server');
$directory = get_config('system', 'directory_server');
// it's possible there is no directory server configured and the local hub is being used.
// If so, default to preserving the absence of a specific server setting.
$isadir = true;
$isadir = true;
if($directory) {
if ($directory) {
$h = parse_url($directory);
if($h) {
$x = zot_finger('sys@' . $h['host']);
if($x['success']) {
$j = json_decode($x['body'],true);
if(array_key_exists('site',$j) && array_key_exists('directory_mode',$j['site'])) {
if($j['site']['directory_mode'] === 'normal') {
if ($h) {
$x = zot_finger('[system]@' . $h['host']);
if ($x['success']) {
$j = json_decode($x['body'], true);
if (array_key_exists('site', $j) && array_key_exists('directory_mode', $j['site'])) {
if ($j['site']['directory_mode'] === 'normal') {
$isadir = false;
}
}
@@ -60,16 +68,61 @@ function check_upstream_directory() {
}
}
if(! $isadir)
set_config('system','directory_server','');
return;
if (! $isadir)
set_config('system', 'directory_server', '');
}
function get_globaldir_setting($observer) {
if($observer)
$globaldir = get_xconfig($observer,'directory','globaldir');
else
$globaldir = ((array_key_exists('globaldir',$_SESSION)) ? intval($_SESSION['globaldir']) : false);
if($globaldir === false)
$globaldir = get_config('directory','globaldir');
return $globaldir;
}
function get_safemode_setting($observer) {
if ($observer)
$safe_mode = get_xconfig($observer,'directory','safe_mode');
else
$safe_mode = ((array_key_exists('safemode',$_SESSION)) ? intval($_SESSION['safemode']) : false);
if($safe_mode === false)
$safe_mode = get_config('directory','safe_mode');
if($safe_mode === false)
$safe_mode = 1;
return $safe_mode;
}
/**
* @brief Called by the directory_sort widget.
*/
function dir_sort_links() {
$safe_mode = 1;
$observer = get_observer_hash();
$safe_mode = get_safemode_setting($observer);
$globaldir = get_globaldir_setting($observer);
// Build urls without order and pubforums so it's easy to tack on the changed value
// Probably there's an easier way to do this
$current_order = (($_REQUEST['order']) ? $_REQUEST['order'] : 'normal');
$directory_sort_order = get_config('system','directory_sort_order');
if(! $directory_sort_order)
$directory_sort_order = 'date';
$current_order = (($_REQUEST['order']) ? $_REQUEST['order'] : $directory_sort_order);
$url = 'directory?f=';
$tmp = array_merge($_GET,$_POST);
@@ -80,6 +133,8 @@ function dir_sort_links() {
$tmp = array_merge($_GET,$_POST);
unset($tmp['pubforums']);
unset($tmp['global']);
unset($tmp['safe']);
unset($tmp['q']);
unset($tmp['f']);
$forumsurl = $url . http_build_query($tmp);
@@ -90,49 +145,43 @@ function dir_sort_links() {
'$reverse' => t('Reverse Alphabetic'),
'$date' => t('Newest to Oldest'),
'$reversedate' => t('Oldest to Newest'),
'$pubforums' => t('Public Forums Only'),
'$pubforumsonly' => x($_REQUEST,'pubforums') ? $_REQUEST['pubforums'] : '',
'$sort' => t('Sort'),
'$selected_sort' => $current_order,
'$sorturl' => $sorturl,
'$forumsurl' => $forumsurl,
'$safemode' => array('safemode', t('Safe Mode'),$safe_mode,'','',' onchange=\'window.location.href="' . $forumsurl . '&safe="+(this.checked ? 1 : 0)\''),
));
return $o;
}
function dir_safe_mode() {
$observer = get_observer_hash();
if (! $observer)
return;
if ($observer)
$safe_mode = get_xconfig($observer,'directory','safe_mode');
if($safe_mode === '0')
$toggle = t('Enable Safe Search');
else
$toggle = t('Disable Safe Search');
$o = replace_macros(get_markup_template('safesearch.tpl'), array(
'$safemode' => t('Safe Mode'),
'$toggle' => $toggle,
'$pubforums' => array('pubforums', t('Public Forums Only'),(x($_REQUEST,'pubforums') ? $_REQUEST['pubforums'] : ''),'','',' onchange=\'window.location.href="' . $forumsurl . '&pubforums="+(this.checked ? 1 : 0)\''),
'$globaldir' => array('globaldir', t('This Website Only'), 1-intval($globaldir),'','',' onchange=\'window.location.href="' . $forumsurl . '&global="+(this.checked ? 0 : 1)\''),
));
return $o;
}
/**
* @brief Checks the directory mode of this hub.
*
* Checks the directory mode of this hub to see if it is some form of directory server. If it is,
* get the directory realm of this hub. Fetch a list of all other directory servers in this realm and request
* a directory sync packet. This will contain both directory updates and new ratings. Store these all in the DB.
* In the case of updates, we will query each of them asynchronously from a poller task. Ratings are stored
* directly if the rater's signature matches.
*
* @param int $dirmode;
*/
function sync_directories($dirmode) {
if($dirmode == DIRECTORY_MODE_STANDALONE || $dirmode == DIRECTORY_MODE_NORMAL)
if ($dirmode == DIRECTORY_MODE_STANDALONE || $dirmode == DIRECTORY_MODE_NORMAL)
return;
$realm = get_directory_realm();
if($realm == DIRECTORY_REALM) {
if ($realm == DIRECTORY_REALM) {
$r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and ( site_realm = '%s' or site_realm = '') ",
intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY),
dbesc(z_root()),
dbesc($realm)
);
}
else {
} else {
$r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and site_realm like '%s' ",
intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY),
dbesc(z_root()),
@@ -141,49 +190,56 @@ function sync_directories($dirmode) {
}
// If there are no directory servers, setup the fallback master
// FIXME - what to do if we're in a different realm?
/** @FIXME What to do if we're in a different realm? */
if((! $r) && (z_root() != DIRECTORY_FALLBACK_MASTER)) {
$r = array(
if ((! $r) && (z_root() != DIRECTORY_FALLBACK_MASTER)) {
$r = array();
$r[] = array(
'site_url' => DIRECTORY_FALLBACK_MASTER,
'site_flags' => DIRECTORY_MODE_PRIMARY,
'site_update' => NULL_DATE,
'site_directory' => DIRECTORY_FALLBACK_MASTER . '/dirsearch',
'site_realm' => DIRECTORY_REALM
'site_realm' => DIRECTORY_REALM,
'site_valid' => 1
);
$x = q("insert into site ( site_url, site_flags, site_update, site_directory, site_realm )
$x = q("insert into site ( site_url, site_flags, site_update, site_directory, site_realm, site_valid )
values ( '%s', %d', '%s', '%s', '%s' ) ",
dbesc($r[0]['site_url']),
intval($r[0]['site_flags']),
dbesc($r[0]['site_update']),
dbesc($r[0]['site_directory']),
dbesc($r[0]['site_realm'])
dbesc($r[0]['site_realm']),
intval($r[0]['site_valid'])
);
$r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s'",
intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY),
dbesc(z_root())
);
}
if(! $r)
}
if (! $r)
return;
foreach($r as $rr) {
if(! $rr['site_directory'])
foreach ($r as $rr) {
if (! $rr['site_directory'])
continue;
logger('sync directories: ' . $rr['site_directory']);
// for brand new directory servers, only load the last couple of days. Everything before that will be repeats.
// for brand new directory servers, only load the last couple of days.
// It will take about a month for a new directory to obtain the full current repertoire of channels.
/** @FIXME Go back and pick up earlier ratings if this is a new directory server. These do not get refreshed. */
$token = get_config('system','realm_token');
$syncdate = (($rr['site_sync'] === NULL_DATE) ? datetime_convert('UTC','UTC','now - 2 days') : $rr['site_sync']);
$x = z_fetch_url($rr['site_directory'] . '?f=&sync=' . urlencode($syncdate));
$x = z_fetch_url($rr['site_directory'] . '?f=&sync=' . urlencode($syncdate) . (($token) ? '&t=' . $token : ''));
if(! $x['success'])
if (! $x['success'])
continue;
$j = json_decode($x['body'],true);
if((! $j['transactions']) || (! is_array($j['transactions'])))
if (!($j['transactions']) || ($j['ratings']))
continue;
q("update site set site_sync = '%s' where site_url = '%s'",
@@ -193,17 +249,18 @@ function sync_directories($dirmode) {
logger('sync_directories: ' . $rr['site_url'] . ': ' . print_r($j,true), LOGGER_DATA);
if(count($j['transactions'])) {
foreach($j['transactions'] as $t) {
if (is_array($j['transactions']) && count($j['transactions'])) {
foreach ($j['transactions'] as $t) {
$r = q("select * from updates where ud_guid = '%s' limit 1",
dbesc($t['transaction_id'])
);
if($r)
continue;
$ud_flags = 0;
if(is_array($t['flags']) && in_array('deleted',$t['flags']))
if (is_array($t['flags']) && in_array('deleted',$t['flags']))
$ud_flags |= UPDATE_FLAGS_DELETED;
if(is_array($t['flags']) && in_array('forced',$t['flags']))
if (is_array($t['flags']) && in_array('forced',$t['flags']))
$ud_flags |= UPDATE_FLAGS_FORCED;
$z = q("insert into updates ( ud_hash, ud_guid, ud_date, ud_flags, ud_addr )
@@ -216,38 +273,41 @@ function sync_directories($dirmode) {
);
}
}
if(count($j['ratings'])) {
foreach($j['ratings'] as $rr) {
if (is_array($j['ratings']) && count($j['ratings'])) {
foreach ($j['ratings'] as $rr) {
$x = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1",
dbesc($rr['channel']),
dbesc($rr['target'])
);
if($x && $x[0]['xlink_updated'] >= $rr['edited'])
if ($x && $x[0]['xlink_updated'] >= $rr['edited'])
continue;
// Ratings are signed by the rater. We need to verify before we can accept it.
/** @TODO Queue or defer if the xchan is not yet present on our site */
$y = q("select xchan_pubkey from xchan where xchan_hash = '%s' limit 1",
dbesc($rr['channel'])
);
if(! $y) {
if (! $y) {
logger('key unavailable on this site for ' . $rr['channel']);
continue;
}
if(! rsa_verify($rr['target'] . '.' . $rr['rating'] . '.' . $rr['rating_text'], base64url_decode($rr['signature']),$y[0]['xchan_pubkey'])) {
logger('failed to verify rating');
if (! rsa_verify($rr['target'] . '.' . $rr['rating'] . '.' . $rr['rating_text'], base64url_decode($rr['signature']),$y[0]['xchan_pubkey'])) {
logger('failed to verify rating');
continue;
}
if($x) {
if ($x) {
$z = q("update xlink set xlink_rating = %d, xlink_rating_text = '%s', xlink_sig = '%s', xlink_updated = '%s' where xlink_id = %d",
intval($rr['rating']),
dbesc($rr['rating_text']),
dbesc($rr['signature']),
dbesc(datetime_convert()),
intval($x[0]['xlink_id'])
);
logger('rating updated');
}
else {
$z = q("insert into xlink ( xlink_xchan, xlink_link, xlink_rating, xlink_rating_text, xlink_sig, xlink_updated, xlink_static ) values( '%s', '%s', %d, '%s', '%s', 1 ) ",
);
logger('rating updated');
} else {
$z = q("insert into xlink ( xlink_xchan, xlink_link, xlink_rating, xlink_rating_text, xlink_sig, xlink_updated, xlink_static ) values( '%s', '%s', %d, '%s', '%s', '%s', 1 ) ",
dbesc($rr['channel']),
dbesc($rr['target']),
intval($rr['rating']),
@@ -263,37 +323,52 @@ function sync_directories($dirmode) {
}
/**
* @brief
*
* Given an update record, probe the channel, grab a zot-info packet and refresh/sync the data.
*
* Ignore updating records marked as deleted.
*
* If successful, sets ud_last in the DB to the current datetime for this
* reddress/webbie.
*
* @param array $ud Entry from update table
*/
function update_directory_entry($ud) {
logger('update_directory_entry: ' . print_r($ud,true), LOGGER_DATA);
if($ud['ud_addr'] && (! ($ud['ud_flags'] & UPDATE_FLAGS_DELETED))) {
if ($ud['ud_addr'] && (! ($ud['ud_flags'] & UPDATE_FLAGS_DELETED))) {
$success = false;
$x = zot_finger($ud['ud_addr'],'');
if($x['success']) {
$j = json_decode($x['body'],true);
if($j)
$x = zot_finger($ud['ud_addr'], '');
if ($x['success']) {
$j = json_decode($x['body'], true);
if ($j)
$success = true;
$y = import_xchan($j,0,$ud);
$y = import_xchan($j, 0, $ud);
}
if(! $success) {
$r = q("update updates set ud_last = '%s' where ud_addr = '%s'",
if (! $success) {
q("update updates set ud_last = '%s' where ud_addr = '%s'",
dbesc(datetime_convert()),
dbesc($ud['ud_addr'])
);
}
}
}
/**
* @function local_dir_update($uid,$force)
* push local channel updates to a local directory server
* @brief Push local channel updates to a local directory server.
*
* This is called from include/directory.php if a profile is to be pushed to the
* directory and the local hub in this case is any kind of directory server.
*
* @param int $uid
* @param boolean $force
*/
function local_dir_update($uid,$force) {
function local_dir_update($uid, $force) {
logger('local_dir_update: uid: ' . $uid, LOGGER_DEBUG);
@@ -304,12 +379,12 @@ function local_dir_update($uid,$force) {
$profile = array();
$profile['encoding'] = 'zot';
if($p) {
if ($p) {
$hash = $p[0]['channel_hash'];
$profile['description'] = $p[0]['pdesc'];
$profile['birthday'] = $p[0]['dob'];
if($age = age($p[0]['dob'],$p[0]['channel_timezone'],''))
if ($age = age($p[0]['dob'],$p[0]['channel_timezone'],''))
$profile['age'] = $age;
$profile['gender'] = $p[0]['gender'];
@@ -323,14 +398,15 @@ function local_dir_update($uid,$force) {
$profile['homepage'] = $p[0]['homepage'];
$profile['hometown'] = $p[0]['hometown'];
if($p[0]['keywords']) {
if ($p[0]['keywords']) {
$tags = array();
$k = explode(' ',$p[0]['keywords']);
if($k)
foreach($k as $kk)
if(trim($kk))
$k = explode(' ', $p[0]['keywords']);
if ($k)
foreach ($k as $kk)
if (trim($kk))
$tags[] = trim($kk);
if($tags)
if ($tags)
$profile['keywords'] = $tags;
}
@@ -351,10 +427,9 @@ function local_dir_update($uid,$force) {
$address = $p[0]['channel_address'] . '@' . get_app()->get_hostname();
if(perm_is_allowed($uid,'','view_profile')) {
import_directory_profile($hash,$profile,$address,0);
}
else {
if (perm_is_allowed($uid, '', 'view_profile')) {
import_directory_profile($hash, $profile, $address, 0);
} else {
// they may have made it private
$r = q("delete from xprof where xprof_hash = '%s'",
dbesc($hash)
@@ -366,7 +441,5 @@ function local_dir_update($uid,$force) {
}
$ud_hash = random_string() . '@' . get_app()->get_hostname();
update_modtime($hash,$ud_hash,$p[0]['channel_address'] . '@' . get_app()->get_hostname(),(($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED));
update_modtime($hash, $ud_hash, $p[0]['channel_address'] . '@' . get_app()->get_hostname(),(($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED));
}

View File

@@ -1,14 +1,23 @@
<?php /** @file */
<?php
/**
* @file include/directory.php
* @brief executes directory_run()
*/
require_once('boot.php');
require_once('include/zot.php');
require_once('include/cli_startup.php');
require_once('include/dir_fns.php');
/**
* @brief
*
* @param array $argv
* @param array $argc
*/
function directory_run($argv, $argc){
cli_startup();
cli_startup();
if($argc < 2)
return;
@@ -37,8 +46,9 @@ function directory_run($argv, $argc){
$channel = $x[0];
if($dirmode != DIRECTORY_MODE_NORMAL) {
if(($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) {
// this is an in-memory update and we don't need to send a network packet.
local_dir_update($argv[1],$force);
@@ -54,6 +64,8 @@ function directory_run($argv, $argc){
return;
}
// otherwise send the changes upstream
$directory = find_upstream_directory($dirmode);
$url = $directory['url'] . '/post';
@@ -66,8 +78,9 @@ function directory_run($argv, $argc){
if(! $z['success']) {
// FIXME - we aren't updating channel_dirdate if we have to queue
// the directory packet. That means we'll try again on the next poll run.
/** @FIXME we aren't updating channel_dirdate if we have to queue
* the directory packet. That means we'll try again on the next poll run.
*/
$hash = random_string();
q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_created, outq_updated, outq_notify, outq_msg )
@@ -83,8 +96,7 @@ function directory_run($argv, $argc){
dbesc($packet),
dbesc('')
);
}
else {
} else {
q("update channel set channel_dirdate = '%s' where channel_id = %d",
dbesc(datetime_convert()),
intval($channel['channel_id'])
@@ -97,7 +109,7 @@ function directory_run($argv, $argc){
}
if (array_search(__file__,get_included_files())===0){
directory_run($argv,$argc);
killme();
if (array_search(__file__, get_included_files()) === 0) {
directory_run($argv, $argc);
killme();
}

View File

@@ -1,33 +1,50 @@
<?php /** @file */
<?php
/**
* @file include/enotify.php
*
* @brief File with functions and a class for email notifications.
*/
/**
* @brief
*
* @param array $params an assoziative array with:
* * \e string \b from_xchan sender xchan hash
* * \e string \b to_xchan recipient xchan hash
* * \e array \b item an assoziative array
* * \e int \b type one of the NOTIFY_* constants from boot.php
* * \e string \b link
* * \e string \b parent_mid
* * \e string \b otype
* * \e string \b verb
* * \e string \b activity
*/
function notification($params) {
logger('notification: entry', LOGGER_DEBUG);
// throw a small amount of entropy into the system to breakup duplicates arriving at the same precise instant.
usleep(mt_rand(0,10000));
usleep(mt_rand(0, 10000));
$a = get_app();
if($params['from_xchan']) {
if ($params['from_xchan']) {
$x = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($params['from_xchan'])
);
}
if($params['to_xchan']) {
if ($params['to_xchan']) {
$y = q("select channel.*, account.* from channel left join account on channel_account_id = account_id
where channel_hash = '%s' and not (channel_pageflags & %d)>0 limit 1",
dbesc($params['to_xchan']),
intval(PAGE_REMOVED)
);
}
if($x & $y) {
if ($x & $y) {
$sender = $x[0];
$recip = $y[0];
}
else {
} else {
logger('notification: no sender or recipient.');
logger('sender: ' . $params['from_xchan']);
logger('recip: ' . $params['to_xchan']);
@@ -55,10 +72,10 @@ function notification($params) {
$additional_mail_header = "";
if(array_key_exists('item',$params)) {
if (array_key_exists('item', $params)) {
require_once('include/conversation.php');
// if it's a normal item...
if(array_key_exists('verb',$params['item'])) {
if (array_key_exists('verb', $params['item'])) {
// localize_item() alters the original item so make a copy first
$i = $params['item'];
logger('calling localize');
@@ -71,8 +88,7 @@ function notification($params) {
$title = $params['item']['title'];
$body = $params['item']['body'];
}
}
else {
} else {
$title = $body = '';
}
@@ -80,7 +96,7 @@ function notification($params) {
// e.g. "your post", "David's photo", etc.
$possess_desc = t('%s <!item_type!>');
if($params['type'] == NOTIFY_MAIL) {
if ($params['type'] == NOTIFY_MAIL) {
logger('notification: mail');
$subject = sprintf( t('[Red:Notify] New mail received at %s'),$sitename);
@@ -92,28 +108,27 @@ function notification($params) {
$itemlink = $siteurl . '/mail/' . $params['item']['id'];
}
if($params['type'] == NOTIFY_COMMENT) {
if ($params['type'] == NOTIFY_COMMENT) {
// logger("notification: params = " . print_r($params, true), LOGGER_DEBUG);
$itemlink = $params['link'];
// ignore like/unlike activity on posts - they probably require a sepearate notification preference
if(array_key_exists('item',$params) && (! visible_activity($params['item'])))
if (array_key_exists('item',$params) && (! visible_activity($params['item'])))
return;
$parent_mid = $params['parent_mid'];
// Check to see if there was already a notify for this post.
// If so don't create a second notification
$p = null;
$p = q("select id from notify where link = '%s' and uid = %d limit 1",
dbesc($params['link']),
intval($recip['channel_id'])
);
if($p) {
if ($p) {
logger('notification: comment already notified');
pop_lang();
return;
@@ -182,26 +197,26 @@ function notification($params) {
$subject = sprintf( t('[Red:Notify] %s posted to your profile wall') , $sender['xchan_name']);
$preamble = sprintf( t('%1$s, %2$s posted to your profile wall at %3$s') , $recip['channel_name'], $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('%1$s, %2$s posted to [zrl=%3$s]your wall[/zrl]') ,
$recip['channel_name'],
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$params['link']);
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf( $sitelink, $siteurl );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
$itemlink = $params['link'];
}
if($params['type'] == NOTIFY_TAGSELF) {
if ($params['type'] == NOTIFY_TAGSELF) {
$p = null;
$p = q("select id from notify where link = '%s' and uid = %d limit 1",
dbesc($params['link']),
intval($recip['channel_id'])
);
if($p) {
if ($p) {
logger('enotify: tag: already notified about this post');
pop_lang();
return;
@@ -220,8 +235,7 @@ function notification($params) {
$itemlink = $params['link'];
}
if($params['type'] == NOTIFY_POKE) {
if ($params['type'] == NOTIFY_POKE) {
$subject = sprintf( t('[Red:Notify] %1$s poked you') , $sender['xchan_name']);
$preamble = sprintf( t('%1$s, %2$s poked you at %3$s') , $recip['channel_name'], $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('%1$s, %2$s [zrl=%2$s]poked you[/zrl].') ,
@@ -239,7 +253,7 @@ function notification($params) {
$itemlink = $params['link'];
}
if($params['type'] == NOTIFY_TAGSHARE) {
if ($params['type'] == NOTIFY_TAGSHARE) {
$subject = sprintf( t('[Red:Notify] %s tagged your post') , $sender['xchan_name']);
$preamble = sprintf( t('%1$s, %2$s tagged your post at %3$s') , $recip['channel_name'],$sender['xchan_name'], $sitename);
$epreamble = sprintf( t('%1$s, %2$s tagged [zrl=%3$s]your post[/zrl]') ,
@@ -253,7 +267,7 @@ function notification($params) {
$itemlink = $params['link'];
}
if($params['type'] == NOTIFY_INTRO) {
if ($params['type'] == NOTIFY_INTRO) {
$subject = sprintf( t('[Red:Notify] Introduction received'));
$preamble = sprintf( t('%1$s, you\'ve received an new connection request from \'%2$s\' at %3$s'), $recip['channel_name'], $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('%1$s, you\'ve received [zrl=%2$s]a new connection request[/zrl] from %3$s.'),
@@ -268,7 +282,7 @@ function notification($params) {
$itemlink = $params['link'];
}
if($params['type'] == NOTIFY_SUGGEST) {
if ($params['type'] == NOTIFY_SUGGEST) {
$subject = sprintf( t('[Red:Notify] Friend suggestion received'));
$preamble = sprintf( t('%1$s, you\'ve received a friend suggestion from \'%2$s\' at %3$s'), $recip['channel_name'], $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('%1$s, you\'ve received [zrl=%2$s]a friend suggestion[/zrl] for %3$s from %4$s.'),
@@ -276,7 +290,7 @@ function notification($params) {
$itemlink,
'[zrl=' . $params['item']['url'] . ']' . $params['item']['name'] . '[/zrl]',
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]');
$body = t('Name:') . ' ' . $params['item']['name'] . "\n";
$body .= t('Photo:') . ' ' . $params['item']['photo'] . "\n";
$body .= sprintf( t('You may visit their profile at %s'),$params['item']['url']);
@@ -287,27 +301,27 @@ function notification($params) {
$itemlink = $params['link'];
}
if($params['type'] == NOTIFY_CONFIRM) {
if ($params['type'] == NOTIFY_CONFIRM) {
// ?
}
if($params['type'] == NOTIFY_SYSTEM) {
if ($params['type'] == NOTIFY_SYSTEM) {
// ?
}
$h = array(
'params' => $params,
'params' => $params,
'subject' => $subject,
'preamble' => $preamble,
'epreamble' => $epreamble,
'body' => $body,
'preamble' => $preamble,
'epreamble' => $epreamble,
'body' => $body,
'sitelink' => $sitelink,
'tsitelink' => $tsitelink,
'hsitelink' => $hsitelink,
'itemlink' => $itemlink
);
call_hooks('enotify',$h);
call_hooks('enotify', $h);
$subject = $h['subject'];
$preamble = $h['preamble'];
@@ -319,16 +333,16 @@ function notification($params) {
$itemlink = $h['itemlink'];
require_once('include/html2bbcode.php');
require_once('include/html2bbcode.php');
do {
$dups = false;
$hash = random_string();
$r = q("SELECT `id` FROM `notify` WHERE `hash` = '%s' LIMIT 1",
$r = q("SELECT `id` FROM `notify` WHERE `hash` = '%s' LIMIT 1",
dbesc($hash));
if(count($r))
if (count($r))
$dups = true;
} while($dups == true);
} while ($dups === true);
$datarray = array();
@@ -348,10 +362,10 @@ function notification($params) {
$datarray['abort'] = false;
$datarray['item'] = $params['item'];
call_hooks('enotify_store', $datarray);
if($datarray['abort']) {
if ($datarray['abort']) {
pop_lang();
return;
}
@@ -365,8 +379,8 @@ function notification($params) {
// So easiest solution to hide them from Notices is to mark them as seen right away.
// Another option would be to not add them to the DB, and change how emails are handled (probably would be better that way)
$always_show_in_notices = get_pconfig($recip['channel_id'],'system','always_show_in_notices');
if(!$always_show_in_notices) {
if(($params['type'] == NOTIFY_WALL) || ($params['type'] == NOTIFY_MAIL) || ($params['type'] == NOTIFY_INTRO)) {
if (!$always_show_in_notices) {
if (($params['type'] == NOTIFY_WALL) || ($params['type'] == NOTIFY_MAIL) || ($params['type'] == NOTIFY_INTRO)) {
$seen = 1;
}
}
@@ -392,9 +406,9 @@ function notification($params) {
dbesc($hash),
intval($recip['channel_id'])
);
if($r)
if ($r) {
$notify_id = $r[0]['id'];
else {
} else {
logger('notification not found.');
pop_lang();
return;
@@ -405,7 +419,7 @@ function notification($params) {
// wretched hack, but we don't want to duplicate all the preamble variations and we also don't want to screw up a translation
if(($a->language === 'en' || (! $a->language)) && strpos($msg,', '))
if (($a->language === 'en' || (! $a->language)) && strpos($msg,', '))
$msg = substr($msg,strpos($msg,', ')+1);
$r = q("update notify set msg = '%s' where id = %d and uid = %d",
@@ -413,12 +427,11 @@ function notification($params) {
intval($notify_id),
intval($datarray['uid'])
);
// send email notification if notification preferences permit
require_once('bbcode.php');
if((intval($recip['channel_notifyflags']) & intval($params['type'])) || $params['type'] == NOTIFY_SYSTEM) {
if ((intval($recip['channel_notifyflags']) & intval($params['type'])) || $params['type'] == NOTIFY_SYSTEM) {
logger('notification: sending notification email');
@@ -429,8 +442,6 @@ function notification($params) {
return;
}
$textversion = strip_tags(html_entity_decode(bbcode(stripslashes(str_replace(array("\\r", "\\n"), array( "", "\n"), $body))),ENT_QUOTES,'UTF-8'));
$htmlversion = bbcode(stripslashes(str_replace(array("\\r","\\n"), array("","<br />\n"),$body)));
@@ -450,7 +461,6 @@ function notification($params) {
unset($_SESSION['zid_override']);
unset($_SESSION['zrl_override']);
$datarray = array();
$datarray['banner'] = $banner;
$datarray['product'] = $product;
@@ -485,13 +495,13 @@ function notification($params) {
$private_activity = false;
if(! $datarray['email_secure']) {
switch($params['type']) {
if (! $datarray['email_secure']) {
switch ($params['type']) {
case NOTIFY_WALL:
case NOTIFY_TAGSELF:
case NOTIFY_POKE:
case NOTIFY_COMMENT:
if(! $private)
if (! $private)
break;
$private_activity = true;
case NOTIFY_MAIL:
@@ -503,11 +513,12 @@ function notification($params) {
}
}
if($private_activity
&& intval(get_pconfig($datarray['uid'],'system','ignore_private_notifications'))) {
if ($private_activity
&& intval(get_pconfig($datarray['uid'], 'system', 'ignore_private_notifications'))) {
pop_lang();
return;
}
}
// load the template for private message notifications
$tpl = get_markup_template('email_notify_html.tpl');
@@ -525,13 +536,13 @@ function notification($params) {
'$hitemlink' => $datarray['hitemlink'],
'$thanks' => $datarray['thanks'],
'$site_admin' => $datarray['site_admin'],
'$title' => $datarray['title'],
'$htmlversion' => $datarray['htmlversion'],
'$title' => $datarray['title'],
'$htmlversion' => $datarray['htmlversion'],
));
// load the template for private message notifications
$tpl = get_markup_template('email_notify_text.tpl');
$email_text_body = replace_macros($tpl,array(
$email_text_body = replace_macros($tpl, array(
'$banner' => $datarray['banner'],
'$product' => $datarray['product'],
'$preamble' => $datarray['preamble'],
@@ -545,8 +556,8 @@ function notification($params) {
'$titemlink' => $datarray['titemlink'],
'$thanks' => $datarray['thanks'],
'$site_admin' => $datarray['site_admin'],
'$title' => $datarray['title'],
'$textversion' => $datarray['textversion'],
'$title' => $datarray['title'],
'$textversion' => $datarray['textversion'],
));
// logger('text: ' . $email_text_body);
@@ -570,41 +581,48 @@ function notification($params) {
}
/**
* @brief A class for sending email notifications.
*
* @fixme Class names start mostly with capital letter to distinguish them easier.
*/
class enotify {
/**
* Send a multipart/alternative message with Text and HTML versions
* @brief Send a multipart/alternative message with Text and HTML versions.
*
* @param fromName name of the sender
* @param fromEmail email fo the sender
* @param replyTo replyTo address to direct responses
* @param toEmail destination email address
* @param messageSubject subject of the message
* @param htmlVersion html version of the message
* @param textVersion text only version of the message
* @param additionalMailHeader additions to the smtp mail header
* @param array $params an assoziative array with:
* * \e string \b fromName name of the sender
* * \e string \b fromEmail email of the sender
* * \e string \b replyTo replyTo address to direct responses
* * \e string \b toEmail destination email address
* * \e string \b messageSubject subject of the message
* * \e string \b htmlVersion html version of the message
* * \e string \b textVersion text only version of the message
* * \e string \b additionalMailHeader additions to the smtp mail header
*/
static public function send($params) {
$fromName = email_header_encode(html_entity_decode($params['fromName'],ENT_QUOTES,'UTF-8'),'UTF-8');
$messageSubject = email_header_encode(html_entity_decode($params['messageSubject'],ENT_QUOTES,'UTF-8'),'UTF-8');
// generate a mime boundary
$mimeBoundary =rand(0,9)."-"
.rand(10000000000,9999999999)."-"
.rand(10000000000,9999999999)."=:"
.rand(10000,99999);
$mimeBoundary = rand(0, 9) . "-"
.rand(10000000000, 9999999999) . "-"
.rand(10000000000, 9999999999) . "=:"
.rand(10000, 99999);
// generate a multipart/alternative message header
$messageHeader =
$params['additionalMailHeader'] .
"From: $fromName <{$params['fromEmail']}>\n" .
"From: $fromName <{$params['fromEmail']}>\n" .
"Reply-To: $fromName <{$params['replyTo']}>\n" .
"MIME-Version: 1.0\n" .
"Content-Type: multipart/alternative; boundary=\"{$mimeBoundary}\"";
// assemble the final multipart message body with the text and html types included
$textBody = chunk_split(base64_encode($params['textVersion']));
$htmlBody = chunk_split(base64_encode($params['htmlVersion']));
$textBody = chunk_split(base64_encode($params['textVersion']));
$htmlBody = chunk_split(base64_encode($params['htmlVersion']));
$multipartMessageBody =
"--" . $mimeBoundary . "\n" . // plain text section
"Content-Type: text/plain; charset=UTF-8\n" .
@@ -618,12 +636,11 @@ class enotify {
// send the message
$res = mail(
$params['toEmail'], // send to address
$params['toEmail'], // send to address
$messageSubject, // subject
$multipartMessageBody, // message body
$multipartMessageBody, // message body
$messageHeader // message headers
);
logger("notification: enotify::send returns " . $res, LOGGER_DEBUG);
}
}

View File

@@ -1,6 +1,14 @@
<?php /** @file */
<?php
/**
* @file include/event.php
*/
/**
* @brief Returns an event as HTML
*
* @param array $ev
* @return string
*/
function format_event_html($ev) {
require_once('include/bbcode.php');
@@ -12,13 +20,12 @@ function format_event_html($ev) {
$o = '<div class="vevent">' . "\r\n";
$o .= '<p class="summary event-summary">' . bbcode($ev['summary']) . '</p>' . "\r\n";
$o .= '<p class="description event-description">' . bbcode($ev['description']) . '</p>' . "\r\n";
$o .= '<p class="event-start">' . t('Starts:') . ' <abbr class="dtstart" title="'
. datetime_convert('UTC','UTC',$ev['start'], (($ev['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' ))
. datetime_convert('UTC', 'UTC', $ev['start'], (($ev['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' ))
. '" >'
. (($ev['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(),
$ev['start'] , $bd_format ))
@@ -38,15 +45,15 @@ function format_event_html($ev) {
if(strlen($ev['location']))
$o .= '<p class="event-location"> ' . t('Location:') . ' <span class="location">'
. bbcode($ev['location'])
. bbcode($ev['location'])
. '</span></p>' . "\r\n";
$o .= '</div>' . "\r\n";
return $o;
}
function ical_wrapper($ev) {
if(! ((is_array($ev)) && count($ev)))
@@ -56,7 +63,7 @@ function ical_wrapper($ev) {
$o .= "\nVERSION:2.0";
$o .= "\nMETHOD:PUBLISH";
$o .= "\nPRODID:-//" . get_config('system','sitename') . "//" . RED_PLATFORM . "//" . strtoupper(get_app()->language). "\n";
if(array_key_exists('start',$ev))
if(array_key_exists('start', $ev))
$o .= format_event_ical($ev);
else {
foreach($ev as $e) {
@@ -84,13 +91,15 @@ function format_event_ical($ev) {
if($ev['description'])
$o .= "\nDESCRIPTION:" . format_ical_text($ev['description']);
$o .= "\nEND:VEVENT\n";
return $o;
}
function format_ical_text($s) {
function format_ical_text($s) {
require_once('include/bbcode.php');
require_once('include/html2plain.php');
return(wordwrap(html2plain(bbcode($s)),72,"\n ",true));
}
@@ -117,16 +126,16 @@ function format_event_bbcode($ev) {
if($ev['adjust'])
$o .= '[event-adjust]' . $ev['adjust'] . '[/event-adjust]';
return $o;
}
function bbtovcal($s) {
$o = '';
$ev = bbtoevent($s);
if($ev['description'])
$o = format_event_html($ev);
return $o;
}
@@ -154,27 +163,41 @@ function bbtoevent($s) {
if(preg_match("/\[event\-adjust\](.*?)\[\/event\-adjust\]/is",$s,$match))
$ev['adjust'] = $match[1];
$ev['nofinish'] = (((x($ev, 'start') && $ev['start']) && (!x($ev, 'finish') || !$ev['finish'])) ? 1 : 0);
return $ev;
return $ev;
}
/**
* @brief Sorts the given array of events by date.
*
* @see ev_compare()
* @param array $arr
* @return sorted array
*/
function sort_by_date($arr) {
if(is_array($arr))
usort($arr,'ev_compare');
if (is_array($arr))
usort($arr, 'ev_compare');
return $arr;
}
function ev_compare($a,$b) {
/**
* @brief Compare function for events.
*
* @see sort_by_date()
* @param array $a
* @param array $b
* @return number return values like strcmp()
*/
function ev_compare($a, $b) {
$date_a = (($a['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$a['start']) : $a['start']);
$date_b = (($b['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$b['start']) : $b['start']);
if($date_a === $date_b)
return strcasecmp($a['description'],$b['description']);
return strcmp($date_a,$date_b);
if ($date_a === $date_b)
return strcasecmp($a['description'], $b['description']);
return strcmp($date_a, $date_b);
}
@@ -182,11 +205,9 @@ function event_store_event($arr) {
$arr['created'] = (($arr['created']) ? $arr['created'] : datetime_convert());
$arr['edited'] = (($arr['edited']) ? $arr['edited'] : datetime_convert());
$arr['type'] = (($arr['type']) ? $arr['type'] : 'event' );
$arr['type'] = (($arr['type']) ? $arr['type'] : 'event' );
$arr['event_xchan'] = (($arr['event_xchan']) ? $arr['event_xchan'] : '');
// Existing event being modified
if($arr['id'] || $arr['event_hash']) {
@@ -206,7 +227,6 @@ function event_store_event($arr) {
);
}
if(! $r)
return false;
@@ -216,7 +236,7 @@ function event_store_event($arr) {
}
$hash = $r[0]['event_hash'];
// The event changed. Update it.
$r = q("UPDATE `event` SET
@@ -251,14 +271,12 @@ function event_store_event($arr) {
intval($r[0]['id']),
intval($arr['uid'])
);
}
else {
} else {
// New event. Store it.
// New event. Store it.
$hash = random_string();
$r = q("INSERT INTO event ( uid,aid,event_xchan,event_hash,created,edited,start,finish,summary,description,location,type,
adjust,nofinish,allow_cid,allow_gid,deny_cid,deny_gid)
VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', '%s', '%s' ) ",
@@ -280,7 +298,6 @@ function event_store_event($arr) {
dbesc($arr['allow_gid']),
dbesc($arr['deny_cid']),
dbesc($arr['deny_gid'])
);
}
@@ -292,7 +309,6 @@ function event_store_event($arr) {
return $r[0];
return false;
}
function event_addtocal($item_id, $uid) {
@@ -339,22 +355,21 @@ function event_addtocal($item_id, $uid) {
intval($item['id']),
intval($channel['channel_id'])
);
return true;
}
}
return false;
}
function event_store_item($arr,$event) {
function event_store_item($arr, $event) {
require_once('include/datetime.php');
require_once('include/items.php');
require_once('include/bbcode.php');
$a = get_app();
$item = null;
if($arr['mid'] && $arr['uid']) {
@@ -370,28 +385,28 @@ function event_store_item($arr,$event) {
$item_arr = array();
$prefix = '';
$birthday = false;
// $birthday = false;
if($event['type'] === 'birthday') {
$prefix = t('This event has been added to your calendar.');
$birthday = true;
// $birthday = true;
// The event is created on your own site by the system, but appears to belong
// to the birthday person. It also isn't propagated - so we need to prevent
// folks from trying to comment on it. If you're looking at this and trying to
// fix it, you'll need to completely change the way birthday events are created
// and send them out from the source. This has its own issues.
// and send them out from the source. This has its own issues.
$item_arr['comment_policy'] = 'none';
}
$r = q("SELECT * FROM item left join xchan on author_xchan = xchan_hash WHERE resource_id = '%s' AND resource_type = 'event' and uid = %d LIMIT 1",
dbesc($event['event_hash']),
dbesc($event['event_hash']),
intval($arr['uid'])
);
if($r) {
$obj = json_encode(array(
$object = json_encode(array(
'type' => ACTIVITY_OBJ_EVENT,
'id' => z_root() . '/event/' . $r[0]['resource_id'],
'title' => $arr['summary'],
@@ -409,7 +424,7 @@ function event_store_item($arr,$event) {
$private = (($arr['allow_cid'] || $arr['allow_gid'] || $arr['deny_cid'] || $arr['deny_gid']) ? 1 : 0);
q("UPDATE item SET title = '%s', body = '%s', object = '%s', allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', edited = '%s', item_flags = %d, item_private = %d WHERE id = %d AND uid = %d",
q("UPDATE item SET title = '%s', body = '%s', object = '%s', allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', edited = '%s', item_flags = %d, item_private = %d, obj_type = '%s' WHERE id = %d AND uid = %d",
dbesc($arr['summary']),
dbesc($prefix . format_event_bbcode($arr)),
dbesc($object),
@@ -420,12 +435,12 @@ function event_store_item($arr,$event) {
dbesc($arr['edited']),
intval($r[0]['item_flags']),
intval($private),
dbesc(ACTIVITY_OBJ_EVENT),
intval($r[0]['id']),
intval($arr['uid'])
);
$s = q("delete from term where oid = %d and otype = %d",
q("delete from term where oid = %d and otype = %d",
intval($r[0]['id']),
intval(TERM_OBJ_POST)
);
@@ -442,19 +457,18 @@ function event_store_item($arr,$event) {
dbesc($t['url'])
);
}
}
}
$item_id = $r[0]['id'];
call_hooks('event_updated', $event['id']);
return $item_id;
}
else {
} else {
$z = q("select * from channel where channel_id = %d limit 1",
intval($arr['uid'])
);
$private = (($arr['allow_cid'] || $arr['allow_gid'] || $arr['deny_cid'] || $arr['deny_gid']) ? 1 : 0);
$item_wall = 0;
@@ -471,7 +485,6 @@ function event_store_item($arr,$event) {
$item_wall = 1;
$item_origin = 1;
}
}
if(! $arr['mid'])
@@ -482,8 +495,6 @@ function event_store_item($arr,$event) {
$item_arr['author_xchan'] = $arr['event_xchan'];
$item_arr['mid'] = $arr['mid'];
$item_arr['parent_mid'] = $arr['mid'];
$item_arr['owner_xchan'] = (($wall) ? $z[0]['channel_hash'] : $arr['event_xchan']);
$item_arr['author_xchan'] = $arr['event_xchan'];
$item_arr['title'] = $arr['summary'];
@@ -497,9 +508,8 @@ function event_store_item($arr,$event) {
$item_arr['item_origin'] = $item_origin;
$item_arr['item_thread_top'] = $item_thread_top;;
if(array_key_exists('term',$arr))
$item_arr['term'] = $arr['term'];
if(array_key_exists('term', $arr))
$item_arr['term'] = $arr['term'];
$item_arr['resource_type'] = 'event';
$item_arr['resource_id'] = $event['event_hash'];
@@ -514,15 +524,13 @@ function event_store_item($arr,$event) {
else
$item_arr['plink'] = z_root() . '/display/' . $item_arr['mid'];
$x = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($arr['event_xchan'])
);
if($x) {
$item_arr['object'] = json_encode(array(
'type' => ACTIVITY_OBJ_EVENT,
'id' => z_root() . '/event/' . $hash,
'id' => z_root() . '/event/' . $event['event_hash'],
'title' => $arr['summary'],
'content' => format_event_bbcode($arr),
'author' => array(
@@ -541,7 +549,7 @@ function event_store_item($arr,$event) {
$item_id = $res['item_id'];
call_hooks("event_created", $event['id']);
call_hooks('event_created', $event['id']);
return $item_id;
}

View File

@@ -1,4 +1,7 @@
<?php /** @file */
<?php
/**
* @file include/expire.php
*/
require_once('boot.php');
require_once('include/cli_startup.php');
@@ -7,58 +10,91 @@ function expire_run($argv, $argc){
cli_startup();
// perform final cleanup on previously delete items
$r = q("select id from item where item_deleted = 1 and not (item_restrict & %d)>0 and changed < %s - INTERVAL %s",
intval(ITEM_PENDING_REMOVE),
db_utcnow(), db_quoteinterval('10 DAY')
);
if($r) {
foreach($r as $rr) {
drop_item($rr['id'],false,DROPITEM_PHASE2);
if ($r) {
foreach ($r as $rr) {
drop_item($rr['id'], false, DROPITEM_PHASE2);
}
}
// physically remove anything that has been deleted for more than two months
/** @FIXME - this is a wretchedly inefficient query */
$r = q("delete from item where ( item_restrict & %d )>0 and changed < %s - INTERVAL %s",
$r = q("delete from item where ( item_restrict & %d ) > 0 and changed < %s - INTERVAL %s",
intval(ITEM_PENDING_REMOVE),
db_utcnow(), db_quoteinterval('36 DAY')
);
// make this optional as it could have a performance impact on large sites
/** @FIXME make this optional as it could have a performance impact on large sites */
if(intval(get_config('system','optimize_items')))
if (intval(get_config('system', 'optimize_items')))
q("optimize table item");
logger('expire: start', LOGGER_DEBUG);
$r = q("SELECT channel_id, channel_address, channel_expire_days from channel where channel_expire_days != 0");
if($r && count($r)) {
foreach($r as $rr) {
logger('Expire: ' . $rr['channel_address'] . ' interval: ' . $rr['channel_expire_days'], LOGGER_DEBUG);
item_expire($rr['channel_id'],$rr['channel_expire_days']);
$site_expire = get_config('system', 'default_expire_days');
logger('site_expire: ' . $site_expire);
$r = q("SELECT channel_id, channel_address, channel_pageflags, channel_expire_days from channel where true");
if ($r) {
foreach ($r as $rr) {
// expire the sys channel separately
if ($rr['channel_pageflags'] & PAGE_SYSTEM)
continue;
// service class default (if non-zero) over-rides the site default
$service_class_expire = service_class_fetch($rr['channel_id'], 'expire_days');
if (intval($service_class_expire))
$channel_expire = $service_class_expire;
else
$channel_expire = $site_expire;
if (intval($channel_expire) && (intval($channel_expire) < intval($rr['channel_expire_days'])) ||
intval($rr['channel_expire_days'] == 0)) {
$expire_days = $channel_expire;
} else {
$expire_days = $rr['channel_expire_days'];
}
// if the site or service class expiration is non-zero and less than person expiration, use that
logger('Expire: ' . $rr['channel_address'] . ' interval: ' . $expire_days, LOGGER_DEBUG);
item_expire($rr['channel_id'], $expire_days);
}
}
$x = get_sys_channel();
if($x) {
if ($x) {
// this should probably just fetch the channel_expire_days from the sys channel,
// but there's no convenient way to set it.
$expire_days = get_config('externals','expire_days');
if($expire_days === false)
$expire_days = get_config('system', 'sys_expire_days');
if ($expire_days === false)
$expire_days = 30;
if($expire_days)
item_expire($x['channel_id'],$expire_days);
if (intval($site_expire) && (intval($site_expire) < intval($expire_days))) {
$expire_days = $site_expire;
}
logger('Expire: sys interval: ' . $expire_days, LOGGER_DEBUG);
if ($expire_days)
item_expire($x['channel_id'], $expire_days);
logger('Expire: sys: done', LOGGER_DEBUG);
}
return;
}
if (array_search(__file__,get_included_files())===0){
expire_run($argv,$argc);
killme();
if (array_search(__file__, get_included_files()) === 0){
expire_run($argv, $argc);
killme();
}

View File

@@ -44,10 +44,8 @@ function get_features() {
array('webpages', t('Web Pages'), t('Provide managed web pages on your channel'),false),
array('private_notes', t('Private Notes'), t('Enables a tool to store notes and reminders'),false),
array('nav_channel_select', t('Navigation Channel Select'), t('Change channels directly from within the navigation dropdown menu'),false),
array('photo_location', t('Photo Location'), t('If location data is available on uploaded photos, link this to a map.'),false),
//FIXME - needs a description, but how the hell do we explain this to normals?
array('sendzid', t('Extended Identity Sharing'), t('Share your identity with all websites on the internet. When disabled, identity is only shared with sites in the matrix.'),false),
array('expert', t('Expert Mode'), t('Enable Expert Mode to provide advanced configuration options'),false),
array('premium_channel', t('Premium Channel'), t('Allows you to set restrictions and terms on those that connect with your channel'),false),
),
@@ -60,7 +58,8 @@ function get_features() {
array('large_photos', t('Large Photos'), t('Include large (640px) photo thumbnails in posts. If not enabled, use small (320px) photo thumbnails'),false),
array('channel_sources', t('Channel Sources'), t('Automatically import channel content from other channels or feeds'),false),
array('content_encrypt', t('Even More Encryption'), t('Allow optional encryption of content end-to-end with a shared secret key'),false),
array('adult_photo_flagging', t('Flag Adult Photos'), t('Provide photo edit option to hide adult photos from default album view'),false),
array('consensus_tools', t('Enable voting tools'), t('Provide a class of post which others can vote on'),false),
),
// Network Tools

View File

@@ -227,10 +227,16 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
);
}
else {
$r = q("insert into abook ( abook_account, abook_channel, abook_xchan, abook_flags, abook_their_perms, abook_my_perms, abook_created, abook_updated )
values( %d, %d, '%s', %d, %d, %d, '%s', '%s' ) ",
$closeness = get_pconfig($uid,'system','new_abook_closeness');
if($closeness === false)
$closeness = 80;
$r = q("insert into abook ( abook_account, abook_channel, abook_closeness, abook_xchan, abook_flags, abook_their_perms, abook_my_perms, abook_created, abook_updated )
values( %d, %d, %d, '%s', %d, %d, %d, '%s', '%s' ) ",
intval($aid),
intval($uid),
intval($closeness),
dbesc($xchan_hash),
intval(($is_http) ? ABOOK_FLAG_FEED : 0),
intval(($is_http) ? $their_perms|PERMS_R_STREAM|PERMS_A_REPUBLISH : $their_perms),

View File

@@ -253,7 +253,7 @@ function group_side($every="connections",$each="group",$edit = false, $group_id
'text' => t('All Channels'),
'id' => 0,
'selected' => (($group_id == 0) ? 'group-selected' : ''),
'href' => $every,
'href' => $every . (($every === 'network') ? '?f=&gid=0' : ''),
);
@@ -296,7 +296,7 @@ function group_side($every="connections",$each="group",$edit = false, $group_id
$o = replace_macros($tpl, array(
'$title' => t('Collections'),
'$edittext' => t('Edit collection'),
'$createtext' => t('Create a new collection'),
'$createtext' => t('Add new collection'),
'$ungrouped' => (($every === 'contacts') ? t('Channels not in any collection') : ''),
'$groups' => $groups,
'$add' => t('add'),

View File

@@ -169,10 +169,22 @@ function hubloc_change_primary($hubloc) {
return true;
}
// We use the post url to distinguish between http and https hublocs.
// The https might be alive, and the http dead.
function hubloc_mark_as_down($posturl) {
$r = q("update hubloc set hubloc_status = ( hubloc_status | %d ) where hubloc_callback = '%s'",
intval(HUBLOC_OFFLINE),
dbesc($posturl)
);
}
function xchan_store($arr) {
logger('xchan_store: ' . print_r($arr,true));
if(! $arr['hash'])
$arr['hash'] = $arr['guid'];
if(! $arr['hash'])
@@ -191,7 +203,7 @@ function xchan_store($arr) {
if(! $arr['url'])
$arr['url'] = z_root();
if(! $arr['photo'])
$arr['photo'] = get_default_profile_photo();
$arr['photo'] = z_root() . '/' . get_default_profile_photo();
$r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_addr, xchan_url, xchan_connurl, xchan_follow, xchan_connpage, xchan_name, xchan_network, xchan_instance_url, xchan_hidden, xchan_orphan, xchan_censored, xchan_selfcensored, xchan_system, xchan_pubforum, xchan_deleted, xchan_name_date ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s','%s','%s','%s',%d, %d, %d, %d, %d, %d, %d, '%s') ",
dbesc($arr['hash']),
@@ -251,12 +263,12 @@ function xchan_fetch($arr) {
if(! $key)
return false;
$r = q("select * from xchan where $key = '$v'");
$r = q("select * from xchan where $key = '$v' limit 1");
if(! $r)
return false;
$ret = array();
foreach($r as $k => $v) {
foreach($r[0] as $k => $v) {
if($k === 'xchan_addr')
$ret['address'] = $v;
else

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -20,6 +20,8 @@ function js_strings() {
'$rating_val' => t('Rating'),
'$rating_text' => t('Describe (optional)'),
'$submit' => t('Submit'),
'$linkurl' => t('Please enter a link URL'),
'$leavethispage' => t('Unsaved changes. Are you sure you wish to leave this page?'),
'$t01' => ((t('timeago.prefixAgo') != 'timeago.prefixAgo') ? t('timeago.prefixAgo') : ''),
'$t02' => ((t('timeago.prefixFromNow') != 'timeago.prefixFromNow') ? t('timeago.prefixFromNow') : ''),

View File

@@ -1,8 +1,8 @@
<?php
/**
* @file
* @file include/language.php
*
* @brief translation support
* @brief Translation support.
*
* This file contains functions to work with translations and other
* language related tasks.
@@ -24,8 +24,9 @@
*/
function get_browser_language() {
$langs = array();
$lang_parse = array();
if (x($_SERVER,'HTTP_ACCEPT_LANGUAGE')) {
if (x($_SERVER, 'HTTP_ACCEPT_LANGUAGE')) {
// break up string into pieces (languages and q factors)
preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i',
$_SERVER['HTTP_ACCEPT_LANGUAGE'], $lang_parse);
@@ -33,7 +34,7 @@ function get_browser_language() {
if (count($lang_parse[1])) {
// create a list like "en" => 0.8
$langs = array_combine($lang_parse[1], $lang_parse[4]);
// set default to 1 for any without q factor
foreach ($langs as $lang => $val) {
if ($val === '') $langs[$lang] = 1;
@@ -109,9 +110,12 @@ function pop_lang() {
$a->language = $a->langsave;
}
// load string translation table for alternate language
/**
* @brief Load string translation table for alternate language.
*
* @param string $lang language code in 2-letter ISO 639-1 (en, de, fr) format
* @param boolean $install (optional) default false
*/
function load_translation_table($lang, $install = false) {
global $a;
@@ -138,52 +142,67 @@ function load_translation_table($lang, $install = false) {
if(file_exists("view/local-$lang/strings.php")) {
include("view/local-$lang/strings.php");
}
}
/**
* @brief translate string if translation exists.
* @brief Translate string if translation exists.
*
* @param $s string that should get translated
* @param $ctx optional context to appear in po file
* @param string $s string that should get translated
* @param string $ctx (optional) context to appear in po file
* @return translated string if exists, otherwise return $s
*
*/
function t($s,$ctx = '') {
function t($s, $ctx = '') {
global $a;
$cs = $ctx?"__ctx:".$ctx."__ ".$s:$s;
if(x($a->strings,$cs)) {
$cs = $ctx ? '__ctx:' . $ctx . '__ ' . $s : $s;
if (x($a->strings, $cs)) {
$t = $a->strings[$cs];
return is_array($t) ? $t[0] : $t;
}
return $s;
}
/**
* @brief
*
* @param string $singular
* @param string $plural
* @param int $count
* @param string $ctx
* @return string
*/
function tt($singular, $plural, $count, $ctx = ''){
$a = get_app();
$cs = $ctx?"__ctx:".$ctx."__ ".$singular:$singular;
if(x($a->strings,$cs)) {
$cs = $ctx ? "__ctx:" . $ctx . "__ " . $singular : $singular;
if (x($a->strings,$cs)) {
$t = $a->strings[$cs];
$f = 'string_plural_select_' . str_replace('-', '_', $a->language);
if(! function_exists($f))
if (! function_exists($f))
$f = 'string_plural_select_default';
$k = $f($count);
return is_array($t) ? $t[$k] : $t;
}
if ($count != 1){
if ($count != 1) {
return $plural;
} else {
return $singular;
}
}
// provide a fallback which will not collide with
// a function defined in any language file
/**
* @brief Provide a fallback which will not collide with a function defined in
* any language file.
*
* @param int $n
* @return boolean
*/
function string_plural_select_default($n) {
return ($n != 1);
}
@@ -199,26 +218,26 @@ function string_plural_select_default($n) {
* returned through config['system']['language_detect_min_confidence'].
*
* @see http://pear.php.net/package/Text_LanguageDetect
* @param s A string to examine
* @param string $s A string to examine
* @return Language code in 2-letter ISO 639-1 (en, de, fr) format
*/
function detect_language($s) {
require_once('Text/LanguageDetect.php');
$min_length = get_config('system', 'language_detect_min_length');
if($min_length === false)
if ($min_length === false)
$min_length = LANGUAGE_DETECT_MIN_LENGTH;
$min_confidence = get_config('system', 'language_detect_min_confidence');
if($min_confidence === false)
if ($min_confidence === false)
$min_confidence = LANGUAGE_DETECT_MIN_CONFIDENCE;
// embedded apps have long base64 strings which will trip up the detector.
$naked_body = preg_replace('/\[app\](.*?)\[\/app\]/','',$s);
// strip off bbcode
$naked_body = preg_replace('/\[(.+?)\]/', '', $naked_body);
if(mb_strlen($naked_body) < intval($min_length)) {
logger('detect language: string length less than ' . intval($min_length), LOGGER_DATA);
if (mb_strlen($naked_body) < intval($min_length)) {
logger('string length less than ' . intval($min_length), LOGGER_DATA);
return '';
}
@@ -232,11 +251,11 @@ function detect_language($s) {
logger('detect language exception: ' . $e->getMessage(), LOGGER_DATA);
}
if((! $lng) || (! (x($lng,'language')))) {
if ((! $lng) || (! (x($lng,'language')))) {
return '';
}
if($lng['confidence'] < (float) $min_confidence) {
if ($lng['confidence'] < (float) $min_confidence) {
logger('detect language: confidence less than ' . (float) $min_confidence, LOGGER_DATA);
return '';
}
@@ -250,38 +269,37 @@ function detect_language($s) {
* By default we use the localized language name. You can switch the result
* to any language with the optional 2nd parameter $l.
*
* $s and $l should be in 2-letter ISO 639-1 format
* $s and $l should be in 2-letter ISO 639-1 format.
*
* If nothing could be looked up it returns $s.
*
* @param $s Language code to look up
* @param $l (optional) In which language to return the name
* @param string $s Language code to look up
* @param string $l (optional) In which language to return the name
* @return string with the language name, or $s if unrecognized
*
* @todo include CommerceGuys\Intl through composer like SabreDAV.
*/
require_once(__DIR__ . '/../library/intl/vendor/autoload.php');
use CommerceGuys\Intl\Language\LanguageRepository;
function get_language_name($s, $l = null) {
// get() expects the second part to be in upper case
if(strpos($s,'-') !== false) $s = substr($s,0,2) . strtoupper(substr($s,2));
if($l !== null && strpos($l,'-') !== false) $l = substr($l,0,2) . strtoupper(substr($l,2));
if (strpos($s, '-') !== false) $s = substr($s, 0, 2) . strtoupper(substr($s, 2));
if ($l !== null && strpos($l, '-') !== false) $l = substr($l, 0, 2) . strtoupper(substr($l, 2));
$languageRepository = new LanguageRepository;
// Sometimes intl doesn't like the second part at all ...
try {
$language = $languageRepository->get($s, $l);
}
catch(CommerceGuys\Intl\Exception\UnknownLanguageException $e) {
$s = substr($s,0,2);
if($l !== null) $l = substr($s,0,2);
} catch(CommerceGuys\Intl\Exception\UnknownLanguageException $e) {
$s = substr($s, 0, 2);
if($l !== null) $l = substr($s, 0, 2);
try {
$language = $languageRepository->get($s, $l);
}
catch(CommerceGuys\Intl\Exception\UnknownLanguageException $e) {
} catch (CommerceGuys\Intl\Exception\UnknownLanguageException $e) {
return $s; // Give up
}
}
}
return $language->getName();
}

View File

@@ -25,6 +25,7 @@ function menu_fetch($name,$uid,$observer_xchan) {
}
function menu_render($menu, $class='', $edit = false) {
if(! $menu)
return '';
@@ -40,6 +41,7 @@ function menu_render($menu, $class='', $edit = false) {
'$menu' => $menu['menu'],
'$class' => $class,
'$edit' => (($edit) ? t("Edit") : ''),
'$id' => $menu['menu']['menu_id'],
'$items' => $menu['items']
));
}
@@ -60,14 +62,13 @@ function menu_fetch_id($menu_id,$channel_id) {
function menu_create($arr) {
$menu_name = trim(escape_tags($arr['menu_name']));
$menu_desc = trim(escape_tags($arr['menu_desc']));
$menu_flags = intval($arr['menu_flags']);
if(! $menu_desc)
$menu_desc = $menu_name;
//allow menu_desc (title) to be empty
//if(! $menu_desc)
// $menu_desc = $menu_name;
if(! $menu_name)
return false;
@@ -144,8 +145,9 @@ function menu_edit($arr) {
$menu_desc = trim(escape_tags($arr['menu_desc']));
$menu_flags = intval($arr['menu_flags']);
if(! $menu_desc)
$menu_desc = $menu_name;
//allow menu_desc (title) to be empty
//if(! $menu_desc)
// $menu_desc = $menu_name;
if(! $menu_name)
return false;
@@ -227,31 +229,10 @@ function menu_add_item($menu_id, $uid, $arr) {
$channel = get_app()->get_channel();
}
if (($channel)
&& (! $arr['contact_allow'])
&& (! $arr['group_allow'])
&& (! $arr['contact_deny'])
&& (! $arr['group_deny'])) {
$str_group_allow = $channel['channel_allow_gid'];
$str_contact_allow = $channel['channel_allow_cid'];
$str_group_deny = $channel['channel_deny_gid'];
$str_contact_deny = $channel['channel_deny_cid'];
}
else {
// use the posted permissions
$str_group_allow = perms2str($arr['group_allow']);
$str_contact_allow = perms2str($arr['contact_allow']);
$str_group_deny = perms2str($arr['group_deny']);
$str_contact_deny = perms2str($arr['contact_deny']);
}
// unused
// $allow_cid = perms2str($arr['allow_cid']);
// $allow_gid = perms2str($arr['allow_gid']);
// $deny_cid = perms2str($arr['deny_cid']);
// $deny_gid = perms2str($arr['deny_gid']);
$str_group_allow = perms2str($arr['group_allow']);
$str_contact_allow = perms2str($arr['contact_allow']);
$str_group_deny = perms2str($arr['group_deny']);
$str_contact_deny = perms2str($arr['contact_deny']);
$r = q("insert into menu_item ( mitem_link, mitem_desc, mitem_flags, allow_cid, allow_gid, deny_cid, deny_gid, mitem_channel_id, mitem_menu_id, mitem_order ) values ( '%s', '%s', %d, '%s', '%s', '%s', '%s', %d, %d, %d ) ",
dbesc($mitem_link),
@@ -283,25 +264,10 @@ function menu_edit_item($menu_id, $uid, $arr) {
$channel = get_app()->get_channel();
}
if ((! $arr['contact_allow'])
&& (! $arr['group_allow'])
&& (! $arr['contact_deny'])
&& (! $arr['group_deny'])) {
$str_group_allow = $channel['channel_allow_gid'];
$str_contact_allow = $channel['channel_allow_cid'];
$str_group_deny = $channel['channel_deny_gid'];
$str_contact_deny = $channel['channel_deny_cid'];
}
else {
// use the posted permissions
$str_group_allow = perms2str($arr['group_allow']);
$str_contact_allow = perms2str($arr['contact_allow']);
$str_group_deny = perms2str($arr['group_deny']);
$str_contact_deny = perms2str($arr['contact_deny']);
}
$str_group_allow = perms2str($arr['group_allow']);
$str_contact_allow = perms2str($arr['contact_allow']);
$str_group_deny = perms2str($arr['group_deny']);
$str_contact_deny = perms2str($arr['contact_deny']);
$r = q("update menu_item set mitem_link = '%s', mitem_desc = '%s', mitem_flags = %d, allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', mitem_order = %d where mitem_channel_id = %d and mitem_menu_id = %d and mitem_id = %d",
dbesc($mitem_link),

View File

@@ -176,10 +176,8 @@ EOT;
if(local_channel()) {
$network_options = get_pconfig(local_channel(),'system','network_page_default');
$nav['network'] = array('network' . (($network_options) ? '?f=&' . $network_options : ''),
t('Matrix'), "", t('Your matrix'),'network_nav_btn');
$nav['network'] = array('network', t('Matrix'), "", t('Your matrix'),'network_nav_btn');
$nav['network']['mark'] = array('', t('Mark all matrix notifications seen'), '','');
$nav['home'] = array('channel/' . $channel['channel_address'], t('Channel Home'), "", t('Channel home'),'home_nav_btn');

View File

@@ -1,38 +1,43 @@
<?php /** @file */
<?php
/**
* @file include/network.php
*/
/**
* @brief Returns path to CA file.
*
* @return string
*/
function get_capath() {
return appdirpath() . '/library/cacert.pem';
}
/**
* @function z_fetch_url
* @brief fetches an URL.
*
* @param string $url
* URL to fetch
* @param boolean $binary = false
* @param boolean $binary default false
* TRUE if asked to return binary results (file download)
* @param int $redirects = 0
* @param int $redirects default 0
* internal use, recursion counter
* @param array $opts (optional parameters)
* 'accept_content' => supply Accept: header with 'accept_content' as the value
* 'timeout' => int seconds, default system config value or 60 seconds
* 'http_auth' => username:password
* 'novalidate' => do not validate SSL certs, default is to validate using our CA list
*
* @returns array
* 'return_code' => HTTP return code or 0 if timeout or failure
* 'success' => boolean true (if HTTP 2xx result) or false
* 'header' => HTTP headers
* 'body' => fetched content
* @param array $opts (optional parameters) assoziative array with:
* * \b accept_content => supply Accept: header with 'accept_content' as the value
* * \b timeout => int seconds, default system config value or 60 seconds
* * \b http_auth => username:password
* * \b novalidate => do not validate SSL certs, default is to validate using our CA list
* * \b nobody => only return the header
*
* @return array an assoziative array with:
* * \e int \b return_code => HTTP return code or 0 if timeout or failure
* * \e boolean \b success => boolean true (if HTTP 2xx result) or false
* * \e string \b header => HTTP headers
* * \e string \b body => fetched content
*/
function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
$ret = array('return_code' => 0, 'success' => false, 'header' => "", 'body' => "");
$a = get_app();
$ch = @curl_init($url);
if(($redirects > 8) || (! $ch))
return false;
@@ -51,6 +56,9 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
if(x($opts,'headers'))
@curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['headers']);
if(x($opts,'nobody'))
@curl_setopt($ch, CURLOPT_NOBODY, $opts['nobody']);
if(x($opts,'timeout') && intval($opts['timeout'])) {
@curl_setopt($ch, CURLOPT_TIMEOUT, $opts['timeout']);
}
@@ -67,7 +75,6 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
@curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,
((x($opts,'novalidate') && intval($opts['novalidate'])) ? false : true));
$prx = get_config('system','proxy');
if(strlen($prx)) {
@curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
@@ -109,7 +116,7 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
$url_parsed = @parse_url($newurl);
if (isset($url_parsed)) {
@curl_close($ch);
return z_fetch_url($newurl,$binary,$redirects++,$opts);
return z_fetch_url($newurl,$binary,++$redirects,$opts);
}
}
@@ -128,14 +135,15 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
if(x($opts,'debug')) {
$ret['debug'] = $curl_info;
}
@curl_close($ch);
return($ret);
}
/**
* @function z_post_url
* @brief
*
* @param string $url
* URL to post
* @param mixed $params
@@ -150,17 +158,15 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
* 'timeout' => int seconds, default system config value or 60 seconds
* 'http_auth' => username:password
* 'novalidate' => do not validate SSL certs, default is to validate using our CA list
*
* @returns array
* 'return_code' => HTTP return code or 0 if timeout or failure
* 'success' => boolean true (if HTTP 2xx result) or false
* 'header' => HTTP headers
* 'body' => fetched content
* @return array an assoziative array with:
* * \e int \b return_code => HTTP return code or 0 if timeout or failure
* * \e boolean \b success => boolean true (if HTTP 2xx result) or false
* * \e string \b header => HTTP headers
* * \e string \b body => content
* * \e string \b debug => from curl_info()
*/
function z_post_url($url,$params, $redirects = 0, $opts = array()) {
$ret = array('return_code' => 0, 'success' => false, 'header' => "", 'body' => "");
$ch = curl_init($url);
@@ -182,6 +188,9 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) {
if(x($opts,'headers'))
@curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['headers']);
if(x($opts,'nobody'))
@curl_setopt($ch, CURLOPT_NOBODY, $opts['nobody']);
if(x($opts,'timeout') && intval($opts['timeout'])) {
@curl_setopt($ch, CURLOPT_TIMEOUT, $opts['timeout']);
}
@@ -239,7 +248,7 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) {
if($http_code == 303) {
return z_fetch_url($newurl,false,$redirects++,$opts);
} else {
return z_post_url($newurl,$params,$redirects++,$opts);
return z_post_url($newurl,$params,++$redirects,$opts);
}
}
}
@@ -253,24 +262,35 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) {
logger('z_post_url: debug: ' . print_r($curl_info,true), LOGGER_DATA);
}
$ret['body'] = substr($s,strlen($header));
$ret['body'] = substr($s, strlen($header));
$ret['header'] = $header;
if(x($opts,'debug')) {
$ret['debug'] = $curl_info;
}
curl_close($ch);
return($ret);
}
/**
* @brief Like z_post_url() but with an application/json HTTP header.
*
* Add a "Content-Type: application/json" HTTP-header to $opts and call z_post_url().
*
* @see z_post_url()
*
* @param string $url
* @param array $params
* @param number $redirects default 0
* @param array $opts (optional) curl options
* @return z_post_url()
*/
function z_post_url_json($url, $params, $redirects = 0, $opts = array()) {
function z_post_url_json($url,$params,$redirects = 0, $opts = array()) {
$opts = array_merge($opts, array('headers' => array('Content-Type: application/json')));
$opts = array_merge($opts,array('headers' => array('Content-Type: application/json')));
return z_post_url($url,json_encode($params),$redirects,$opts);
}
@@ -301,22 +321,19 @@ function xml_status($st, $message = '') {
}
/**
* @function http_status_exit
*
* Send HTTP status header and exit
* @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 = '') {
function http_status_exit($val,$msg = '') {
$err = '';
if($val >= 400)
if ($val >= 400)
$msg = (($msg) ? $msg : 'Error');
if($val >= 200 && $val < 300)
if ($val >= 200 && $val < 300)
$msg = (($msg) ? $msg : 'OK');
logger('http_status_exit ' . $val . ' ' . $msg);
@@ -511,6 +528,7 @@ function allowed_email($email) {
function avatar_img($email) {
$avatar = array();
$a = get_app();
$avatar['size'] = 175;
@@ -520,10 +538,11 @@ function avatar_img($email) {
call_hooks('avatar_lookup', $avatar);
if(! $avatar['success'])
if (! $avatar['success'])
$avatar['url'] = $a->get_baseurl() . '/' . get_default_profile_photo();
logger('Avatar: ' . $avatar['email'] . ' ' . $avatar['url'], LOGGER_DEBUG);
return $avatar['url'];
}
@@ -1530,7 +1549,7 @@ function service_plink($contact, $guid) {
$m = parse_url($contact['xchan_url']);
if($m) {
$url = $scheme . '://' . $m['host'] . (($m['port']) ? ':' . $m['port'] : '');
$url = $m['scheme'] . '://' . $m['host'] . (($m['port']) ? ':' . $m['port'] : '');
}
else
$url = 'https://' . substr($contact['xchan_addr'],strpos($contact['xchan_addr'],'@')+1);

View File

@@ -100,10 +100,14 @@ function notifier_run($argv, $argc){
// Get the recipient
$r = q("select abook.*, hubloc.* from abook
left join hubloc on hubloc_hash = abook_xchan
where abook_id = %d and not ( abook_flags & %d )>0 limit 1",
where abook_id = %d and not ( abook_flags & %d ) > 0
and not (hubloc_flags & %d) > 0 and not (hubloc_status & %d) > 0 limit 1",
intval($item_id),
intval(ABOOK_FLAG_SELF)
intval(ABOOK_FLAG_SELF),
intval(HUBLOC_FLAGS_DELETED),
intval(HUBLOC_OFFLINE)
);
if($r) {
// Get the sender
$s = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1",
@@ -116,8 +120,11 @@ function notifier_run($argv, $argc){
}
else {
// send a refresh message to each hub they have registered here
$h = q("select * from hubloc where hubloc_hash = '%s'",
dbesc($r[0]['hubloc_hash'])
$h = q("select * from hubloc where hubloc_hash = '%s'
and not (hubloc_flags & %d) > 0 and not (hubloc_status & %d) > 0",
dbesc($r[0]['hubloc_hash']),
intval(HUBLOC_FLAGS_DELETED),
intval(HUBLOC_OFFLINE)
);
if($h) {
foreach($h as $hh) {
@@ -128,17 +135,31 @@ function notifier_run($argv, $argc){
));
if($data) {
$result = zot_zot($hh['hubloc_callback'],$data);
// zot_queue_item is not yet written
// if(! $result['success'])
// zot_queue_item();
// if immediate delivery failed, stick it in the queue to try again later.
if(! $result['success']) {
$hash = random_string();
q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_created, outq_updated, outq_notify, outq_msg )
values ( '%s', %d, %d, '%s', '%s', %d, '%s', '%s', '%s', '%s' )",
dbesc($hash),
intval($s[0]['channel_account_id']),
intval($s[0]['channel_id']),
dbesc('zot'),
dbesc($hh['hubloc_callback']),
intval(1),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
dbesc($data),
dbesc('')
);
}
}
}
}
}
}
}
return;
}
@@ -313,9 +334,12 @@ function notifier_run($argv, $argc){
$r = fetch_post_tags($r);
$target_item = $r[0];
$deleted_item = false;
if(intval($target_item['item_deleted']))
logger('notifier: target item ITEM_DELETED', LOGGER_DEBUG);
$deleted_item = true;
}
if(intval($target_item['item_type']) != ITEM_TYPE_POST) {
logger('notifier: target item not forwardable: type ' . $target_item['item_type'], LOGGER_DEBUG);
@@ -364,7 +388,16 @@ function notifier_run($argv, $argc){
$encoded_item = encode_item($target_item);
$relay_to_owner = (((! $top_level_post) && (intval($target_item['item_origin']))) ? true : false);
// Send comments to the owner to re-deliver to everybody in the conversation
// We only do this if the item in question originated on this site. This prevents looping.
// To clarify, a site accepting a new comment is responsible for sending it to the owner for relay.
// Relaying should never be initiated on a post that arrived from elsewhere.
// We should normally be able to rely on ITEM_ORIGIN, but start_delivery_chain() incorrectly set this
// flag on comments for an extended period. So we'll also call comment_local_origin() which looks at
// the hostname in the message_id and provides a second (fallback) opinion.
$relay_to_owner = (((! $top_level_post) && (intval($target_item['item_origin'])) && comment_local_origin($target_item)) ? true : false);
$uplink = false;
@@ -476,6 +509,9 @@ function notifier_run($argv, $argc){
logger('notifier: hub choice: ' . intval($relay_to_owner) . ' ' . intval($private) . ' ' . $cmd, LOGGER_DEBUG);
// FIXME: I think we need to remove the private bit or this clause will never execute. Needs more coffee to think it through.
// We may in fact have to send it to clones in case the one we pick recently died.
if($relay_to_owner && (! $private) && ($cmd !== 'relay')) {
// If sending a followup to the post owner, only send it to one channel clone - to avoid race conditions.

View File

@@ -29,7 +29,7 @@ function format_notification($item) {
'url' => $item['author']['xchan_url'],
'photo' => $item['author']['xchan_photo_s'],
'when' => relative_date($item['created']),
'class' => (($item['item_unseen']) ? 'notify-unseen' : 'notify-seen'),
'class' => (intval($item['item_unseen']) ? 'notify-unseen' : 'notify-seen'),
'message' => strip_tags(bbcode($itemem_text))
);

View File

@@ -8,13 +8,25 @@ function oembed_replacecb($matches){
}
// if the url is embeddable with oembed, return the bbcode link.
function oembed_process($url) {
$j = oembed_fetch_url($url);
logger('oembed_process: ' . print_r($j,true));
if($j && $j->type !== 'error')
return '[embed]' . $url . '[/embed]';
return false;
}
function oembed_fetch_url($embedurl){
$a = get_app();
$txt = Cache::get($a->videowidth . $embedurl);
if(strstr($txt,'youtu')) {
if(strstr($txt,'youtu') && strstr(z_root(),'https:')) {
$txt = str_replace('http:','https:',$txt);
}
@@ -105,7 +117,7 @@ function oembed_format_object($j){
$th=120; $tw = $th*$tr;
$tpl=get_markup_template('oembed_video.tpl');
if(strstr($embedurl,'youtu')) {
if(strstr($embedurl,'youtu') && strstr(z_root(),'https:')) {
$embedurl = str_replace('http:','https:',$embedurl);
$j->thumbnail_url = str_replace('http:','https:', $j->thumbnail_url);
$jhtml = str_replace('http:','https:', $jhtml);
@@ -142,7 +154,7 @@ function oembed_format_object($j){
// add link to source if not present in "rich" type
if ( $j->type!='rich' || !strpos($j->html,$embedurl) ){
$embedlink = (isset($j->title))?$j->title:$embedurl;
$ret .= "<a href='$embedurl' rel='oembed'>$embedlink</a>";
$ret .= '<span class="bookmark-identifier">#^</span>' . "<a href='$embedurl' rel='oembed'>$embedlink</a>";
$ret .= "<br>";
if (isset($j->author_name)) $ret.=" by ".$j->author_name;
if (isset($j->provider_name)) $ret.=" on ".$j->provider_name;

View File

@@ -125,7 +125,7 @@ function onepoll_run($argv, $argc){
if(($x) && ($x['success'])) {
$total = 0;
logger('onepoll: feed update ' . $contact['xchan_name']);
logger('onepoll: feed update ' . $contact['xchan_name'] . ' ' . $feedurl);
$j = json_decode($x['body'],true);
if($j['success'] && $j['messages']) {

View File

@@ -1,6 +1,6 @@
<?php
/**
* @file incldue/permissions.php
* @file include/permissions.php
*
* This file conntains functions to check and work with permissions.
*/
@@ -422,12 +422,12 @@ function site_default_perms() {
'post_wall' => PERMS_SPECIFIC,
'post_comments' => PERMS_SPECIFIC,
'post_mail' => PERMS_SPECIFIC,
'post_photos' => 0,
'post_photos' => PERMS_SPECIFIC,
'tag_deliver' => PERMS_SPECIFIC,
'chat' => PERMS_SPECIFIC,
'write_storage' => 0,
'write_pages' => 0,
'delegate' => 0,
'write_storage' => PERMS_SPECIFIC,
'write_pages' => PERMS_SPECIFIC,
'delegate' => PERMS_SPECIFIC,
'post_like' => PERMS_NETWORK
);
@@ -445,21 +445,21 @@ function site_default_perms() {
/**
* @function get_role_perms($role)
* @param string $role
*
* Given a string for the channel role ('social','forum', etc)
* @brief Return an array of all permissions for this role.
*
* Given a string for the channel role ('social','forum', etc)
* return an array of all permission fields pre-filled for this role.
* This includes the channel permission scope indicators (anything beginning with 'channel_') as well as
* perms_auto: true or false to create auto-permissions for this channel
* perms_follow: The permissions to apply when initiating a connection request to another channel
* perms_accept: The permissions to apply when accepting a connection request from another channel (not automatic)
* default_collection: true or false to make the default ACL include the channel's default collection
* directory_publish: true or false to publish this channel in the directory
* * perms_auto: true or false to create auto-permissions for this channel
* * perms_follow: The permissions to apply when initiating a connection request to another channel
* * perms_accept: The permissions to apply when accepting a connection request from another channel (not automatic)
* * default_collection: true or false to make the default ACL include the channel's default collection
* * directory_publish: true or false to publish this channel in the directory
* Any attributes may be extended (new roles defined) and modified (specific permissions altered) by plugins
*
* @param string $role
* @return array
*/
function get_role_perms($role) {
$ret = array();
@@ -487,13 +487,13 @@ function get_role_perms($role) {
$ret['channel_w_tagwall'] = PERMS_SPECIFIC;
$ret['channel_w_comment'] = PERMS_SPECIFIC;
$ret['channel_w_mail'] = PERMS_SPECIFIC;
$ret['channel_w_photos'] = 0;
$ret['channel_w_photos'] = PERMS_SPECIFIC;
$ret['channel_w_chat'] = PERMS_SPECIFIC;
$ret['channel_a_delegate'] = 0;
$ret['channel_a_delegate'] = PERMS_SPECIFIC;
$ret['channel_r_storage'] = PERMS_PUBLIC;
$ret['channel_w_storage'] = 0;
$ret['channel_w_storage'] = PERMS_SPECIFIC;
$ret['channel_r_pages'] = PERMS_PUBLIC;
$ret['channel_w_pages'] = 0;
$ret['channel_w_pages'] = PERMS_SPECIFIC;
$ret['channel_a_republish'] = PERMS_SPECIFIC;
$ret['channel_w_like'] = PERMS_NETWORK;
@@ -519,13 +519,13 @@ function get_role_perms($role) {
$ret['channel_w_tagwall'] = PERMS_SPECIFIC;
$ret['channel_w_comment'] = PERMS_SPECIFIC;
$ret['channel_w_mail'] = PERMS_SPECIFIC;
$ret['channel_w_photos'] = 0;
$ret['channel_w_photos'] = PERMS_SPECIFIC;
$ret['channel_w_chat'] = PERMS_SPECIFIC;
$ret['channel_a_delegate'] = 0;
$ret['channel_a_delegate'] = PERMS_SPECIFIC;
$ret['channel_r_storage'] = PERMS_PUBLIC;
$ret['channel_w_storage'] = 0;
$ret['channel_w_storage'] = PERMS_SPECIFIC;
$ret['channel_r_pages'] = PERMS_PUBLIC;
$ret['channel_w_pages'] = 0;
$ret['channel_w_pages'] = PERMS_SPECIFIC;
$ret['channel_a_republish'] = PERMS_SPECIFIC;
$ret['channel_w_like'] = PERMS_SPECIFIC;
@@ -551,13 +551,13 @@ function get_role_perms($role) {
$ret['channel_w_tagwall'] = PERMS_SPECIFIC;
$ret['channel_w_comment'] = PERMS_SPECIFIC;
$ret['channel_w_mail'] = PERMS_SPECIFIC;
$ret['channel_w_photos'] = 0;
$ret['channel_w_photos'] = PERMS_SPECIFIC;
$ret['channel_w_chat'] = PERMS_SPECIFIC;
$ret['channel_a_delegate'] = 0;
$ret['channel_a_delegate'] = PERMS_SPECIFIC;
$ret['channel_r_storage'] = PERMS_PUBLIC;
$ret['channel_w_storage'] = 0;
$ret['channel_w_storage'] = PERMS_SPECIFIC;
$ret['channel_r_pages'] = PERMS_PUBLIC;
$ret['channel_w_pages'] = 0;
$ret['channel_w_pages'] = PERMS_SPECIFIC;
$ret['channel_a_republish'] = PERMS_SPECIFIC;
$ret['channel_w_like'] = PERMS_SPECIFIC;
@@ -578,18 +578,18 @@ function get_role_perms($role) {
$ret['channel_r_profile'] = PERMS_PUBLIC;
$ret['channel_r_photos'] = PERMS_PUBLIC;
$ret['channel_r_abook'] = PERMS_PUBLIC;
$ret['channel_w_stream'] = 0;
$ret['channel_w_stream'] = PERMS_SPECIFIC;
$ret['channel_w_wall'] = PERMS_SPECIFIC;
$ret['channel_w_tagwall'] = PERMS_SPECIFIC;
$ret['channel_w_comment'] = PERMS_SPECIFIC;
$ret['channel_w_mail'] = PERMS_SPECIFIC;
$ret['channel_w_photos'] = 0;
$ret['channel_w_photos'] = PERMS_SPECIFIC;
$ret['channel_w_chat'] = PERMS_SPECIFIC;
$ret['channel_a_delegate'] = 0;
$ret['channel_a_delegate'] = PERMS_SPECIFIC;
$ret['channel_r_storage'] = PERMS_PUBLIC;
$ret['channel_w_storage'] = 0;
$ret['channel_w_storage'] = PERMS_SPECIFIC;
$ret['channel_r_pages'] = PERMS_PUBLIC;
$ret['channel_w_pages'] = 0;
$ret['channel_w_pages'] = PERMS_SPECIFIC;
$ret['channel_a_republish'] = PERMS_SPECIFIC;
$ret['channel_w_like'] = PERMS_NETWORK;
@@ -610,18 +610,18 @@ function get_role_perms($role) {
$ret['channel_r_profile'] = PERMS_PUBLIC;
$ret['channel_r_photos'] = PERMS_PUBLIC;
$ret['channel_r_abook'] = PERMS_PUBLIC;
$ret['channel_w_stream'] = 0;
$ret['channel_w_stream'] = PERMS_SPECIFIC;
$ret['channel_w_wall'] = PERMS_SPECIFIC;
$ret['channel_w_tagwall'] = PERMS_SPECIFIC;
$ret['channel_w_comment'] = PERMS_SPECIFIC;
$ret['channel_w_mail'] = PERMS_SPECIFIC;
$ret['channel_w_photos'] = 0;
$ret['channel_w_photos'] = PERMS_SPECIFIC;
$ret['channel_w_chat'] = PERMS_SPECIFIC;
$ret['channel_a_delegate'] = 0;
$ret['channel_a_delegate'] = PERMS_SPECIFIC;
$ret['channel_r_storage'] = PERMS_PUBLIC;
$ret['channel_w_storage'] = 0;
$ret['channel_w_storage'] = PERMS_SPECIFIC;
$ret['channel_r_pages'] = PERMS_PUBLIC;
$ret['channel_w_pages'] = 0;
$ret['channel_w_pages'] = PERMS_SPECIFIC;
$ret['channel_a_republish'] = PERMS_SPECIFIC;
$ret['channel_w_like'] = PERMS_SPECIFIC;
@@ -642,18 +642,18 @@ function get_role_perms($role) {
$ret['channel_r_profile'] = PERMS_SPECIFIC;
$ret['channel_r_photos'] = PERMS_SPECIFIC;
$ret['channel_r_abook'] = PERMS_SPECIFIC;
$ret['channel_w_stream'] = 0;
$ret['channel_w_stream'] = PERMS_SPECIFIC;
$ret['channel_w_wall'] = PERMS_SPECIFIC;
$ret['channel_w_tagwall'] = 0;
$ret['channel_w_tagwall'] = PERMS_SPECIFIC;
$ret['channel_w_comment'] = PERMS_SPECIFIC;
$ret['channel_w_mail'] = PERMS_SPECIFIC;
$ret['channel_w_photos'] = 0;
$ret['channel_w_photos'] = PERMS_SPECIFIC;
$ret['channel_w_chat'] = PERMS_SPECIFIC;
$ret['channel_a_delegate'] = 0;
$ret['channel_a_delegate'] = PERMS_SPECIFIC;
$ret['channel_r_storage'] = PERMS_SPECIFIC;
$ret['channel_w_storage'] = 0;
$ret['channel_w_storage'] = PERMS_SPECIFIC;
$ret['channel_r_pages'] = PERMS_SPECIFIC;
$ret['channel_w_pages'] = 0;
$ret['channel_w_pages'] = PERMS_SPECIFIC;
$ret['channel_a_republish'] = PERMS_SPECIFIC;
$ret['channel_w_like'] = PERMS_SPECIFIC;
@@ -679,13 +679,13 @@ function get_role_perms($role) {
$ret['channel_w_tagwall'] = PERMS_SPECIFIC;
$ret['channel_w_comment'] = PERMS_SPECIFIC;
$ret['channel_w_mail'] = PERMS_SPECIFIC;
$ret['channel_w_photos'] = 0;
$ret['channel_w_photos'] = PERMS_SPECIFIC;
$ret['channel_w_chat'] = PERMS_SPECIFIC;
$ret['channel_a_delegate'] = 0;
$ret['channel_a_delegate'] = PERMS_SPECIFIC;
$ret['channel_r_storage'] = PERMS_PUBLIC;
$ret['channel_w_storage'] = 0;
$ret['channel_w_storage'] = PERMS_SPECIFIC;
$ret['channel_r_pages'] = PERMS_PUBLIC;
$ret['channel_w_pages'] = 0;
$ret['channel_w_pages'] = PERMS_SPECIFIC;
$ret['channel_a_republish'] = PERMS_NETWORK;
$ret['channel_w_like'] = PERMS_NETWORK;
@@ -711,13 +711,13 @@ function get_role_perms($role) {
$ret['channel_w_tagwall'] = PERMS_SPECIFIC;
$ret['channel_w_comment'] = PERMS_SPECIFIC;
$ret['channel_w_mail'] = PERMS_SPECIFIC;
$ret['channel_w_photos'] = 0;
$ret['channel_w_photos'] = PERMS_SPECIFIC;
$ret['channel_w_chat'] = PERMS_SPECIFIC;
$ret['channel_a_delegate'] = 0;
$ret['channel_a_delegate'] = PERMS_SPECIFIC;
$ret['channel_r_storage'] = PERMS_PUBLIC;
$ret['channel_w_storage'] = 0;
$ret['channel_w_storage'] = PERMS_SPECIFIC;
$ret['channel_r_pages'] = PERMS_PUBLIC;
$ret['channel_w_pages'] = 0;
$ret['channel_w_pages'] = PERMS_SPECIFIC;
$ret['channel_a_republish'] = PERMS_SPECIFIC;
$ret['channel_w_like'] = PERMS_NETWORK;
@@ -736,18 +736,18 @@ function get_role_perms($role) {
$ret['channel_r_profile'] = PERMS_PUBLIC;
$ret['channel_r_photos'] = PERMS_PUBLIC;
$ret['channel_r_abook'] = PERMS_PUBLIC;
$ret['channel_w_stream'] = 0;
$ret['channel_w_wall'] = 0;
$ret['channel_w_tagwall'] = 0;
$ret['channel_w_comment'] = 0;
$ret['channel_w_mail'] = 0;
$ret['channel_w_photos'] = 0;
$ret['channel_w_chat'] = 0;
$ret['channel_a_delegate'] = 0;
$ret['channel_w_stream'] = PERMS_SPECIFIC;
$ret['channel_w_wall'] = PERMS_SPECIFIC;
$ret['channel_w_tagwall'] = PERMS_SPECIFIC;
$ret['channel_w_comment'] = PERMS_SPECIFIC;
$ret['channel_w_mail'] = PERMS_SPECIFIC;
$ret['channel_w_photos'] = PERMS_SPECIFIC;
$ret['channel_w_chat'] = PERMS_SPECIFIC;
$ret['channel_a_delegate'] = PERMS_SPECIFIC;
$ret['channel_r_storage'] = PERMS_PUBLIC;
$ret['channel_w_storage'] = 0;
$ret['channel_w_storage'] = PERMS_SPECIFIC;
$ret['channel_r_pages'] = PERMS_PUBLIC;
$ret['channel_w_pages'] = 0;
$ret['channel_w_pages'] = PERMS_SPECIFIC;
$ret['channel_a_republish'] = PERMS_SPECIFIC;
$ret['channel_w_like'] = PERMS_NETWORK;
@@ -775,7 +775,7 @@ function get_role_perms($role) {
$ret['channel_w_mail'] = PERMS_SPECIFIC;
$ret['channel_w_photos'] = PERMS_SPECIFIC;
$ret['channel_w_chat'] = PERMS_SPECIFIC;
$ret['channel_a_delegate'] = 0;
$ret['channel_a_delegate'] = PERMS_SPECIFIC;
$ret['channel_r_storage'] = PERMS_PUBLIC;
$ret['channel_w_storage'] = PERMS_SPECIFIC;
$ret['channel_r_pages'] = PERMS_PUBLIC;
@@ -800,9 +800,8 @@ function get_role_perms($role) {
}
/**
* @brief Returns a list or roles, grouped by type
* @brief Returns a list or roles, grouped by type.
*
* @param string $current The current role
* @return string Returns an array of roles, grouped by type
*/
function get_roles() {
@@ -811,7 +810,8 @@ function get_roles() {
t('Community Forum') => array('forum' => t('Mostly Public'), 'forum_restricted' => t('Restricted'), 'forum_private' => t('Private')),
t('Feed Republish') => array('feed' => t('Mostly Public'), 'feed_restricted' => t('Restricted')),
t('Special Purpose') => array('soapbox' => t('Celebrity/Soapbox'), 'repository' => t('Group Repository')),
t('Other') => array('custom' => t('Custom/Expert Mode')));
t('Other') => array('custom' => t('Custom/Expert Mode'))
);
return $roles;
}

View File

@@ -241,9 +241,9 @@ abstract class photo_driver {
if((! function_exists('exif_read_data')) || ($this->getType() !== 'image/jpeg'))
return;
$exif = @exif_read_data($filename);
$exif = @exif_read_data($filename,null,true);
if($exif) {
$ort = $exif['Orientation'];
$ort = $exif['IFD0']['Orientation'];
switch($ort)
{
@@ -280,7 +280,14 @@ abstract class photo_driver {
$this->rotate(90);
break;
}
// logger('exif: ' . print_r($exif,true));
return $exif;
}
return false;
}

View File

@@ -1,10 +1,21 @@
<?php /** @file */
<?php
/**
* @file include/photos.php
* @brief Functions related to photo handling.
*/
require_once('include/permissions.php');
require_once('include/items.php');
require_once('include/photo/photo_driver.php');
/**
* @brief
*
* @param array $channel
* @param array $observer
* @param array $args
* @return array
*/
function photo_upload($channel, $observer, $args) {
$ret = array('success' => false);
@@ -18,12 +29,12 @@ function photo_upload($channel, $observer, $args) {
call_hooks('photo_upload_begin', $args);
/**
/*
* Determine the album to use
*/
$album = $args['album'];
$newalbum = $args['newalbum'];
$album = $args['album'];
$newalbum = $args['newalbum'];
logger('photo_upload: album= ' . $album . ' newalbum= ' . $newalbum , LOGGER_DEBUG);
@@ -31,39 +42,20 @@ function photo_upload($channel, $observer, $args) {
if($newalbum)
$album = $newalbum;
else
$album = datetime_convert('UTC',date_default_timezone_get(),'now', 'Y');
$album = datetime_convert('UTC',date_default_timezone_get(),'now', 'Y-m');
}
/**
*
* We create a wall item for every photo, but we don't want to
* overwhelm the data stream with a hundred newly uploaded photos.
* So we will make the first photo uploaded to this album in the last several hours
* visible by default, the rest will become visible over time when and if
* they acquire comments, likes, dislikes, and/or tags
*
*/
$r = q("SELECT * FROM photo WHERE album = '%s' AND uid = %d AND created > %s - INTERVAL %s ",
dbesc($album),
intval($channel_id),
db_utcnow(), db_quoteinterval('3 HOUR')
);
if((! $r) || ($album == t('Profile Photos')))
if(intval($args['visible']) || $args['visible'] === 'true')
$visible = 1;
else
$visible = 0;
if(intval($args['not_visible']) || $args['not_visible'] === 'true')
$visible = 0;
$str_group_allow = perms2str(((is_array($args['group_allow'])) ? $args['group_allow'] : explode(',',$args['group_allow'])));
$str_contact_allow = perms2str(((is_array($args['contact_allow'])) ? $args['contact_allow'] : explode(',',$args['contact_allow'])));
$str_group_deny = perms2str(((is_array($args['group_deny'])) ? $args['group_deny'] : explode(',',$args['group_deny'])));
$str_contact_deny = perms2str(((is_array($args['contact_deny'])) ? $args['contact_deny'] : explode(',',$args['contact_deny'])));
if($args['data']) {
if ($args['data']) {
// allow an import from a binary string representing the image.
// This bypasses the upload step and max size limit checking
@@ -74,23 +66,21 @@ function photo_upload($channel, $observer, $args) {
// this is going to be deleted if it exists
$src = '/tmp/deletemenow';
$type = $args['type'];
}
else {
} else {
$f = array('src' => '', 'filename' => '', 'filesize' => 0, 'type' => '');
call_hooks('photo_upload_file',$f);
if(x($f,'src') && x($f,'filesize')) {
if (x($f,'src') && x($f,'filesize')) {
$src = $f['src'];
$filename = $f['filename'];
$filesize = $f['filesize'];
$type = $f['type'];
}
else {
$src = $_FILES['userfile']['tmp_name'];
$filename = basename($_FILES['userfile']['name']);
$filesize = intval($_FILES['userfile']['size']);
$type = $_FILES['userfile']['type'];
} else {
$src = $_FILES['userfile']['tmp_name'];
$filename = basename($_FILES['userfile']['name']);
$filesize = intval($_FILES['userfile']['size']);
$type = $_FILES['userfile']['type'];
}
if (! $type)
@@ -98,17 +88,16 @@ function photo_upload($channel, $observer, $args) {
logger('photo_upload: received file: ' . $filename . ' as ' . $src . ' ('. $type . ') ' . $filesize . ' bytes', LOGGER_DEBUG);
$maximagesize = get_config('system','maximagesize');
if(($maximagesize) && ($filesize > $maximagesize)) {
if (($maximagesize) && ($filesize > $maximagesize)) {
$ret['message'] = sprintf ( t('Image exceeds website size limit of %lu bytes'), $maximagesize);
@unlink($src);
call_hooks('photo_upload_end',$ret);
return $ret;
}
if(! $filesize) {
if (! $filesize) {
$ret['message'] = t('Image file is empty.');
@unlink($src);
call_hooks('photo_post_end',$ret);
@@ -120,24 +109,22 @@ function photo_upload($channel, $observer, $args) {
$imagedata = @file_get_contents($src);
}
$r = q("select sum(size) as total from photo where aid = %d and scale = 0 ",
intval($account_id)
);
$limit = service_class_fetch($channel_id,'photo_upload_limit');
if(($r) && ($limit !== false) && (($r[0]['total'] + strlen($imagedata)) > $limit)) {
if (($r) && ($limit !== false) && (($r[0]['total'] + strlen($imagedata)) > $limit)) {
$ret['message'] = upgrade_message();
@unlink($src);
call_hooks('photo_post_end',$ret);
return $ret;
}
$ph = photo_factory($imagedata, $type);
if(! $ph->is_valid()) {
if (! $ph->is_valid()) {
$ret['message'] = t('Unable to process image');
logger('photo_upload: unable to process image');
@unlink($src);
@@ -145,13 +132,14 @@ function photo_upload($channel, $observer, $args) {
return $ret;
}
$ph->orient($src);
$exif = $ph->orient($src);
@unlink($src);
$max_length = get_config('system','max_image_length');
if(! $max_length)
if (! $max_length)
$max_length = MAX_IMAGE_LENGTH;
if($max_length > 0)
if ($max_length > 0)
$ph->scaleImage($max_length);
$width = $ph->getWidth();
@@ -162,7 +150,7 @@ function photo_upload($channel, $observer, $args) {
$photo_hash = (($args['resource_id']) ? $args['resource_id'] : photo_new_resource());
$visitor = '';
if($channel['channel_hash'] !== $observer['xchan_hash'])
if ($channel['channel_hash'] !== $observer['xchan_hash'])
$visitor = $observer['xchan_hash'];
$errors = false;
@@ -181,11 +169,10 @@ function photo_upload($channel, $observer, $args) {
if($args['description'])
$p['description'] = $args['description'];
$r1 = $ph->save($p);
if(! $r1)
$errors = true;
if(($width > 640 || $height > 640) && (! $errors)) {
$ph->scaleImage(640);
$p['scale'] = 1;
@@ -204,7 +191,6 @@ function photo_upload($channel, $observer, $args) {
$errors = true;
}
if($errors) {
q("delete from photo where resource_id = '%s' and uid = %d",
dbesc($photo_hash),
@@ -220,17 +206,31 @@ function photo_upload($channel, $observer, $args) {
$width_x_height = $ph->getWidth() . 'x' . $ph->getHeight();
$basename = basename($filename);
$mid = item_message_id();
// Create item container
$item_hidden = (($visible) ? 0 : 1 );
$lat = $lon = null;
if($exif && $exif['GPS']) {
if(feature_enabled($channel_id,'photo_location')) {
$lat = getGps($exif['GPS']['GPSLatitude'], $exif['GPS']['GPSLatitudeRef']);
$lon = getGps($exif['GPS']['GPSLongitude'], $exif['GPS']['GPSLongitudeRef']);
}
}
$title = '';
$mid = item_message_id();
$arr = array();
if($lat && $lon)
$arr['coord'] = $lat . ' ' . $lon;
$arr['aid'] = $account_id;
$arr['uid'] = $channel_id;
$arr['mid'] = $mid;
@@ -249,12 +249,13 @@ function photo_upload($channel, $observer, $args) {
$arr['item_wall'] = 1;
$arr['item_origin'] = 1;
$arr['item_thread_top'] = 1;
$arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $arr['mid'];
// We should also put a width_x_height on large photos. Left as an exercise for
// devs looking fo simple stuff to fix.
$larger = feature_enabled($channel['channel_id'],'large_photos');
$larger = feature_enabled($channel['channel_id'], 'large_photos');
if($larger) {
$tag = '[zmg]';
if($r2)
@@ -269,11 +270,10 @@ function photo_upload($channel, $observer, $args) {
$tag = '[zmg]';
}
$arr['body'] = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash . ']'
. $tag . z_root() . "/photo/{$photo_hash}-{$smallest}.".$ph->getExt() . '[/zmg]'
. '[/zrl]';
$arr['body'] = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash . ']'
. $tag . z_root() . "/photo/{$photo_hash}-{$smallest}.".$ph->getExt() . '[/zmg]'
. '[/zrl]';
$result = item_store($arr);
$item_id = $result['item_id'];
@@ -291,18 +291,26 @@ function photo_upload($channel, $observer, $args) {
return $ret;
}
function photos_albums_list($channel,$observer) {
/**
* @brief Returns a list with all photo albums observer is allowed to see.
*
* Returns an associative array with all albums where observer has permissions.
*
* @param array $channel
* @param array $observer
* @return bool|array false if no view_photos permission or an array
* * success (bool)
* * albums (array)
*/
function photos_albums_list($channel, $observer) {
$channel_id = $channel['channel_id'];
$observer_xchan = (($observer) ? $observer['xchan_hash'] : '');
if(! perm_is_allowed($channel_id,$observer_xchan,'view_photos'))
if(! perm_is_allowed($channel_id, $observer_xchan, 'view_photos'))
return false;
// FIXME - create a permissions SQL which works on arbitrary observers and channels, regardless of login or web status
/** @FIXME create a permissions SQL which works on arbitrary observers and channels, regardless of login or web status */
$sql_extra = permissions_sql($channel_id);
@@ -310,7 +318,6 @@ function photos_albums_list($channel,$observer) {
intval($channel_id),
intval(PHOTO_NORMAL),
intval(PHOTO_PROFILE)
);
// add various encodings to the array so we can just loop through and pick them out in a template
@@ -326,12 +333,13 @@ function photos_albums_list($channel,$observer) {
'total' => $album['total'],
'url' => z_root() . '/photos/' . $channel['channel_address'] . '/album/' . bin2hex($album['album']),
'urlencode' => urlencode($album['album']),
'bin2hex' => bin2hex($album['album']));
'bin2hex' => bin2hex($album['album'])
);
$ret['albums'][] = $entry;
}
}
return $ret;
return $ret;
}
function photos_album_widget($channelx,$observer,$albums = null) {
@@ -359,11 +367,19 @@ function photos_album_widget($channelx,$observer,$albums = null) {
? t('Upload New Photos') : '')
));
}
return $o;
}
function photos_list_photos($channel,$observer,$album = '') {
/**
* @brief
*
* @param array $channel
* @param array $observer
* @param string $album default empty
* @return boolean|array
*/
function photos_list_photos($channel, $observer, $album = '') {
$channel_id = $channel['channel_id'];
$observer_xchan = (($observer) ? $observer['xchan_hash'] : '');
@@ -383,7 +399,7 @@ function photos_list_photos($channel,$observer,$album = '') {
intval(PHOTO_NORMAL),
intval(PHOTO_PROFILE)
);
if($r) {
for($x = 0; $x < count($r); $x ++) {
$r[$x]['src'] = z_root() . '/photo/' . $r[$x]['resource_id'] . '-' . $r[$x]['scale'];
@@ -395,17 +411,33 @@ function photos_list_photos($channel,$observer,$album = '') {
return $ret;
}
function photos_album_exists($channel_id,$album) {
$r = q("SELECT id from photo where album = '%s' and uid = %d limit 1",
/**
* @brief Check if given photo album exists in channel.
*
* @param int $channel_id id of the channel
* @param string $album name of the album
* @return boolean
*/
function photos_album_exists($channel_id, $album) {
$r = q("SELECT id FROM photo WHERE album = '%s' AND uid = %d limit 1",
dbesc($album),
intval($channel_id)
);
return (($r) ? true : false);
}
function photos_album_rename($channel_id,$oldname,$newname) {
/**
* @brief Renames a photo album in a channel.
*
* @todo Do we need to check if new album name already exists?
*
* @param int $channel_id id of the channel
* @param string $oldname The name of the album to rename
* @param string $newname The new name of the album
* @return bool|array
*/
function photos_album_rename($channel_id, $oldname, $newname) {
return q("UPDATE photo SET album = '%s' WHERE album = '%s' AND uid = %d",
dbesc($newname),
dbesc($oldname),
@@ -413,43 +445,58 @@ function photos_album_rename($channel_id,$oldname,$newname) {
);
}
/**
* @brief
*
* @param int $channel_id
* @param string $album
* @param string $remote_xchan
* @return string|boolean
*/
function photos_album_get_db_idstr($channel_id, $album, $remote_xchan = '') {
function photos_album_get_db_idstr($channel_id,$album,$remote_xchan = '') {
if($remote_xchan) {
if ($remote_xchan) {
$r = q("SELECT distinct resource_id as from photo where xchan = '%s' and uid = %d and album = '%s' ",
dbesc($remote_xchan),
intval($channel_id),
dbesc($album)
);
}
else {
} else {
$r = q("SELECT distinct resource_id from photo where uid = %d and album = '%s' ",
intval($channel_id),
dbesc($album)
);
}
if($r) {
if ($r) {
$arr = array();
foreach($r as $rr) {
foreach ($r as $rr) {
$arr[] = "'" . dbesc($rr['resource_id']) . "'" ;
}
$str = implode(',',$arr);
return $str;
}
return false;
return false;
}
/**
* @brief Creates a new photo item.
*
* @param array $channel
* @param string $creator_hash
* @param array $photo
* @param boolean $visible default false
* @return int item_id
*/
function photos_create_item($channel, $creator_hash, $photo, $visible = false) {
// Create item container
$item_hidden = (($visible) ? 0 : 1 );
$title = '';
$mid = item_message_id();
$arr = array();
$arr['aid'] = $channel['channel_account_id'];
@@ -475,9 +522,34 @@ function photos_create_item($channel, $creator_hash, $photo, $visible = false) {
$arr['body'] = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo['resource_id'] . ']'
. '[zmg]' . z_root() . '/photo/' . $photo['resource_id'] . '-' . $photo['scale'] . '[/zmg]'
. '[/zrl]';
$result = item_store($arr);
$item_id = $result['item_id'];
return $item_id;
return $item_id;
}
function getGps($exifCoord, $hemi) {
$degrees = count($exifCoord) > 0 ? gps2Num($exifCoord[0]) : 0;
$minutes = count($exifCoord) > 1 ? gps2Num($exifCoord[1]) : 0;
$seconds = count($exifCoord) > 2 ? gps2Num($exifCoord[2]) : 0;
$flip = ($hemi == 'W' or $hemi == 'S') ? -1 : 1;
return floatval($flip * ($degrees + ($minutes / 60) + ($seconds / 3600)));
}
function gps2Num($coordPart) {
$parts = explode('/', $coordPart);
if (count($parts) <= 0)
return 0;
if (count($parts) == 1)
return $parts[0];
return floatval($parts[0]) / floatval($parts[1]);
}

View File

@@ -7,13 +7,12 @@
require_once("include/smarty.php");
/**
* @brief unloads an addon.
*
* @param string $plugin name of the addon
* @return void
*/
function unload_plugin($plugin){
logger("Addons: unloading " . $plugin, LOGGER_DEBUG);
@@ -28,9 +27,8 @@ function unload_plugin($plugin){
* @brief uninstalls an addon.
*
* @param string $plugin name of the addon
* @return bool
* @return boolean
*/
function uninstall_plugin($plugin) {
unload_plugin($plugin);
@@ -38,7 +36,7 @@ function uninstall_plugin($plugin) {
return false;
logger("Addons: uninstalling " . $plugin);
$t = @filemtime('addon/' . $plugin . '/' . $plugin . '.php');
//$t = @filemtime('addon/' . $plugin . '/' . $plugin . '.php');
@include_once('addon/' . $plugin . '/' . $plugin . '.php');
if(function_exists($plugin . '_uninstall')) {
$func = $plugin . '_uninstall';
@@ -68,9 +66,9 @@ function install_plugin($plugin) {
$func();
}
$plugin_admin = (function_exists($plugin . "_plugin_admin") ? 1 : 0);
$plugin_admin = (function_exists($plugin . '_plugin_admin') ? 1 : 0);
$r = q("INSERT INTO `addon` (`name`, `installed`, `timestamp`, `plugin_admin`) VALUES ( '%s', 1, %d , %d ) ",
q("INSERT INTO `addon` (`name`, `installed`, `timestamp`, `plugin_admin`) VALUES ( '%s', 1, %d , %d ) ",
dbesc($plugin),
intval($t),
$plugin_admin
@@ -91,7 +89,7 @@ function load_plugin($plugin) {
return false;
logger("Addons: loading " . $plugin, LOGGER_DEBUG);
$t = @filemtime('addon/' . $plugin . '/' . $plugin . '.php');
//$t = @filemtime('addon/' . $plugin . '/' . $plugin . '.php');
@include_once('addon/' . $plugin . '/' . $plugin . '.php');
if(function_exists($plugin . '_load')) {
$func = $plugin . '_load';
@@ -120,6 +118,7 @@ function plugin_is_installed($name) {
);
if($r)
return true;
return false;
}
@@ -189,12 +188,13 @@ function register_hook($hook, $file, $function, $priority = 0) {
if(count($r))
return true;
$r = q("INSERT INTO `hook` (`hook`, `file`, `function`, `priority`) VALUES ( '%s', '%s', '%s', '%s' ) ",
$r = q("INSERT INTO `hook` (`hook`, `file`, `function`, `priority`) VALUES ( '%s', '%s', '%s', '%s' )",
dbesc($hook),
dbesc($file),
dbesc($function),
dbesc($priority)
);
return $r;
}
@@ -205,7 +205,7 @@ function register_hook($hook, $file, $function, $priority = 0) {
* @param string $hook the name of the hook
* @param string $file the name of the file that hooks into
* @param string $function the name of the function that the hook called
* @return mixed
* @return array
*/
function unregister_hook($hook, $file, $function) {
$r = q("DELETE FROM hook WHERE hook = '%s' AND `file` = '%s' AND `function` = '%s'",
@@ -213,6 +213,7 @@ function unregister_hook($hook, $file, $function) {
dbesc($file),
dbesc($function)
);
return $r;
}
@@ -228,11 +229,13 @@ function load_hooks() {
$a = get_app();
// if(! is_array($a->hooks))
$a->hooks = array();
$r = q("SELECT * FROM hook WHERE true ORDER BY priority DESC");
if($r) {
foreach($r as $rr) {
if(! array_key_exists($rr['hook'],$a->hooks))
$a->hooks[$rr['hook']] = array();
$a->hooks[$rr['hook']][] = array($rr['file'],$rr['function']);
}
}
@@ -240,8 +243,7 @@ function load_hooks() {
}
/**
*
* @function insert_hook($hook,$fn)
* @brief Inserts a hook into a page request.
*
* Insert a short-lived hook into the running page request.
* Hooks are normally persistent so that they can be called
@@ -252,36 +254,45 @@ function load_hooks() {
* which will not persist beyond the life of this page request
* or the current process.
*
* @param string $hook;
* @param string $hook
* name of hook to attach callback
* @param string $fn;
* @param string $fn
* function name of callback handler
*
*/
function insert_hook($hook,$fn) {
function insert_hook($hook, $fn) {
$a = get_app();
if(! is_array($a->hooks))
$a->hooks = array();
if(! array_key_exists($hook,$a->hooks))
if(! array_key_exists($hook, $a->hooks))
$a->hooks[$hook] = array();
$a->hooks[$hook][] = array('',$fn);
$a->hooks[$hook][] = array('', $fn);
}
/**
* @brief Calls a hook.
*
* Use this function when you want to be able to allow a hook to manipulate
* the provided data.
*
* @param string $name of the hook to call
* @param string|array &$data to transmit to the callback handler
*/
function call_hooks($name, &$data = null) {
$a = get_app();
if((is_array($a->hooks)) && (array_key_exists($name,$a->hooks))) {
if((is_array($a->hooks)) && (array_key_exists($name, $a->hooks))) {
foreach($a->hooks[$name] as $hook) {
if($hook[0])
@include_once($hook[0]);
if(function_exists($hook[1])) {
$func = $hook[1];
$func($a,$data);
}
else {
$func($a, $data);
} else {
// remove orphan hooks
q("delete from hook where hook = '%s' and file = '$s' and function = '%s' limit 1",
q("DELETE FROM hook WHERE hook = '%s' AND file = '%s' AND function = '%s'",
dbesc($name),
dbesc($hook[0]),
dbesc($hook[1])
@@ -293,9 +304,10 @@ function call_hooks($name, &$data = null) {
/**
* @brief parse plugin comment in search of plugin infos.
* @brief Parse plugin comment in search of plugin infos.
*
* like
* \code
* * Name: Plugin
* * Description: A plugin which plugs in
* * Version: 1.2.3
@@ -303,21 +315,23 @@ function call_hooks($name, &$data = null) {
* * Author: Jane <email>
* * Compat: Red [(version)], Friendica [(version)]
* *
*
*\endcode
* @param string $plugin the name of the plugin
* @return array with the plugin information
*/
function get_plugin_info($plugin){
$info = Array(
$m = array();
$info = array(
'name' => $plugin,
'description' => "",
'description' => '',
'author' => array(),
'version' => "",
'compat' => ""
'version' => '',
'compat' => ''
);
if (!is_file("addon/$plugin/$plugin.php")) return $info;
if (!is_file("addon/$plugin/$plugin.php"))
return $info;
$f = file_get_contents("addon/$plugin/$plugin.php");
$r = preg_match("|/\*.*\*/|msU", $f, $m);
@@ -328,7 +342,7 @@ function get_plugin_info($plugin){
if ($l != ""){
list($k, $v) = array_map("trim", explode(":", $l, 2));
$k = strtolower($k);
if ($k == "author"){
if ($k == 'author'){
$r = preg_match("|([^<]+)<([^>]+)>|", $v, $m);
if ($r) {
$info['author'][] = array('name' => $m[1], 'link' => $m[2]);
@@ -343,14 +357,16 @@ function get_plugin_info($plugin){
}
}
}
return $info;
}
/**
* @brief parse theme comment in search of theme infos.
* @brief Parse theme comment in search of theme infos.
*
* like
* \code
* * Name: My Theme
* * Description: My Cool Theme
* * Version: 1.2.3
@@ -358,18 +374,19 @@ function get_plugin_info($plugin){
* * Maintainer: Jane <profile url>
* * Compat: Friendica [(version)], Red [(version)]
* *
*
* \endcode
* @param string $theme the name of the theme
* @return array
*/
function get_theme_info($theme){
$info=Array(
$m = array();
$info = array(
'name' => $theme,
'description' => "",
'description' => '',
'author' => array(),
'version' => "",
'compat' => "",
'credits' => "",
'version' => '',
'compat' => '',
'credits' => '',
'maintainer' => array(),
'experimental' => false,
'unsupported' => false
@@ -377,10 +394,12 @@ function get_theme_info($theme){
if(file_exists("view/theme/$theme/experimental"))
$info['experimental'] = true;
if(file_exists("view/theme/$theme/unsupported"))
$info['unsupported'] = true;
if (!is_file("view/theme/$theme/php/theme.php")) return $info;
if (!is_file("view/theme/$theme/php/theme.php"))
return $info;
$f = file_get_contents("view/theme/$theme/php/theme.php");
$r = preg_match("|/\*.*\*/|msU", $f, $m);
@@ -392,7 +411,7 @@ function get_theme_info($theme){
if ($l != ""){
list($k, $v) = array_map("trim", explode(":", $l, 2));
$k = strtolower($k);
if ($k == "author"){
if ($k == 'author'){
$r = preg_match("|([^<]+)<([^>]+)>|", $v, $m);
if ($r) {
$info['author'][] = array('name' => $m[1], 'link' => $m[2]);
@@ -400,7 +419,7 @@ function get_theme_info($theme){
$info['author'][] = array('name' => $v);
}
}
elseif ($k == "maintainer"){
elseif ($k == 'maintainer'){
$r = preg_match("|([^<]+)<([^>]+)>|", $v, $m);
if ($r) {
$info['maintainer'][] = array('name' => $m[1], 'link' => $m[2]);
@@ -415,10 +434,18 @@ function get_theme_info($theme){
}
}
}
return $info;
}
/**
* @brief Returns the theme's screenshot.
*
* The screenshot is expected as view/theme/$theme/img/screenshot.[png|jpg].
*
* @param sring $theme The name of the theme
* @return string
*/
function get_theme_screenshot($theme) {
$a = get_app();
$exts = array('.png', '.jpg');
@@ -426,16 +453,15 @@ function get_theme_screenshot($theme) {
if(file_exists('view/theme/' . $theme . '/img/screenshot' . $ext))
return($a->get_baseurl() . '/view/theme/' . $theme . '/img/screenshot' . $ext);
}
return($a->get_baseurl() . '/images/blank.png');
}
/**
* @brief add CSS to <head>
* @brief add CSS to \<head\>
*
* @param string $src
* @param string $media change media attribute (default to 'screen')
* @return void
*/
function head_add_css($src, $media = 'screen') {
get_app()->css_sources[] = array($src, $media);
@@ -444,21 +470,23 @@ function head_add_css($src, $media = 'screen') {
function head_remove_css($src, $media = 'screen') {
$a = get_app();
$index = array_search(array($src, $media), $a->css_sources);
if($index !== false)
if ($index !== false)
unset($a->css_sources[$index]);
}
function head_get_css() {
$str = '';
$sources = get_app()->css_sources;
if(count($sources))
foreach($sources as $source)
if (count($sources)) {
foreach ($sources as $source)
$str .= format_css_if_exists($source);
}
return $str;
}
function format_css_if_exists($source) {
if(strpos($source[0],'/') !== false)
if (strpos($source[0], '/') !== false)
$path = $source[0];
else
$path = theme_include($source[0]);
@@ -565,6 +593,7 @@ function theme_include($file, $root = '') {
if(file_exists($p))
return $p;
}
return '';
}

View File

@@ -41,6 +41,12 @@ function poller_run($argv, $argc){
// run queue delivery process in the background
proc_run('php',"include/queue.php");
// maintenance for mod sharedwithme - check for updated items and remove them
require_once('include/sharedwithme.php');
apply_updates();
// expire any expired mail
@@ -81,11 +87,13 @@ function poller_run($argv, $argc){
}
// publish any applicable items that were set to be published in the future
// (time travel posts)
// (time travel posts). Restrict to items that have come of age in the last
// couple of days to limit the query to something reasonable.
$r = q("select id from item where ( item_restrict & %d ) > 0 and created <= %s ",
$r = q("select id from item where ( item_restrict & %d ) > 0 and created <= %s and created > '%s' ",
intval(ITEM_DELAYED_PUBLISH),
db_utcnow()
db_utcnow(),
dbesc(datetime_convert('UTC','UTC','now - 2 days'))
);
if($r) {
foreach($r as $rr) {
@@ -149,6 +157,7 @@ function poller_run($argv, $argc){
call_hooks('cron_weekly',datetime_convert());
z_check_cert();
require_once('include/hubloc.php');
prune_hub_reinstalls();
@@ -164,8 +173,8 @@ function poller_run($argv, $argc){
);
$dirmode = intval(get_config('system','directory_mode'));
if($dirmode == DIRECTORY_MODE_SECONDARY) {
logger('regdir: ' . print_r(z_fetch_url(get_directory_primary() . '/regdir?f=&url=' . z_root() . '&realm=' . get_directory_realm()),true));
if($dirmode === DIRECTORY_MODE_SECONDARY || $dirmode === DIRECTORY_MODE_PRIMARY) {
logger('regdir: ' . print_r(z_fetch_url(get_directory_primary() . '/regdir?f=&url=' . urlencode(z_root()) . '&realm=' . urlencode(get_directory_realm())),true));
}
/**

View File

@@ -39,12 +39,25 @@ function queue_run($argv, $argc){
// so that we don't start off a thousand deliveries for a couple of dead hubs.
// The zot driver will deliver everything destined for a single hub once contact is made (*if* contact is made).
// Other drivers will have to do something different here and may need their own query.
// Note: this requires some tweaking as new posts to long dead hubs once a day will keep them in the
// "every 15 minutes" category. We probably need to prioritise them when inserted into the queue
// or just prior to this query based on recent and long-term delivery history. If we have good reason to believe
// the site is permanently down, there's no reason to attempt delivery at all, or at most not more than once
// or twice a day.
// FIXME: can we sort postgres on outq_priority and maintain the 'distinct' ?
// The order by max(outq_priority) might be a dodgy query because of the group by.
// The desired result is to return a sequence in the order most likely to be delivered in this run.
// If a hub has already been sitting in the queue for a few days, they should be delivered last;
// hence every failure should drop them further down the priority list.
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
$prefix = 'DISTINCT ON (outq_posturl)';
$suffix = 'ORDER BY outq_posturl';
} else {
$prefix = '';
$suffix = 'GROUP BY outq_posturl';
$suffix = 'GROUP BY outq_posturl ORDER BY max(outq_priority)';
}
$r = q("SELECT $prefix * FROM outq WHERE outq_delivered = 0 and (( outq_created > %s - INTERVAL %s and outq_updated < %s - INTERVAL %s ) OR ( outq_updated < %s - INTERVAL %s )) $suffix",
db_utcnow(), db_quoteinterval('12 HOUR'),
@@ -69,7 +82,7 @@ function queue_run($argv, $argc){
}
else {
logger('queue: queue post returned ' . $result['return_code'] . ' from ' . $rr['outq_posturl'],LOGGER_DEBUG);
$y = q("update outq set outq_updated = '%s' where outq_hash = '%s'",
$y = q("update outq set outq_updated = '%s', outq_priority = outq_priority + 10 where outq_hash = '%s'",
dbesc(datetime_convert()),
dbesc($rr['outq_hash'])
);
@@ -78,11 +91,13 @@ function queue_run($argv, $argc){
}
$result = zot_zot($rr['outq_posturl'],$rr['outq_notify']);
if($result['success']) {
logger('queue: deliver zot success to ' . $rr['outq_posturl'], LOGGER_DEBUG);
zot_process_response($rr['outq_posturl'],$result, $rr);
}
else {
$deadguys[] = $rr['outq_posturl'];
$y = q("update outq set outq_updated = '%s' where outq_hash = '%s'",
logger('queue: deliver zot returned ' . $result['return_code'] . ' from ' . $rr['outq_posturl'],LOGGER_DEBUG);
$y = q("update outq set outq_updated = '%s', outq_priority = outq_priority + 10 where outq_hash = '%s'",
dbesc(datetime_convert()),
dbesc($rr['outq_hash'])
);

View File

@@ -76,8 +76,8 @@ function ratenotif_run($argv, $argc){
if($j && $j['success'] && is_array($j['directories'])) {
foreach($j['directories'] as $h) {
// if($h == z_root())
// continue;
if($h == z_root())
continue;
$hash = random_string();
$n = zot_build_packet($channel,'notify',null,null,$hash);
@@ -94,21 +94,21 @@ function ratenotif_run($argv, $argc){
dbesc($n),
dbesc(json_encode($encoded_item))
);
}
$deliver[] = $hash;
if(count($deliver) >= $deliveries_per_process) {
proc_run('php','include/deliver.php',$deliver);
$deliver = array();
if($interval)
@time_sleep_until(microtime(true) + (float) $interval);
}
$deliver[] = $hash;
if(count($deliver) >= $deliveries_per_process) {
proc_run('php','include/deliver.php',$deliver);
$deliver = array();
if($interval)
@time_sleep_until(microtime(true) + (float) $interval);
}
}
// catch any stragglers
if(count($deliver)) {
proc_run('php','include/deliver.php',$deliver);
proc_run('php','include/deliver.php',$deliver);
}
}
}

View File

@@ -22,7 +22,7 @@ function authenticate_success($user_record, $login_initial = false, $interactive
$a->account = $user_record;
$_SESSION['account_id'] = $user_record['account_id'];
$_SESSION['authenticated'] = 1;
if($login_initial || $update_lastlog) {
q("update account set account_lastlog = '%s' where account_id = %d",
dbesc(datetime_convert()),
@@ -150,11 +150,7 @@ function change_channel($change_channel) {
*/
function permissions_sql($owner_id, $remote_verified = false, $groups = null) {
if(defined('STATUSNET_PRIVACY_COMPATIBILITY'))
return '';
$local_channel = local_channel();
$remote_channel = remote_channel();
/**
* Construct permissions
@@ -173,7 +169,7 @@ function permissions_sql($owner_id, $remote_verified = false, $groups = null) {
*/
if(($local_channel) && ($local_channel == $owner_id)) {
$sql = '';
$sql = '';
}
/**
@@ -194,7 +190,7 @@ function permissions_sql($owner_id, $remote_verified = false, $groups = null) {
if(is_array($groups) && count($groups)) {
foreach($groups as $g)
$gs .= '|<' . $g . '>';
}
}
$regexop = db_getfunc('REGEXP');
$sql = sprintf(
" AND ( NOT (deny_cid like '%s' OR deny_gid $regexop '%s')
@@ -223,11 +219,7 @@ function permissions_sql($owner_id, $remote_verified = false, $groups = null) {
*/
function item_permissions_sql($owner_id, $remote_verified = false, $groups = null) {
if(defined('STATUSNET_PRIVACY_COMPATIBILITY'))
return '';
$local_channel = local_channel();
$remote_channel = remote_channel();
/**
* Construct permissions
@@ -246,7 +238,7 @@ function item_permissions_sql($owner_id, $remote_verified = false, $groups = nul
}
/**
* Authenticated visitor. Unless pre-verified,
* Authenticated visitor. Unless pre-verified,
* check that the contact belongs to this $owner_id
* and load the groups the visitor belongs to.
* If pre-verified, the caller is expected to have already
@@ -330,7 +322,7 @@ function public_permissions_sql($observer_hash) {
*/
function get_form_security_token($typename = '') {
$a = get_app();
$timestamp = time();
$sec_hash = hash('whirlpool', $a->user['guid'] . $a->user['prvkey'] . session_id() . $timestamp . $typename);
@@ -340,16 +332,16 @@ function get_form_security_token($typename = '') {
function check_form_security_token($typename = '', $formname = 'form_security_token') {
if (!x($_REQUEST, $formname)) return false;
$hash = $_REQUEST[$formname];
$max_livetime = 10800; // 3 hours
$a = get_app();
$x = explode('.', $hash);
if (time() > (IntVal($x[0]) + $max_livetime)) return false;
$sec_hash = hash('whirlpool', $a->user['guid'] . $a->user['prvkey'] . session_id() . $x[0] . $typename);
return ($sec_hash == $x[1]);
}
@@ -404,20 +396,22 @@ function init_groups_visitor($contact_id) {
// will likely be too expensive.
// Returns a string list of comma separated channel_ids suitable for direct inclusion in a SQL query
function stream_perms_api_uids($perms = NULL ) {
function stream_perms_api_uids($perms = NULL, $limit = 0, $rand = 0 ) {
$perms = is_null($perms) ? (PERMS_SITE|PERMS_NETWORK|PERMS_PUBLIC) : $perms;
$ret = array();
$limit_sql = (($limit) ? " LIMIT " . intval($limit) . " " : '');
$random_sql = (($rand) ? " ORDER BY " . db_getfunc('RAND') . " " : '');
if(local_channel())
$ret[] = local_channel();
$r = q("select channel_id from channel where channel_r_stream > 0 and (channel_r_stream & %d)>0 and not (channel_pageflags & %d)>0",
$r = q("select channel_id from channel where channel_r_stream > 0 and ( channel_r_stream & %d )>0 and ( channel_pageflags & %d ) = 0 $random_sql $limit_sql ",
intval($perms),
intval(PAGE_ADULT|PAGE_CENSORED|PAGE_SYSTEM|PAGE_REMOVED)
);
if($r) {
foreach($r as $rr)
if(! in_array($rr['channel_id'], $ret))
$ret[] = $rr['channel_id'];
$ret[] = $rr['channel_id'];
}
$str = '';
@@ -425,7 +419,7 @@ function stream_perms_api_uids($perms = NULL ) {
foreach($ret as $rr) {
if($str)
$str .= ',';
$str .= intval($rr);
$str .= intval($rr);
}
}
logger('stream_perms_api_uids: ' . $str, LOGGER_DEBUG);
@@ -447,7 +441,7 @@ function stream_perms_xchans($perms = NULL ) {
if($r) {
foreach($r as $rr)
if(! in_array($rr['channel_hash'], $ret))
$ret[] = $rr['channel_hash'];
$ret[] = $rr['channel_hash'];
}
$str = '';
@@ -455,7 +449,7 @@ function stream_perms_xchans($perms = NULL ) {
foreach($ret as $rr) {
if($str)
$str .= ',';
$str .= "'" . dbesc($rr) . "'";
$str .= "'" . dbesc($rr) . "'";
}
}
logger('stream_perms_xchans: ' . $str, LOGGER_DEBUG);

View File

@@ -1,24 +1,29 @@
<?php /** @file */
// Session management functions. These provide database storage of PHP
// session info.
<?php
/**
* @file include/session.php
*
* @brief This file includes session related functions.
*
* Session management functions. These provide database storage of PHP
* session info.
*/
$session_exists = 0;
$session_expire = 180000;
function new_cookie($time) {
$old_sid = session_id();
$old_sid = session_id();
// ??? This shouldn't have any effect if called after session_start()
// We probably need to set the session expiration and change the PHPSESSID cookie.
session_set_cookie_params($time);
session_regenerate_id(false);
session_set_cookie_params($time);
session_regenerate_id(false);
q("UPDATE session SET sid = '%s' WHERE sid = '%s'", dbesc(session_id()), dbesc($old_sid));
q("UPDATE session SET sid = '%s' WHERE sid = '%s'",
dbesc(session_id()),
dbesc($old_sid)
);
if (x($_COOKIE, 'jsAvailable')) {
if ($time) {
@@ -31,62 +36,72 @@ function new_cookie($time) {
}
function ref_session_open ($s,$n) {
return true;
function ref_session_open ($s, $n) {
return true;
}
function ref_session_read ($id) {
global $session_exists;
if(x($id))
$r = q("SELECT `data` FROM `session` WHERE `sid`= '%s'", dbesc($id));
if(count($r)) {
$session_exists = true;
return $r[0]['data'];
}
return '';
global $session_exists;
if(x($id))
$r = q("SELECT `data` FROM `session` WHERE `sid`= '%s'", dbesc($id));
if(count($r)) {
$session_exists = true;
return $r[0]['data'];
}
return '';
}
function ref_session_write ($id,$data) {
global $session_exists, $session_expire;
if(! $id || ! $data) {
return false;
}
function ref_session_write ($id, $data) {
global $session_exists, $session_expire;
$expire = time() + $session_expire;
$default_expire = time() + 300;
if(! $id || ! $data) {
return false;
}
if($session_exists)
$r = q("UPDATE `session`
SET `data` = '%s', `expire` = '%s'
WHERE `sid` = '%s'",
dbesc($data), dbesc($expire), dbesc($id));
else
$r = q("INSERT INTO `session` (sid, expire, data) values ('%s', '%s', '%s')",
//SET `sid` = '%s', `expire` = '%s', `data` = '%s'",
dbesc($id), dbesc($default_expire), dbesc($data));
$expire = time() + $session_expire;
$default_expire = time() + 300;
return true;
if($session_exists) {
q("UPDATE `session`
SET `data` = '%s', `expire` = '%s' WHERE `sid` = '%s'",
dbesc($data),
dbesc($expire),
dbesc($id)
);
} else {
q("INSERT INTO `session` (sid, expire, data) values ('%s', '%s', '%s')",
//SET `sid` = '%s', `expire` = '%s', `data` = '%s'",
dbesc($id),
dbesc($default_expire),
dbesc($data)
);
}
return true;
}
function ref_session_close() {
return true;
return true;
}
function ref_session_destroy ($id) {
q("DELETE FROM `session` WHERE `sid` = '%s'", dbesc($id));
return true;
q("DELETE FROM `session` WHERE `sid` = '%s'", dbesc($id));
return true;
}
function ref_session_gc($expire) {
q("DELETE FROM session WHERE expire < %d", dbesc(time()));
if (! get_config('system','innodb'))
db_optimizetable('session');
return true;
q("DELETE FROM session WHERE expire < %d", dbesc(time()));
if (! get_config('system', 'innodb'))
db_optimizetable('session');
return true;
}
$gc_probability = 50;
@@ -95,5 +110,14 @@ ini_set('session.gc_probability', $gc_probability);
ini_set('session.use_only_cookies', 1);
ini_set('session.cookie_httponly', 1);
session_set_save_handler ('ref_session_open', 'ref_session_close', 'ref_session_read', 'ref_session_write', 'ref_session_destroy', 'ref_session_gc');
/*
* PHP function which sets our user-level session storage functions.
*/
session_set_save_handler(
'ref_session_open',
'ref_session_close',
'ref_session_read',
'ref_session_write',
'ref_session_destroy',
'ref_session_gc'
);

32
include/sharedwithme.php Normal file
View File

@@ -0,0 +1,32 @@
<?php
function apply_updates() {
//check for updated items and remove them
$x = q("SELECT mid, max(object) AS object FROM item WHERE verb = '%s' AND obj_type = '%s' GROUP BY mid",
dbesc(ACTIVITY_UPDATE),
dbesc(ACTIVITY_OBJ_FILE)
);
if($x) {
foreach($x as $xx) {
$object = json_decode($xx['object'],true);
$d_mid = $object['d_mid'];
$u_mid = $xx['mid'];
$y = q("DELETE FROM item WHERE obj_type = '%s' AND (verb = '%s' AND mid = '%s') OR (verb = '%s' AND mid = '%s')",
dbesc(ACTIVITY_OBJ_FILE),
dbesc(ACTIVITY_POST),
dbesc($d_mid),
dbesc(ACTIVITY_UPDATE),
dbesc($u_mid)
);
}
}
}

View File

@@ -3,7 +3,7 @@
require_once('include/dir_fns.php');
require_once('include/zot.php');
/*
/**
* poco_load
*
* xchan is your connection
@@ -21,13 +21,10 @@ require_once('include/zot.php');
* the given uid, cid to the global contact entry. There can be many uid/cid combinations
* pointing to the same global contact id.
*
* @param string $xchan
* @param string $url
*/
function poco_load($xchan = '',$url = null) {
$a = get_app();
function poco_load($xchan = '', $url = null) {
if($xchan && ! $url) {
$r = q("select xchan_connurl from xchan where xchan_hash = '%s' limit 1",
@@ -43,7 +40,6 @@ function poco_load($xchan = '',$url = null) {
return;
}
$url = $url . '?f=&fields=displayName,hash,urls,photos,rating' ;
logger('poco_load: ' . $url, LOGGER_DEBUG);
@@ -148,7 +144,7 @@ function poco_load($xchan = '',$url = null) {
logger('poco_load: missing data');
continue;
}
$x = q("select xchan_hash from xchan where xchan_hash = '%s' limit 1",
dbesc($hash)
);
@@ -182,7 +178,7 @@ function poco_load($xchan = '',$url = null) {
continue;
}
}
$total ++;
@@ -192,19 +188,15 @@ function poco_load($xchan = '',$url = null) {
);
if(! $r) {
q("insert into xlink ( xlink_xchan, xlink_link, xlink_rating, xlink_rating_text, xlink_updated, xlink_static ) values ( '%s', '%s', %d, '%s', '%s', 0 ) ",
q("insert into xlink ( xlink_xchan, xlink_link, xlink_updated, xlink_static ) values ( '%s', '%s', '%s', 0 ) ",
dbesc($xchan),
dbesc($hash),
intval($rating),
dbesc($rating_text),
dbesc(datetime_convert())
);
}
else {
q("update xlink set xlink_updated = '%s', xlink_rating = %d, xlink_rating_text = '%s' where xlink_id = %d",
q("update xlink set xlink_updated = '%s' where xlink_id = %d",
dbesc(datetime_convert()),
intval($rating),
dbesc($rating_text),
intval($r[0]['xlink_id'])
);
}
@@ -216,7 +208,6 @@ function poco_load($xchan = '',$url = null) {
db_utcnow(), db_quoteinterval('2 DAY')
);
}
@@ -253,7 +244,6 @@ function common_friends($uid,$xchan,$start = 0,$limit=100000000,$shuffle = false
);
return $r;
}
@@ -269,8 +259,8 @@ function count_common_friends_zcid($uid,$zcid) {
if(count($r))
return $r[0]['total'];
return 0;
return 0;
}
function common_friends_zcid($uid,$zcid,$start = 0, $limit = 9999,$shuffle = false) {
@@ -292,7 +282,6 @@ function common_friends_zcid($uid,$zcid,$start = 0, $limit = 9999,$shuffle = fal
);
return $r;
}
@@ -307,8 +296,8 @@ function count_all_friends($uid,$cid) {
if(count($r))
return $r[0]['total'];
return 0;
return 0;
}
@@ -377,9 +366,7 @@ function suggestion_query($uid, $myxchan, $start = 0, $limit = 80) {
function update_suggestions() {
$a = get_app();
$dirmode = get_config('system','directory_mode');
$dirmode = get_config('system', 'directory_mode');
if($dirmode === false)
$dirmode = DIRECTORY_MODE_NORMAL;
@@ -393,8 +380,6 @@ function update_suggestions() {
if(! $url)
return;
$ret = z_fetch_url($url);
if($ret['success']) {
@@ -407,7 +392,6 @@ function update_suggestions() {
db_utcnow(), db_quoteinterval('7 DAY')
);
$j = json_decode($ret['body'],true);
if($j && $j['success']) {
foreach($j['entries'] as $host) {
@@ -441,7 +425,6 @@ function poco($a,$extended = false) {
$system_mode = true;
}
$format = (($_REQUEST['format']) ? $_REQUEST['format'] : 'json');
$justme = false;
@@ -456,7 +439,7 @@ function poco($a,$extended = false) {
}
if(argc() > 4 && intval(argv(4)) && $justme == false)
$cid = intval(argv(4));
if(! $system_mode) {
$r = q("SELECT channel_id from channel where channel_address = '%s' limit 1",
@@ -506,8 +489,8 @@ function poco($a,$extended = false) {
$startIndex = intval($_GET['startIndex']);
if(! $startIndex)
$startIndex = 0;
$itemsPerPage = ((x($_GET,'count') && intval($_GET['count'])) ? intval($_GET['count']) : $totalResults);
$itemsPerPage = ((x($_GET,'count') && intval($_GET['count'])) ? intval($_GET['count']) : $totalResults);
if($system_mode) {
$r = q("SELECT abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash where ( abook_flags & " . ABOOK_FLAG_SELF .
@@ -515,8 +498,7 @@ function poco($a,$extended = false) {
intval($itemsPerPage),
intval($startIndex)
);
}
else {
} else {
$r = q("SELECT abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d
$sql_extra LIMIT %d OFFSET %d",
intval($channel_id),
@@ -544,8 +526,7 @@ function poco($a,$extended = false) {
}
}
$ret['entry'] = array();
$ret['entry'] = array();
$fields_ret = array(
'id' => false,
@@ -559,10 +540,10 @@ function poco($a,$extended = false) {
'rating' => false
);
if((! x($_GET,'fields')) || ($_GET['fields'] === '@all'))
if((! x($_GET,'fields')) || ($_GET['fields'] === '@all')) {
foreach($fields_ret as $k => $v)
$fields_ret[$k] = true;
else {
} else {
$fields_req = explode(',',$_GET['fields']);
foreach($fields_req as $f)
$fields_ret[trim($f)] = true;

View File

@@ -38,6 +38,7 @@ function term_query($table,$s,$type = TERM_UNKNOWN) {
function store_item_tag($uid,$iid,$otype,$type,$term,$url = '') {
if(! $term)
return false;
$r = q("select * from term
where uid = %d and oid = %d and otype = %d and type = %d
and term = '%s' and url = '%s' ",
@@ -50,6 +51,7 @@ function store_item_tag($uid,$iid,$otype,$type,$term,$url = '') {
);
if($r)
return false;
$r = q("insert into term (uid, oid, otype, type, term, url)
values( %d, %d, %d, %d, '%s', '%s') ",
intval($uid),
@@ -59,9 +61,11 @@ function store_item_tag($uid,$iid,$otype,$type,$term,$url = '') {
dbesc($term),
dbesc($url)
);
return $r;
}
function get_terms_oftype($arr,$type) {
$ret = array();
if(! (is_array($arr) && count($arr)))
@@ -74,6 +78,7 @@ function get_terms_oftype($arr,$type) {
foreach($arr as $x)
if($x['type'] == $t)
$ret[] = $x;
return $ret;
}
@@ -98,7 +103,12 @@ function format_term_for_display($term) {
function tagadelic($uid, $count = 0, $authors = '', $flags = 0, $restrict = 0, $type = TERM_HASHTAG) {
$sql_options = '';
require_once('include/security.php');
if(! perm_is_allowed($uid,get_observer_hash(),'view_stream'))
return array();
$sql_options = item_permissions_sql($uid);
$count = intval($count);
if($flags) {
@@ -109,6 +119,7 @@ function tagadelic($uid, $count = 0, $authors = '', $flags = 0, $restrict = 0, $
if($authors) {
if(! is_array($authors))
$authors = array($authors);
stringify_array_elms($authors,true);
$sql_options .= " and author_xchan in (" . implode(',',$authors) . ") ";
}
@@ -128,8 +139,8 @@ function tagadelic($uid, $count = 0, $authors = '', $flags = 0, $restrict = 0, $
if(! $r)
return array();
// Find minimum and maximum log-count.
// Find minimum and maximum log-count.
$tags = array();
$min = 1e9;
$max = -1e9;
@@ -149,22 +160,23 @@ function tagadelic($uid, $count = 0, $authors = '', $flags = 0, $restrict = 0, $
$range = max(.01, $max - $min) * 1.0001;
for($x = 0; $x < count($tags); $x ++) {
$tags[$x][2] = 1 + floor(5 * ($tags[$x][1] - $min) / $range);
$tags[$x][2] = 1 + floor(9 * ($tags[$x][1] - $min) / $range);
}
return $tags;
}
function tags_sort($a,$b) {
if(strtolower($a[0]) == strtolower($b[0]))
return 0;
return((strtolower($a[0]) < strtolower($b[0])) ? -1 : 1);
if(strtolower($a[0]) == strtolower($b[0]))
return 0;
return((strtolower($a[0]) < strtolower($b[0])) ? -1 : 1);
}
function dir_tagadelic($count = 0) {
$sql_options = '';
$count = intval($count);
// Fetch tags
@@ -175,8 +187,8 @@ function dir_tagadelic($count = 0) {
if(! $r)
return array();
// Find minimum and maximum log-count.
// Find minimum and maximum log-count.
$tags = array();
$min = 1e9;
$max = -1e9;
@@ -196,7 +208,7 @@ function dir_tagadelic($count = 0) {
$range = max(.01, $max - $min) * 1.0001;
for($x = 0; $x < count($tags); $x ++) {
$tags[$x][2] = 1 + floor(5 * ($tags[$x][1] - $min) / $range);
$tags[$x][2] = 1 + floor(9 * ($tags[$x][1] - $min) / $range);
}
return $tags;
@@ -204,65 +216,71 @@ function dir_tagadelic($count = 0) {
function tagblock($link,$uid,$count = 0,$authors = '',$flags = 0,$restrict = 0,$type = TERM_HASHTAG) {
$o = '';
$tab = 0;
$r = tagadelic($uid,$count,$authors,$flags,$restrict,$type);
$o = '';
if($r) {
$o = '<div class="tagblock widget"><h3>' . t('Tags') . '</h3><div class="tags" align="center">';
foreach($r as $rr) {
$o .= '<span class="tag'.$rr[2].'">#</span><a href="'.$link .'/' . '?f=&tag=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n";
$r = tagadelic($uid,$count,$authors,$flags,$restrict,$type);
if($r) {
$o = '<div class="tagblock widget"><h3>' . t('Tags') . '</h3><div class="tags" align="center">';
foreach($r as $rr) {
$o .= '<span class="tag'.$rr[2].'">#</span><a href="'.$link .'/' . '?f=&tag=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n";
}
$o .= '</div></div>';
}
$o .= '</div></div>';
}
return $o;
}
function wtagblock($uid,$count = 0,$authors = '',$flags = 0,$restrict = 0,$type = TERM_HASHTAG) {
$o = '';
$tab = 0;
$r = tagadelic($uid,$count,$authors,$flags,$restrict,$type);
$o = '';
if($r) {
$c = q("select channel_address from channel where channel_id = %d limit 1",
intval($uid)
);
$r = tagadelic($uid,$count,$authors,$flags,$restrict,$type);
$o = '<div class="tagblock widget"><h3>' . t('Tags') . '</h3><div class="tags" align="center">';
foreach($r as $rr) {
$o .= '<span class="tag' . $rr[2] . '">#</span><a href="channel/' . $c[0]['channel_address'] . '?f=&tag=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n";
if($r) {
$c = q("select channel_address from channel where channel_id = %d limit 1",
intval($uid)
);
$o = '<div class="tagblock widget"><h3>' . t('Tags') . '</h3><div class="tags" align="center">';
foreach($r as $rr) {
$o .= '<span class="tag' . $rr[2] . '">#</span><a href="channel/' . $c[0]['channel_address'] . '?f=&tag=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n";
}
$o .= '</div></div>';
}
$o .= '</div></div>';
}
return $o;
}
function catblock($uid,$count = 0,$authors = '',$flags = 0,$restrict = 0,$type = TERM_CATEGORY) {
$o = '';
$tab = 0;
$o = '';
$r = tagadelic($uid,$count,$authors,$flags,$restrict,$type);
$r = tagadelic($uid,$count,$authors,$flags,$restrict,$type);
if($r) {
$c = q("select channel_address from channel where channel_id = %d limit 1",
intval($uid)
);
$o = '<div class="tagblock widget"><h3>' . t('Categories') . '</h3><div class="tags" align="center">';
foreach($r as $rr) {
$o .= '<a href="channel/' . $c[0]['channel_address']. '?f=&cat=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n";
if($r) {
$c = q("select channel_address from channel where channel_id = %d limit 1",
intval($uid)
);
$o = '<div class="tagblock widget"><h3>' . t('Categories') . '</h3><div class="tags" align="center">';
foreach($r as $rr) {
$o .= '<a href="channel/' . $c[0]['channel_address']. '?f=&cat=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n";
}
$o .= '</div></div>';
}
$o .= '</div></div>';
}
return $o;
}
function dir_tagblock($link,$r) {
$o = '';
$tab = 0;
$observer = get_observer_hash();
if(! get_globaldir_setting($observer))
return $o;
if(! $r)
$r = get_app()->data['directory_keywords'];
@@ -274,14 +292,12 @@ function dir_tagblock($link,$r) {
}
$o .= '</div></div>';
}
return $o;
}
/**
* verbs: [0] = first person singular, e.g. "I want", [1] = 3rd person singular, e.g. "Bill wants"
* We use the first person form when creating an activity, but the third person for use in activities
@@ -289,8 +305,6 @@ function dir_tagblock($link,$r) {
* require obj_verbs() to provide full conjugations and specify which form to use in the $_REQUEST params to this module.
*/
function obj_verbs() {
$verbs = array(
'has' => array( t('have'), t('has')),
@@ -301,26 +315,27 @@ function obj_verbs() {
$arr = array('verbs' => $verbs);
call_hooks('obj_verbs', $arr);
return $arr['verbs'];
}
function obj_verb_selector($current = '') {
$verbs = obj_verbs();
$o .= '<select class="obj-verb-selector" name="verb" >';
$o = '<select class="obj-verb-selector" name="verb">';
foreach($verbs as $k => $v) {
$selected = (($k == $current) ? ' selected="selected" ' : '');
$o .= '<option value="' . urlencode($k) . '"' . $selected . '>' . $v[1] . '</option>';
}
$o .= '</select>';
return $o;
return $o;
}
function get_things($profile_hash,$uid) {
$sql_extra = (($profile_hash) ? " and obj_page = '" . $profile_hash . "' " : '');
$r = q("select * from obj left join term on obj_obj = term_hash where term_hash != '' and uid = %d and obj_type = %d $sql_extra order by obj_verb, term",
intval($uid),
intval(TERM_OBJ_THING)
@@ -376,11 +391,11 @@ function get_things($profile_hash,$uid) {
for($x = 0; $x < count($l); $x ++)
$l[$x]['xchan_url'] = zid($l[$x]['xchan_url']);
if(! $things[$rr['obj_verb']])
$things[$rr['obj_verb']] = array();
$things[$rr['obj_verb']][] = array('term' => $rr['term'],'url' => $rr['url'],'img' => $rr['imgurl'], 'profile' => $rr['profile_name'],'term_hash' => $rr['term_hash'], 'likes' => $l,'like_count' => count($l),'like_label' => tt('Like','Likes',count($l),'noun'));
$things[$rr['obj_verb']][] = array('term' => $rr['term'],'url' => $rr['url'],'img' => $rr['imgurl'], 'profile' => $rr['profile_name'],'term_hash' => $rr['term_hash'], 'likes' => $l,'like_count' => count($l),'like_label' => tt('Like','Likes',count($l),'noun'));
}
$sorted_things = array();
if($things) {
@@ -392,6 +407,6 @@ function get_things($profile_hash,$uid) {
}
}
//logger('things: ' . print_r($sorted_things,true));
return $sorted_things;
return $sorted_things;
}

View File

@@ -1,305 +1,307 @@
<?php
require_once 'include/ITemplateEngine.php';
require_once 'include/ITemplateEngine.php';
define ("KEY_NOT_EXISTS", '^R_key_not_Exists^');
define ("KEY_NOT_EXISTS", '^R_key_not_Exists^');
class Template implements ITemplateEngine {
static $name ="internal";
var $r;
var $search;
var $replace;
var $stack = array();
var $nodes = array();
var $done = false;
var $d = false;
var $lang = null;
var $debug=false;
private function _preg_error(){
switch(preg_last_error()){
case PREG_INTERNAL_ERROR: echo('PREG_INTERNAL_ERROR'); break;
case PREG_BACKTRACK_LIMIT_ERROR: echo('PREG_BACKTRACK_LIMIT_ERROR'); break;
case PREG_RECURSION_LIMIT_ERROR: echo('PREG_RECURSION_LIMIT_ERROR'); break;
case PREG_BAD_UTF8_ERROR: echo('PREG_BAD_UTF8_ERROR'); break;
class Template implements ITemplateEngine {
static $name ="internal";
var $r;
var $search;
var $replace;
var $stack = array();
var $nodes = array();
var $done = false;
var $d = false;
var $lang = null;
var $debug=false;
private function _preg_error() {
switch(preg_last_error()) {
case PREG_INTERNAL_ERROR: echo('PREG_INTERNAL_ERROR'); break;
case PREG_BACKTRACK_LIMIT_ERROR: echo('PREG_BACKTRACK_LIMIT_ERROR'); break;
case PREG_RECURSION_LIMIT_ERROR: echo('PREG_RECURSION_LIMIT_ERROR'); break;
case PREG_BAD_UTF8_ERROR: echo('PREG_BAD_UTF8_ERROR'); break;
// This is only valid for php > 5.3, not certain how to code around it for unit tests
// case PREG_BAD_UTF8_OFFSET_ERROR: echo('PREG_BAD_UTF8_OFFSET_ERROR'); break;
default:
//die("Unknown preg error.");
return;
}
echo "<hr><pre>";
debug_print_backtrace();
die();
// case PREG_BAD_UTF8_OFFSET_ERROR: echo('PREG_BAD_UTF8_OFFSET_ERROR'); break;
default:
//die("Unknown preg error.");
return;
}
private function _push_stack(){
$this->stack[] = array($this->r, $this->nodes);
}
private function _pop_stack(){
list($this->r, $this->nodes) = array_pop($this->stack);
}
private function _get_var($name, $retNoKey=false){
$keys = array_map('trim',explode(".",$name));
if ($retNoKey && !array_key_exists($keys[0], $this->r)) return KEY_NOT_EXISTS;
$val = $this->r;
foreach($keys as $k) {
$val = (isset($val[$k]) ? $val[$k] : null);
}
return template_escape($val);
}
/**
* IF node
*
* {{ if <$var> }}...[{{ else }} ...] {{ endif }}
* {{ if <$var>==<val|$var> }}...[{{ else }} ...]{{ endif }}
* {{ if <$var>!=<val|$var> }}...[{{ else }} ...]{{ endif }}
*/
private function _replcb_if($args){
if (strpos($args[2],"==")>0){
list($a,$b) = array_map("trim",explode("==",$args[2]));
$a = $this->_get_var($a);
if ($b[0]=="$") $b = $this->_get_var($b);
$val = ($a == $b);
} else if (strpos($args[2],"!=")>0){
list($a,$b) = array_map("trim", explode("!=",$args[2]));
$a = $this->_get_var($a);
if ($b[0]=="$") $b = $this->_get_var($b);
$val = ($a != $b);
} else {
$val = $this->_get_var($args[2]);
}
$x = preg_split("|{{ *else *}}|", $args[3]);
return ( ($val) ? $x[0] : (isset($x[1]) ? $x[1] : ""));
}
/**
* FOR node
*
* {{ for <$var> as $name }}...{{ endfor }}
* {{ for <$var> as $key=>$name }}...{{ endfor }}
*/
private function _replcb_for($args){
$m = array_map('trim', explode(" as ", $args[2]));
$x = explode("=>",$m[1]);
if (count($x) == 1) {
$varname = $x[0];
$keyname = "";
} else {
list($keyname, $varname) = $x;
}
if ($m[0]=="" || $varname=="" || is_null($varname)) die("template error: 'for ".$m[0]." as ".$varname."'") ;
//$vals = $this->r[$m[0]];
$vals = $this->_get_var($m[0]);
$ret="";
if (!is_array($vals)) return $ret;
foreach ($vals as $k=>$v){
$this->_push_stack();
$r = $this->r;
$r[$varname] = $v;
if ($keyname!='') $r[$keyname] = (($k === 0) ? '0' : $k);
$ret .= $this->replace($args[3], $r);
$this->_pop_stack();
}
return $ret;
echo "<hr><pre>";
debug_print_backtrace();
die();
}
private function _push_stack() {
$this->stack[] = array($this->r, $this->nodes);
}
private function _pop_stack(){
list($this->r, $this->nodes) = array_pop($this->stack);
}
private function _get_var($name, $retNoKey=false) {
$keys = array_map('trim',explode(".",$name));
if ($retNoKey && !array_key_exists($keys[0], $this->r))
return KEY_NOT_EXISTS;
$val = $this->r;
foreach($keys as $k) {
$val = (isset($val[$k]) ? $val[$k] : null);
}
/**
* INC node
*
* {{ inc <templatefile> [with $var1=$var2] }}{{ endinc }}
*/
private function _replcb_inc($args){
if (strpos($args[2],"with")) {
list($tplfile, $newctx) = array_map('trim', explode("with",$args[2]));
} else {
$tplfile = trim($args[2]);
$newctx = null;
}
if ($tplfile[0]=="$") $tplfile = $this->_get_var($tplfile);
return template_escape($val);
}
/**
* IF node
* \code
* {{ if <$var> }}...[{{ else }} ...] {{ endif }}
* {{ if <$var>==<val|$var> }}...[{{ else }} ...]{{ endif }}
* {{ if <$var>!=<val|$var> }}...[{{ else }} ...]{{ endif }}
* \endcode
*/
private function _replcb_if($args) {
if (strpos($args[2],"==")>0){
list($a,$b) = array_map("trim",explode("==",$args[2]));
$a = $this->_get_var($a);
if ($b[0]=="$") $b = $this->_get_var($b);
$val = ($a == $b);
} else if (strpos($args[2],"!=")>0){
list($a,$b) = array_map("trim", explode("!=",$args[2]));
$a = $this->_get_var($a);
if ($b[0]=="$") $b = $this->_get_var($b);
$val = ($a != $b);
} else {
$val = $this->_get_var($args[2]);
}
$x = preg_split("|{{ *else *}}|", $args[3]);
return ( ($val) ? $x[0] : (isset($x[1]) ? $x[1] : ""));
}
/**
* FOR node
* \code
* {{ for <$var> as $name }}...{{ endfor }}
* {{ for <$var> as $key=>$name }}...{{ endfor }}
* \endcode
*/
private function _replcb_for($args) {
$m = array_map('trim', explode(" as ", $args[2]));
$x = explode("=>",$m[1]);
if (count($x) == 1) {
$varname = $x[0];
$keyname = "";
} else {
list($keyname, $varname) = $x;
}
if ($m[0]=="" || $varname=="" || is_null($varname)) die("template error: 'for ".$m[0]." as ".$varname."'") ;
//$vals = $this->r[$m[0]];
$vals = $this->_get_var($m[0]);
$ret="";
if (!is_array($vals)) return $ret;
foreach ($vals as $k=>$v){
$this->_push_stack();
$r = $this->r;
if (!is_null($newctx)) {
list($a,$b) = array_map('trim', explode("=",$newctx));
$r[$a] = $this->_get_var($b);
}
$this->nodes = Array();
$tpl = get_markup_template($tplfile);
$ret = $this->replace($tpl, $r);
$r[$varname] = $v;
if ($keyname!='') $r[$keyname] = (($k === 0) ? '0' : $k);
$ret .= $this->replace($args[3], $r);
$this->_pop_stack();
return $ret;
}
/**
* DEBUG node
*
* {{ debug $var [$var [$var [...]]] }}{{ enddebug }}
*
* replace node with <pre>var_dump($var, $var, ...);</pre>
return $ret;
}
/**
* INC node
* \code
* {{ inc <templatefile> [with $var1=$var2] }}{{ endinc }}
* \endcode
*/
private function _replcb_inc($args) {
if (strpos($args[2],"with")) {
list($tplfile, $newctx) = array_map('trim', explode("with",$args[2]));
} else {
$tplfile = trim($args[2]);
$newctx = null;
}
if ($tplfile[0]=="$") $tplfile = $this->_get_var($tplfile);
$this->_push_stack();
$r = $this->r;
if (!is_null($newctx)) {
list($a,$b) = array_map('trim', explode("=",$newctx));
$r[$a] = $this->_get_var($b);
}
$this->nodes = Array();
$tpl = get_markup_template($tplfile);
$ret = $this->replace($tpl, $r);
$this->_pop_stack();
return $ret;
}
/**
* DEBUG node
* \code
* {{ debug $var [$var [$var [...]]] }}{{ enddebug }}
* \endcode
* replace node with <pre>var_dump($var, $var, ...);</pre>
*/
private function _replcb_debug($args) {
$vars = array_map('trim', explode(" ",$args[2]));
$vars[] = $args[1];
$ret = "<pre>";
foreach ($vars as $var){
$ret .= htmlspecialchars(var_export( $this->_get_var($var), true ));
$ret .= "\n";
}
$ret .= "</pre>";
return $ret;
}
private function _replcb_node($m) {
$node = $this->nodes[$m[1]];
if (method_exists($this, "_replcb_".$node[1])){
$s = call_user_func(array($this, "_replcb_".$node[1]), $node);
} else {
$s = "";
}
$s = preg_replace_callback('/\|\|([0-9]+)\|\|/', array($this, "_replcb_node"), $s);
return $s;
}
private function _replcb($m) {
//var_dump(array_map('htmlspecialchars', $m));
$this->done = false;
$this->nodes[] = (array) $m;
return "||". (count($this->nodes)-1) ."||";
}
private function _build_nodes($s) {
$this->done = false;
while (!$this->done) {
$this->done=true;
$s = preg_replace_callback('|{{ *([a-z]*) *([^}]*)}}([^{]*({{ *else *}}[^{]*)?){{ *end\1 *}}|', array($this, "_replcb"), $s);
if ($s==Null) $this->_preg_error();
}
//({{ *else *}}[^{]*)?
krsort($this->nodes);
return $s;
}
private function var_replace($s) {
$m = array();
/** regexp:
* \$ literal $
* (\[)? optional open square bracket
* ([a-zA-Z0-9-_]+\.?)+ var name, followed by optional
* dot, repeated at least 1 time
* (?(1)\]) if there was opened square bracket
* (subgrup 1), match close bracket
*/
private function _replcb_debug($args){
$vars = array_map('trim', explode(" ",$args[2]));
$vars[] = $args[1];
$ret = "<pre>";
foreach ($vars as $var){
$ret .= htmlspecialchars(var_export( $this->_get_var($var), true ));
$ret .= "\n";
}
$ret .= "</pre>";
return $ret;
}
private function _replcb_node($m) {
$node = $this->nodes[$m[1]];
if (method_exists($this, "_replcb_".$node[1])){
$s = call_user_func(array($this, "_replcb_".$node[1]), $node);
} else {
$s = "";
}
$s = preg_replace_callback('/\|\|([0-9]+)\|\|/', array($this, "_replcb_node"), $s);
return $s;
}
private function _replcb($m){
//var_dump(array_map('htmlspecialchars', $m));
$this->done = false;
$this->nodes[] = (array) $m;
return "||". (count($this->nodes)-1) ."||";
}
private function _build_nodes($s){
$this->done = false;
while (!$this->done){
$this->done=true;
$s = preg_replace_callback('|{{ *([a-z]*) *([^}]*)}}([^{]*({{ *else *}}[^{]*)?){{ *end\1 *}}|', array($this, "_replcb"), $s);
if ($s==Null) $this->_preg_error();
}
//({{ *else *}}[^{]*)?
krsort($this->nodes);
return $s;
}
private function var_replace($s){
$m = array();
/** regexp:
* \$ literal $
* (\[)? optional open square bracket
* ([a-zA-Z0-9-_]+\.?)+ var name, followed by optional
* dot, repeated at least 1 time
* (?(1)\]) if there was opened square bracket
* (subgrup 1), match close bracket
*/
if (preg_match_all('/\$(\[)?([a-zA-Z0-9-_]+\.?)+(?(1)\])/', $s,$m)){
foreach($m[0] as $var){
$exp = str_replace(array("[", "]"), array("", ""), $var);
$exptks = explode("|", $exp);
$varn = $exptks[0];
unset($exptks[0]);
$val = $this->_get_var($varn, true);
if ($val != KEY_NOT_EXISTS) {
/* run filters */
/*
* Filter are in form of:
* filtername:arg:arg:arg
*
* "filtername" is function name
* "arg"s are optional, var value is appended to the end
* if one "arg"==='x' , is replaced with var value
*
* examples:
* $item.body|htmlspecialchars // escape html chars
* $item.body|htmlspecialchars|strtoupper // escape html and uppercase result
* $item.created|date:%Y %M %j // format date (created is a timestamp)
* $item.body|str_replace:cat:dog // replace all "cat" with "dog"
* $item.body|str_replace:cat:dog:x:1 // replace one "cat" with "dog"
*/
foreach ($exptks as $filterstr) {
$filter = explode(":", $filterstr);
$filtername = $filter[0];
unset($filter[0]);
$valkey = array_search("x", $filter);
if ($valkey === false) {
$filter[] = $val;
} else {
$filter[$valkey] = $val;
}
if (function_exists($filtername)) {
$val = call_user_func_array($filtername, $filter);
}
}
$s = str_replace($var, $val, $s);
if (preg_match_all('/\$(\[)?([a-zA-Z0-9-_]+\.?)+(?(1)\])/', $s,$m)) {
foreach ($m[0] as $var) {
$exp = str_replace(array("[", "]"), array("", ""), $var);
$exptks = explode("|", $exp);
$varn = $exptks[0];
unset($exptks[0]);
$val = $this->_get_var($varn, true);
if ($val != KEY_NOT_EXISTS) {
/* run filters */
/*
* Filter are in form of:
* filtername:arg:arg:arg
*
* "filtername" is function name
* "arg"s are optional, var value is appended to the end
* if one "arg"==='x' , is replaced with var value
*
* examples:
* $item.body|htmlspecialchars // escape html chars
* $item.body|htmlspecialchars|strtoupper // escape html and uppercase result
* $item.created|date:%Y %M %j // format date (created is a timestamp)
* $item.body|str_replace:cat:dog // replace all "cat" with "dog"
* $item.body|str_replace:cat:dog:x:1 // replace one "cat" with "dog"
*/
foreach ($exptks as $filterstr) {
$filter = explode(":", $filterstr);
$filtername = $filter[0];
unset($filter[0]);
$valkey = array_search("x", $filter);
if ($valkey === false) {
$filter[] = $val;
} else {
$filter[$valkey] = $val;
}
if (function_exists($filtername)) {
$val = call_user_func_array($filtername, $filter);
}
}
$s = str_replace($var, $val, $s);
}
}
return $s;
}
private function replace($s,$r) {
$this->replace_macros($s, $r);
}
// TemplateEngine interface
public function replace_macros($s, $r) {
$this->r = $r;
$s = $this->_build_nodes($s);
$s = preg_replace_callback('/\|\|([0-9]+)\|\|/', array($this, "_replcb_node"), $s);
if ($s==Null) $this->_preg_error();
// remove comments block
$s = preg_replace('/{#[^#]*#}/', "" , $s);
$t2 = dba_timer();
// replace strings recursively (limit to 10 loops)
$os = ""; $count=0;
while(($os !== $s) && $count<10){
$os=$s; $count++;
$s = $this->var_replace($s);
}
return $s;
}
public function get_markup_template($file, $root='') {
$template_file = theme_include($file, $root);
if ($template_file) {
$content = file_get_contents($template_file);
}
return $content;
}
return $s;
}
private function replace($s, $r) {
$this->replace_macros($s, $r);
}
// TemplateEngine interface
public function replace_macros($s, $r) {
$this->r = $r;
$s = $this->_build_nodes($s);
$s = preg_replace_callback('/\|\|([0-9]+)\|\|/', array($this, "_replcb_node"), $s);
if ($s == Null)
$this->_preg_error();
// remove comments block
$s = preg_replace('/{#[^#]*#}/', "" , $s);
//$t2 = dba_timer();
// replace strings recursively (limit to 10 loops)
$os = "";
$count=0;
while (($os !== $s) && $count<10) {
$os=$s;
$count++;
$s = $this->var_replace($s);
}
return $s;
}
public function get_markup_template($file, $root='') {
$template_file = theme_include($file, $root);
if ($template_file) {
$content = file_get_contents($template_file);
}
return $content;
}
}
function template_escape($s) {
return str_replace(array('$','{{'),array('!_Doll^Ars1Az_!','!_DoubLe^BraceS4Rw_!'),$s);
}
function template_unescape($s) {
return str_replace(array('!_Doll^Ars1Az_!','!_DoubLe^BraceS4Rw_!'),array('$','{{'),$s);
}

File diff suppressed because it is too large Load Diff

View File

@@ -233,7 +233,6 @@ function widget_savedsearch($arr) {
$srchurl = rtrim(preg_replace('/searchsave\=[^\&].*?(\&|$)/is','',$srchurl),'&');
$hasq = ((strpos($srchurl,'?') !== false) ? true : false);
$srchurl = rtrim(preg_replace('/searchremove\=[^\&].*?(\&|$)/is','',$srchurl),'&');
$hasq = ((strpos($srchurl,'?') !== false) ? true : false);
$srchurl = rtrim(preg_replace('/search\=[^\&].*?(\&|$)/is','',$srchurl),'&');
$srchurl = rtrim(preg_replace('/submit\=[^\&].*?(\&|$)/is','',$srchurl),'&');
@@ -241,7 +240,10 @@ function widget_savedsearch($arr) {
$hasq = ((strpos($srchurl,'?') !== false) ? true : false);
$hasamp = ((strpos($srchurl,'&') !== false) ? true : false);
if(($hasamp) && (! $hasq))
$srchurl = substr($srchurl,0,strpos($srchurl,'&')) . '?f=&' . substr($srchurl,strpos($srchurl,'&')+1);
$o = '';
@@ -257,8 +259,8 @@ function widget_savedsearch($arr) {
$saved[] = array(
'id' => $rr['tid'],
'term' => $rr['term'],
'dellink' => z_root() . '/' . $srchurl . (($hasq) ? '' : '?f=') . '&amp;searchremove=1&amp;search=' . urlencode($rr['term']),
'srchlink' => z_root() . '/' . $srchurl . (($hasq) ? '' : '?f=') . '&amp;search=' . urlencode($rr['term']),
'dellink' => z_root() . '/' . $srchurl . (($hasq || $hasamp) ? '' : '?f=') . '&amp;searchremove=1&amp;search=' . urlencode($rr['term']),
'srchlink' => z_root() . '/' . $srchurl . (($hasq || $hasamp) ? '' : '?f=') . '&amp;search=' . urlencode($rr['term']),
'displayterm' => htmlspecialchars($rr['term'], ENT_COMPAT,'UTF-8'),
'encodedterm' => urlencode($rr['term']),
'delete' => t('Remove term'),
@@ -418,18 +420,35 @@ function widget_affinity($arr) {
$cmin = ((x($_REQUEST,'cmin')) ? intval($_REQUEST['cmin']) : 0);
$cmax = ((x($_REQUEST,'cmax')) ? intval($_REQUEST['cmax']) : 99);
if(feature_enabled(local_channel(),'affinity')) {
$labels = array(
t('Me'),
t('Family'),
t('Friends'),
t('Acquaintances'),
t('All')
);
call_hooks('affinity_labels',$labels);
$label_str = '';
if($labels) {
foreach($labels as $l) {
if($label_str) {
$label_str .= ", '|'";
$label_str .= ", '" . $l . "'";
}
else
$label_str .= "'" . $l . "'";
}
}
$tpl = get_markup_template('main_slider.tpl');
$x = replace_macros($tpl,array(
'$val' => $cmin . ',' . $cmax,
'$refresh' => t('Refresh'),
'$me' => t('Me'),
'$intimate' => t('Best Friends'),
'$friends' => t('Friends'),
'$coworkers' => t('Co-workers'),
'$oldfriends' => t('Former Friends'),
'$acquaintances' => t('Acquaintances'),
'$world' => t('Everybody')
'$labels' => $label_str,
));
$arr = array('html' => $x);
call_hooks('main_slider',$arr);
@@ -605,9 +624,6 @@ function widget_vcard($arr) {
* The following directory widgets are only useful on the directory page
*/
function widget_dirsafemode($arr) {
return dir_safe_mode();
}
function widget_dirsort($arr) {
return dir_sort_links();
@@ -963,3 +979,12 @@ function widget_rating($arr) {
return $o;
}
// used by site ratings pages to provide a return link
function widget_pubsites() {
if(get_app()->poi)
return;
return '<div class="widget"><ul class="nav nav-pills"><li><a href="pubsites">' . t('Public Hubs') . '</a></li></ul></div>';
}

File diff suppressed because it is too large Load Diff