aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/Contact.php19
-rw-r--r--include/ItemObject.php19
-rw-r--r--include/account.php5
-rw-r--r--include/acl_selectors.php2
-rw-r--r--include/activities.php2
-rw-r--r--include/api.php58
-rw-r--r--include/attach.php221
-rw-r--r--include/auth.php17
-rw-r--r--include/bbcode.php198
-rw-r--r--include/bookmarks.php55
-rw-r--r--include/chat.php182
-rw-r--r--include/config.php8
-rw-r--r--include/contact_widgets.php3
-rw-r--r--include/conversation.php91
-rw-r--r--include/crypto.php4
-rw-r--r--include/deliver.php1
-rw-r--r--include/dir_fns.php11
-rw-r--r--include/enotify.php13
-rw-r--r--include/event.php22
-rw-r--r--include/features.php11
-rw-r--r--include/group.php28
-rw-r--r--include/identity.php186
-rwxr-xr-xinclude/items.php263
-rw-r--r--include/menu.php71
-rw-r--r--include/nav.php14
-rw-r--r--include/network.php10
-rw-r--r--include/notifier.php24
-rwxr-xr-xinclude/oembed.php31
-rw-r--r--include/permissions.php3
-rw-r--r--include/photo/photo_driver.php56
-rw-r--r--include/photos.php37
-rwxr-xr-xinclude/plugin.php42
-rw-r--r--include/reddav.php1015
-rw-r--r--include/security.php94
-rw-r--r--include/session.php9
-rw-r--r--include/spam.php35
-rw-r--r--include/taxonomy.php95
-rwxr-xr-xinclude/text.php146
-rw-r--r--include/widgets.php296
-rw-r--r--include/zot.php71
40 files changed, 2822 insertions, 646 deletions
diff --git a/include/Contact.php b/include/Contact.php
index 5725e06f0..fd450033c 100644
--- a/include/Contact.php
+++ b/include/Contact.php
@@ -77,6 +77,23 @@ function vcard_from_xchan($xchan, $observer = null, $mode = '') {
$a = get_app();
+ if(! $xchan) {
+ if($a->poi) {
+ $xchan = $a->poi;
+ }
+ elseif($a->profile['channel_hash']) {
+ $r = q("select * from xchan where xchan_hash = '%s' limit 1",
+ dbesc($a->profile['channel_hash'])
+ );
+ if($r)
+ $xchan = $r[0];
+ }
+ }
+
+ if(! $xchan)
+ return;
+
+// FIXME - show connect button to observer if appropriate
$connect = false;
if(local_user()) {
$r = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
@@ -238,7 +255,7 @@ function channel_remove($channel_id, $local = true) {
}
- q("DELETE FROM `group` WHERE `uid` = %d", intval($channel_id));
+ q("DELETE FROM `groups` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `group_member` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `event` WHERE `uid` = %d", intval($channel_id));
q("DELETE FROM `item` WHERE `uid` = %d", intval($channel_id));
diff --git a/include/ItemObject.php b/include/ItemObject.php
index 6088a2c1c..9b1a6fbcd 100644
--- a/include/ItemObject.php
+++ b/include/ItemObject.php
@@ -10,6 +10,7 @@ require_once('boot.php');
/**
* An item
*/
+
class Item extends BaseObject {
public $data = array();
private $template = 'conv_item.tpl';
@@ -170,6 +171,15 @@ class Item extends BaseObject {
);
}
+ $has_bookmarks = false;
+ if(is_array($item['term'])) {
+ foreach($item['term'] as $t) {
+ if($t['type'] == TERM_BOOKMARK)
+ $has_bookmarks = true;
+ }
+ }
+
+
if($this->is_commentable()) {
$like = array( t("I like this \x28toggle\x29"), t("like"));
$dislike = array( t("I don't like this \x28toggle\x29"), t("dislike"));
@@ -217,6 +227,7 @@ class Item extends BaseObject {
'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')) : ''),
+ 'expiretime' => (($item['expires'] !== '0000-00-00 00:00:00') ? sprintf( t('Expires: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['expires'], 'r')):''),
'lock' => $lock,
'verified' => $verified,
'unverified' => $unverified,
@@ -230,11 +241,12 @@ class Item extends BaseObject {
'like' => $like,
'dislike' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike : ''),
'share' => $share,
- 'plink' => get_plink($item,$mode),
+ 'plink' => get_plink($item),
'edpost' => ((feature_enabled($conv->get_profile_owner(),'edit_posts')) ? $edpost : ''),
'star' => ((feature_enabled($conv->get_profile_owner(),'star_posts')) ? $star : ''),
'tagger' => ((feature_enabled($conv->get_profile_owner(),'commtag')) ? $tagger : ''),
'filer' => ((feature_enabled($conv->get_profile_owner(),'filing')) ? $filer : ''),
+ 'bookmark' => (($conv->get_profile_owner() == local_user() && $has_bookmarks) ? t('Bookmark Links') : ''),
'drop' => $drop,
'multidrop' => ((feature_enabled($conv->get_profile_owner(),'multi_delete')) ? $multidrop : ''),
// end toolbar buttons
@@ -457,6 +469,11 @@ class Item extends BaseObject {
return $this->template;
}
+
+ private function set_template($t) {
+ $this->template = $t;
+ }
+
/**
* Check if this is a toplevel post
*/
diff --git a/include/account.php b/include/account.php
index ab442ab39..7d1aa598d 100644
--- a/include/account.php
+++ b/include/account.php
@@ -111,6 +111,7 @@ function create_account($arr) {
$expires = ((x($arr,'expires')) ? intval($arr['expires']) : '0000-00-00 00:00:00');
$default_service_class = get_config('system','default_service_class');
+
if($default_service_class === false)
$default_service_class = '';
@@ -382,11 +383,11 @@ function user_deny($hash) {
if(! count($register))
return false;
- $user = q("SELECT account_id FROM account WHERE account_id = %d LIMIT 1",
+ $account = q("SELECT account_id FROM account WHERE account_id = %d LIMIT 1",
intval($register[0]['uid'])
);
- if(! $user)
+ if(! $account)
return false;
$r = q("DELETE FROM account WHERE account_id = %d LIMIT 1",
diff --git a/include/acl_selectors.php b/include/acl_selectors.php
index 930f9967a..749ca75eb 100644
--- a/include/acl_selectors.php
+++ b/include/acl_selectors.php
@@ -14,7 +14,7 @@ function group_select($selname,$selclass,$preselected = false,$size = 4) {
$o .= "<select name=\"{$selname}[]\" id=\"$selclass\" class=\"$selclass\" multiple=\"multiple\" size=\"$size\" >\r\n";
- $r = q("SELECT * FROM `group` WHERE `deleted` = 0 AND `uid` = %d ORDER BY `name` ASC",
+ $r = q("SELECT * FROM `groups` WHERE `deleted` = 0 AND `uid` = %d ORDER BY `name` ASC",
intval(local_user())
);
diff --git a/include/activities.php b/include/activities.php
index 73180eae0..4502b758e 100644
--- a/include/activities.php
+++ b/include/activities.php
@@ -24,6 +24,8 @@ function profile_activity($changed, $value) {
$arr['item_flags'] = ITEM_WALL|ITEM_ORIGIN|ITEM_THREAD_TOP;
$arr['verb'] = ACTIVITY_UPDATE;
$arr['obj_type'] = ACTIVITY_OBJ_PROFILE;
+
+ $arr['$plink'] = z_root() . '/channel/' . $self['channel_address'] . '/?f=&mid=' . $arr['mid'];
$A = '[url=' . z_root() . '/channel/' . $self['channel_address'] . ']' . $self['channel_name'] . '[/url]';
diff --git a/include/api.php b/include/api.php
index 093839875..dc270167b 100644
--- a/include/api.php
+++ b/include/api.php
@@ -7,6 +7,7 @@ require_once("oauth.php");
require_once("html2plain.php");
require_once('include/security.php');
require_once('include/photos.php');
+require_once('include/items.php');
/*
*
@@ -362,7 +363,8 @@ require_once('include/photos.php');
'location' => ($usr) ? $usr[0]['channel_location'] : '',
'profile_image_url' => $uinfo[0]['xchan_photo_l'],
'url' => $uinfo[0]['xchan_url'],
- 'contact_url' => $a->get_baseurl()."/connections/".$uinfo[0]['abook_id'],
+//FIXME
+ 'contact_url' => $a->get_baseurl() . "/connections/".$uinfo[0]['abook_id'],
'protected' => false,
'friends_count' => intval($countfriends),
'created_at' => api_date($uinfo[0]['abook_created']),
@@ -555,7 +557,7 @@ require_once('include/photos.php');
function api_photos(&$a,$type) {
$album = $_REQUEST['album'];
- json_return_and_die(photos_list_photos($a->get_channel(),$a->get_observer()),$album);
+ json_return_and_die(photos_list_photos($a->get_channel(),$a->get_observer(),$album));
}
api_register_func('api/red/photos','api_photos', true);
@@ -1241,27 +1243,43 @@ require_once('include/photos.php');
$sql_extra = '';
if ($user_info['self']==1) $sql_extra .= " AND `item`.`wall` = 1 ";
+
+//FIXME - this isn't yet implemented
if ($exclude_replies > 0) $sql_extra .= ' AND `item`.`parent` = `item`.`id`';
- $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`.`contact-id` = %d
- AND `item`.`visible` = 1 and `item`.`moderated` = 0 AND `item`.`deleted` = 0
- AND `contact`.`id` = `item`.`contact-id`
- AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
- $sql_extra
- AND `item`.`id`>%d
- ORDER BY `item`.`received` DESC LIMIT %d ,%d ",
- intval(api_user()),
- intval($user_info['id']),
- intval($since_id),
- intval($start), intval($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`.`contact-id` = %d
+// AND `item`.`visible` = 1 and `item`.`moderated` = 0 AND `item`.`deleted` = 0
+// AND `contact`.`id` = `item`.`contact-id`
+// AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
+// $sql_extra
+// AND `item`.`id`>%d
+// ORDER BY `item`.`received` DESC LIMIT %d ,%d ",
+// intval(api_user()),
+// intval($user_info['id']),
+// intval($since_id),
+// intval($start), intval($count)
+// );
+
+ $arr = array(
+ 'uid' => api_user(),
+ 'since_id' => $since_id,
+ 'start' => $start,
+ 'records' => $count);
+
+ if ($user_info['self']==1)
+ $arr['wall'] = 1;
+ else
+ $arr['cid'] = $user_info['id'];
+
+ $r = items_fetch($arr,get_app()->get_channel(),get_observer_hash());
+
$ret = api_format_items($r,$user_info);
diff --git a/include/attach.php b/include/attach.php
index 0c748cba6..af1159957 100644
--- a/include/attach.php
+++ b/include/attach.php
@@ -26,6 +26,7 @@ function z_mime_content_type($filename) {
'xml' => 'application/xml',
'swf' => 'application/x-shockwave-flash',
'flv' => 'video/x-flv',
+ 'epub' => 'application/epub+zip',
// images
'png' => 'image/png',
@@ -79,17 +80,12 @@ function z_mime_content_type($filename) {
if (array_key_exists($ext, $mime_types)) {
return $mime_types[$ext];
}
+
+
}
-// can't use this because we're just passing a name, e.g. not a file that can be opened
-// elseif (function_exists('finfo_open')) {
-// $finfo = @finfo_open(FILEINFO_MIME);
-// $mimetype = @finfo_file($finfo, $filename);
-// @finfo_close($finfo);
-// return $mimetype;
-// }
- else {
- return 'application/octet-stream';
- }
+
+ return 'application/octet-stream';
+
}
@@ -193,13 +189,13 @@ function attach_by_hash($hash,$rev = 0) {
$sql_extra = permissions_sql($r[0]['uid']);
// Now we'll see if we can access the attachment
-dbg(1);
+
$r = q("SELECT * FROM attach WHERE hash = '%s' and uid = %d $sql_extra LIMIT 1",
dbesc($hash),
intval($r[0]['uid'])
);
-dbg(0);
+
if(! $r) {
$ret['message'] = t('Permission denied.');
return $ret;
@@ -242,7 +238,7 @@ function attach_by_hash_nodata($hash,$rev = 0) {
// Now we'll see if we can access the attachment
- $r = q("select id, aid, uid, hash, filename, filetype, filesize, revision, folder, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where uid = %d and hash = '%s' $sql_extra limit 1",
+ $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 uid = %d and hash = '%s' $sql_extra limit 1",
intval($r[0]['uid']),
dbesc($hash)
);
@@ -334,9 +330,10 @@ function attach_store($channel,$observer_hash,$options = '',$arr = null) {
}
$limit = service_class_fetch($channel_id,'attach_upload_limit');
+
if($limit !== false) {
- $r = q("select sum(filesize) as total from attach where uid = %d ",
- intval($channel_id)
+ $r = q("select sum(filesize) as total from attach where aid = %d ",
+ intval($channel['channel_account_id'])
);
if(($r) && (($r[0]['total'] + $filesize) > ($limit - $existing_size))) {
$ret['message'] = upgrade_message(true).sprintf(t("You have reached your limit of %1$.0f Mbytes attachment storage."),$limit / 1024000);
@@ -363,11 +360,12 @@ function attach_store($channel,$observer_hash,$options = '',$arr = null) {
);
}
elseif($options === 'revise') {
- $r = q("insert into attach ( aid, uid, hash, filename, filetype, filesize, revision, data, created, edited, allow_cid, allow_gid, deny_cid, deny_gid )
- VALUES ( %d, %d, '%s', '%s', '%s', %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
+ $r = q("insert into attach ( aid, uid, hash, creator, filename, filetype, filesize, revision, data, created, edited, allow_cid, allow_gid, deny_cid, deny_gid )
+ VALUES ( %d, %d, '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
intval($x[0]['aid']),
intval($channel_id),
dbesc($x[0]['hash']),
+ dbesc(get_observer_hash()),
dbesc($filename),
dbesc($mimetype),
intval($filesize),
@@ -398,11 +396,12 @@ function attach_store($channel,$observer_hash,$options = '',$arr = null) {
}
else {
- $r = q("INSERT INTO attach ( aid, uid, hash, filename, filetype, filesize, revision, data, created, edited, allow_cid, allow_gid,deny_cid, deny_gid )
- VALUES ( %d, %d, '%s', '%s', '%s', %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
+ $r = q("INSERT INTO attach ( aid, uid, hash, creator, filename, filetype, filesize, revision, data, created, edited, allow_cid, allow_gid,deny_cid, deny_gid )
+ VALUES ( %d, %d, '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
intval($channel['channel_account_id']),
intval($channel_id),
dbesc($hash),
+ dbesc(get_observer_hash()),
dbesc($filename),
dbesc($mimetype),
intval($filesize),
@@ -427,7 +426,7 @@ function attach_store($channel,$observer_hash,$options = '',$arr = null) {
// Caution: This re-uses $sql_options set further above
- $r = q("select id, aid, uid, hash, filename, filetype, filesize, revision, folder, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where uid = %d and hash = '%s' $sql_options limit 1",
+ $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 uid = %d and hash = '%s' $sql_options limit 1",
intval($channel_id),
dbesc($hash)
);
@@ -487,7 +486,7 @@ function z_readdir($channel_id,$observer_hash,$pathname, $parent_hash = '') {
else
$paths = array($pathname);
- $r = q("select id, aid, uid, hash, 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 ) " . permissions_sql($channel_id),
+ $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 ) " . permissions_sql($channel_id),
intval($channel_id),
dbesc($parent_hash),
dbesc($paths[0]),
@@ -531,11 +530,14 @@ function attach_mkdir($channel,$observer_hash,$arr = null) {
$sql_options = '';
$basepath = 'store/' . $channel['channel_address'];
+
+ logger('attach_mkdir: basepath: ' . $basepath);
+
if(! is_dir($basepath))
- @mkdir($basepath,STORAGE_DEFAULT_PERMISSIONS,true);
+ mkdir($basepath,STORAGE_DEFAULT_PERMISSIONS,true);
- if(! perm_is_allowed($channel_id, get_observer_hash(),'write_storage')) {
+ if(! perm_is_allowed($channel_id, $observer_hash,'write_storage')) {
$ret['message'] = t('Permission denied.');
return $ret;
}
@@ -571,16 +573,19 @@ function attach_mkdir($channel,$observer_hash,$arr = null) {
$lpath = '';
$lfile = $arr['folder'];
- $sql_options = permissions_sql($channel);
+ $sql_options = permissions_sql($channel['channel_id']);
do {
+
$r = q("select filename, hash, flags, folder from attach where uid = %d and hash = '%s' and ( flags & %d )
$sql_options limit 1",
intval($channel['channel_id']),
dbesc($lfile),
intval(ATTACH_FLAG_DIR)
);
+
if(! $r) {
+ logger('attach_mkdir: hash ' . $lfile . ' not found in ' . $lpath);
$ret['message'] = t('Path not found.');
return $ret;
}
@@ -598,28 +603,29 @@ function attach_mkdir($channel,$observer_hash,$arr = null) {
$created = datetime_convert();
- $r = q("INSERT INTO attach ( aid, uid, hash, filename, filetype, filesize, revision, folder, flags, data, created, edited, allow_cid, allow_gid, deny_cid, deny_gid )
- VALUES ( %d, %d, '%s', '%s', '%s', %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
+ $r = q("INSERT INTO attach ( aid, uid, hash, creator, filename, filetype, filesize, revision, folder, flags, data, created, edited, allow_cid, allow_gid, deny_cid, deny_gid )
+ VALUES ( %d, %d, '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
intval($channel['channel_account_id']),
intval($channel_id),
dbesc($arr['hash']),
+ dbesc(get_observer_hash()),
dbesc($arr['filename']),
dbesc('multipart/mixed'),
intval(0),
intval(0),
dbesc($arr['folder']),
- intval(ATTACH_FLAG_DIR),
- dbesc(''),
+ intval(ATTACH_FLAG_DIR|ATTACH_FLAG_OS),
+ dbesc($path),
dbesc($created),
dbesc($created),
- dbesc(($arr && array_key_exists('allow_cid',$arr)) ? $arr['allow_cid'] : ''),
- dbesc(($arr && array_key_exists('allow_gid',$arr)) ? $arr['allow_gid'] : ''),
- dbesc(($arr && array_key_exists('deny_cid',$arr)) ? $arr['deny_cid'] : ''),
- dbesc(($arr && array_key_exists('deny_gid',$arr)) ? $arr['deny_gid'] : '')
+ dbesc(($arr && array_key_exists('allow_cid',$arr)) ? $arr['allow_cid'] : $channel['channel_allow_cid']),
+ dbesc(($arr && array_key_exists('allow_gid',$arr)) ? $arr['allow_gid'] : $channel['channel_allow_gid']),
+ dbesc(($arr && array_key_exists('deny_cid',$arr)) ? $arr['deny_cid'] : $channel['channel_deny_cid']),
+ dbesc(($arr && array_key_exists('deny_gid',$arr)) ? $arr['deny_gid'] : $channel['channel_deny_gid'])
);
if($r) {
- if(mkdir($path,STORAGE_DEFAULT_PERMISSIONS)) {
+ if(mkdir($path,STORAGE_DEFAULT_PERMISSIONS,true)) {
$ret['success'] = true;
$ret['data'] = $arr;
}
@@ -633,4 +639,153 @@ function attach_mkdir($channel,$observer_hash,$arr = null) {
return $ret;
+}
+
+
+
+function attach_change_permissions($channel_id,$resource,$allow_cid,$allow_gid,$deny_cid,$deny_gid,$recurse = false) {
+
+ $r = q("select hash, flags from attach where hash = '%s' and uid = %d limit 1",
+ dbesc($resource),
+ intval($channel_id)
+ );
+
+ if(! $r)
+ return;
+
+ if($r[0]['flags'] & ATTACH_FLAG_DIR) {
+ if($recurse) {
+ $r = q("select hash, flags from attach where folder = '%s' and uid = %d",
+ dbesc($resource),
+ intval($channel_id)
+ );
+ if($r) {
+ foreach($r as $rr) {
+ attach_change_permissions($channel_id,$resource,$allow_cid,$allow_gid,$deny_cid,$deny_gid,$recurse);
+ }
+ }
+ }
+ }
+
+ $x = q("update attach set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' where hash = '%s' and uid = %d limit 1",
+ dbesc($allow_cid),
+ dbesc($allow_gid),
+ dbesc($deny_cid),
+ dbesc($deny_gid),
+ dbesc($resource),
+ intval($channel_id)
+ );
+
+ return;
+}
+
+
+
+function attach_delete($channel_id,$resource) {
+
+
+ $c = q("select channel_address from channel where channel_id = %d limit 1",
+ intval($channel_id)
+ );
+
+ $channel_address = (($c) ? $c[0]['channel_address'] : 'notfound');
+
+ $r = q("select hash, flags from attach where hash = '%s' and uid = %d limit 1",
+ dbesc($resource),
+ intval($channel_id)
+ );
+
+
+ if(! $r)
+ return;
+
+ if($r[0]['flags'] & ATTACH_FLAG_DIR) {
+ $x = q("select hash, flags from attach where folder = '%s' and uid = %d",
+ dbesc($resource),
+ intval($channel_id)
+ );
+ if($x) {
+ foreach($x as $xx) {
+ attach_delete($channel_id,$xx['hash']);
+ }
+ }
+ }
+ if($r[0]['flags'] & ATTACH_FLAG_OS) {
+ $y = q("select data from attach where hash = '%s' and uid = %d limit 1",
+ dbesc($resource),
+ intval($channel_id)
+ );
+
+ if($y) {
+ $f = 'store/' . $channel_address . '/' . $y[0]['data'];
+ if(is_dir($f))
+ @rmdir($f);
+ elseif(file_exists($f))
+ unlink($f);
+ }
+ }
+
+ $z = q("delete from attach where hash = '%s' and uid = %d limit 1",
+ dbesc($resource),
+ intval($channel_id)
+ );
+
+ return;
+}
+
+
+
+function get_cloudpath($arr) {
+
+ $basepath = 'cloud/';
+ if($arr['uid']) {
+ $r = q("select channel_address from channel where channel_id = %d limit 1",
+ intval($arr['uid'])
+ );
+ if($r)
+ $basepath .= $r[0]['channel_address'] . '/';
+ }
+
+
+ $path = $basepath;
+
+ if($arr['folder']) {
+
+ $lpath = '';
+ $lfile = $arr['folder'];
+
+ do {
+ $r = q("select filename, hash, flags, folder from attach where uid = %d and hash = '%s' and ( flags & %d )
+ limit 1",
+ intval($arr['uid']),
+ dbesc($lfile),
+ intval(ATTACH_FLAG_DIR)
+ );
+
+ if(! $r)
+ break;
+
+ if($lfile)
+ $lpath = $r[0]['filename'] . '/' . $lpath;
+ $lfile = $r[0]['folder'];
+
+ } while ( ($r[0]['folder']) && ($r[0]['flags'] & ATTACH_FLAG_DIR)) ;
+
+ $path .= $lpath;
+
+ }
+
+ $path .= $arr['filename'];
+ return $path;
+
+}
+
+
+
+
+function pipe_streams($in, $out) {
+ $size = 0;
+ while (!feof($in))
+ $size += fwrite($out,fread($in,8192));
+ return $size;
} \ No newline at end of file
diff --git a/include/auth.php b/include/auth.php
index c0002e6c1..a92f998bf 100644
--- a/include/auth.php
+++ b/include/auth.php
@@ -34,6 +34,7 @@ function nuke_session() {
*/
function account_verify_password($email,$pass) {
+
$r = q("select * from account where account_email = '%s'",
dbesc($email)
);
@@ -46,7 +47,13 @@ function account_verify_password($email,$pass) {
return $record;
}
}
- logger('password failed for ' . $email);
+ $error = 'password failed for ' . $email;
+ logger($error);
+ // Also log failed logins to a separate auth log to reduce overhead for server side intrusion prevention
+ $authlog = get_config('system', 'authlog');
+ if ($authlog)
+ @file_put_contents($authlog, datetime_convert() . ':' . session_id() . ' ' . $error . "\n", FILE_APPEND);
+
return null;
}
@@ -186,7 +193,13 @@ else {
}
if((! $record) || (! count($record))) {
- logger('authenticate: failed login attempt: ' . notags(trim($_POST['username'])) . ' from IP ' . $_SERVER['REMOTE_ADDR']);
+ $error = 'authenticate: failed login attempt: ' . notags(trim($_POST['username'])) . ' from IP ' . $_SERVER['REMOTE_ADDR'];
+ logger($error);
+ // Also log failed logins to a separate auth log to reduce overhead for server side intrusion prevention
+ $authlog = get_config('system', 'authlog');
+ if ($authlog)
+ @file_put_contents($authlog, datetime_convert() . ':' . session_id() . ' ' . $error . "\n", FILE_APPEND);
+
notice( t('Login failed.') . EOL );
goaway(z_root());
}
diff --git a/include/bbcode.php b/include/bbcode.php
index 271cace73..bd2c7d11a 100644
--- a/include/bbcode.php
+++ b/include/bbcode.php
@@ -16,6 +16,40 @@ function tryoembed($match) {
return $html;
}
+function tryzrlaudio($match) {
+
+ $link = $match[1];
+ $m = @parse_url($link);
+ $zrl = false;
+ if($m['host']) {
+ $r = q("select hubloc_url from hubloc where hubloc_host = '%s' limit 1",
+ dbesc($m['host'])
+ );
+ if($r)
+ $zrl = true;
+ }
+ if($zrl)
+ $link = zid($link);
+ return '<audio src="' . $link . '" controls="controls" ><a href="' . $link . '">' . $link . '</a></audio>';
+}
+
+function tryzrlvideo($match) {
+ $link = $match[1];
+ $m = @parse_url($link);
+ $zrl = false;
+ if($m['host']) {
+ $r = q("select hubloc_url from hubloc where hubloc_host = '%s' limit 1",
+ dbesc($m['host'])
+ );
+ if($r)
+ $zrl = true;
+ }
+ if($zrl)
+ $link = zid($link);
+ return '<video src="' . $link . '" controls="controls" width="' . get_app()->videowidth . '" height="' . $a->videoheight . '"><a href="' . $link . '">' . $link . '</a></video>';
+
+}
+
// [noparse][i]italic[/i][/noparse] turns into
// [noparse][ i ]italic[ /i ][/noparse],
// to hide them from parser.
@@ -105,21 +139,24 @@ function bb_parse_crypt($match) {
$attributes = $match[1];
$algorithm = "";
+
preg_match("/alg='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
- $algorithm = html_entity_decode($matches[1],ENT_QUOTES,'UTF-8');
+ $algorithm = $matches[1];
preg_match("/alg=\&quot\;(.*?)\&quot\;/ism", $attributes, $matches);
if ($matches[1] != "")
- $algorithm = html_entity_decode($matches[1],ENT_QUOTES,'UTF-8');
+ $algorithm = $matches[1];
$hint = "";
+
+
preg_match("/hint='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
- $hint = html_entity_decode($matches[1],ENT_QUOTES,'UTF-8');
+ $hint = $matches[1];
preg_match("/hint=\&quot\;(.*?)\&quot\;/ism", $attributes, $matches);
if ($matches[1] != "")
- $hint = html_entity_decode($matches[1],ENT_QUOTES,'UTF-8');
+ $hint = $matches[1];
$x = random_string();
@@ -129,6 +166,9 @@ function bb_parse_crypt($match) {
}
+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) {
@@ -183,6 +223,10 @@ function bb_ShareAttributes($match) {
return($text);
}
+function bb_location($match) {
+ // not yet implemented
+}
+
function bb_ShareAttributesSimple($match) {
$attributes = $match[1];
@@ -218,6 +262,56 @@ function rpost_callback($match) {
}
}
+function bb_sanitize_style($input) {
+ //whitelist 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,
+ // text properties
+ "text-decoration" => 0,
+
+ );
+
+ $css_string = $input[1];
+ $a = explode(';',$css_string);
+ foreach($a as $parts){
+ list($k, $v) = explode(':', $parts);
+ $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);
+
+ foreach($css as $key => $value) {
+ if($w[$key] != null) {
+ foreach($w[$key] as $limit_key => $limit_value) {
+ //sanitize values
+ 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) {
+ return $limit_value . $limit_key;
+ } else {
+ return $match[1] . $limit_key;
+ }
+ },
+ $value
+ );
+ }
+ }
+ }
+ $css_string_san .= $key . ":" . $value ."; ";
+ }
+ 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
@@ -250,6 +344,11 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
$Text = preg_replace_callback("/\[pre\](.*?)\[\/pre\]/ism", 'bb_spacefy',$Text);
}
+// Not yet implemented - thinking this should display a map or perhaps be a map directive
+// if (strpos($Text,'[location]') !== false) {
+// $Text = preg_replace_callback("/\[location\](.*?)\[\/location\]/ism", 'bb_location',$Text);
+// }
+
// If we find any event code, turn it into an event.
@@ -260,6 +359,7 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
// process [observer] tags before we do anything else because we might
// be stripping away stuff that then doesn't need to be worked on anymore
+
$observer = $a->get_observer();
if ((strpos($Text,'[/observer]') !== false) || (strpos($Text,'[/rpost]') !== false)) {
if ($observer) {
@@ -273,6 +373,9 @@ 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
@@ -325,6 +428,12 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
if (strpos($Text,'http') !== false) {
$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);
+ }
+
+
if (strpos($Text,'[/share]') !== false) {
$Text = preg_replace_callback("/\[share(.*?)\](.*?)\[\/share\]/ism","bb_ShareAttributes",$Text);
}
@@ -383,14 +492,6 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
// Check for list text
$Text = str_replace("[*]", "<li>", $Text);
- // Check for style sheet commands
- if (strpos($Text,'[/style]') !== false) {
- $Text = preg_replace("(\[style=(.*?)\](.*?)\[\/style\])ism","<span style=\"$1;\">$2</span>",$Text);
- }
- // Check for CSS classes
- if (strpos($Text,'[/class]') !== false) {
- $Text = preg_replace("(\[class=(.*?)\](.*?)\[\/class\])ism","<span class=\"$1\">$2</span>",$Text);
- }
// handle nested lists
$endlessloop = 0;
@@ -418,7 +519,7 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
if (strpos($Text,'[tr]') !== false) {
$Text = preg_replace("/\[tr\](.*?)\[\/tr\]/sm", '<tr>$1</tr>' ,$Text);
}
- if (strpos($Text,'[table]') !== false) {
+ 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);
@@ -480,36 +581,74 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
"<br /><strong class=".'"author"'.">" . $t_wrote . "</strong><blockquote>$2</blockquote>",
$Text);
- // [img=widthxheight]image source[/img]
- //$Text = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '<img src="$3" style="height: $2px; width: $1px;" >', $Text);
- if (strpos($Text,'[/img]') !== false) {
- $Text = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '<img src="$3" style="width: $1px;" >', $Text);
- }
- if (strpos($Text,'[/zmg]') !== false) {
- $Text = preg_replace("/\[zmg\=([0-9]*)x([0-9]*)\](.*?)\[\/zmg\]/ism", '<img class="zrl" src="$3" style="width: $1px;" >', $Text);
- }
// Images
// [img]pathtoimage[/img]
- if (strpos($Text,'[/img]') !== false) {
+ if (strpos($Text,'[/img]') !== false) {
$Text = preg_replace("/\[img\](.*?)\[\/img\]/ism", '<img src="$1" alt="' . t('Image/photo') . '" />', $Text);
}
- if (strpos($Text,'[/zmg]') !== false) {
+ if (strpos($Text,'[/zmg]') !== false) {
$Text = preg_replace("/\[zmg\](.*?)\[\/zmg\]/ism", '<img class="zrl" src="$1" alt="' . t('Image/photo') . '" />', $Text);
}
+ // [img float={left, right}]pathtoimage[/img]
+ if (strpos($Text,'[/img]') !== false) {
+ $Text = preg_replace("/\[img float=left\](.*?)\[\/img\]/ism", '<img src="$1" style="float: left;" alt="' . t('Image/photo') . '" />', $Text);
+ }
+ if (strpos($Text,'[/img]') !== false) {
+ $Text = preg_replace("/\[img float=right\](.*?)\[\/img\]/ism", '<img src="$1" style="float: right;" alt="' . t('Image/photo') . '" />', $Text);
+ }
+ if (strpos($Text,'[/zmg]') !== false) {
+ $Text = preg_replace("/\[zmg float=left\](.*?)\[\/zmg\]/ism", '<img class="zrl" src="$1" style="float: left;" alt="' . t('Image/photo') . '" />', $Text);
+ }
+ if (strpos($Text,'[/zmg]') !== false) {
+ $Text = preg_replace("/\[zmg float=right\](.*?)\[\/zmg\]/ism", '<img class="zrl" src="$1" style="float: right;" alt="' . t('Image/photo') . '" />', $Text);
+ }
+
+ // [img=widthxheight]pathtoimage[/img]
+ if (strpos($Text,'[/img]') !== false) {
+ $Text = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '<img src="$3" style="width: $1px;" alt="' . t('Image/photo') . '" >', $Text);
+ }
+ if (strpos($Text,'[/zmg]') !== false) {
+ $Text = preg_replace("/\[zmg\=([0-9]*)x([0-9]*)\](.*?)\[\/zmg\]/ism", '<img class="zrl" src="$3" style="width: $1px;" alt="' . t('Image/photo') . '" >', $Text);
+ }
+
+ // [img=widthxheight float={left, right}]pathtoimage[/img]
+ if (strpos($Text,'[/img]') !== false) {
+ $Text = preg_replace("/\[img\=([0-9]*)x([0-9]*) float=left\](.*?)\[\/img\]/ism", '<img src="$3" style="width: $1px; float: left;" alt="' . t('Image/photo') . '" >', $Text);
+ }
+ if (strpos($Text,'[/img]') !== false) {
+ $Text = preg_replace("/\[img\=([0-9]*)x([0-9]*) float=right\](.*?)\[\/img\]/ism", '<img src="$3" style="width: $1px; float: right;" alt="' . t('Image/photo') . '" >', $Text);
+ }
+ if (strpos($Text,'[/zmg]') !== false) {
+ $Text = preg_replace("/\[zmg\=([0-9]*)x([0-9]*) float=left\](.*?)\[\/zmg\]/ism", '<img class="zrl" src="$3" style="width: $1px; float: left;" alt="' . t('Image/photo') . '" >', $Text);
+ }
+ if (strpos($Text,'[/zmg]') !== false) {
+ $Text = preg_replace("/\[zmg\=([0-9]*)x([0-9]*) float=right\](.*?)\[\/zmg\]/ism", '<img class="zrl" src="$3" style="width: $1px; float: right;" alt="' . t('Image/photo') . '" >', $Text);
+ }
+
+ // style (sanitized)
+ if (strpos($Text,'[/style]') !== false) {
+ $Text = preg_replace_callback("(\[style=(.*?)\](.*?)\[\/style\])ism", "bb_sanitize_style", $Text);
+ }
+
+ // crypt
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_callback("/\[crypt (.*?)\](.*?)\[\/crypt\]/ism", 'bb_parse_crypt', $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,'[/audio]') !== false) {
+ $Text = preg_replace_callback("/\[audio\](.*?\.(ogg|ogv|oga|ogm|webm|mp4|mp3))\[\/audio\]/ism", 'tryzrlaudio', $Text);
+ }
+
// Try to Oembed
if ($tryoembed) {
- if (strpos($Text,'[/video]') !== false) {
- $Text = preg_replace("/\[video\](.*?\.(ogg|ogv|oga|ogm|webm|mp4))\[\/video\]/ism", '<video src="$1" controls="controls" width="' . $a->videowidth . '" height="' . $a->videoheight . '"><a href="$1">$1</a></video>', $Text);
- }
- if (strpos($Text,'[/audio]') !== false) {
- $Text = preg_replace("/\[audio\](.*?\.(ogg|ogv|oga|ogm|webm|mp4|mp3))\[\/audio\]/ism", '<audio src="$1" controls="controls"><a href="$1">$1</a></audio>', $Text);
- }
+
if (strpos($Text,'[/video]') !== false) {
$Text = preg_replace_callback("/\[video\](.*?)\[\/video\]/ism", 'tryoembed', $Text);
}
@@ -527,7 +666,6 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
}
- // html5 video and audio
if ($tryoembed){
diff --git a/include/bookmarks.php b/include/bookmarks.php
new file mode 100644
index 000000000..99cb60e64
--- /dev/null
+++ b/include/bookmarks.php
@@ -0,0 +1,55 @@
+<?php /** @file */
+
+require_once('include/menu.php');
+
+function bookmark_add($channel,$sender,$taxonomy,$private) {
+
+ $iarr = array();
+ $channel_id = $channel['channel_id'];
+
+ if($private)
+ $iarr['contact_allow'] = array($channel['channel_hash']);
+ $iarr['mitem_link'] = $taxonomy['url'];
+ $iarr['mitem_desc'] = $taxonomy['term'];
+ $iarr['mitem_flags'] = 0;
+
+ $m = @parse_url($taxonomy['url']);
+ $zrl = false;
+ if($m['host']) {
+ $r = q("select hubloc_url from hubloc where hubloc_host = '%s' limit 1",
+ dbesc($m['host'])
+ );
+ if($r)
+ $zrl = true;
+ }
+
+ if($zrl)
+ $iarr['mitem_flags'] |= MENU_ITEM_ZID;
+
+ $arr = array();
+ $arr['menu_name'] = substr($sender['xchan_hash'],0,16) . ' ' . $sender['xchan_name'];
+ $arr['menu_desc'] = sprintf( t('%1$s\'s bookmarks'), $sender['xchan_name']);
+ $arr['menu_flags'] = (($sender['xchan_hash'] === $channel['channel_hash']) ? MENU_BOOKMARK : MENU_SYSTEM|MENU_BOOKMARK);
+ $arr['menu_channel_id'] = $channel_id;
+
+ $x = menu_list($arr['menu_channel_id'],$arr['menu_name'],$arr['menu_flags']);
+ if($x)
+ $menu_id = $x[0]['menu_id'];
+ else
+ $menu_id = menu_create($arr);
+ if(! $menu_id) {
+ logger('bookmark_add: unable to create menu ' . $arr['menu_name']);
+ return;
+ }
+ logger('add_bookmark: menu_id ' . $menu_id);
+ $r = q("select * from menu_item where mitem_link = '%s' and mitem_menu_id = %d and mitem_channel_id = %d limit 1",
+ dbesc($iarr['mitem_link']),
+ intval($menu_id),
+ intval($channel_id)
+ );
+ if($r)
+ logger('add_bookmark: duplicate menu entry', LOGGER_DEBUG);
+ if(! $r)
+ $r = menu_add_item($menu_id,$channel_id,$iarr);
+ return $r;
+} \ No newline at end of file
diff --git a/include/chat.php b/include/chat.php
new file mode 100644
index 000000000..fb1d4fe65
--- /dev/null
+++ b/include/chat.php
@@ -0,0 +1,182 @@
+<?php /** @file */
+
+
+function chatroom_create($channel,$arr) {
+
+ $ret = array('success' => false);
+
+ $name = trim($arr['name']);
+ if(! $name) {
+ $ret['message'] = t('Missing room name');
+ return $ret;
+ }
+
+ $r = q("select cr_id from chatroom where cr_uid = %d and cr_name = '%s' limit 1",
+ intval($channel['channel_id']),
+ dbesc($name)
+ );
+ if($r) {
+ $ret['message'] = t('Duplicate room name');
+ return $ret;
+ }
+
+ $r = q("select count(cr_id) as total from chatroom where cr_aid = %d",
+ intval($channel['channel_account_id'])
+ );
+ if($r)
+ $limit = service_class_fetch($channel_id,'chatrooms');
+
+ if(($r) && ($limit !== false) && ($r[0]['total'] >= $limit)) {
+ $ret['message'] = upgrade_message();
+ return $ret;
+ }
+
+ if(! array_key_exists('expire',$arr))
+ $arr['expire'] = 120; // minutes, e.g. 2 hours
+
+ $created = datetime_convert();
+
+ $x = q("insert into chatroom ( cr_aid, cr_uid, cr_name, cr_created, cr_edited, cr_expire, allow_cid, allow_gid, deny_cid, deny_gid )
+ values ( %d, %d , '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s' ) ",
+ intval($channel['channel_account_id']),
+ intval($channel['channel_id']),
+ dbesc($name),
+ dbesc($created),
+ dbesc($created),
+ intval($arr['expire']),
+ dbesc($arr['allow_cid']),
+ dbesc($arr['allow_gid']),
+ dbesc($arr['deny_cid']),
+ dbesc($arr['deny_gid'])
+ );
+
+ if($x)
+ $ret['success'] = true;
+
+ return $ret;
+}
+
+
+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']))
+ $sql_extra = " and cr_name = '" . protect_sprintf(dbesc(trim($arr['cr_name']))) . "' ";
+ else {
+ $ret['message'] = t('Invalid room specifier.');
+ return $ret;
+ }
+
+ $r = q("select * from chatroom where cr_uid = %d $sql_extra limit 1",
+ intval($channel['channel_id'])
+ );
+ if(! $r) {
+ $ret['message'] = t('Invalid room specifier.');
+ return $ret;
+ }
+
+ q("delete from chatroom where cr_id = %d limit 1",
+ intval($r[0]['cr_id'])
+ );
+ if($r[0]['cr_id']) {
+ q("delete from chatpresence where cp_room = %d",
+ intval($r[0]['cr_id'])
+ );
+ }
+ $ret['success'] = true;
+ return $ret;
+}
+
+
+function chatroom_enter($observer_xchan,$room_id,$status,$client) {
+
+ if(! $room_id || ! $observer_xchan)
+ return;
+
+ $r = q("select * from chatroom where cr_id = %d limit 1",
+ intval($room_id)
+ );
+ if(! $r) {
+ notice( t('Room not found.') . EOL);
+ return false;
+ }
+ require_once('include/security.php');
+ $sql_extra = permissions_sql($r[0]['cr_uid']);
+
+ $x = q("select * from chatroom where cr_id = %d and cr_uid = %d $sql_extra limit 1",
+ intval($room_id),
+ intval($r[0]['cr_uid'])
+ );
+ if(! $x) {
+ notice( t('Permission denied.') . EOL);
+ return false;
+ }
+
+ $limit = service_class_fetch($r[0]['cr_uid'],'chatters_inroom');
+ if($limit !== false) {
+ $x = q("select count(*) as total from chatpresence where cp_room = %d",
+ intval($room_id)
+ );
+ if($x && $x[0]['total'] > $limit) {
+ notice( t('Room is full') . EOL);
+ return false;
+ }
+ }
+
+ if(intval($x[0]['cr_expire']))
+ $r = q("delete from chat where created < UTC_TIMESTAMP() - INTERVAL " . intval($x[0]['cr_expire']) . " MINUTE and chat_room = " . intval($x[0]['cr_id']));
+
+ $r = q("select * from chatpresence where cp_xchan = '%s' and cp_room = %d limit 1",
+ dbesc($observer_xchan),
+ intval($room_id)
+ );
+ if($r) {
+ q("update chatpresence set cp_last = '%s' where cp_id = %d and cp_client = '%s' limit 1",
+ dbesc(datetime_convert()),
+ intval($r[0]['cp_id']),
+ dbesc($client)
+ );
+ return true;
+ }
+
+ $r = q("insert into chatpresence ( cp_room, cp_xchan, cp_last, cp_status, cp_client )
+ values ( %d, '%s', '%s', '%s', '%s' )",
+ intval($room_id),
+ dbesc($observer_xchan),
+ dbesc(datetime_convert()),
+ dbesc($status),
+ dbesc($client)
+ );
+ return $r;
+}
+
+
+function chatroom_leave($observer_xchan,$room_id,$client) {
+ if(! $room_id || ! $observer_xchan)
+ return;
+
+ $r = q("select * from chatpresence where cp_xchan = '%s' and cp_room = %d and cp_client = '%s' limit 1",
+ dbesc($observer_xchan),
+ intval($room_id),
+ dbesc($client)
+ );
+ if($r) {
+ q("delete from chatpresence where cp_id = %d limit 1",
+ intval($r[0]['cp_id'])
+ );
+ }
+
+ return true;
+}
+
+
+function chatroom_list($uid) {
+
+ $r = q("select cr_name, cr_id, count(cp_id) as cr_inroom from chatroom left join chatpresence on cr_id = cp_room where cr_uid = %d group by cr_name order by cr_name",
+ intval($uid)
+ );
+
+ return $r;
+} \ No newline at end of file
diff --git a/include/config.php b/include/config.php
index bccf0737f..8d98d56fa 100644
--- a/include/config.php
+++ b/include/config.php
@@ -65,7 +65,7 @@ function get_config($family, $key) {
if(! array_key_exists($key,$a->config[$family])) {
return false;
}
- return ((preg_match('|^a:[0-9]+:{.*}$|s', $a->config[$family][$key]))
+ return ((! is_array($a->config[$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', $a->config[$family][$key]))
? unserialize($a->config[$family][$key])
: $a->config[$family][$key]
);
@@ -174,8 +174,8 @@ function get_pconfig($uid,$family, $key, $instore = false) {
if((! array_key_exists($family,$a->config[$uid])) || (! array_key_exists($key,$a->config[$uid][$family])))
return false;
-
- return ((preg_match('|^a:[0-9]+:{.*}$|s', $a->config[$uid][$family][$key]))
+
+ return ((! is_array($a->config[$uid][$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', $a->config[$uid][$family][$key]))
? unserialize($a->config[$uid][$family][$key])
: $a->config[$uid][$family][$key]
);
@@ -304,7 +304,7 @@ function get_xconfig($xchan,$family, $key) {
if((! array_key_exists($family,$a->config[$xchan])) || (! array_key_exists($key,$a->config[$xchan][$family])))
return false;
- return ((preg_match('|^a:[0-9]+:{.*}$|s', $a->config[$xchan][$family][$key]))
+ return ((! is_array($a->config[$xchan][$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', $a->config[$xchan][$family][$key]))
? unserialize($a->config[$xchan][$family][$key])
: $a->config[$xchan][$family][$key]
);
diff --git a/include/contact_widgets.php b/include/contact_widgets.php
index cc0a3d617..482bbed78 100644
--- a/include/contact_widgets.php
+++ b/include/contact_widgets.php
@@ -25,7 +25,8 @@ function findpeople_widget() {
'$suggest' => t('Channel Suggestions'),
'$similar' => '', // FIXME and uncomment when mod/match working // t('Similar Interests'),
'$random' => t('Random Profile'),
- '$inv' => t('Invite Friends')
+ '$inv' => t('Invite Friends'),
+ '$loggedin' => local_user()
));
}
diff --git a/include/conversation.php b/include/conversation.php
index f5fc9da93..77c7bac70 100644
--- a/include/conversation.php
+++ b/include/conversation.php
@@ -687,12 +687,13 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
'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')) : ''),
+ 'expiretime' => (($item['expires'] !== '0000-00-00 00:00:00') ? sprintf( t('Expires: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['expires'], 'r')):''),
'location' => $location,
'indent' => '',
'owner_name' => $owner_name,
'owner_url' => $owner_url,
'owner_photo' => $owner_photo,
- 'plink' => get_plink($item,$mode),
+ 'plink' => get_plink($item,false),
'edpost' => false,
'isstarred' => $isstarred,
'star' => $star,
@@ -782,6 +783,9 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
// $tx1 = dba_timer();
$item_object = new Item($item);
$conv->add_thread($item_object);
+ if($page_mode === 'list')
+ $item_object->set_template('conv_list.tpl');
+
// $tx2 = dba_timer();
// if($mode === 'network')
// profiler($tx1,$tx2,'add thread ' . $item['id']);
@@ -908,14 +912,14 @@ function item_photo_menu($item){
}
$profile_link = z_root() . "/chanview/?f=&hash=" . $item['author_xchan'];
- $pm_url = $a->get_baseurl($ssl_state) . '/message/new/?f=&hash=' . $item['author_xchan'];
+ $pm_url = $a->get_baseurl($ssl_state) . '/mail/new/?f=&hash=' . $item['author_xchan'];
if($a->contacts && array_key_exists($item['author_xchan'],$a->contacts))
$contact = $a->contacts[$item['author_xchan']];
if($contact) {
$poke_link = $a->get_baseurl($ssl_state) . '/poke/?f=&c=' . $contact['abook_id'];
- $contact_url = $a->get_baseurl($ssl_state) . '/connections/' . $contact['abook_id'];
+ $contact_url = $a->get_baseurl($ssl_state) . '/connedit/' . $contact['abook_id'];
$posts_link = $a->get_baseurl($ssl_state) . '/network/?cid=' . $contact['abook_id'];
$clean_url = normalise_link($item['author-link']);
@@ -1108,7 +1112,7 @@ function status_editor($a,$x,$popup=false) {
'$shortsetloc' => t('set location'),
'$noloc' => t('Clear browser location'),
'$shortnoloc' => t('clear location'),
- '$title' => ((x($x,'title')) ? htmlspecialchars($x['title']) : ''),
+ '$title' => ((x($x,'title')) ? htmlspecialchars($x['title'], ENT_COMPAT,'UTF-8') : ''),
'$placeholdertitle' => t('Set title'),
'$catsenabled' => ((feature_enabled($x['profile_uid'],'categories') && (! $webpage)) ? 'categories' : ''),
'$category' => "",
@@ -1117,7 +1121,7 @@ function status_editor($a,$x,$popup=false) {
'$permset' => t('Permission settings'),
'$shortpermset' => t('permissions'),
'$ptyp' => (($notes_cid) ? 'note' : 'wall'),
- '$content' => ((x($x,'body')) ? htmlspecialchars($x['body']) : ''),
+ '$content' => ((x($x,'body')) ? htmlspecialchars($x['body'], ENT_COMPAT,'UTF-8') : ''),
'$post_id' => '',
'$baseurl' => $a->get_baseurl(true),
'$defloc' => $x['default_location'],
@@ -1142,6 +1146,8 @@ function status_editor($a,$x,$popup=false) {
'$feature_encrypt' => ((feature_enabled($x['profile_uid'],'content_encrypt') && (! $webpage)) ? 'block' : 'none'),
'$encrypt' => t('Encrypt text'),
'$cipher' => $cipher,
+ '$expiryModalOK' => t('OK'),
+ '$expiryModalCANCEL' => t('Cancel'),
));
@@ -1294,18 +1300,25 @@ function prepare_page($item) {
$a = get_app();
$naked = ((get_pconfig($item['uid'],'system','nakedpage')) ? 1 : 0);
+ $observer = $a->get_observer();
+ $zid = ($observer['xchan_addr']);
+ //240 chars is the longest we can have before we start hitting problems with suhosin sites
+ $preview = substr(urlencode($item['body']), 0, 240);
+ $link = z_root() . '/' . $a->cmd;
if(array_key_exists('webpage',$a->layout) && array_key_exists('authored',$a->layout['webpage'])) {
if($a->layout['webpage']['authored'] === 'none')
$naked = 1;
// ... other possible options
}
-
return replace_macros(get_markup_template('page_display.tpl'),array(
'$author' => (($naked) ? '' : $item['author']['xchan_name']),
'$auth_url' => (($naked) ? '' : $item['author']['xchan_url']),
+ '$zid' => $zid,
'$date' => (($naked) ? '' : datetime_convert('UTC',date_default_timezone_get(),$item['created'],'Y-m-d H:i')),
'$title' => smilies(bbcode($item['title'])),
- '$body' => prepare_body($item,true)
+ '$body' => prepare_body($item,true),
+ '$preview' => $preview,
+ '$link' => $link,
));
}
@@ -1366,26 +1379,26 @@ function network_tabs() {
$tabs = array(
array(
'label' => t('Commented Order'),
- 'url'=>$a->get_baseurl(true) . '/' . $cmd . '?f=&order=comment' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : ''),
+ 'url'=>$a->get_baseurl(true) . '/' . $cmd . '?f=&order=comment' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''),
'sel'=>$all_active,
'title'=> t('Sort by Comment Date'),
),
array(
'label' => t('Posted Order'),
- 'url'=>$a->get_baseurl(true) . '/' . $cmd . '?f=&order=post' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : ''),
+ 'url'=>$a->get_baseurl(true) . '/' . $cmd . '?f=&order=post' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''),
'sel'=>$postord_active,
'title' => t('Sort by Post Date'),
),
array(
'label' => t('Personal'),
- 'url' => $a->get_baseurl(true) . '/' . $cmd . ((x($_GET,'cid')) ? '/?f=&cid=' . $_GET['cid'] : '') . '&conv=1',
+ 'url' => $a->get_baseurl(true) . '/' . $cmd . '?f=' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . '&conv=1',
'sel' => $conv_active,
'title' => t('Posts that mention or involve you'),
),
array(
'label' => t('New'),
- 'url' => $a->get_baseurl(true) . '/' . $cmd . ((x($_GET,'cid')) ? '/?f=&cid=' . $_GET['cid'] : '') . '&new=1',
+ 'url' => $a->get_baseurl(true) . '/' . $cmd . '?f=' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . '&new=1' . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''),
'sel' => $new_active,
'title' => t('Activity Stream - by date'),
),
@@ -1423,7 +1436,8 @@ function network_tabs() {
function profile_tabs($a, $is_owner=False, $nickname=Null){
//echo "<pre>"; var_dump($a->user); killme();
-
+
+
$channel = $a->get_channel();
if (is_null($nickname))
@@ -1443,24 +1457,51 @@ function profile_tabs($a, $is_owner=False, $nickname=Null){
'title' => t('Status Messages and Posts'),
'id' => 'status-tab',
),
- array(
+ );
+
+ $p = get_all_perms($a->profile['profile_uid'],get_observer_hash());
+
+ if($p['view_profile']) {
+ $tabs[] = array(
'label' => t('About'),
'url' => $pr,
'sel' => ((argv(0) == 'profile') ? 'active' : ''),
'title' => t('Profile Details'),
'id' => 'profile-tab',
- ),
- array(
+ );
+ }
+ if($p['view_photos']) {
+ $tabs[] = array(
'label' => t('Photos'),
'url' => $a->get_baseurl() . '/photos/' . $nickname,
'sel' => ((argv(0) == 'photos') ? 'active' : ''),
'title' => t('Photo Albums'),
'id' => 'photo-tab',
- ),
+ );
+ }
+ if($p['view_storage']) {
+ $tabs[] = array(
+ 'label' => t('Files'),
+ 'url' => $a->get_baseurl() . '/cloud/' . $nickname . ((get_observer_hash()) ? '' : '?f=&davguest=1'),
+ 'sel' => ((argv(0) == 'cloud') ? 'active' : ''),
+ 'title' => t('Files and Storage'),
+ 'id' => 'files-tab',
+ );
+ }
+
+ require_once('include/chat.php');
+ $chats = chatroom_list($a->profile['profile_uid']);
+
+ $tabs[] = array(
+ 'label' => t('Chatrooms') . '(' . count($chats) . ')',
+ 'url' => $a->get_baseurl() . '/chat/' . $nickname,
+ 'sel' => ((argv(0) == 'chat') ? 'active' : ''),
+ 'title' => t('Chatrooms'),
+ 'id' => 'chat-tab',
);
- if ($is_owner){
+ if($is_owner) {
$tabs[] = array(
'label' => t('Events'),
'url' => $a->get_baseurl() . '/events',
@@ -1468,15 +1509,27 @@ function profile_tabs($a, $is_owner=False, $nickname=Null){
'title' => t('Events and Calendar'),
'id' => 'events-tab',
);
- if(feature_enabled(local_user(),'webpages')){
+
+ $tabs[] = array(
+ 'label' => t('Bookmarks'),
+ 'url' => $a->get_baseurl() . '/bookmarks',
+ 'sel' => ((argv(0) == 'bookmarks') ? 'active' : ''),
+ 'title' => t('Saved Bookmarks'),
+ 'id' => 'bookmarks-tab',
+ );
+ }
+
+
+ if($is_owner && feature_enabled($a->profile['profile_uid'],'webpages')) {
$tabs[] = array(
'label' => t('Webpages'),
'url' => $a->get_baseurl() . '/webpages/' . $nickname,
'sel' => ((argv(0) == 'webpages') ? 'active' : ''),
'title' => t('Manage Webpages'),
'id' => 'webpages-tab',
- );}
+ );
}
+
else {
// FIXME
// we probably need a listing of events that were created by
diff --git a/include/crypto.php b/include/crypto.php
index e9372fbb4..33cdc10c0 100644
--- a/include/crypto.php
+++ b/include/crypto.php
@@ -4,6 +4,8 @@ function rsa_sign($data,$key,$alg = 'sha256') {
if(! $key)
return 'no key';
$sig = '';
+ if(intval(OPENSSL_ALGO_SHA256) && $alg === 'sha256')
+ $alg = OPENSSL_ALGO_SHA256;
openssl_sign($data,$sig,$key,$alg);
return $sig;
}
@@ -13,6 +15,8 @@ function rsa_verify($data,$sig,$key,$alg = 'sha256') {
if(! $key)
return false;
+ if(intval(OPENSSL_ALGO_SHA256) && $alg === 'sha256')
+ $alg = OPENSSL_ALGO_SHA256;
$verify = openssl_verify($data,$sig,$key,$alg);
return $verify;
}
diff --git a/include/deliver.php b/include/deliver.php
index b1314ce39..b0d15e1ef 100644
--- a/include/deliver.php
+++ b/include/deliver.php
@@ -26,6 +26,7 @@ function deliver_run($argv, $argc) {
// If there is no outq_msg, this is a refresh_all message which does not require local handling
if($r[0]['outq_msg']) {
$msg = array('body' => json_encode(array('pickup' => array(array('notify' => json_decode($r[0]['outq_notify'],true),'message' => json_decode($r[0]['outq_msg'],true))))));
+
zot_import($msg,z_root());
$r = q("delete from outq where outq_hash = '%s' limit 1",
dbesc($argv[$x])
diff --git a/include/dir_fns.php b/include/dir_fns.php
index 0c9a6bd9f..ab8b67985 100644
--- a/include/dir_fns.php
+++ b/include/dir_fns.php
@@ -22,7 +22,8 @@ function dir_sort_links() {
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')
@@ -166,6 +167,10 @@ function syncdirs($uid) {
$profile['region'] = $p[0]['region'];
$profile['postcode'] = $p[0]['postal_code'];
$profile['country'] = $p[0]['country_name'];
+ $profile['about'] = $p[0]['about'];
+ $profile['homepage'] = $p[0]['homepage'];
+ $profile['hometown'] = $p[0]['hometown'];
+
if($p[0]['keywords']) {
$tags = array();
$k = explode(' ',$p[0]['keywords']);
@@ -200,10 +205,10 @@ function syncdirs($uid) {
}
+ $address = $p[0]['channel_address'] . '@' . get_app()->get_hostname();
if(perm_is_allowed($uid,'','view_profile')) {
- import_directory_profile($hash,$profile);
-
+ import_directory_profile($hash,$profile,$address,0);
}
else {
// they may have made it private
diff --git a/include/enotify.php b/include/enotify.php
index 011a1cde2..e0991257f 100644
--- a/include/enotify.php
+++ b/include/enotify.php
@@ -86,14 +86,17 @@ function notification($params) {
$preamble = sprintf( t('%1$s, %2$s sent you a new private message at %3$s.'),$recip['channel_name'], $sender['xchan_name'],$sitename);
$epreamble = sprintf( t('%1$s sent you %2$s.'),'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]', '[zrl=$itemlink]' . t('a private message') . '[/zrl]');
$sitelink = t('Please visit %s to view and/or reply to your private messages.');
- $tsitelink = sprintf( $sitelink, $siteurl . '/message/' . $params['item']['id'] );
- $hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '/message/' . $params['item']['id'] . '">' . $sitename . '</a>');
+ $tsitelink = sprintf( $sitelink, $siteurl . '/mail/' . $params['item']['id'] );
+ $hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '/mail/' . $params['item']['id'] . '">' . $sitename . '</a>');
$itemlink = $siteurl . '/message/' . $params['item']['id'];
}
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'])))
@@ -171,7 +174,6 @@ function notification($params) {
$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_WALL) {
@@ -183,9 +185,6 @@ function notification($params) {
$recip['channel_name'],
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$params['link']);
-
- // FIXME - check the item privacy
- $private = false;
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf( $sitelink, $siteurl );
@@ -455,6 +454,8 @@ function notification($params) {
if(! $datarray['email_secure']) {
switch($params['type']) {
case NOTIFY_WALL:
+ case NOTIFY_TAGSELF:
+ case NOTIFY_POKE:
case NOTIFY_COMMENT:
if(! $private)
break;
diff --git a/include/event.php b/include/event.php
index 7873de1ef..08b94dafa 100644
--- a/include/event.php
+++ b/include/event.php
@@ -15,7 +15,7 @@ function format_event_html($ev) {
$o .= '<p class="summary event-summary">' . bbcode($ev['summary']) . '</p>' . "\r\n";
- $o .= '<p class="description event-description">' . bbcode($ev['desc']) . '</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' ))
@@ -52,8 +52,8 @@ function format_event_bbcode($ev) {
if($ev['summary'])
$o .= '[event-summary]' . $ev['summary'] . '[/event-summary]';
- if($ev['desc'])
- $o .= '[event-description]' . $ev['desc'] . '[/event-description]';
+ if($ev['description'])
+ $o .= '[event-description]' . $ev['description'] . '[/event-description]';
if($ev['start'])
$o .= '[event-start]' . $ev['start'] . '[/event-start]';
@@ -75,7 +75,7 @@ function format_event_bbcode($ev) {
function bbtovcal($s) {
$o = '';
$ev = bbtoevent($s);
- if($ev['desc'])
+ if($ev['description'])
$o = format_event_html($ev);
return $o;
}
@@ -90,7 +90,7 @@ function bbtoevent($s) {
$ev['summary'] = $match[1];
$match = '';
if(preg_match("/\[event\-description\](.*?)\[\/event\-description\]/is",$s,$match))
- $ev['desc'] = $match[1];
+ $ev['description'] = $match[1];
$match = '';
if(preg_match("/\[event\-start\](.*?)\[\/event\-start\]/is",$s,$match))
$ev['start'] = $match[1];
@@ -122,7 +122,7 @@ function ev_compare($a,$b) {
$date_b = (($b['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$b['start']) : $b['start']);
if($date_a === $date_b)
- return strcasecmp($a['desc'],$b['desc']);
+ return strcasecmp($a['description'],$b['description']);
return strcmp($date_a,$date_b);
}
@@ -178,7 +178,7 @@ function event_store($arr) {
`start` = '%s',
`finish` = '%s',
`summary` = '%s',
- `desc` = '%s',
+ `description` = '%s',
`location` = '%s',
`type` = '%s',
`adjust` = %d,
@@ -193,7 +193,7 @@ function event_store($arr) {
dbesc($arr['start']),
dbesc($arr['finish']),
dbesc($arr['summary']),
- dbesc($arr['desc']),
+ dbesc($arr['description']),
dbesc($arr['location']),
dbesc($arr['type']),
intval($arr['adjust']),
@@ -266,7 +266,7 @@ function event_store($arr) {
$arr['mid'] = item_message_id();
- $r = q("INSERT INTO event ( uid,aid,event_xchan,event_hash,created,edited,start,finish,summary, `desc`,location,type,
+ $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' ) ",
intval($arr['uid']),
@@ -278,7 +278,7 @@ function event_store($arr) {
dbesc($arr['start']),
dbesc($arr['finish']),
dbesc($arr['summary']),
- dbesc($arr['desc']),
+ dbesc($arr['description']),
dbesc($arr['location']),
dbesc($arr['type']),
intval($arr['adjust']),
@@ -337,6 +337,8 @@ function event_store($arr) {
$item_arr['obj_type'] = ACTIVITY_OBJ_EVENT;
$item_arr['body'] = format_event_bbcode($arr);
+ $item_arr['plink'] = z_root() . '/channel/' . $z[0]['channel_address'] . '/?f=&mid=' . $item_arr['mid'];
+
$x = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($arr['event_xchan'])
);
diff --git a/include/features.php b/include/features.php
index 05206106a..cc8d457bc 100644
--- a/include/features.php
+++ b/include/features.php
@@ -7,6 +7,8 @@
function feature_enabled($uid,$feature) {
$x = get_pconfig($uid,'feature',$feature);
+ if($x === false)
+ $x = get_config('feature',$feature);
$arr = array('uid' => $uid, 'feature' => $feature, 'enabled' => $x);
call_hooks('feature_enabled',$arr);
return($arr['enabled']);
@@ -24,9 +26,11 @@ function get_features() {
array('multi_profiles', t('Multiple Profiles'), t('Ability to create multiple profiles')),
array('webpages', t('Web Pages'), t('Provide managed web pages on your channel')),
array('private_notes', t('Private Notes'), t('Enables a tool to store notes and reminders')),
- array('prettyphoto', t('Enhanced Photo Albums'), t('Enable photo album with enhanced features')),
+// prettyphoto has licensing issues and will no longer be provided in core -
+// in any event this setting should probably be a theme option or plugin
+// array('prettyphoto', t('Enhanced Photo Albums'), t('Enable photo album with enhanced features')),
//FIXME - needs a description, but how the hell do we explain this to normals?
- array('sendzid', t('Extended Identity Sharing'), t(' ')),
+ 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.')),
array('expert', t('Expert Mode'), t('Enable Expert Mode to provide advanced configuration options')),
array('premium_channel', t('Premium Channel'), t('Allows you to set restrictions and terms on those that connect with your channel')),
),
@@ -37,7 +41,7 @@ function get_features() {
array('richtext', t('Richtext Editor'), t('Enable richtext editor')),
array('preview', t('Post Preview'), t('Allow previewing posts and comments before publishing them')),
array('channel_sources', t('Channel Sources'), t('Automatically import channel content from other channels or feeds')),
- array('content_encrypt', t('Even More Encryption'), t('Allow encryption of content end-to-end with a shared secret key')),
+ array('content_encrypt', t('Even More Encryption'), t('Allow optional encryption of content end-to-end with a shared secret key')),
),
// Network Tools
@@ -49,6 +53,7 @@ function get_features() {
array('personal_tab', t('Network Personal Tab'), t('Enable tab to display only Network posts that you\'ve interacted on')),
array('new_tab', t('Network New Tab'), t('Enable tab to display all new Network activity')),
array('affinity', t('Affinity Tool'), t('Filter stream activity by depth of relationships')),
+ array('suggest', t('Suggest Channels'), t('Show channel suggestions')),
),
// Item tools
diff --git a/include/group.php b/include/group.php
index 8f690785d..56a7555bc 100644
--- a/include/group.php
+++ b/include/group.php
@@ -14,11 +14,11 @@ function group_add($uid,$name,$public = 0) {
// access lists. What we're doing here is reviving the dead group, but old content which
// was restricted to this group may now be seen by the new group members.
- $z = q("SELECT * FROM `group` WHERE `id` = %d LIMIT 1",
+ $z = q("SELECT * FROM `groups` WHERE `id` = %d LIMIT 1",
intval($r)
);
if(count($z) && $z[0]['deleted']) {
- $r = q("UPDATE `group` SET `deleted` = 0 WHERE `uid` = %d AND `name` = '%s' LIMIT 1",
+ $r = q("UPDATE `groups` SET `deleted` = 0 WHERE `uid` = %d AND `name` = '%s' LIMIT 1",
intval($uid),
dbesc($name)
);
@@ -31,13 +31,13 @@ function group_add($uid,$name,$public = 0) {
$dups = false;
$hash = random_string() . $name;
- $r = q("SELECT id FROM `group` WHERE hash = '%s' LIMIT 1", dbesc($hash));
+ $r = q("SELECT id FROM `groups` WHERE hash = '%s' LIMIT 1", dbesc($hash));
if($r)
$dups = true;
} while($dups == true);
- $r = q("INSERT INTO `group` ( hash, uid, visible, name )
+ $r = q("INSERT INTO `groups` ( hash, uid, visible, name )
VALUES( '%s', %d, %d, '%s' ) ",
dbesc($hash),
intval($uid),
@@ -53,7 +53,7 @@ function group_add($uid,$name,$public = 0) {
function group_rmv($uid,$name) {
$ret = false;
if(x($uid) && x($name)) {
- $r = q("SELECT id, hash FROM `group` WHERE `uid` = %d AND `name` = '%s' LIMIT 1",
+ $r = q("SELECT id, hash FROM `groups` WHERE `uid` = %d AND `name` = '%s' LIMIT 1",
intval($uid),
dbesc($name)
);
@@ -104,7 +104,7 @@ function group_rmv($uid,$name) {
);
// remove group
- $r = q("UPDATE `group` SET `deleted` = 1 WHERE `uid` = %d AND `name` = '%s' LIMIT 1",
+ $r = q("UPDATE `groups` SET `deleted` = 1 WHERE `uid` = %d AND `name` = '%s' LIMIT 1",
intval($uid),
dbesc($name)
);
@@ -119,7 +119,7 @@ function group_rmv($uid,$name) {
function group_byname($uid,$name) {
if((! $uid) || (! strlen($name)))
return false;
- $r = q("SELECT * FROM `group` WHERE `uid` = %d AND `name` = '%s' LIMIT 1",
+ $r = q("SELECT * FROM `groups` WHERE `uid` = %d AND `name` = '%s' LIMIT 1",
intval($uid),
dbesc($name)
);
@@ -132,7 +132,7 @@ function group_byname($uid,$name) {
function group_rec_byhash($uid,$hash) {
if((! $uid) || (! strlen($hash)))
return false;
- $r = q("SELECT * FROM `group` WHERE `uid` = %d AND `hash` = '%s' LIMIT 1",
+ $r = q("SELECT * FROM `groups` WHERE `uid` = %d AND `hash` = '%s' LIMIT 1",
intval($uid),
dbesc($hash)
);
@@ -207,7 +207,7 @@ function mini_group_select($uid,$group = '') {
$grps = array();
$o = '';
- $r = q("SELECT * FROM `group` WHERE `deleted` = 0 AND `uid` = %d ORDER BY `name` ASC",
+ $r = q("SELECT * FROM `groups` WHERE `deleted` = 0 AND `uid` = %d ORDER BY `name` ASC",
intval($uid)
);
$grps[] = array('name' => '', 'hash' => '0', 'selected' => '');
@@ -229,7 +229,7 @@ function mini_group_select($uid,$group = '') {
-function group_side($every="contacts",$each="group",$edit = false, $group_id = 0, $cid = '',$mode = 1) {
+function group_side($every="connections",$each="group",$edit = false, $group_id = 0, $cid = '',$mode = 1) {
$o = '';
@@ -246,7 +246,7 @@ function group_side($every="contacts",$each="group",$edit = false, $group_id = 0
);
- $r = q("SELECT * FROM `group` WHERE `deleted` = 0 AND `uid` = %d ORDER BY `name` ASC",
+ $r = q("SELECT * FROM `groups` WHERE `deleted` = 0 AND `uid` = %d ORDER BY `name` ASC",
intval($_SESSION['uid'])
);
$member_of = array();
@@ -272,7 +272,7 @@ function group_side($every="contacts",$each="group",$edit = false, $group_id = 0
'cid' => $cid,
'text' => $rr['name'],
'selected' => $selected,
- 'href' => (($mode == 0) ? $each.'?f=&gid='.$rr['id'] : $each."/".$rr['id']),
+ 'href' => (($mode == 0) ? $each.'?f=&gid='.$rr['id'] : $each."/".$rr['id']) . ((x($_GET,'new')) ? '&new=' . $_GET['new'] : '') . ((x($_GET,'order')) ? '&order=' . $_GET['order'] : ''),
'edit' => $groupedit,
'ismember' => in_array($rr['id'],$member_of),
);
@@ -302,7 +302,7 @@ function expand_groups($a) {
$groups = implode(',', $x);
if($groups)
- $r = q("SELECT xchan FROM group_member WHERE gid IN ( select id from `group` where hash in ( $groups ))");
+ $r = q("SELECT xchan FROM group_member WHERE gid IN ( select id from `groups` where hash in ( $groups ))");
$ret = array();
if($r)
@@ -314,7 +314,7 @@ function expand_groups($a) {
function member_of($c) {
- $r = q("SELECT `group`.`name`, `group`.`id` FROM `group` LEFT JOIN `group_member` ON `group_member`.`gid` = `group`.`id` WHERE `group_member`.`xchan` = '%s' AND `group`.`deleted` = 0 ORDER BY `group`.`name` ASC ",
+ $r = q("SELECT `groups`.`name`, `groups`.`id` FROM `groups` LEFT JOIN `group_member` ON `group_member`.`gid` = `groups`.`id` WHERE `group_member`.`xchan` = '%s' AND `groups`.`deleted` = 0 ORDER BY `groups`.`name` ASC ",
dbesc($c)
);
diff --git a/include/identity.php b/include/identity.php
index b25594c87..2db5d8ece 100644
--- a/include/identity.php
+++ b/include/identity.php
@@ -71,23 +71,34 @@ function validate_channelname($name) {
/**
- * @function create_dir_account()
+ * @function create_sys_channel()
* Create a system channel - which has no account attached
*
- * Currently unused.
- *
*/
-function create_dir_account() {
+function create_sys_channel() {
+ if(get_sys_channel())
+ return;
create_identity(array(
'account_id' => 'xxx', // This will create an identity with an (integer) account_id of 0, but account_id is required
- 'nickname' => 'dir',
- 'name' => 'Directory',
- 'pageflags' => PAGE_DIRECTORY_CHANNEL|PAGE_HIDDEN,
- 'publish' => 0
+ 'nickname' => 'sys',
+ 'name' => 'System',
+ 'pageflags' => PAGE_SYSTEM,
+ 'publish' => 0,
+ 'xchanflags' => XCHAN_FLAGS_SYSTEM
));
}
+function get_sys_channel() {
+ $r = q("select * from channel left join xchan on channel_hash = xchan_hash where (channel_pageflags & %d) limit 1",
+ intval(PAGE_SYSTEM)
+ );
+ if($r)
+ return $r[0];
+ return false;
+}
+
+
/**
* @channel_total()
* Return the total number of channels on this site. No filtering is performed.
@@ -145,7 +156,7 @@ function create_identity($arr) {
$name = escape_tags($arr['name']);
$pageflags = ((x($arr,'pageflags')) ? intval($arr['pageflags']) : PAGE_NORMAL);
-
+ $xchanflags = ((x($arr,'xchanflags')) ? intval($arr['xchanflags']) : XCHAN_FLAGS_NORMAL);
$name_error = validate_channelname($arr['name']);
if($name_error) {
$ret['message'] = $name_error;
@@ -243,7 +254,7 @@ function create_identity($arr) {
$newuid = $ret['channel']['channel_id'];
- $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_photo_l, xchan_photo_m, xchan_photo_s, xchan_addr, xchan_url, xchan_follow, xchan_connurl, xchan_name, xchan_network, xchan_photo_date, xchan_name_date ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')",
+ $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_photo_l, xchan_photo_m, xchan_photo_s, xchan_addr, xchan_url, xchan_follow, xchan_connurl, xchan_name, xchan_network, xchan_photo_date, xchan_name_date, xchan_flags ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d)",
dbesc($hash),
dbesc($guid),
dbesc($sig),
@@ -258,7 +269,8 @@ function create_identity($arr) {
dbesc($ret['channel']['channel_name']),
dbesc('zot'),
dbesc(datetime_convert()),
- dbesc(datetime_convert())
+ dbesc(datetime_convert()),
+ intval($xchanflags)
);
// Not checking return value.
@@ -396,7 +408,7 @@ function identity_basic_export($channel_id) {
$ret['hubloc'] = $r;
}
- $r = q("select * from `group` where uid = %d ",
+ $r = q("select * from `groups` where uid = %d ",
intval($channel_id)
);
@@ -532,6 +544,9 @@ function profile_load(&$a, $nickname, $profile = '') {
}
$a->profile = $r[0];
+ $online = get_online_status($nickname);
+ $a->profile['online_status'] = $online['result'];
+
$a->profile_uid = $r[0]['profile_uid'];
$a->page['title'] = $a->profile['channel_name'] . " - " . $a->profile['channel_address'] . "@" . $a->get_hostname();
@@ -655,6 +670,7 @@ function profile_sidebar($profile, $block = 0, $show_connect = true) {
}
}
+
if((x($profile,'address') == 1)
|| (x($profile,'locality') == 1)
|| (x($profile,'region') == 1)
@@ -665,9 +681,15 @@ function profile_sidebar($profile, $block = 0, $show_connect = true) {
$gender = ((x($profile,'gender') == 1) ? t('Gender:') : False);
$marital = ((x($profile,'marital') == 1) ? t('Status:') : False);
$homepage = ((x($profile,'homepage') == 1) ? t('Homepage:') : False);
+ $profile['online'] = (($profile['online_status'] === 'online') ? t('Online Now') : False);
+logger('online: ' . $profile['online']);
+
+ if(! perm_is_allowed($profile['uid'],((is_array($observer)) ? $observer['xchan_hash'] : ''),'view_profile')) {
+ $block = true;
+ }
if(($profile['hidewall'] || $block) && (! local_user()) && (! remote_user())) {
- $location = $pdesc = $gender = $marital = $homepage = False;
+ $location = $pdesc = $gender = $marital = $homepage = $online = False;
}
$firstname = ((strpos($profile['name'],' '))
@@ -688,7 +710,7 @@ function profile_sidebar($profile, $block = 0, $show_connect = true) {
$channel_menu = menu_render($m);
}
$menublock = get_pconfig($profile['uid'],'system','channel_menublock');
- if ($menublock) {
+ if ($menublock && (! $block)) {
require_once('include/comanche.php');
$channel_menu .= comanche_block($menublock);
}
@@ -935,6 +957,8 @@ function advanced_profile(&$a) {
if($txt = prepare_text($a->profile['contact'])) $profile['contact'] = array( t('Contact information and Social Networks:'), $txt);
+ if($txt = prepare_text($a->profile['channels'])) $profile['channels'] = array( t('My other channels:'), $txt);
+
if($txt = prepare_text($a->profile['music'])) $profile['music'] = array( t('Musical interests:'), $txt);
if($txt = prepare_text($a->profile['book'])) $profile['book'] = array( t('Books, literature:'), $txt);
@@ -949,44 +973,15 @@ function advanced_profile(&$a) {
if($txt = prepare_text($a->profile['education'])) $profile['education'] = array( t('School/education:'), $txt );
- $r = q("select * from obj left join term on obj_obj = term_hash where term_hash != '' and obj_page = '%s' and uid = %d and obj_type = %d
- order by obj_verb, term",
- dbesc($a->profile['profile_guid']),
- intval($a->profile['profile_uid']),
- intval(TERM_OBJ_THING)
- );
- $things = null;
+ $things = get_things($a->profile['profile_guid'],$a->profile['profile_uid']);
- if($r) {
- $things = array();
-
- // Use the system obj_verbs array as a sort key, since we don't really
- // want an alphabetic sort. To change the order, use a plugin to
- // alter the obj_verbs() array or alter it in code. Unknown verbs come
- // after the known ones - in no particular order.
-
- $v = obj_verbs();
- foreach($v as $k => $foo)
- $things[$k] = null;
- foreach($r as $rr) {
- if(! $things[$rr['obj_verb']])
- $things[$rr['obj_verb']] = array();
- $things[$rr['obj_verb']][] = array('term' => $rr['term'],'url' => $rr['url'],'img' => $rr['imgurl']);
- }
- $sorted_things = array();
- if($things)
- foreach($things as $k => $v)
- if(is_array($things[$k]))
- $sorted_things[$k] = $v;
- }
-
- logger('mod_profile: things: ' . print_r($sorted_things,true), LOGGER_DATA);
+ logger('mod_profile: things: ' . print_r($things,true), LOGGER_DATA);
return replace_macros($tpl, array(
'$title' => t('Profile'),
'$profile' => $profile,
- '$things' => $sorted_things
+ '$things' => $things
));
}
@@ -1031,12 +1026,13 @@ function zid_init(&$a) {
call_hooks('zid_init',$arr);
if((! local_user()) && (! remote_user())) {
logger('zid_init: not authenticated. Invoking reverse magic-auth for ' . $tmp_str);
- $r = q("select * from hubloc where hubloc_addr = '%s' order by hubloc_id desc limit 1",
+ $r = q("select * from hubloc where hubloc_addr = '%s' order by hubloc_connected desc limit 1",
dbesc($tmp_str)
);
// try to avoid recursion - but send them home to do a proper magic auth
- $dest = '/' . $a->query_string;
- $dest = str_replace(array('?zid=','&zid='),array('?rzid=','&rzid='),$dest);
+ $query = $a->query_string;
+ $query = str_replace(array('?zid=','&zid='),array('?rzid=','&rzid='),$query);
+ $dest = '/' . urlencode($query);
if($r && ($r[0]['hubloc_url'] != z_root()) && (! strstr($dest,'/magic')) && (! strstr($dest,'/rmagic'))) {
goaway($r[0]['hubloc_url'] . '/magic' . '?f=&rev=1&dest=' . z_root() . $dest);
}
@@ -1104,3 +1100,95 @@ function get_theme_uid() {
}
return $uid;
}
+
+/**
+* @function get_default_profile_photo($size = 175)
+* Retrieves the path of the default_profile_photo for this system
+* with the specified size.
+* @param int $size
+* one of (175, 80, 48)
+* @returns string
+*
+*/
+
+function get_default_profile_photo($size = 175) {
+ $scheme = get_config('system','default_profile_photo');
+ if(! $scheme)
+ $scheme = 'rainbow_man';
+ return 'images/default_profile_photos/' . $scheme . '/' . $size . '.jpg';
+}
+
+
+/**
+ *
+ * @function is_foreigner($s)
+ * Test whether a given identity is NOT a member of the Red Matrix
+ * @param string $s;
+ * xchan_hash of the identity in question
+ *
+ * @returns boolean true or false
+ *
+ */
+
+function is_foreigner($s) {
+ return((strpbrk($s,':@')) ? true : false);
+}
+
+
+/**
+ *
+ * @function is_member($s)
+ * Test whether a given identity is a member of the Red Matrix
+ * @param string $s;
+ * xchan_hash of the identity in question
+ *
+ * @returns boolean true or false
+ *
+ */
+
+function is_member($s) {
+ return((is_foreigner($s)) ? false : true);
+}
+
+function get_online_status($nick) {
+
+ $ret = array('result' => false);
+
+ $r = q("select channel_id, channel_hash from channel where channel_address = '%s' limit 1",
+ dbesc(argv(1))
+ );
+ if($r) {
+ $hide = get_pconfig($r[0]['channel_id'],'system','hide_online_status');
+ if($hide)
+ return $ret;
+ $x = q("select cp_status from chatpresence where cp_xchan = '%s' and cp_room = 0 limit 1",
+ dbesc($r[0]['channel_hash'])
+ );
+ if($x)
+ $ret['result'] = $x[0]['cp_status'];
+ }
+
+ return $ret;
+}
+
+
+function remote_online_status($webbie) {
+
+ $result = false;
+ $r = q("select * from hubloc where hubloc_addr = '%s' limit 1",
+ dbesc($webbie)
+ );
+ if(! $r)
+ return $result;
+
+ $url = $r[0]['hubloc_url'] . '/online/' . substr($webbie,0,strpos($webbie,'@'));
+
+ $x = z_fetch_url($url);
+ if($x['success']) {
+ $j = json_decode($x['body'],true);
+ if($j)
+ $result = (($j['result']) ? $j['result'] : false);
+ }
+ return $result;
+
+}
diff --git a/include/items.php b/include/items.php
index dd3cf7644..88b258604 100755
--- a/include/items.php
+++ b/include/items.php
@@ -18,10 +18,17 @@ function collect_recipients($item,&$private) {
require_once('include/group.php');
- if($item['item_private'])
- $private = true;
+ $private = ((intval($item['item_private'])) ? true : false);
+ $recipients = array();
+
+ // if the post is marked private but there are no recipients, only add the author and owner
+ // as recipients. The ACL for the post may live on the hub of a different clone. We need to
+ // get the post to that hub.
if($item['allow_cid'] || $item['allow_gid'] || $item['deny_cid'] || $item['deny_gid']) {
+
+ // it is private
+
$allow_people = expand_acl($item['allow_cid']);
$allow_groups = expand_groups(expand_acl($item['allow_gid']));
@@ -54,19 +61,19 @@ function collect_recipients($item,&$private) {
$private = true;
}
else {
- $recipients = array();
- $r = q("select * from abook where abook_channel = %d and not (abook_flags & %d) and not (abook_flags & %d) and not (abook_flags & %d)",
- intval($item['uid']),
- intval(ABOOK_FLAG_SELF),
- intval(ABOOK_FLAG_PENDING),
- intval(ABOOK_FLAG_ARCHIVED)
- );
- if($r) {
- foreach($r as $rr) {
- $recipients[] = $rr['abook_xchan'];
+ if(! $private) {
+ $r = q("select abook_xchan from abook where abook_channel = %d and not (abook_flags & %d) and not (abook_flags & %d) and not (abook_flags & %d)",
+ intval($item['uid']),
+ intval(ABOOK_FLAG_SELF),
+ intval(ABOOK_FLAG_PENDING),
+ intval(ABOOK_FLAG_ARCHIVED)
+ );
+ if($r) {
+ foreach($r as $rr) {
+ $recipients[] = $rr['abook_xchan'];
+ }
}
}
- $private = false;
}
// This is a somewhat expensive operation but important.
@@ -153,8 +160,8 @@ function red_zrl_callback($matches) {
$zrl = true;
}
if($zrl)
- return $matches[1] . '[zrl=' . $matches[2] . ']' . $matches[2] . '[/zrl]';
- return $matches[0];
+ return $matches[1] . '#^[zrl=' . $matches[2] . ']' . $matches[2] . '[/zrl]';
+ return $matches[1] . '#^[url=' . $matches[2] . ']' . $matches[2] . '[/url]';
}
@@ -243,6 +250,12 @@ function post_activity_item($arr) {
$arr['comment_policy'] = map_scope($channel['channel_w_comment']);
+
+ if ((! $arr['plink']) && ($arr['item_flags'] & ITEM_THREAD_TOP)) {
+ $arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $arr['mid'];
+ }
+
+
// for the benefit of plugins, we will behave as if this is an API call rather than a normal online post
$_REQUEST['api_source'] = 1;
@@ -564,9 +577,9 @@ function title_is_body($title, $body) {
function get_item_elements($x) {
-// logger('get_item_elements');
+
$arr = array();
- $arr['body'] = (($x['body']) ? htmlentities($x['body'],ENT_COMPAT,'UTF-8',false) : '');
+ $arr['body'] = (($x['body']) ? htmlspecialchars($x['body'],ENT_COMPAT,'UTF-8',false) : '');
$arr['created'] = datetime_convert('UTC','UTC',$x['created']);
$arr['edited'] = datetime_convert('UTC','UTC',$x['edited']);
@@ -584,27 +597,27 @@ function get_item_elements($x) {
? datetime_convert('UTC','UTC',$x['commented'])
: $arr['created']);
- $arr['title'] = (($x['title']) ? htmlentities($x['title'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['title'] = (($x['title']) ? htmlspecialchars($x['title'], ENT_COMPAT,'UTF-8',false) : '');
if(mb_strlen($arr['title']) > 255)
$arr['title'] = mb_substr($arr['title'],0,255);
- $arr['app'] = (($x['app']) ? htmlentities($x['app'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['mid'] = (($x['message_id']) ? htmlentities($x['message_id'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['parent_mid'] = (($x['message_top']) ? htmlentities($x['message_top'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['thr_parent'] = (($x['message_parent']) ? htmlentities($x['message_parent'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['app'] = (($x['app']) ? htmlspecialchars($x['app'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['mid'] = (($x['message_id']) ? htmlspecialchars($x['message_id'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['parent_mid'] = (($x['message_top']) ? htmlspecialchars($x['message_top'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['thr_parent'] = (($x['message_parent']) ? htmlspecialchars($x['message_parent'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['plink'] = (($x['permalink']) ? htmlentities($x['permalink'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['location'] = (($x['location']) ? htmlentities($x['location'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['coord'] = (($x['longlat']) ? htmlentities($x['longlat'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['verb'] = (($x['verb']) ? htmlentities($x['verb'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['mimetype'] = (($x['mimetype']) ? htmlentities($x['mimetype'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['obj_type'] = (($x['object_type']) ? htmlentities($x['object_type'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['tgt_type'] = (($x['target_type']) ? htmlentities($x['target_type'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['comment_policy'] = (($x['comment_scope']) ? htmlentities($x['comment_scope'], ENT_COMPAT,'UTF-8',false) : 'contacts');
+ $arr['plink'] = (($x['permalink']) ? htmlspecialchars($x['permalink'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['location'] = (($x['location']) ? htmlspecialchars($x['location'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['coord'] = (($x['longlat']) ? htmlspecialchars($x['longlat'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['verb'] = (($x['verb']) ? htmlspecialchars($x['verb'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['mimetype'] = (($x['mimetype']) ? htmlspecialchars($x['mimetype'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['obj_type'] = (($x['object_type']) ? htmlspecialchars($x['object_type'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['tgt_type'] = (($x['target_type']) ? htmlspecialchars($x['target_type'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['comment_policy'] = (($x['comment_scope']) ? htmlspecialchars($x['comment_scope'], ENT_COMPAT,'UTF-8',false) : 'contacts');
- $arr['sig'] = (($x['signature']) ? htmlentities($x['signature'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['sig'] = (($x['signature']) ? htmlspecialchars($x['signature'], ENT_COMPAT,'UTF-8',false) : '');
$arr['object'] = activity_sanitise($x['object']);
@@ -667,7 +680,6 @@ function get_item_elements($x) {
$arr['body'] = json_encode(crypto_encapsulate($arr['body'],$key));
}
-
return $arr;
}
@@ -810,7 +822,7 @@ function encode_item_xchan($xchan) {
function encode_item_terms($terms) {
$ret = array();
- $allowed_export_terms = array( TERM_UNKNOWN, TERM_HASHTAG, TERM_MENTION, TERM_CATEGORY );
+ $allowed_export_terms = array( TERM_UNKNOWN, TERM_HASHTAG, TERM_MENTION, TERM_CATEGORY, TERM_BOOKMARK );
if($terms) {
foreach($terms as $term) {
@@ -822,7 +834,7 @@ function encode_item_terms($terms) {
}
function termtype($t) {
- $types = array('unknown','hashtag','mention','category','private_category','file','search');
+ $types = array('unknown','hashtag','mention','category','private_category','file','search','thing','bookmark');
return(($types[$t]) ? $types[$t] : 'unknown');
}
@@ -832,8 +844,8 @@ function decode_tags($t) {
$ret = array();
foreach($t as $x) {
$tag = array();
- $tag['term'] = htmlentities($x['tag'], ENT_COMPAT,'UTF-8',false);
- $tag['url'] = htmlentities($x['url'], ENT_COMPAT,'UTF-8',false);
+ $tag['term'] = htmlspecialchars($x['tag'], ENT_COMPAT,'UTF-8',false);
+ $tag['url'] = htmlspecialchars($x['url'], ENT_COMPAT,'UTF-8',false);
switch($x['type']) {
case 'hashtag':
$tag['type'] = TERM_HASHTAG;
@@ -853,6 +865,12 @@ function decode_tags($t) {
case 'search':
$tag['type'] = TERM_SEARCH;
break;
+ case 'thing':
+ $tag['type'] = TERM_THING;
+ break;
+ case 'bookmark':
+ $tag['type'] = TERM_BOOKMARK;
+ break;
default:
case 'unknown':
$tag['type'] = TERM_UNKNOWN;
@@ -876,12 +894,12 @@ function activity_sanitise($arr) {
if(is_array($x))
$ret[$k] = activity_sanitise($x);
else
- $ret[$k] = htmlentities($x, ENT_COMPAT,'UTF-8',false);
+ $ret[$k] = htmlspecialchars($x, ENT_COMPAT,'UTF-8',false);
}
return $ret;
}
else {
- return htmlentities($arr, ENT_COMPAT,'UTF-8', false);
+ return htmlspecialchars($arr, ENT_COMPAT,'UTF-8', false);
}
}
return '';
@@ -893,7 +911,7 @@ function array_sanitise($arr) {
if($arr) {
$ret = array();
foreach($arr as $x) {
- $ret[] = htmlentities($x, ENT_COMPAT,'UTF-8',false);
+ $ret[] = htmlspecialchars($x, ENT_COMPAT,'UTF-8',false);
}
return $ret;
}
@@ -958,8 +976,8 @@ function get_mail_elements($x) {
$arr = array();
- $arr['body'] = (($x['body']) ? htmlentities($x['body'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['title'] = (($x['title'])? htmlentities($x['title'],ENT_COMPAT,'UTF-8',false) : '');
+ $arr['body'] = (($x['body']) ? htmlspecialchars($x['body'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['title'] = (($x['title'])? htmlspecialchars($x['title'],ENT_COMPAT,'UTF-8',false) : '');
$arr['created'] = datetime_convert('UTC','UTC',$x['created']);
if((! array_key_exists('expires',$x)) || ($x['expires'] === '0000-00-00 00:00:00'))
@@ -977,18 +995,18 @@ function get_mail_elements($x) {
$key = get_config('system','pubkey');
$arr['mail_flags'] |= MAIL_OBSCURED;
- $arr['body'] = htmlentities($arr['body'],ENT_COMPAT,'UTF-8',false);
+ $arr['body'] = htmlspecialchars($arr['body'],ENT_COMPAT,'UTF-8',false);
if($arr['body'])
$arr['body'] = json_encode(crypto_encapsulate($arr['body'],$key));
- $arr['title'] = htmlentities($arr['title'],ENT_COMPAT,'UTF-8',false);
+ $arr['title'] = htmlspecialchars($arr['title'],ENT_COMPAT,'UTF-8',false);
if($arr['title'])
$arr['title'] = json_encode(crypto_encapsulate($arr['title'],$key));
if($arr['created'] > datetime_convert())
$arr['created'] = datetime_convert();
- $arr['mid'] = (($x['message_id']) ? htmlentities($x['message_id'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['parent_mid'] = (($x['message_parent']) ? htmlentities($x['message_parent'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['mid'] = (($x['message_id']) ? htmlspecialchars($x['message_id'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['parent_mid'] = (($x['message_parent']) ? htmlspecialchars($x['message_parent'], ENT_COMPAT,'UTF-8',false) : '');
if($x['attach'])
$arr['attach'] = activity_sanitise($x['attach']);
@@ -1017,18 +1035,18 @@ function get_profile_elements($x) {
else
return array();
- $arr['desc'] = (($x['title']) ? htmlentities($x['title'],ENT_COMPAT,'UTF-8',false) : '');
+ $arr['desc'] = (($x['title']) ? htmlspecialchars($x['title'],ENT_COMPAT,'UTF-8',false) : '');
$arr['dob'] = datetime_convert('UTC','UTC',$x['birthday'],'Y-m-d');
$arr['age'] = (($x['age']) ? intval($x['age']) : 0);
- $arr['gender'] = (($x['gender']) ? htmlentities($x['gender'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['marital'] = (($x['marital']) ? htmlentities($x['marital'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['sexual'] = (($x['sexual']) ? htmlentities($x['sexual'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['locale'] = (($x['locale']) ? htmlentities($x['locale'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['region'] = (($x['region']) ? htmlentities($x['region'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['postcode'] = (($x['postcode']) ? htmlentities($x['postcode'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['country'] = (($x['country']) ? htmlentities($x['country'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['gender'] = (($x['gender']) ? htmlspecialchars($x['gender'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['marital'] = (($x['marital']) ? htmlspecialchars($x['marital'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['sexual'] = (($x['sexual']) ? htmlspecialchars($x['sexual'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['locale'] = (($x['locale']) ? htmlspecialchars($x['locale'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['region'] = (($x['region']) ? htmlspecialchars($x['region'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['postcode'] = (($x['postcode']) ? htmlspecialchars($x['postcode'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['country'] = (($x['country']) ? htmlspecialchars($x['country'], ENT_COMPAT,'UTF-8',false) : '');
$arr['keywords'] = (($x['keywords'] && is_array($x['keywords'])) ? array_sanitise($x['keywords']) : array());
@@ -1606,6 +1624,8 @@ function item_store($arr,$allow_exec = false) {
if(! $arr['plink'])
$arr['plink'] = $arr['llink'];
+
+
if($arr['parent_mid'] === $arr['mid']) {
$parent_id = 0;
$parent_deleted = 0;
@@ -2087,6 +2107,17 @@ function send_status_notifications($post_id,$item) {
}
}
+ $link = get_app()->get_baseurl() . '/display/' . $item['mid'];
+
+
+ $y = q("select id from notify where link = '%s' and uid = %d limit 1",
+ dbesc($link),
+ intval($item['uid'])
+ );
+
+ if($y)
+ $notify = false;
+
if(! $notify)
return;
require_once('include/enotify.php');
@@ -2095,7 +2126,7 @@ function send_status_notifications($post_id,$item) {
'from_xchan' => $item['author_xchan'],
'to_xchan' => $r[0]['channel_hash'],
'item' => $item,
- 'link' => get_app()->get_baseurl() . '/display/' . $item['mid'],
+ 'link' => $link,
'verb' => ACTIVITY_POST,
'otype' => 'item',
'parent' => $parent,
@@ -2150,6 +2181,34 @@ function tag_deliver($uid,$item_id) {
$item = $i[0];
+ $terms = get_terms_oftype($item['term'],TERM_BOOKMARK);
+
+ if($terms && (! $item['item_restrict'])) {
+ logger('tag_deliver: found bookmark');
+ $bookmark_self = intval(get_pconfig($uid,'system','bookmark_self'));
+ if(perm_is_allowed($u[0]['channel_id'],$item['author_xchan'],'bookmark') && (($item['author_xchan'] != $u[0]['channel_hash']) || ($bookmark_self))) {
+ require_once('include/bookmarks.php');
+ require_once('include/Contact.php');
+
+ $s = q("select * from xchan where xchan_hash = '%s' limit 1",
+ dbesc($item['author_xchan'])
+ );
+ if($s) {
+ foreach($terms as $t) {
+ bookmark_add($u[0],$s[0],$t,$item['item_private']);
+ }
+ }
+ }
+ }
+
+ if(($item['source_xchan']) && ($item['item_flags'] & ITEM_UPLINK) && ($item['item_flags'] & ITEM_THREAD_TOP) && ($item['edited'] != $item['created'])) {
+ // this is an update to a post which was already processed by us and has a second delivery chain
+ // Just start the second delivery chain to deliver the updated post
+ proc_run('php','include/notifier.php','tgroup',$item['id']);
+ return;
+ }
+
+
if($item['obj_type'] === ACTIVITY_OBJ_TAGTERM) {
// We received a community tag activity for a post.
@@ -2245,7 +2304,7 @@ function tag_deliver($uid,$item_id) {
if($terms) {
foreach($terms as $term) {
- if(($term['term'] == $u[0]['channel_name']) && link_compare($term['url'],$link)) {
+ if((strcasecmp($term['term'],$u[0]['channel_name']) == 0) && link_compare($term['url'],$link)) {
$mention = true;
break;
}
@@ -2278,7 +2337,7 @@ function tag_deliver($uid,$item_id) {
$body = preg_replace('/\[share(.*?)\[\/share\]/','',$body);
- $pattern = '/@\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($u[0]['channel_name'],'/') . '\[\/zrl\]/';
+ $pattern = '/@\!?\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($u[0]['channel_name'],'/') . '\[\/zrl\]/';
if(! preg_match($pattern,$body,$matches)) {
logger('tag_deliver: mention was in a reshare - ignoring');
@@ -2308,8 +2367,10 @@ function tag_deliver($uid,$item_id) {
}
- if((! $mention) && (! $union))
+ if((! $mention) && (! $union)) {
+ logger('tag_deliver: no mention and no union.');
return;
+ }
// tgroup delivery - setup a second delivery chain
@@ -2363,12 +2424,13 @@ function tgroup_check($uid,$item) {
$mention = false;
// check that the message originated elsewhere and is a top-level post
- // or is a followup and we have already accepted the top level post
+ // or is a followup and we have already accepted the top level post as an uplink
if($item['mid'] != $item['parent_mid']) {
- $r = q("select id from item where mid = '%s' and uid = %d limit 1",
+ $r = q("select id from item where mid = '%s' and uid = %d and ( item_flags & %d ) limit 1",
dbesc($item['parent_mid']),
- intval($uid)
+ intval($uid),
+ intval(ITEM_UPLINK)
);
if($r)
return true;
@@ -2411,7 +2473,7 @@ function tgroup_check($uid,$item) {
$body = preg_replace('/\[share(.*?)\[\/share\]/','',$item['body']);
- $pattern = '/@\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($u[0]['channel_name'],'/') . '\[\/zrl\]/';
+ $pattern = '/@\!?\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($u[0]['channel_name'],'/') . '\[\/zrl\]/';
if(! preg_match($pattern,$body,$matches)) {
logger('tgroup_check: mention was in a reshare - ignoring');
@@ -2442,9 +2504,9 @@ function check_item_source($uid,$item) {
return false;
- $r = q("select * from source where src_channel_id = %d and src_xchan = '%s' limit 1",
+ $r = q("select * from source where src_channel_id = %d and ( src_xchan = '%s' || src_xchan = '*' ) limit 1",
intval($uid),
- dbesc($item['owner_xchan'])
+ dbesc(($item['source_xchan']) ? $item['source_xchan'] : $item['owner_xchan'])
);
if(! $r)
@@ -2478,7 +2540,7 @@ function check_item_source($uid,$item) {
foreach($words as $word) {
if(substr($word,0,1) === '#' && $tags) {
foreach($tags as $t)
- if($t['type'] == TERM_HASHTAG && substr($t,1) === $word)
+ if(($t['type'] == TERM_HASHTAG) && ((substr($t,1) === substr($word,1)) || (substr($word,1) === '*')))
return true;
}
if(stristr($text,$word) !== false)
@@ -3695,23 +3757,28 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
$def_acl = '';
$item_uids = ' true ';
-
+
+ if ($arr['uid']) $uid= $arr['uid'];
+
if($channel) {
$uid = $channel['channel_id'];
$uidhash = $channel['channel_hash'];
$item_uids = " item.uid = " . intval($uid) . " ";
}
-
+
if($arr['star'])
$sql_options .= " and (item_flags & " . intval(ITEM_STARRED) . ") ";
if($arr['wall'])
$sql_options .= " and (item_flags & " . intval(ITEM_WALL) . ") ";
-
+
$sql_extra = " AND item.parent IN ( SELECT parent FROM item WHERE (item_flags & " . intval(ITEM_THREAD_TOP) . ") $sql_options ) ";
-
+
+ if($arr['since_id'])
+ $sql_extra .= " and item.id > " . $since_id . " ";
+
if($arr['gid'] && $uid) {
- $r = q("SELECT * FROM `group` WHERE id = %d AND uid = %d LIMIT 1",
+ $r = q("SELECT * FROM `groups` WHERE id = %d AND uid = %d LIMIT 1",
intval($arr['group']),
intval($uid)
);
@@ -3789,6 +3856,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
);
}
+
if(($client_mode & CLIENT_MODE_UPDATE) && (! ($client_mode & CLIENT_MODE_LOAD))) {
// only setup pagination on initial page view
@@ -3801,6 +3869,8 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
$pager_sql = sprintf(" LIMIT %d, %d ",intval(get_app()->pager['start']), intval(get_app()->pager['itemspage']));
}
+ if(isset($arr['start']) && isset($arr['records']))
+ $pager_sql = sprintf(" LIMIT %d, %d ",intval($arr['start']), intval($arr['records']));
if(($arr['cmin'] != 0) || ($arr['cmax'] != 99)) {
@@ -3835,7 +3905,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
$item_restrict = " AND item_restrict = 0 ";
- if($arr['nouveau'] && ($client_mode & CLIENT_MODELOAD) && $channel) {
+ if($arr['nouveau'] && ($client_mode & CLIENT_MODE_LOAD) && $channel) {
// "New Item View" - show all items unthreaded in reverse created date order
$items = q("SELECT item.*, item.id AS item_id FROM item
@@ -3860,7 +3930,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
else
$ordering = "commented";
- if(($client_mode & CLIENT_MODE_LOAD) || ($client_mode & CLIENT_MODE_NORMAL)) {
+ if(($client_mode & CLIENT_MODE_LOAD) || ($client_mode == CLIENT_MODE_NORMAL)) {
// Fetch a page full of parent items for this page
@@ -3873,7 +3943,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
ORDER BY item.$ordering DESC $pager_sql ",
intval(ABOOK_FLAG_BLOCKED)
);
-
+
}
else {
// update
@@ -3928,3 +3998,52 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
return $items;
}
+
+
+function update_remote_id($channel,$post_id,$webpage,$pagetitle,$namespace,$remote_id,$mid) {
+
+ $page_type = '';
+
+ if($webpage & ITEM_WEBPAGE)
+ $page_type = 'WEBPAGE';
+ elseif($webpage & ITEM_BUILDBLOCK)
+ $page_type = 'BUILDBLOCK';
+ elseif($webpage & ITEM_PDL)
+ $page_type = 'PDL';
+ elseif($namespace && $remote_id) {
+ $page_type = $namespace;
+ $pagetitle = $remote_id;
+ }
+
+ if($page_type) {
+
+ // store page info as an alternate message_id so we can access it via
+ // https://sitename/page/$channelname/$pagetitle
+ // if no pagetitle was given or it couldn't be transliterated into a url, use the first
+ // sixteen bytes of the mid - which makes the link portable and not quite as daunting
+ // as the entire mid. If it were the post_id the link would be less portable.
+
+ $r = q("select * from item_id where iid = %d and uid = %d and service = '%s' limit 1",
+ intval($post_id),
+ intval($channel['channel_id']),
+ dbesc($page_type)
+ );
+ if($r) {
+ q("update item_id set sid = '%s' where id = %d limit 1",
+ dbesc(($pagetitle) ? $pagetitle : substr($mid,0,16)),
+ intval($r[0]['id'])
+ );
+ }
+ else {
+ q("insert into item_id ( iid, uid, sid, service ) values ( %d, %d, '%s','%s' )",
+ intval($post_id),
+ intval($channel['channel_id']),
+ dbesc(($pagetitle) ? $pagetitle : substr($mid,0,16)),
+ dbesc($page_type)
+ );
+ }
+ }
+
+}
+
+
diff --git a/include/menu.php b/include/menu.php
index c10a669b3..b879af845 100644
--- a/include/menu.php
+++ b/include/menu.php
@@ -1,6 +1,7 @@
<?php /** @file */
require_once('include/security.php');
+require_once('include/bbcode.php');
function menu_fetch($name,$uid,$observer_xchan) {
@@ -23,15 +24,17 @@ function menu_fetch($name,$uid,$observer_xchan) {
return null;
}
-
function menu_render($menu) {
if(! $menu)
return '';
- for($x = 0; $x < count($menu['items']); $x ++)
- if($menu['items']['mitem_flags'] & MENU_ITEM_ZID)
- $menu['items']['mitem_link'] = zid($menu['items']['mitem_link']);
- if($menu['items']['mitem_flags'] & MENU_ITEM_NEWWIN)
- $menu['items']['newwin'] = '1';
+
+ for($x = 0; $x < count($menu['items']); $x ++) {
+ if($menu['items'][$x]['mitem_flags'] & MENU_ITEM_ZID)
+ $menu['items'][$x]['mitem_link'] = zid($menu['items'][$x]['mitem_link']);
+ if($menu['items'][$x]['mitem_flags'] & MENU_ITEM_NEWWIN)
+ $menu['items'][$x]['newwin'] = '1';
+ $menu['items'][$x]['mitem_desc'] = bbcode($menu['items'][$x]['mitem_desc']);
+ }
return replace_macros(get_markup_template('usermenu.tpl'),array(
'$menu' => $menu['menu'],
@@ -58,6 +61,8 @@ 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;
@@ -65,6 +70,9 @@ function menu_create($arr) {
if(! $menu_name)
return false;
+ if(! $menu_flags)
+ $menu_flags = 0;
+
$menu_channel_id = intval($arr['menu_channel_id']);
@@ -76,10 +84,11 @@ function menu_create($arr) {
if($r)
return false;
- $r = q("insert into menu ( menu_name, menu_desc, menu_channel_id )
- values( '%s', '%s', %d )",
+ $r = q("insert into menu ( menu_name, menu_desc, menu_flags, menu_channel_id )
+ values( '%s', '%s', %d, %d )",
dbesc($menu_name),
dbesc($menu_desc),
+ intval($menu_flags),
intval($menu_channel_id)
);
if(! $r)
@@ -95,8 +104,19 @@ function menu_create($arr) {
}
-function menu_list($channel_id) {
- $r = q("select * from menu where menu_channel_id = %d order by menu_name",
+/**
+ * If $flags is present, check that all the bits in $flags are set
+ * so that MENU_SYSTEM|MENU_BOOKMARK will return entries with both
+ * bits set. We will use this to find system generated bookmarks.
+ */
+
+function menu_list($channel_id, $name = '', $flags = 0) {
+
+ $sel_options = '';
+ $sel_options .= (($name) ? " and menu_name = '" . protect_sprintf(dbesc($name)) . "' " : '');
+ $sel_options .= (($flags) ? " and menu_flags = " . intval($flags) . " " : '');
+
+ $r = q("select * from menu where menu_channel_id = %d $sel_options order by menu_desc",
intval($channel_id)
);
return $r;
@@ -110,6 +130,7 @@ function menu_edit($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;
@@ -117,6 +138,9 @@ function menu_edit($arr) {
if(! $menu_name)
return false;
+ if(! $menu_flags)
+ $menu_flags = 0;
+
$menu_channel_id = intval($arr['menu_channel_id']);
@@ -139,21 +163,11 @@ function menu_edit($arr) {
return false;
}
-
- $r = q("select * from menu where menu_name = '%s' and menu_channel_id = %d and menu_desc = '%s' limit 1",
- dbesc($menu_name),
- intval($menu_channel_id),
- dbesc($menu_desc)
- );
-
- if($r)
- return false;
-
-
- return q("update menu set menu_name = '%s', menu_desc = '%s'
+ return q("update menu set menu_name = '%s', menu_desc = '%s', menu_flags = %d
where menu_id = %d and menu_channel_id = %d limit 1",
dbesc($menu_name),
dbesc($menu_desc),
+ intval($menu_flags),
intval($menu_id),
intval($menu_channel_id)
);
@@ -201,7 +215,8 @@ function menu_add_item($menu_id, $uid, $arr) {
$channel = get_app()->get_channel();
}
- if ((! $arr['contact_allow'])
+ if (($channel)
+ && (! $arr['contact_allow'])
&& (! $arr['group_allow'])
&& (! $arr['contact_deny'])
&& (! $arr['group_deny'])) {
@@ -220,11 +235,11 @@ function menu_add_item($menu_id, $uid, $arr) {
$str_contact_deny = perms2str($arr['contact_deny']);
}
-
- $allow_cid = perms2str($arr['allow_cid']);
- $allow_gid = perms2str($arr['allow_gid']);
- $deny_cid = perms2str($arr['deny_cid']);
- $deny_gid = perms2str($arr['deny_gid']);
+// 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']);
$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),
diff --git a/include/nav.php b/include/nav.php
index f89de2de0..8fef4a1f9 100644
--- a/include/nav.php
+++ b/include/nav.php
@@ -75,10 +75,14 @@ EOT;
$nav['usermenu'][] = Array('channel/' . $channel['channel_address'], t('Home'), "", t('Your posts and conversations'));
$nav['usermenu'][] = Array('profile/' . $channel['channel_address'], t('View Profile'), "", t('Your profile page'));
if(feature_enabled(local_user(),'multi_profiles'))
- $nav['usermenu'][] = Array('profiles', t('Edit Profiles'),"", t('Manage/Edit Profiles'));
+ $nav['usermenu'][] = Array('profiles', t('Edit Profiles'),"", t('Manage/Edit profiles'));
$nav['usermenu'][] = Array('photos/' . $channel['channel_address'], t('Photos'), "", t('Your photos'));
-// $nav['usermenu'][] = Array('events/', t('Events'), "", t('Your events'));
-
+ $nav['usermenu'][] = Array('cloud/' . $channel['channel_address'],t('Files'),"",t('Your files'));
+ $nav['usermenu'][] = Array('chat/' . $channel['channel_address'],t('Chat'),"",t('Your chatrooms'));
+ $nav['usermenu'][] = Array('events', t('Events'), "", t('Your events'));
+ $nav['usermenu'][] = Array('bookmarks', t('Bookmarks'), "", t('Your bookmarks'));
+ if(feature_enabled($channel['channel_id'],'webpages'))
+ $nav['usermenu'][] = Array('webpages/' . $channel['channel_address'],t('Webpages'),"",t('Your webpages'));
}
else {
if(! get_account_id())
@@ -165,7 +169,7 @@ EOT;
$nav['messages']['mark'] = array('', t('Mark all private messages seen'), '','');
$nav['messages']['inbox'] = array('message', t('Inbox'), "", t('Inbox'));
$nav['messages']['outbox']= array('message/sent', t('Outbox'), "", t('Outbox'));
- $nav['messages']['new'] = array('message/new', t('New Message'), "", t('New Message'));
+ $nav['messages']['new'] = array('mail/new', t('New Message'), "", t('New Message'));
$nav['all_events'] = array('events', t('Events'), "", t('Event Calendar'));
@@ -196,7 +200,7 @@ EOT;
$banner = get_config('system','banner');
if($banner === false)
- $banner = 'red';
+ $banner = get_config('system','sitename');
$x = array('nav' => $nav, 'usermenu' => $userinfo );
call_hooks('nav', $x);
diff --git a/include/network.php b/include/network.php
index 50f853ca0..1fb4beaa7 100644
--- a/include/network.php
+++ b/include/network.php
@@ -78,7 +78,7 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
@curl_setopt($ch, CURLOPT_BINARYTRANSFER,1);
- // don't let curl abort the entire application
+ // don't let curl abort the entire application'
// if it throws any errors.
$s = @curl_exec($ch);
@@ -86,7 +86,7 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
$base = $s;
$curl_info = @curl_getinfo($ch);
$http_code = $curl_info['http_code'];
-// logger('fetch_url:' . $http_code . ' data: ' . $s);
+ //logger('fetch_url:' . $http_code . ' data: ' . $s);
$header = '';
// Pull out multiple headers, e.g. proxy and continuation headers
@@ -129,7 +129,7 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
function z_post_url($url,$params, $redirects = 0, $opts = array()) {
-
+
$ret = array('return_code' => 0, 'success' => false, 'header' => "", 'body' => "");
$ch = curl_init($url);
@@ -548,7 +548,7 @@ function avatar_img($email) {
call_hooks('avatar_lookup', $avatar);
if(! $avatar['success'])
- $avatar['url'] = $a->get_baseurl() . '/images/default_profile_photos/rainbow_man/175.jpg';
+ $avatar['url'] = $a->get_baseurl() . '/' . get_default_profile_photo();
logger('Avatar: ' . $avatar['email'] . ' ' . $avatar['url'], LOGGER_DEBUG);
return $avatar['url'];
@@ -582,7 +582,7 @@ function scale_external_images($s, $include_link = true, $scale_replace = false)
$a = get_app();
// Picture addresses can contain special characters
- $s = htmlspecialchars_decode($s);
+ $s = htmlspecialchars_decode($s, ENT_COMPAT);
$matches = null;
$c = preg_match_all('/\[img(.*?)\](.*?)\[\/img\]/ism',$s,$matches,PREG_SET_ORDER);
diff --git a/include/notifier.php b/include/notifier.php
index 0868ac77e..81f971107 100644
--- a/include/notifier.php
+++ b/include/notifier.php
@@ -425,8 +425,28 @@ function notifier_run($argv, $argc){
$sql_extra = (($private) ? "" : " or hubloc_url = '" . dbesc(z_root()) . "' ");
- $r = q("select hubloc_sitekey, hubloc_flags, hubloc_callback, hubloc_host from hubloc
- where hubloc_hash in (" . implode(',',$recipients) . ") $sql_extra group by hubloc_sitekey");
+
+ 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.
+ // In this case we'll pick the most recently contacted hub, as their primary might be down and the most
+ // recently contacted has the best chance of being alive.
+
+ // For private posts or uplinks we have to do things differently as only the sending clone will have the recipient list.
+ // We have to send to all clone channels of the owner to find out who has the definitive list. Posts with
+ // item_private set (but no ACL list) will return empty recipients (except for the sender and owner) in
+ // collect_recipients() above. The end result is we should get only one delivery per delivery chain if we
+ // aren't the owner or author.
+
+
+ $r = q("select hubloc_sitekey, hubloc_flags, hubloc_callback, hubloc_host from hubloc
+ where hubloc_hash in (" . implode(',',$recipients) . ") group by hubloc_sitekey order by hubloc_connected desc limit 1");
+ }
+ else {
+ $r = q("select hubloc_sitekey, hubloc_flags, hubloc_callback, hubloc_host from hubloc
+ where hubloc_hash in (" . implode(',',$recipients) . ") $sql_extra group by hubloc_sitekey");
+ }
+
if(! $r) {
logger('notifier: no hubs');
return;
diff --git a/include/oembed.php b/include/oembed.php
index 520b69892..d8671a752 100755
--- a/include/oembed.php
+++ b/include/oembed.php
@@ -1,12 +1,10 @@
<?php /** @file */
function oembed_replacecb($matches){
-// logger('oembedcb');
+
$embedurl=$matches[1];
$j = oembed_fetch_url($embedurl);
- $s = oembed_format_object($j);
- return $s;//oembed_iframe($s,$j->width,$j->height);
-
-
+ $s = oembed_format_object($j);
+ return $s;
}
@@ -26,7 +24,21 @@ function oembed_fetch_url($embedurl){
if(is_null($txt)){
$txt = "";
- if (!in_array($ext, $noexts)){
+ if (in_array($ext, $noexts)) {
+ $m = @parse_url($embedurl);
+ $zrl = false;
+ if($m['host']) {
+ $r = q("select hubloc_url from hubloc where hubloc_host = '%s' limit 1",
+ dbesc($m['host'])
+ );
+ if($r)
+ $zrl = true;
+ }
+ if($zrl) {
+ $embedurl = zid($embedurl);
+ }
+ }
+ else {
// try oembed autodiscovery
$redirects = 0;
@@ -57,12 +69,6 @@ function oembed_fetch_url($embedurl){
call_hooks('oembed_probe',$x);
if(array_key_exists('embed',$x))
$txt = $x['embed'];
-
- // try oohembed service
-// $ourl = "http://oohembed.com/oohembed/?url=".urlencode($embedurl).'&maxwidth=' . $a->videowidth;
-// $result = z_fetch_url($ourl);
-// if($result['success'])
-// $txt = $result['body'];
}
$txt=trim($txt);
@@ -82,6 +88,7 @@ function oembed_format_object($j){
$a = get_app();
$embedurl = $j->embedurl;
$jhtml = oembed_iframe($j->embedurl,(isset($j->width) ? $j->width : null), (isset($j->height) ? $j->height : null) );
+
$ret="<span class='oembed ".$j->type."'>";
switch ($j->type) {
case "video": {
diff --git a/include/permissions.php b/include/permissions.php
index 45ea7c3eb..420591c54 100644
--- a/include/permissions.php
+++ b/include/permissions.php
@@ -24,11 +24,12 @@ function get_perms() {
'post_mail' => array('channel_w_mail', intval(PERMS_W_MAIL), false, t('Can send me private mail messages'), ''),
'post_photos' => array('channel_w_photos', intval(PERMS_W_PHOTOS), false, t('Can post photos to my photo albums'), ''),
'tag_deliver' => array('channel_w_tagwall', intval(PERMS_W_TAGWALL), false, t('Can forward to all my channel contacts via post @mentions'), t('Advanced - useful for creating group forum channels')),
- 'chat' => array('channel_w_chat', intval(PERMS_W_CHAT), false, t('Can chat with me (when available)'), t('Requires compatible chat plugin')),
+ 'chat' => array('channel_w_chat', intval(PERMS_W_CHAT), false, t('Can chat with me (when available)'), t('')),
'write_storage' => array('channel_w_storage', intval(PERMS_W_STORAGE), false, t('Can write to my "public" file storage'), ''),
'write_pages' => array('channel_w_pages', intval(PERMS_W_PAGES), false, t('Can edit my "public" pages'), ''),
'republish' => array('channel_a_republish', intval(PERMS_A_REPUBLISH), false, t('Can source my "public" posts in derived channels'), t('Somewhat advanced - very useful in open communities')),
+ 'bookmark' => array('channel_a_bookmark', intval(PERMS_A_BOOKMARK), false, t('Can send me bookmarks'), 'Bookmarks from this person will automatically be saved'),
'delegate' => array('channel_a_delegate', intval(PERMS_A_DELEGATE), false, t('Can administer my channel resources'), t('Extremely advanced. Leave this alone unless you know what you are doing')),
);
$ret = array('global_permissions' => $global_perms);
diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php
index 8730b4298..c2eeafa54 100644
--- a/include/photo/photo_driver.php
+++ b/include/photo/photo_driver.php
@@ -357,7 +357,7 @@ abstract class photo_driver {
dbesc($p['resource_id']),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
- dbesc(basename($filename)),
+ dbesc(basename($p['filename'])),
dbesc($this->getType()),
dbesc($p['album']),
intval($this->getHeight()),
@@ -513,20 +513,28 @@ function guess_image_type($filename, $headers = '') {
}
-function import_profile_photo($photo,$xchan) {
+function import_profile_photo($photo,$xchan,$thing = false) {
$a = get_app();
+ $flags = (($thing) ? PHOTO_THING : PHOTO_XCHAN);
+ $album = (($thing) ? 'Things' : 'Contact Photos');
+
logger('import_profile_photo: updating channel photo from ' . $photo . ' for ' . $xchan, LOGGER_DEBUG);
- $r = q("select resource_id from photo where xchan = '%s' and scale = 4 limit 1",
- dbesc($xchan)
- );
- if($r) {
- $hash = $r[0]['resource_id'];
- }
- else {
+ if($thing)
$hash = photo_new_resource();
+ else {
+ $r = q("select resource_id from photo where xchan = '%s' and (photo_flags & %d ) and scale = 4 limit 1",
+ dbesc($xchan),
+ intval(PHOTO_XCHAN)
+ );
+ if($r) {
+ $hash = $r[0]['resource_id'];
+ }
+ else {
+ $hash = photo_new_resource();
+ }
}
$photo_failure = false;
@@ -541,10 +549,30 @@ function import_profile_photo($photo,$xchan) {
$img = photo_factory($img_str, $type);
if($img->is_valid()) {
+ $width = $img->getWidth();
+ $height = $img->getHeight();
+
+ if($width && $height) {
+ if(($width / $height) > 1.2) {
+ // crop out the sides
+ $margin = $width - $height;
+ $img->cropImage(175,($margin / 2),0,$height,$height);
+ }
+ elseif(($height / $width) > 1.2) {
+ // crop out the bottom
+ $margin = $height - $width;
+ $img->cropImage(175,0,0,$width,$width);
- $img->scaleImageSquare(175);
+ }
+ else {
+ $img->scaleImageSquare(175);
+ }
+
+ }
+ else
+ $photo_failure = true;
- $p = array('xchan' => $xchan,'resource_id' => $hash, 'filename' => 'Contact Photos', 'photo_flags' => PHOTO_XCHAN, 'scale' => 4);
+ $p = array('xchan' => $xchan,'resource_id' => $hash, 'filename' => basename($photo), 'album' => $album, 'photo_flags' => $flags, 'scale' => 4);
$r = $img->save($p);
@@ -576,9 +604,9 @@ function import_profile_photo($photo,$xchan) {
$photo_failure = true;
}
if($photo_failure) {
- $photo = $a->get_baseurl() . '/images/default_profile_photos/rainbow_man/175.jpg';
- $thumb = $a->get_baseurl() . '/images/default_profile_photos/rainbow_man/80.jpg';
- $micro = $a->get_baseurl() . '/images/default_profile_photos/rainbow_man/48.jpg';
+ $photo = $a->get_baseurl() . '/' . get_default_profile_photo();
+ $thumb = $a->get_baseurl() . '/' . get_default_profile_photo(80);
+ $micro = $a->get_baseurl() . '/' . get_default_profile_photo(48);
$type = 'image/jpeg';
}
diff --git a/include/photos.php b/include/photos.php
index ea4b494e0..82af4aaeb 100644
--- a/include/photos.php
+++ b/include/photos.php
@@ -77,6 +77,7 @@ function photo_upload($channel, $observer, $args) {
$filesize = intval($_FILES['userfile']['size']);
$type = $_FILES['userfile']['type'];
}
+
if (! $type)
$type=guess_image_type($filename);
@@ -102,12 +103,10 @@ function photo_upload($channel, $observer, $args) {
$imagedata = @file_get_contents($src);
- $r = q("select sum(size) as total from photo where uid = %d and scale = 0 ",
- intval($channel_id)
+ $r = q("select sum(size) as total from photo where aid = %d and scale = 0 ",
+ intval($account_id)
);
-// FIXME service class limits should probably apply to accounts and not channels
-
$limit = service_class_fetch($channel_id,'photo_upload_limit');
if(($r) && ($limit !== false) && (($r[0]['total'] + strlen($imagedata)) > $limit)) {
@@ -218,6 +217,9 @@ function photo_upload($channel, $observer, $args) {
$arr['deny_gid'] = $str_group_deny;
$arr['verb'] = ACTIVITY_POST;
+ $arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $arr['mid'];
+
+
$arr['body'] = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash . ']'
. '[zmg]' . z_root() . "/photo/{$photo_hash}-{$smallest}.".$ph->getExt() . '[/zmg]'
. '[/zrl]';
@@ -267,7 +269,11 @@ function photos_albums_list($channel,$observer) {
if($albums) {
$ret['success'] = true;
foreach($albums as $k => $album) {
- $entry = array('text' => $album['album'], 'urlencode' => urlencode($album['album']),'bin2hex' => bin2hex($album['album']));
+ $entry = array(
+ 'text' => $album['album'],
+ 'url' => z_root() . '/photos/' . $channel['channel_address'] . '/album/' . bin2hex($album['album']),
+ 'urlencode' => urlencode($album['album']),
+ 'bin2hex' => bin2hex($album['album']));
$ret[] = $entry;
}
}
@@ -279,8 +285,16 @@ function photos_album_widget($channelx,$observer,$albums = null) {
$o = '';
- if(! $albums)
- $albums = photos_albums_list($channelx,$observer);
+ // If we weren't passed an album list, see if the photos module
+ // dropped one for us to find in $a->data['albums'].
+ // If all else fails, load it.
+
+ if(! $albums) {
+ if(array_key_exists('albums', get_app()->data))
+ $albums = get_app()->data['albums'];
+ else
+ $albums = photos_albums_list($channelx,$observer);
+ }
if($albums) {
$o = replace_macros(get_markup_template('photo_albums.tpl'),array(
@@ -311,13 +325,16 @@ function photos_list_photos($channel,$observer,$album = '') {
$ret = array('success' => false);
- $r = q("select resource_id, created, edited, title, `desc`, album, filename, `type`, height, width, `size`, `scale`, profile, photo_flags, allow_cid, allow_gid, deny_cid, deny_gid from photo where uid = %d and ( photo_flags = %d or photo_flags = %d ) $sql_extra ",
+ $r = q("select resource_id, created, edited, title, description, album, filename, type, height, width, size, scale, profile, photo_flags, allow_cid, allow_gid, deny_cid, deny_gid from photo where uid = %d and ( photo_flags = %d or photo_flags = %d ) $sql_extra ",
intval($channel_id),
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'];
+ }
$ret['success'] = true;
$ret['photos'] = $r;
}
@@ -398,6 +415,8 @@ function photos_create_item($channel, $creator_hash, $photo, $visible = false) {
$arr['allow_gid'] = $photo['allow_gid'];
$arr['deny_cid'] = $photo['deny_cid'];
$arr['deny_gid'] = $photo['deny_gid'];
+
+ $arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $arr['mid'];
$arr['body'] = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo['resource_id'] . ']'
. '[zmg]' . z_root() . '/photo/' . $photo['resource_id'] . '-' . $photo['scale'] . '[/zmg]'
diff --git a/include/plugin.php b/include/plugin.php
index 5ed2a1736..9982a48a2 100755
--- a/include/plugin.php
+++ b/include/plugin.php
@@ -494,6 +494,15 @@ function head_add_css($src,$media = 'screen') {
get_app()->css_sources[] = array($src,$media);
}
+
+function head_remove_css($src,$media = 'screen') {
+ $a = get_app();
+ $index = array_search(array($src,$media),$a->css_sources);
+ if($index !== false)
+ unset($a->css_sources[$index]);
+
+}
+
function head_get_css() {
$str = '';
$sources = get_app()->css_sources;
@@ -511,15 +520,44 @@ function format_css_if_exists($source) {
$path = theme_include($source[0]);
if($path)
- return '<link rel="stylesheet" href="' . z_root() . '/' . $path . '" type="text/css" media="' . $source[1] . '" />' . "\r\n";
+ return '<link rel="stylesheet" href="' . script_path() . '/' . $path . '" type="text/css" media="' . $source[1] . '" />' . "\r\n";
}
+function script_path() {
+ if(x($_SERVER,'HTTPS') && $_SERVER['HTTPS'])
+ $scheme = 'https';
+ elseif(x($_SERVER,'SERVER_PORT') && (intval($_SERVER['SERVER_PORT']) == 443))
+ $scheme = 'https';
+ else
+ $scheme = 'http';
+
+ if(x($_SERVER,'SERVER_NAME')) {
+ $hostname = $_SERVER['SERVER_NAME'];
+ }
+ else {
+ return z_root();
+ }
+
+ if(x($_SERVER,'SERVER_PORT') && $_SERVER['SERVER_PORT'] != 80 && $_SERVER['SERVER_PORT'] != 443) {
+ $hostname .= ':' . $_SERVER['SERVER_PORT'];
+ }
+
+ return $scheme . '://' . $hostname;
+}
function head_add_js($src) {
get_app()->js_sources[] = $src;
}
+function head_remove_js($src) {
+ $a = get_app();
+ $index = array_search($src,$a->js_sources);
+ if($index !== false)
+ unset($a->js_sources[$index]);
+
+}
+
function head_get_js() {
$str = '';
$sources = get_app()->js_sources;
@@ -536,7 +574,7 @@ function format_js_if_exists($source) {
else
$path = theme_include($source);
if($path)
- return '<script src="' . z_root() . '/' . $path . '" ></script>' . "\r\n" ;
+ return '<script src="' . script_path() . '/' . $path . '" ></script>' . "\r\n" ;
}
diff --git a/include/reddav.php b/include/reddav.php
index c24414610..af79a0db1 100644
--- a/include/reddav.php
+++ b/include/reddav.php
@@ -1,196 +1,1025 @@
<?php /** @file */
use Sabre\DAV;
- require_once('vendor/autoload.php');
+require_once('vendor/autoload.php');
-class RedInode implements DAV\INode {
+require_once('include/attach.php');
- private $attach;
+class RedDirectory extends DAV\Node implements DAV\ICollection, DAV\IQuota {
+
+ private $red_path;
+ private $folder_hash;
+ private $ext_path;
+ private $root_dir = '';
+ private $auth;
+ private $os_path = '';
+
+ function __construct($ext_path,&$auth_plugin) {
+ logger('RedDirectory::__construct() ' . $ext_path, LOGGER_DEBUG);
+ $this->ext_path = $ext_path;
+ $this->red_path = ((strpos($ext_path,'/cloud') === 0) ? substr($ext_path,6) : $ext_path);
+ if(! $this->red_path)
+ $this->red_path = '/';
+ $this->auth = $auth_plugin;
+ $this->folder_hash = '';
+
+ $this->getDir();
+
+ if($this->auth->browser)
+ $this->auth->browser->set_writeable();
- function __construct($attach) {
- $this->attach = $attach;
}
+ function getChildren() {
- function delete() {
- if(! perm_is_allowed($this->channel_id,'','view_storage'))
- return;
-
- /**
- * Since I don't believe this is documented elsewhere -
- * ATTACH_FLAG_OS means that the file contents are stored in the OS
- * rather than in the DB - as is the case for attachments.
- * Exactly how they are stored (what path and filename) are still
- * TBD. We will probably not be using the original filename but
- * instead the attachment 'hash' as this will prevent folks from
- * uploading PHP code onto misconfigured servers and executing it.
- * It's easy to misconfigure servers because we can provide a
- * rule for Apache, but folks using nginx will then be susceptible.
- * Then there are those who don't understand these kinds of exploits
- * and don't have any idea allowing uploaded PHP files to be executed
- * by the server could be a problem. We also don't have any idea what
- * executable types are served on their system - like .py, .pyc, .pl, .sh
- * .cgi, .exe, .bat, .net, whatever.
- */
-
- if($this->attach['flags'] & ATTACH_FLAG_OS) {
- // FIXME delete physical file
- }
- if($this->attach['flags'] & ATTACH_FLAG_DIR) {
- // FIXME delete contents (recursive?)
+ if(get_config('system','block_public') && (! $this->auth->channel_id) && (! $this->auth->observer)) {
+ throw new DAV\Exception\Forbidden('Permission denied.');
+ return;
}
+
+ if(($this->auth->owner_id) && (! perm_is_allowed($this->auth->owner_id,$this->auth->observer,'view_storage'))) {
+ throw new DAV\Exception\Forbidden('Permission denied.');
+ return;
+ }
+
+ $contents = RedCollectionData($this->red_path,$this->auth);
+ return $contents;
+ }
+
+
+ function getChild($name) {
+
+ logger('RedDirectory::getChild : ' . $name, LOGGER_DATA);
+
+ if(get_config('system','block_public') && (! $this->auth->channel_id) && (! $this->auth->observer)) {
+ throw new DAV\Exception\Forbidden('Permission denied.');
+ return;
+ }
+
+ if(($this->auth->owner_id) && (! perm_is_allowed($this->auth->owner_id,$this->auth->observer,'view_storage'))) {
+ throw new DAV\Exception\Forbidden('Permission denied.');
+ return;
+ }
+
+ if($this->red_path === '/' && $name === 'cloud') {
+ return new RedDirectory('/cloud', $this->auth);
+ }
+
+ $x = RedFileData($this->ext_path . '/' . $name, $this->auth);
+ if($x)
+ return $x;
+
+ throw new DAV\Exception\NotFound('The file with name: ' . $name . ' could not be found');
- q("delete from attach where id = %d limit 1",
- intval($this->attach['id'])
+ }
+
+ function getName() {
+ logger('RedDirectory::getName returns: ' . basename($this->red_path), LOGGER_DATA);
+ return (basename($this->red_path));
+ }
+
+
+
+
+ function createFile($name,$data = null) {
+ logger('RedDirectory::createFile : ' . $name, LOGGER_DEBUG);
+
+ if(! $this->auth->owner_id) {
+ logger('createFile: permission denied');
+ throw new DAV\Exception\Forbidden('Permission denied.');
+ return;
+ }
+
+ if(! perm_is_allowed($this->auth->owner_id,$this->auth->observer,'write_storage')) {
+ logger('createFile: permission denied');
+ throw new DAV\Exception\Forbidden('Permission denied.');
+ return;
+ }
+
+ $mimetype = z_mime_content_type($name);
+
+
+ $c = q("select * from channel where channel_id = %d and not (channel_pageflags & %d) limit 1",
+ intval($this->auth->owner_id),
+ intval(PAGE_REMOVED)
+
+ );
+
+ if(! $c) {
+ logger('createFile: no channel');
+ throw new DAV\Exception\Forbidden('Permission denied.');
+ return;
+ }
+
+
+ $filesize = 0;
+ $hash = random_string();
+
+ $r = q("INSERT INTO attach ( aid, uid, hash, creator, filename, folder, flags, filetype, filesize, revision, data, created, edited, allow_cid, allow_gid, deny_cid, deny_gid )
+ VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
+ intval($c[0]['channel_account_id']),
+ intval($c[0]['channel_id']),
+ dbesc($hash),
+ dbesc($this->auth->observer),
+ dbesc($name),
+ dbesc($this->folder_hash),
+ dbesc(ATTACH_FLAG_OS),
+ dbesc($mimetype),
+ intval($filesize),
+ intval(0),
+ dbesc($this->os_path . '/' . $hash),
+ dbesc(datetime_convert()),
+ dbesc(datetime_convert()),
+ dbesc($c[0]['channel_allow_cid']),
+ dbesc($c[0]['channel_allow_gid']),
+ dbesc($c[0]['channel_deny_cid']),
+ dbesc($c[0]['channel_deny_gid'])
+
+
);
+ $f = 'store/' . $this->auth->owner_nick . '/' . (($this->os_path) ? $this->os_path . '/' : '') . $hash;
+
+ file_put_contents($f, $data);
+ $size = filesize($f);
+
+ $edited = datetime_convert();
+
+ $d = q("update attach set filesize = '%s', edited = '%s' where hash = '%s' and uid = %d limit 1",
+ dbesc($size),
+ dbesc($edited),
+ dbesc($hash),
+ intval($c[0]['channel_id'])
+ );
+
+ $e = q("update attach set edited = '%s' where folder = '%s' and uid = %d limit 1",
+ dbesc($edited),
+ dbesc($this->folder_hash),
+ intval($c[0]['channel_id'])
+ );
+
+ $maxfilesize = get_config('system','maxfilesize');
+
+ if(($maxfilesize) && ($size > $maxfilesize)) {
+ attach_delete($c[0]['channel_id'],$hash);
+ return;
+ }
+
+ $limit = service_class_fetch($c[0]['channel_id'],'attach_upload_limit');
+ if($limit !== false) {
+ $x = q("select sum(filesize) as total from attach where aid = %d ",
+ intval($c[0]['channel_account_id'])
+ );
+ if(($x) && ($x[0]['total'] + $size > $limit)) {
+ logger('reddav: service class limit exceeded for ' . $c[0]['channel_name'] . ' total usage is ' . $x[0]['total'] . ' limit is ' . $limit);
+ attach_delete($c[0]['channel_id'],$hash);
+ return;
+ }
+ }
}
- function getName() {
- return $this->attach['filename'];
+
+ function createDirectory($name) {
+
+ logger('RedDirectory::createDirectory: ' . $name, LOGGER_DEBUG);
+
+ if((! $this->auth->owner_id) || (! perm_is_allowed($this->auth->owner_id,$this->auth->observer,'write_storage'))) {
+ throw new DAV\Exception\Forbidden('Permission denied.');
+ return;
+ }
+
+ $r = q("select * from channel where channel_id = %d and not (channel_pageflags & %d) limit 1",
+ intval($this->auth->owner_id),
+ intval(PAGE_REMOVED)
+ );
+
+ if($r) {
+ $result = attach_mkdir($r[0],$this->auth->observer,array('filename' => $name,'folder' => $this->folder_hash));
+ if(! $result['success'])
+ logger('RedDirectory::createDirectory: ' . print_r($result,true), LOGGER_DEBUG);
+ }
}
- function setName($newName) {
- if((! $newName) || (! perm_is_allowed($this->channel_id,'','view_storage')))
+ function childExists($name) {
+
+ if($this->red_path === '/' && $name === 'cloud') {
+ logger('RedDirectory::childExists /cloud: true', LOGGER_DATA);
+ return true;
+ }
+
+ $x = RedFileData($this->ext_path . '/' . $name, $this->auth,true);
+ logger('RedFileData returns: ' . print_r($x,true), LOGGER_DATA);
+ if($x)
+ return true;
+ return false;
+ }
+
+ function getDir() {
+ logger('getDir: ' . $this->ext_path, LOGGER_DEBUG);
+
+ $file = $this->ext_path;
+
+ $x = strpos($file,'/cloud');
+ if($x === false)
return;
+ if($x === 0) {
+ $file = substr($file,6);
+ }
- $this->attach['filename'] = $newName;
- $r = q("update attach set filename = '%s' where id = %d limit 1",
- dbesc($this->attach['filename']),
- intval($this->attach['id'])
+ if((! $file) || ($file === '/')) {
+ return;
+ }
+
+ $file = trim($file,'/');
+ $path_arr = explode('/', $file);
+
+ if(! $path_arr)
+ return;
+
+
+ logger('getDir(): path: ' . print_r($path_arr,true));
+
+ $channel_name = $path_arr[0];
+
+
+ $r = q("select channel_id from channel where channel_address = '%s' and not ( channel_pageflags & %d ) limit 1",
+ dbesc($channel_name),
+ intval(PAGE_REMOVED)
);
+ if(! $r) {
+ throw new DAV\Exception\NotFound('The file with name: ' . $channel_name . ' could not be found');
+
+ return;
+ }
+ $channel_id = $r[0]['channel_id'];
+ $this->auth->owner_id = $channel_id;
+ $this->auth->owner_nick = $channel_name;
+
+ $path = '/' . $channel_name;
+
+ $folder = '';
+ $os_path = '';
+
+ for($x = 1; $x < count($path_arr); $x ++) {
+
+ $r = q("select id, hash, filename, flags from attach where folder = '%s' and filename = '%s' and (flags & %d)",
+ dbesc($folder),
+ dbesc($path_arr[$x]),
+ intval($channel_id),
+ intval(ATTACH_FLAG_DIR)
+ );
+
+ if($r && ( $r[0]['flags'] & ATTACH_FLAG_DIR)) {
+ $folder = $r[0]['hash'];
+ if(strlen($os_path))
+ $os_path .= '/';
+ $os_path .= $folder;
+
+ $path = $path . '/' . $r[0]['filename'];
+ }
+ }
+ $this->folder_hash = $folder;
+ $this->os_path = $os_path;
+ return;
}
+
function getLastModified() {
- return $this->attach['edited'];
+ $r = q("select edited from attach where folder = '%s' and uid = %d order by edited desc limit 1",
+ dbesc($this->folder_hash),
+ intval($this->auth->owner_id)
+ );
+ if($r)
+ return datetime_convert('UTC','UTC', $r[0]['edited'],'U');
+ return '';
+ }
+
+
+ public function getQuotaInfo() {
+
+ $limit = disk_total_space('store');
+ $free = disk_free_space('store');
+
+ if($this->auth->owner_id) {
+
+ $c = q("select * from channel where channel_id = %d and not (channel_pageflags & %d) limit 1",
+ intval($this->auth->owner_id),
+ intval(PAGE_REMOVED)
+
+ );
+
+ $ulimit = service_class_fetch($c[0]['channel_id'],'attach_upload_limit');
+ $limit = (($ulimit) ? $ulimit : $limit);
+
+ $x = q("select sum(filesize) as total from attach where aid = %d ",
+ intval($c[0]['channel_account_id'])
+ );
+ $free = (($x) ? $limit - $x[0]['total'] : 0);
+ }
+
+ return array(
+ $limit - $free,
+ $free
+ );
+
}
}
-abstract class RedDirectory extends DAV\Node implements DAV\ICollection {
+class RedFile extends DAV\Node implements DAV\IFile {
- private $red_path;
- private $dir_key;
+ private $data;
private $auth;
- private $channel_id;
+ private $name;
- function __construct($red_path,$auth_plugin) {
- $this->red_path = $red_path;
- $this->auth = $auth_plugin;
+ function __construct($name, $data, &$auth) {
+ $this->name = $name;
+ $this->data = $data;
+ $this->auth = $auth;
+
+ logger('RedFile::_construct: ' . print_r($this->data,true), LOGGER_DATA);
}
- function getChildren() {
- if(! perm_is_allowed($this->channel_id,'','view_storage'))
- return array();
+ function getName() {
+ logger('RedFile::getName: ' . basename($this->name), LOGGER_DEBUG);
+ return basename($this->name);
+
+ }
+
+
+ function setName($newName) {
+ logger('RedFile::setName: ' . basename($this->name) . ' -> ' . $newName, LOGGER_DEBUG);
+
+ if((! $newName) || (! $this->auth->owner_id) || (! perm_is_allowed($this->auth->owner_id,$this->auth->observer,'write_storage'))) {
+ throw new DAV\Exception\Forbidden('Permission denied.');
+ return;
+ }
+
+ $newName = str_replace('/','%2F',$newName);
+
+ $r = q("update attach set filename = '%s' where hash = '%s' and id = %d limit 1",
+ dbesc($this->data['filename']),
+ intval($this->data['id'])
+ );
+
+ }
+
+
+ function put($data) {
+ logger('RedFile::put: ' . basename($this->name), LOGGER_DEBUG);
+
+ $c = q("select * from channel where channel_id = %d and not (channel_pageflags & %d) limit 1",
+ intval(PAGE_REMOVED),
+ intval($this->auth->owner_id)
+ );
- $ret = array();
- $r = q("select distinct filename from attach where folder = '%s' and uid = %d group by filename",
- dbesc($this->dir_key),
- intval($this->channel_id)
+ $r = q("select flags, folder, data from attach where hash = '%s' and uid = %d limit 1",
+ dbesc($this->data['hash']),
+ intval($c[0]['channel_id'])
);
if($r) {
- foreach($r as $rr) {
- $ret[] = $rr['filename'];
+ if($r[0]['flags'] & ATTACH_FLAG_OS) {
+ $f = 'store/' . $this->auth->owner_nick . '/' . (($r[0]['data']) ? $r[0]['data'] : '');
+ @file_put_contents($f, $data);
+ $size = @filesize($f);
+ logger('reddav: put() filename: ' . $f . ' size: ' . $size, LOGGER_DEBUG);
+ }
+ else {
+ $r = q("update attach set data = '%s' where hash = '%s' and uid = %d limit 1",
+ dbesc(stream_get_contents($data)),
+ dbesc($this->data['hash']),
+ intval($this->data['uid'])
+ );
+ $r = q("select length(data) as fsize from attach where hash = '%s' and uid = %d limit 1",
+ dbesc($this->data['hash']),
+ intval($this->data['uid'])
+ );
+ if($r)
+ $size = $r[0]['fsize'];
}
+
+ }
+
+ $edited = datetime_convert();
+
+ $d = q("update attach set filesize = '%s', edited = '%s' where hash = '%s' and uid = %d limit 1",
+ dbesc($size),
+ dbesc($edited),
+ dbesc($this->data['hash']),
+ intval($c[0]['channel_id'])
+ );
+
+ $e = q("update attach set edited = '%s' where folder = '%s' and uid = %d limit 1",
+ dbesc($edited),
+ dbesc($r[0]['folder']),
+ intval($c[0]['channel_id'])
+ );
+
+ $maxfilesize = get_config('system','maxfilesize');
+
+ if(($maxfilesize) && ($size > $maxfilesize)) {
+ attach_delete($c[0]['channel_id'],$this->data['hash']);
+ return;
}
- return $ret;
+ $limit = service_class_fetch($c[0]['channel_id'],'attach_upload_limit');
+ if($limit !== false) {
+ $x = q("select sum(filesize) as total from attach where aid = %d ",
+ intval($c[0]['channel_account_id'])
+ );
+ if(($x) && ($x[0]['total'] + $size > $limit)) {
+ logger('reddav: service class limit exceeded for ' . $c[0]['channel_name'] . ' total usage is ' . $x[0]['total'] . ' limit is ' . $limit);
+ attach_delete($c[0]['channel_id'],$this->data['hash']);
+ return;
+ }
+ }
}
- function getChild($name) {
- if(! perm_is_allowed($this->channel_id,'','view_storage')) {
+ function get() {
+ logger('RedFile::get: ' . basename($this->name), LOGGER_DEBUG);
+
+ $r = q("select data, flags from attach where hash = '%s' and uid = %d limit 1",
+ dbesc($this->data['hash']),
+ intval($this->data['uid'])
+ );
+ if($r) {
+ if($r[0]['flags'] & ATTACH_FLAG_OS ) {
+ $f = 'store/' . $this->auth->owner_nick . '/' . (($this->os_path) ? $this->os_path . '/' : '') . $r[0]['data'];
+ return fopen($f,'rb');
+ }
+ return $r[0]['data'];
+ }
+
+ }
+
+ function getETag() {
+ return $this->data['hash'];
+ }
+
+
+ function getContentType() {
+ return $this->data['filetype'];
+ }
+
+
+ function getSize() {
+ return $this->data['filesize'];
+ }
+
+
+ function getLastModified() {
+ return datetime_convert('UTC','UTC',$this->data['edited'],'U');
+ }
+
+
+ function delete() {
+ if((! $this->auth->owner_id) || (! perm_is_allowed($this->auth->owner_id,$this->auth->observer,'write_storage'))) {
throw new DAV\Exception\Forbidden('Permission denied.');
return;
}
-// FIXME check revisions
+ if($this->auth->owner_id !== $this->auth->channel_id) {
+ if(($this->auth->observer !== $this->data['creator']) || ($this->data['flags'] & ATTACH_FLAG_DIR)) {
+ throw new DAV\Exception\Forbidden('Permission denied.');
+ return;
+ }
+ }
+
+ attach_delete($this->auth->owner_id,$this->data['hash']);
+ }
+
+}
+
+function RedChannelList(&$auth) {
+
+ $ret = array();
+
+ $r = q("select channel_id, channel_address from channel where not (channel_pageflags & %d) and not (channel_pageflags & %d) ",
+ intval(PAGE_REMOVED),
+ intval(PAGE_HIDDEN)
+ );
+
+ if($r) {
+ foreach($r as $rr) {
+ if(perm_is_allowed($rr['channel_id'],$auth->observer,'view_storage')) {
+ $ret[] = new RedDirectory('/cloud/' . $rr['channel_address'],$auth);
+ }
+ }
+ }
+ return $ret;
+
+}
+
+
+function RedCollectionData($file,&$auth) {
+
+ $ret = array();
+
+ $x = strpos($file,'/cloud');
+ if($x === 0) {
+ $file = substr($file,6);
+ }
+
+ if((! $file) || ($file === '/')) {
+ return RedChannelList($auth);
+ }
- $r = q("select * from attach where folder = '%s' and filename = '%s' and uid = %d limit 1",
- dbesc($this->dir_key),
- dbesc($name),
- dbesc($this->channel_id)
+ $file = trim($file,'/');
+ $path_arr = explode('/', $file);
+
+ if(! $path_arr)
+ return null;
+
+ $channel_name = $path_arr[0];
+
+ $r = q("select channel_id from channel where channel_address = '%s' limit 1",
+ dbesc($channel_name)
+ );
+
+ if(! $r)
+ return null;
+
+ $channel_id = $r[0]['channel_id'];
+ $perms = permissions_sql($channel_id);
+
+ $auth->owner_id = $channel_id;
+
+ $path = '/' . $channel_name;
+
+ $folder = '';
+ $errors = false;
+ $permission_error = false;
+
+ for($x = 1; $x < count($path_arr); $x ++) {
+ $r = q("select id, hash, filename, flags from attach where folder = '%s' and filename = '%s' and (flags & %d) $perms limit 1",
+ dbesc($folder),
+ dbesc($path_arr[$x]),
+ intval(ATTACH_FLAG_DIR)
);
if(! $r) {
- throw new DAV\Exception\NotFound('The file with name: ' . $name . ' could not be found');
- }
+ // path wasn't found. Try without permissions to see if it was the result of permissions.
+ $errors = true;
+ $r = q("select id, hash, filename, flags from attach where folder = '%s' and filename = '%s' and (flags & %d) limit 1",
+ dbesc($folder),
+ basename($path_arr[$x]),
+ intval(ATTACH_FLAG_DIR)
+ );
+ if($r) {
+ $permission_error = true;
+ }
+ break;
+ }
-
+ if($r && ( $r[0]['flags'] & ATTACH_FLAG_DIR)) {
+ $folder = $r[0]['hash'];
+ $path = $path . '/' . $r[0]['filename'];
+ }
}
+ if($errors) {
+ if($permission_error) {
+ throw new DAV\Exception\Forbidden('Permission denied.');
+ return;
+ }
+ else {
+ throw new DAV\Exception\NotFound('A component of the request file path could not be found');
+ return;
+ }
+ }
- function createFile($name,$data = null) {
+ // This should no longer be needed since we just returned errors for paths not found
+
+ if($path !== '/' . $file) {
+ logger("RedCollectionData: Path mismatch: $path !== /$file");
+ return NULL;
+ }
+ $ret = array();
+ $r = q("select id, uid, hash, filename, filetype, filesize, revision, folder, flags, created, edited from attach where folder = '%s' and uid = %d $perms group by filename",
+ dbesc($folder),
+ intval($channel_id)
+ );
+
+ foreach($r as $rr) {
+ if($rr['flags'] & ATTACH_FLAG_DIR)
+ $ret[] = new RedDirectory('/cloud' . $path . '/' . $rr['filename'],$auth);
+ else
+ $ret[] = new RedFile('/cloud' . $path . '/' . $rr['filename'],$rr,$auth);
}
- function createDirectory($name) {
+ return $ret;
+}
+
+function RedFileData($file, &$auth,$test = false) {
+
+ logger('RedFileData:' . $file . (($test) ? ' (test mode) ' : ''), LOGGER_DEBUG);
+ $x = strpos($file,'/cloud');
+ if($x === 0) {
+ $file = substr($file,6);
}
+ if((! $file) || ($file === '/')) {
+ return new RedDirectory('/',$auth);
- function childExists($name) {
- $r = q("select distinct filename from attach where folder = '%s' and filename = '%s' and uid = %d group by filename",
- dbesc($this->dir_key),
- dbesc($name),
- intval($this->channel_id)
+ }
+
+ $file = trim($file,'/');
+
+ $path_arr = explode('/', $file);
+
+ if(! $path_arr)
+ return null;
+
+
+ $channel_name = $path_arr[0];
+
+
+ $r = q("select channel_id from channel where channel_address = '%s' limit 1",
+ dbesc($channel_name)
+ );
+
+ if(! $r)
+ return null;
+
+ $channel_id = $r[0]['channel_id'];
+
+ $path = '/' . $channel_name;
+
+ $auth->owner_id = $channel_id;
+
+ $permission_error = false;
+
+ $folder = '';
+
+ require_once('include/security.php');
+ $perms = permissions_sql($channel_id);
+
+ $errors = false;
+
+ for($x = 1; $x < count($path_arr); $x ++) {
+ $r = q("select id, hash, filename, flags from attach where folder = '%s' and filename = '%s' and uid = %d and (flags & %d) $perms",
+ dbesc($folder),
+ dbesc($path_arr[$x]),
+ intval($channel_id),
+ intval(ATTACH_FLAG_DIR)
);
- if($r)
+
+ if($r && ( $r[0]['flags'] & ATTACH_FLAG_DIR)) {
+ $folder = $r[0]['hash'];
+ $path = $path . '/' . $r[0]['filename'];
+ }
+ if(! $r) {
+ $r = q("select id, uid, hash, filename, filetype, filesize, revision, folder, flags, created, edited from attach
+ where folder = '%s' and filename = '%s' and uid = %d $perms group by filename limit 1",
+ dbesc($folder),
+ basename($file),
+ intval($channel_id)
+
+ );
+ }
+ if(! $r) {
+
+ $errors = true;
+ $r = q("select id, uid, hash, filename, filetype, filesize, revision, folder, flags, created, edited from attach
+ where folder = '%s' and filename = '%s' and uid = %d group by filename limit 1",
+ dbesc($folder),
+ basename($file),
+ intval($channel_id)
+ );
+ if($r)
+ $permission_error = true;
+
+ }
+
+ }
+
+ if($path === '/' . $file) {
+ if($test)
return true;
- return false;
+ // final component was a directory.
+ return new RedDirectory('/cloud/' . $file,$auth);
+ }
+ if($errors) {
+ logger('RedFileData: not found');
+ if($test)
+ return false;
+ if($permission_error) {
+ logger('RedFileData: permission error');
+ throw new DAV\Exception\Forbidden('Permission denied.');
+ }
+ return;
}
+ if($r) {
+ if($test)
+ return true;
+
+ if($r[0]['flags'] & ATTACH_FLAG_DIR)
+ return new RedDirectory('/cloud' . $path . '/' . $r[0]['filename'],$auth);
+ else
+ return new RedFile('/cloud' . $path . '/' . $r[0]['filename'],$r[0],$auth);
+ }
+ return false;
}
-abstract class RedFile extends DAV\Node implements DAV\IFile {
+class RedBasicAuth extends Sabre\DAV\Auth\Backend\AbstractBasic {
- private $data;
+ public $channel_name = '';
+ public $channel_id = 0;
+ public $channel_hash = '';
+ public $observer = '';
+ public $browser;
+ public $owner_id;
+ public $owner_nick = '';
+ public $timezone;
+ protected function validateUserPass($username, $password) {
- function __construct($data) {
- $this->data = $data;
+ if(trim($password) === '+++') {
+ logger('reddav: validateUserPass: guest ' . $username);
+ return true;
+ }
+ require_once('include/auth.php');
+ $record = account_verify_password($username,$password);
+ if($record && $record['account_default_channel']) {
+ $r = q("select * from channel where channel_account_id = %d and channel_id = %d limit 1",
+ intval($record['account_id']),
+ intval($record['account_default_channel'])
+ );
+ if($r) {
+ $this->currentUser = $r[0]['channel_address'];
+ $this->channel_name = $r[0]['channel_address'];
+ $this->channel_id = $r[0]['channel_id'];
+ $this->channel_hash = $this->observer = $r[0]['channel_hash'];
+ return true;
+ }
+ }
+ $r = q("select * from channel where channel_address = '%s' limit 1",
+ dbesc($username)
+ );
+ if($r) {
+ $x = q("select * from account where account_id = %d limit 1",
+ intval($r[0]['channel_account_id'])
+ );
+ if($x) {
+ foreach($x as $record) {
+ if(($record['account_flags'] == ACCOUNT_OK) || ($record['account_flags'] == ACCOUNT_UNVERIFIED)
+ && (hash('whirlpool',$record['account_salt'] . $password) === $record['account_password'])) {
+ logger('(DAV) RedBasicAuth: password verified for ' . $username);
+ $this->currentUser = $r[0]['channel_address'];
+ $this->channel_name = $r[0]['channel_address'];
+ $this->channel_id = $r[0]['channel_id'];
+ $this->channel_hash = $this->observer = $r[0]['channel_hash'];
+ return true;
+ }
+ }
+ }
+ }
+ logger('(DAV) RedBasicAuth: password failed for ' . $username);
+ return false;
}
+ function setCurrentUser($name) {
+ $this->currentUser = $name;
+ }
+ function setBrowserPlugin($browser) {
+ $this->browser = $browser;
+ }
+
+}
- function put($data) {
- }
+class RedBrowser extends DAV\Browser\Plugin {
+
+ private $auth;
+ function __construct(&$auth) {
- function get() {
+ $this->auth = $auth;
}
- function getETag() {
+ // The DAV browser is instantiated after the auth module and directory classes but before we know the current
+ // directory and who the owner and observer are. So we add a pointer to the browser into the auth module and vice
+ // versa. Then when we've figured out what directory is actually being accessed, we call the following function
+ // to decide whether or not to show web elements which include writeable objects.
+ function set_writeable() {
- }
+ if(! $this->auth->owner_id)
+ $this->enablePost = false;
+ if(! perm_is_allowed($this->auth->owner_id, get_observer_hash(), 'write_storage'))
+ $this->enablePost = false;
+ else
+ $this->enablePost = true;
- function getContentType() {
- return $this->data['filetype'];
}
+ public function generateDirectoryIndex($path) {
+
+ if($this->auth->timezone)
+ date_default_timezone_set($this->auth->timezone);
- function getSize() {
- return $this->data['filesize'];
- }
+ $version = '';
+
+ $html = "
+<body>
+ <h1>Index for " . $this->escapeHTML($path) . "/</h1>
+ <table>
+ <tr><th width=\"24\"></th><th>Name</th><th>Type</th><th>Size</th><th>Last modified</th></tr>
+ <tr><td colspan=\"5\"><hr /></td></tr>";
-}
+ $files = $this->server->getPropertiesForPath($path,array(
+ '{DAV:}displayname',
+ '{DAV:}resourcetype',
+ '{DAV:}getcontenttype',
+ '{DAV:}getcontentlength',
+ '{DAV:}getlastmodified',
+ ),1);
+
+ $parent = $this->server->tree->getNodeForPath($path);
+ if ($path) {
+ list($parentUri) = DAV\URLUtil::splitPath($path);
+ $fullPath = DAV\URLUtil::encodePath($this->server->getBaseUri() . $parentUri);
+ $icon = $this->enableAssets?'<a href="' . $fullPath . '"><img src="' . $this->getAssetUrl('icons/parent' . $this->iconExtension) . '" width="24" alt="Parent" /></a>':'';
+ $html.= "<tr>
+ <td>$icon</td>
+ <td><a href=\"{$fullPath}\">..</a></td>
+ <td>[parent]</td>
+ <td></td>
+ <td></td>
+ </tr>";
+ }
+
+ foreach($files as $file) {
+
+ // This is the current directory, we can skip it
+ if (rtrim($file['href'],'/')==$path) continue;
+
+ list(, $name) = DAV\URLUtil::splitPath($file['href']);
+
+ $type = null;
+
+
+ if (isset($file[200]['{DAV:}resourcetype'])) {
+ $type = $file[200]['{DAV:}resourcetype']->getValue();
+
+ // resourcetype can have multiple values
+ if (!is_array($type)) $type = array($type);
+
+ foreach($type as $k=>$v) {
+
+ // Some name mapping is preferred
+ switch($v) {
+ case '{DAV:}collection' :
+ $type[$k] = 'Collection';
+ break;
+ case '{DAV:}principal' :
+ $type[$k] = 'Principal';
+ break;
+ case '{urn:ietf:params:xml:ns:carddav}addressbook' :
+ $type[$k] = 'Addressbook';
+ break;
+ case '{urn:ietf:params:xml:ns:caldav}calendar' :
+ $type[$k] = 'Calendar';
+ break;
+ case '{urn:ietf:params:xml:ns:caldav}schedule-inbox' :
+ $type[$k] = 'Schedule Inbox';
+ break;
+ case '{urn:ietf:params:xml:ns:caldav}schedule-outbox' :
+ $type[$k] = 'Schedule Outbox';
+ break;
+ case '{http://calendarserver.org/ns/}calendar-proxy-read' :
+ $type[$k] = 'Proxy-Read';
+ break;
+ case '{http://calendarserver.org/ns/}calendar-proxy-write' :
+ $type[$k] = 'Proxy-Write';
+ break;
+ }
+
+ }
+ $type = implode(', ', $type);
+ }
+
+ // If no resourcetype was found, we attempt to use
+ // the contenttype property
+ if (!$type && isset($file[200]['{DAV:}getcontenttype'])) {
+ $type = $file[200]['{DAV:}getcontenttype'];
+ }
+ if (!$type) $type = 'Unknown';
+
+ $size = isset($file[200]['{DAV:}getcontentlength'])?(int)$file[200]['{DAV:}getcontentlength']:'';
+ $lastmodified = ((isset($file[200]['{DAV:}getlastmodified']))? $file[200]['{DAV:}getlastmodified']->getTime()->format('Y-m-d H:i:s') :'');
+
+ $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);
+ $type = $this->escapeHTML($type);
+
+ $icon = '';
+
+ if ($this->enableAssets) {
+ $node = $this->server->tree->getNodeForPath(($path?$path.'/':'') . $name);
+ foreach(array_reverse($this->iconMap) as $class=>$iconName) {
+
+ if ($node instanceof $class) {
+ $icon = '<a href="' . $fullPath . '"><img src="' . $this->getAssetUrl($iconName . $this->iconExtension) . '" alt="" width="24" /></a>';
+ break;
+ }
+
+
+ }
+
+ }
+
+ $html.= "<tr>
+ <td>$icon</td>
+ <td><a href=\"{$fullPath}\">{$displayName}</a></td>
+ <td>{$type}</td>
+ <td>{$size}</td>
+ <td>" . (($lastmodified) ? datetime_convert('UTC', date_default_timezone_get(),$lastmodified) : '') . "</td>
+ </tr>";
+
+ }
+
+ $html.= "<tr><td colspan=\"5\"><hr /></td></tr>";
+
+ $output = '';
+
+ if ($this->enablePost) {
+ $this->server->broadcastEvent('onHTMLActionsPanel',array($parent, &$output));
+ }
+
+ $html.=$output;
+
+ $html.= "</table>";
+
+ get_app()->page['content'] = $html;
+ construct_page(get_app());
+
+// return $html;
+
+ }
+
+
+ public function htmlActionsPanel(DAV\INode $node, &$output) {
+
+ if (!$node instanceof DAV\ICollection)
+ return;
+
+ // We also know fairly certain that if an object is a non-extended
+ // SimpleCollection, we won't need to show the panel either.
+
+ if (get_class($node)==='Sabre\\DAV\\SimpleCollection')
+ return;
+
+ $output.= '<tr><td colspan="2"><form method="post" action="">
+ <h3>Create new folder</h3>
+ <input type="hidden" name="sabreAction" value="mkcol" />
+ Name: <input type="text" name="name" />
+ <input type="submit" value="create" />
+ </form>
+ <form method="post" action="" enctype="multipart/form-data">
+ <h3>Upload file</h3>
+ <input type="hidden" name="sabreAction" value="put" />
+ Name (optional): <input type="text" name="name" /><br />
+ File: <input type="file" name="file" /><br />
+ <input type="submit" value="upload" />
+ </form>
+ </td></tr>';
+
+
+ if($this->auth->owner_id && $this->auth->owner_id == $this->auth->channel_id) {
+ $channel = get_app()->get_channel();
+ if($channel) {
+ $output .= '<tr><td>&nbsp;</td></tr><tr><td colspan="2"><a href="filestorage/' . $channel['channel_address'] . '" >' . t('Edit File properties') . '</a></td></tr>';
+ }
+ }
+
+ }
+
+
+}
diff --git a/include/security.php b/include/security.php
index 296fa450f..5e86cf790 100644
--- a/include/security.php
+++ b/include/security.php
@@ -31,90 +31,6 @@ function authenticate_success($user_record, $login_initial = false, $interactive
}
}
- else {
- $_SESSION['uid'] = $user_record['uid'];
- $_SESSION['theme'] = $user_record['theme'];
- $_SESSION['mobile_theme'] = get_pconfig($user_record['uid'], 'system', 'mobile_theme');
- $_SESSION['authenticated'] = 1;
- $_SESSION['page_flags'] = $user_record['page-flags'];
- $_SESSION['my_url'] = $a->get_baseurl() . '/channel/' . $user_record['nickname'];
- $_SESSION['my_address'] = $user_record['nickname'] . '@' . substr($a->get_baseurl(),strpos($a->get_baseurl(),'://')+3);
-
- $a->user = $user_record;
-
- if($interactive) {
- if($a->user['login_date'] === '0000-00-00 00:00:00') {
- $_SESSION['return_url'] = 'profile_photo/new';
- $a->module = 'profile_photo';
- info( t("Welcome ") . $a->user['username'] . EOL);
- info( t('Please upload a profile photo.') . EOL);
- }
- else
- info( t("Welcome back ") . $a->user['username'] . EOL);
- }
-
- $member_since = strtotime($a->user['register_date']);
- if(time() < ($member_since + ( 60 * 60 * 24 * 14)))
- $_SESSION['new_member'] = true;
- else
- $_SESSION['new_member'] = false;
- if(strlen($a->user['timezone'])) {
- date_default_timezone_set($a->user['timezone']);
- $a->timezone = $a->user['timezone'];
- }
-
- $master_record = $a->user;
-
- if((x($_SESSION,'submanage')) && intval($_SESSION['submanage'])) {
- $r = q("select * from user where uid = %d limit 1",
- intval($_SESSION['submanage'])
- );
- if(count($r))
- $master_record = $r[0];
- }
-
- $r = q("SELECT `uid`,`username`,`nickname` FROM `user` WHERE `password` = '%s' AND `email` = '%s'",
- dbesc($master_record['password']),
- dbesc($master_record['email'])
- );
- if($r && count($r))
- $a->identities = $r;
- else
- $a->identities = array();
-
- $r = q("select `user`.`uid`, `user`.`username`, `user`.`nickname`
- from manage left join user on manage.mid = user.uid
- where `manage`.`uid` = %d",
- intval($master_record['uid'])
- );
- if($r && count($r))
- $a->identities = array_merge($a->identities,$r);
-
- if($login_initial)
- logger('auth_identities: ' . print_r($a->identities,true), LOGGER_DEBUG);
-
- $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1",
- intval($_SESSION['uid']));
- if(count($r)) {
- $a->contact = $r[0];
- $a->cid = $r[0]['id'];
- $_SESSION['cid'] = $a->cid;
- }
-
- header('X-Account-Management-Status: active; name="' . $a->user['username'] . '"; id="' . $a->user['nickname'] .'"');
-
- if($login_initial) {
- $l = get_browser_language();
-
- q("UPDATE `user` SET `login_date` = '%s', `language` = '%s' WHERE `uid` = %d LIMIT 1",
- dbesc(datetime_convert()),
- dbesc($l),
- intval($_SESSION['uid'])
- );
-
-
- }
- }
if($login_initial)
call_hooks('logged_in', $user_record);
@@ -144,6 +60,7 @@ function change_channel($change_channel) {
intval(get_account_id()),
intval(PAGE_REMOVED)
);
+
if($r) {
$hash = $r[0]['channel_hash'];
$_SESSION['uid'] = intval($r[0]['channel_id']);
@@ -158,11 +75,14 @@ function change_channel($change_channel) {
);
if($x) {
$_SESSION['my_url'] = $x[0]['xchan_url'];
- $_SESSION['my_address'] = $x[0]['xchan_addr'];
+ $_SESSION['my_address'] = $r[0]['channel_address'] . '@' . substr(get_app()->get_baseurl(),strpos(get_app()->get_baseurl(),'://')+3);
get_app()->set_observer($x[0]);
get_app()->set_perms(get_all_perms(local_user(),$hash));
}
+ if(! is_dir('store/' . $r[0]['channel_address']))
+ @mkdir('store/' . $r[0]['channel_address'], STORAGE_DEFAULT_PERMISSIONS,true);
+
}
return $ret;
@@ -336,7 +256,7 @@ function get_form_security_token($typename = '') {
$timestamp = time();
$sec_hash = hash('whirlpool', $a->user['guid'] . $a->user['prvkey'] . session_id() . $timestamp . $typename);
-
+
return $timestamp . '.' . $sec_hash;
}
@@ -386,7 +306,7 @@ function check_form_security_token_ForbiddenOnErr($typename = '', $formname = 'f
if(! function_exists('init_groups_visitor')) {
function init_groups_visitor($contact_id) {
$groups = array();
- $r = q("SELECT hash FROM `group` left join group_member on group.id = group_member.gid WHERE xchan = '%s' ",
+ $r = q("SELECT hash FROM `groups` left join group_member on groups.id = group_member.gid WHERE xchan = '%s' ",
dbesc($contact_id)
);
if(count($r)) {
diff --git a/include/session.php b/include/session.php
index 6072bdb33..be1ec5ee7 100644
--- a/include/session.php
+++ b/include/session.php
@@ -15,6 +15,15 @@ function new_cookie($time) {
session_regenerate_id(false);
q("UPDATE session SET sid = '%s' WHERE sid = '%s'", dbesc(session_id()), dbesc($old_sid));
+
+ if (x($_COOKIE, 'jsAvailable')) {
+ if ($time) {
+ $expires = time() + $time;
+ } else {
+ $expires = 0;
+ }
+ setcookie('jsAvailable', $_COOKIE['jsAvailable'], $expires);
+ }
}
diff --git a/include/spam.php b/include/spam.php
new file mode 100644
index 000000000..8b158b7ae
--- /dev/null
+++ b/include/spam.php
@@ -0,0 +1,35 @@
+<?php /** @file */
+
+
+function string_splitter($s) {
+
+ if(! $s)
+ return array();
+
+ $s = preg_replace('/\pP+/','',$s);
+
+ $x = mb_split("\[|\]|\s",$s);
+
+ $ret = array();
+ if($x) {
+ foreach($x as $y) {
+ if(mb_strlen($y) > 2)
+ $ret[] = substr($y,0,64);
+ }
+ }
+ return $ret;
+}
+
+
+
+function get_words($uid,$list) {
+
+ stringify($list,true);
+
+ $r = q("select * from spam where term in ( " . $list . ") and uid = %d",
+ intval($uid)
+ );
+
+ return $r;
+}
+
diff --git a/include/taxonomy.php b/include/taxonomy.php
index 5159dad02..4f2b5e8fd 100644
--- a/include/taxonomy.php
+++ b/include/taxonomy.php
@@ -87,9 +87,9 @@ function format_term_for_display($term) {
return $s;
if($term['url'])
- $s .= '<a href="' . $term['url'] . '">' . htmlspecialchars($term['term']) . '</a>';
+ $s .= '<a href="' . $term['url'] . '">' . htmlspecialchars($term['term'], ENT_COMPAT,'UTF-8') . '</a>';
else
- $s .= htmlspecialchars($term['term']);
+ $s .= htmlspecialchars($term['term'], ENT_COMPAT,'UTF-8');
return $s;
}
@@ -217,16 +217,19 @@ function tagblock($link,$uid,$count = 0,$authors = '',$flags = 0,$restrict = 0,$
}
function dir_tagblock($link,$r) {
- $o = '';
- $tab = 0;
+ $o = '';
+ $tab = 0;
- if($r) {
- $o = '<div class="dirtagblock widget"><h3>' . t('Keywords') . '</h3><div class="tags" align="center">';
- foreach($r as $rr) {
- $o .= '<a href="'.$link .'/' . '?f=&keywords=' . urlencode($rr['term']).'" class="tag'.$rr['normalise'].'" rel="nofollow" >'.$rr['term'].'</a> ' . "\r\n";
+ if(! $r)
+ $r = get_app()->data['directory_keywords'];
+
+ if($r) {
+ $o = '<div class="dirtagblock widget"><h3>' . t('Keywords') . '</h3><div class="tags" align="center">';
+ foreach($r as $rr) {
+ $o .= '<a href="'.$link .'/' . '?f=&keywords=' . urlencode($rr['term']).'" class="tag'.$rr['normalise'].'" rel="nofollow" >'.$rr['term'].'</a> ' . "\r\n";
+ }
+ $o .= '</div></div>';
}
- $o .= '</div></div>';
- }
return $o;
}
@@ -258,13 +261,81 @@ function obj_verbs() {
}
-function obj_verb_selector() {
+function obj_verb_selector($current = '') {
$verbs = obj_verbs();
$o .= '<select class="obj-verb-selector" name="verb" >';
foreach($verbs as $k => $v) {
- $o .= '<option value="' . urlencode($k) . '">' . $v[0] . '</option>';
+ $selected = (($k == $current) ? ' selected="selected" ' : '');
+ $o .= '<option value="' . urlencode($k) . '"' . $selected . '>' . $v[0] . '</option>';
}
$o .= '</select>';
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)
+ );
+
+ $things = $sorted_things = null;
+
+ $profile_hashes = array();
+
+ if($r) {
+
+ // if no profile_hash was specified (display on profile page mode), match each of the things to a profile name
+ // (list all my things mode). This is harder than it sounds.
+
+ foreach($r as $rr) {
+ $rr['profile_name'] = '';
+ if(! in_array($rr['term_hash'],$profile_hashes))
+ $profile_hashes[] = $rr['term_hash'];
+ }
+ stringify_array_elms($profile_hashes);
+ if(! $profile_hash) {
+ $exp = explode(',',$profile_hashes);
+ $p = q("select profile_guid as hash, profile_name as name from profile where profile_guid in ( $exp ) ");
+ if($p) {
+ foreach($r as $rr) {
+ foreach($p as $pp) {
+ if($rr['obj_page'] == $pp['hash']) {
+ $rr['profile_name'] == $pp['name'];
+ }
+ }
+ }
+ }
+ }
+
+ $things = array();
+
+ // Use the system obj_verbs array as a sort key, since we don't really
+ // want an alphabetic sort. To change the order, use a plugin to
+ // alter the obj_verbs() array or alter it in code. Unknown verbs come
+ // after the known ones - in no particular order.
+
+ $v = obj_verbs();
+ foreach($v as $k => $foo)
+ $things[$k] = null;
+ foreach($r as $rr) {
+ 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']);
+ }
+ $sorted_things = array();
+ if($things) {
+ foreach($things as $k => $v) {
+ if(is_array($things[$k])) {
+ $sorted_things[$k] = $v;
+ }
+ }
+ }
+ }
+
+ return $sorted_things;
+
} \ No newline at end of file
diff --git a/include/text.php b/include/text.php
index aa23f96b0..2b334068f 100755
--- a/include/text.php
+++ b/include/text.php
@@ -442,7 +442,7 @@ function item_message_id() {
$mid = $hash . '@' . get_app()->get_hostname();
- $r = q("SELECT `id` FROM `item` WHERE `mid` = '%s' LIMIT 1",
+ $r = q("SELECT id FROM item WHERE mid = '%s' LIMIT 1",
dbesc($mid));
if(count($r))
$dups = true;
@@ -459,7 +459,7 @@ function photo_new_resource() {
do {
$found = false;
$resource = hash('md5',uniqid(mt_rand(),true));
- $r = q("SELECT `id` FROM `photo` WHERE `resource_id` = '%s' LIMIT 1",
+ $r = q("SELECT id FROM photo WHERE resource_id = '%s' LIMIT 1",
dbesc($resource)
);
if(count($r))
@@ -565,6 +565,10 @@ function get_tags($s) {
$s = preg_replace('/\[code\](.*?)\[\/code\]/sm','',$s);
+ // ignore anything in [style= ]
+
+ $s = preg_replace('/\[style=(.*?)\]/sm','',$s);
+
// Match full names against @tags including the space between first and last
// We will look these up afterward to see if they are full names or not recognisable.
@@ -593,7 +597,7 @@ function get_tags($s) {
if(substr($mtch,-1,1) === '.')
$mtch = substr($mtch,0,-1);
// ignore strictly numeric tags like #1
- if((strpos($mtch,'#') === 0) && ctype_digit(substr($mtch,1)))
+ if((strpos($mtch,'#') === 0) && ( ctype_digit(substr($mtch,1)) || substr($mtch,1,1) === '^'))
continue;
// try not to catch url fragments
if(strpos($s,$mtch) && preg_match('/[a-zA-z0-9\/]/',substr($s,strpos($s,$mtch)-1,1)))
@@ -601,6 +605,18 @@ function get_tags($s) {
$ret[] = $mtch;
}
}
+
+ // bookmarks
+
+ if(preg_match_all('/#\^\[(url|zrl)(.*?)\](.*?)\[\/(url|zrl)\]/',$s,$match,PREG_SET_ORDER)) {
+ foreach($match as $mtch) {
+ $ret[] = $mtch[0];
+ }
+ }
+
+
+ // logger('get_tags: ' . print_r($ret,true));
+
return $ret;
}
@@ -781,6 +797,34 @@ function linkify($s) {
return($s);
}
+/**
+ * @function sslify($s)
+ * Replace media element using http url with https to a local redirector if using https locally
+ * @param string $s
+ *
+ * Looks for HTML tags containing src elements that are http when we're viewing an https page
+ * Typically this throws an insecure content violation in the browser. So we redirect them
+ * to a local redirector which uses https and which redirects to the selected content
+ *
+ * @returns string
+ */
+
+
+function sslify($s) {
+ if(strpos(z_root(),'https:') === false)
+ return $s;
+ $matches = null;
+ $cnt = preg_match_all("/\<(.*?)src=\"(http\:.*?)\"(.*?)\>/",$s,$matches,PREG_SET_ORDER);
+ if($cnt) {
+ foreach($matches as $match) {
+ $s = str_replace($match[2],z_root() . '/sslify?f=&url=' . urlencode($match[2]),$s);
+ }
+ }
+ return $s;
+}
+
+
+
function get_poke_verbs() {
// index is present tense verb
@@ -843,8 +887,8 @@ function get_mood_verbs() {
* Returns string
*
* It is expected that this function will be called using HTML text.
- * We will escape text between HTML pre and code blocks from being
- * processed.
+ * We will escape text between HTML pre and code blocks, and HTML attributes
+ * (such as urls) from being processed.
*
* At a higher level, the bbcode [nosmile] tag can be used to prevent this
* function from being executed by the prepare_text() routine when preparing
@@ -861,8 +905,8 @@ function smilies($s, $sample = false) {
|| (local_user() && intval(get_pconfig(local_user(),'system','no_smilies'))))
return $s;
- $s = preg_replace_callback('/<pre>(.*?)<\/pre>/ism','smile_encode',$s);
- $s = preg_replace_callback('/<code>(.*?)<\/code>/ism','smile_encode',$s);
+ $s = preg_replace_callback('{<(pre|code)>.*?</\1>}ism','smile_shield',$s);
+ $s = preg_replace_callback('/<[a-z]+ .*?>/ism','smile_shield',$s);
$texts = array(
'&lt;3',
@@ -953,19 +997,18 @@ function smilies($s, $sample = false) {
$s = str_replace($params['texts'],$params['icons'],$params['string']);
}
- $s = preg_replace_callback('/<pre>(.*?)<\/pre>/ism','smile_decode',$s);
- $s = preg_replace_callback('/<code>(.*?)<\/code>/ism','smile_decode',$s);
+ $s = preg_replace_callback('/<!--base64:(.*?)-->/ism', 'smile_unshield', $s);
return $s;
}
-function smile_encode($m) {
- return(str_replace($m[1],base64url_encode($m[1]),$m[0]));
+function smile_shield($m) {
+ return '<!--base64:' . base64url_encode($m[0]) . '-->';
}
-function smile_decode($m) {
- return(str_replace($m[1],base64url_decode($m[1]),$m[0]));
+function smile_unshield($m) {
+ return base64url_decode($m[1]);
}
// expand <3333 to the correct number of hearts
@@ -1065,7 +1108,7 @@ function theme_attachments(&$item) {
break;
}
- $title = htmlentities($r['title'], ENT_COMPAT,'UTF-8');
+ $title = htmlspecialchars($r['title'], ENT_COMPAT,'UTF-8');
if(! $title)
$title = t('unknown.???');
$title .= ' ' . $r['length'] . ' ' . t('bytes');
@@ -1095,7 +1138,7 @@ function format_categories(&$item,$writeable) {
if($terms) {
$categories = array();
foreach($terms as $t) {
- $term = htmlspecialchars($t['term'],ENT_COMPAT,'UTF-8') ;
+ $term = htmlspecialchars($t['term'],ENT_COMPAT,'UTF-8',false) ;
if(! trim($term))
continue;
$removelink = (($writeable) ? z_root() . '/filerm/' . $item['id'] . '?f=&cat=' . urlencode($t['term']) : '');
@@ -1117,7 +1160,7 @@ function format_filer(&$item) {
if($terms) {
$categories = array();
foreach($terms as $t) {
- $term = htmlspecialchars($t['term'],ENT_COMPAT,'UTF-8') ;
+ $term = htmlspecialchars($t['term'],ENT_COMPAT,'UTF-8',false) ;
if(! trim($term))
continue;
$removelink = z_root() . '/filerm/' . $item['id'] . '?f=&term=' . urlencode($t['term']);
@@ -1166,6 +1209,10 @@ function prepare_body(&$item,$attach = false) {
if(local_user() == $item['uid'])
$s .= format_filer($item);
+
+ $s = sslify($s);
+
+
// Look for spoiler
$spoilersearch = '<blockquote class="spoiler">';
@@ -1357,9 +1404,9 @@ function feed_salmonlinks($nick) {
}
-function get_plink($item,$mode) {
+function get_plink($item,$conversation_mode = true) {
$a = get_app();
- if($mode == 'display')
+ if($conversation_mode)
$key = 'plink';
else
$key = 'llink';
@@ -1485,20 +1532,6 @@ function return_bytes ($size_str) {
}
}
-function generate_user_guid() {
- $found = true;
- do {
- $guid = random_string(16);
- $x = q("SELECT `uid` FROM `user` WHERE `guid` = '%s' LIMIT 1",
- dbesc($guid)
- );
- if(! count($x))
- $found = false;
- } while ($found == true );
- return $guid;
-}
-
-
function base64url_encode($s, $strip_padding = true) {
@@ -1516,23 +1549,6 @@ function base64url_decode($s) {
logger('base64url_decode: illegal input: ' . print_r(debug_backtrace(), true));
return $s;
}
-
-/*
- * // Placeholder for new rev of salmon which strips base64 padding.
- * // PHP base64_decode handles the un-padded input without requiring this step
- * // Uncomment if you find you need it.
- *
- * $l = strlen($s);
- * if(! strpos($s,'=')) {
- * $m = $l % 4;
- * if($m == 2)
- * $s .= '==';
- * if($m == 3)
- * $s .= '=';
- * }
- *
- */
-
return base64_decode(strtr($s,'-_','+/'));
}
@@ -1637,17 +1653,12 @@ function item_post_type($item) {
}
-function normalise_openid($s) {
- return trim(str_replace(array('http://','https://'),array('',''),$s),'/');
-}
-
-
function undo_post_tagging($s) {
$matches = null;
- $cnt = preg_match_all('/([@#])\[zrl=(.*?)\](.*?)\[\/zrl\]/ism',$s,$matches,PREG_SET_ORDER);
+ $cnt = preg_match_all('/([@#])(\!*)\[zrl=(.*?)\](.*?)\[\/zrl\]/ism',$s,$matches,PREG_SET_ORDER);
if($cnt) {
foreach($matches as $mtch) {
- $s = str_replace($mtch[0], $mtch[1] . $mtch[3],$s);
+ $s = str_replace($mtch[0], $mtch[1] . $mtch[2] . str_replace(' ','_',$mtch[4]),$s);
}
}
return $s;
@@ -1889,18 +1900,17 @@ function json_decode_plus($s) {
function design_tools() {
-$channel = get_app()->get_channel();
-$who = $channel['channel_address'];
-
-return replace_macros(get_markup_template('design_tools.tpl'), array(
- '$title' => t('Design'),
- '$who' => $who,
- '$blocks' => t('Blocks'),
- '$menus' => t('Menus'),
- '$layout' => t('Layouts'),
- '$pages' => t('Pages')
- ));
-
+ $channel = get_app()->get_channel();
+ $who = $channel['channel_address'];
+
+ return replace_macros(get_markup_template('design_tools.tpl'), array(
+ '$title' => t('Design'),
+ '$who' => $who,
+ '$blocks' => t('Blocks'),
+ '$menus' => t('Menus'),
+ '$layout' => t('Layouts'),
+ '$pages' => t('Pages')
+ ));
}
/* case insensitive in_array() */
diff --git a/include/widgets.php b/include/widgets.php
index cea5a6ce2..0151f7c27 100644
--- a/include/widgets.php
+++ b/include/widgets.php
@@ -1,17 +1,7 @@
<?php /** @file */
-function list_widgets() {
- $widgets = array(
- 'profile' => t('Displays a full channel profile'),
- 'tagcloud' => t('Tag cloud of webpage categories'),
- 'collections' => t('List and filter by collection'),
- 'suggestions' => t('Show a couple of channel suggestion'),
- 'follow' => t('Provide a channel follow form')
- );
- $arr = array('widgets' => $widgets);
- call_hooks('list_widgets',$arr);
- return $arr['widgets'];
-}
+require_once('include/dir_fns.php');
+require_once('include/contact_widgets.php');
function widget_profile($args) {
@@ -47,16 +37,48 @@ function widget_tagcloud($args) {
function widget_collections($args) {
require_once('include/group.php');
- $page = argv(0);
- $gid = $_REQUEST['gid'];
- return group_side($page,$page,true,$_REQUEST['gid'],'',0);
+ $mode = ((array_key_exists('mode',$args)) ? $args['mode'] : 'conversation');
+ switch($mode) {
+ case 'conversation':
+ $every = argv(0);
+ $each = argv(0);
+ $edit = true;
+ $current = $_REQUEST['gid'];
+ $abook_id = 0;
+ $wmode = 0;
+ break;
+ case 'groups':
+ $every = 'connections';
+ $each = argv(0);
+ $edit = false;
+ $current = intval(argv(1));
+ $abook_id = 0;
+ $wmode = 1;
+ break;
+ case 'abook':
+ $every = 'connections';
+ $each = 'group';
+ $edit = false;
+ $current = 0;
+ $abook_id = get_app()->poi['abook_xchan'];
+ $wmode = 1;
+ break;
+ default:
+ return '';
+ break;
+ }
+
+ return group_side($every, $each, $edit, $current, $abook_id, $wmode);
}
function widget_suggestions($arr) {
+ if((! local_user()) || (! feature_enabled(local_user(),'suggest')))
+ return '';
+
require_once('include/socgraph.php');
$r = suggestion_query(local_user(),get_observer_hash(),0,20);
@@ -143,7 +165,7 @@ function widget_notes($arr) {
if(! feature_enabled(local_user(),'private_notes'))
return '';
- $text = htmlspecialchars(get_pconfig(local_user(),'notes','text'));
+ $text = get_pconfig(local_user(),'notes','text');
$o = replace_macros(get_markup_template('notes.tpl'), array(
'$banner' => t('Notes'),
@@ -216,7 +238,7 @@ function widget_savedsearch($arr) {
'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']),
- 'displayterm' => htmlspecialchars($rr['term']),
+ 'displayterm' => htmlspecialchars($rr['term'], ENT_COMPAT,'UTF-8'),
'encodedterm' => urlencode($rr['term']),
'delete' => t('Remove term'),
'selected' => ($search==$rr['term']),
@@ -314,7 +336,7 @@ function widget_fullprofile($arr) {
function widget_categories($arr) {
$a = get_app();
- $cat = ((x($_REQUEST,'cat')) ? htmlspecialchars($_REQUEST['cat']) : '');
+ $cat = ((x($_REQUEST,'cat')) ? htmlspecialchars($_REQUEST['cat'],ENT_COMPAT,'UTF-8') : '');
$srchurl = $a->query_string;
$srchurl = rtrim(preg_replace('/cat\=[^\&].*?(\&|$)/is','',$srchurl),'&');
$srchurl = str_replace(array('?f=','&f='),array('',''),$srchurl);
@@ -330,4 +352,240 @@ function widget_tagcloud_wall($arr) {
if(feature_enabled($a->profile['profile_uid'],'tagadelic'))
return tagblock('search',$a->profile['profile_uid'],$limit,$a->profile['channel_hash'],ITEM_WALL);
return '';
-} \ No newline at end of file
+}
+
+
+function widget_affinity($arr) {
+
+ if(! local_user())
+ return '';
+
+ $cmin = ((x($_REQUEST,'cmin')) ? intval($_REQUEST['cmin']) : 0);
+ $cmax = ((x($_REQUEST,'cmax')) ? intval($_REQUEST['cmax']) : 99);
+
+ if(feature_enabled(local_user(),'affinity')) {
+ $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')
+ ));
+ $arr = array('html' => $x);
+ call_hooks('main_slider',$arr);
+ return $arr['html'];
+ }
+ return '';
+}
+
+
+function widget_settings_menu($arr) {
+
+ if(! local_user())
+ return;
+
+ $a = get_app();
+ $channel = $a->get_channel();
+
+ $abook_self_id = 0;
+
+ // Retrieve the 'self' address book entry for use in the auto-permissions link
+
+ $abk = q("select abook_id from abook where abook_channel = %d and ( abook_flags & %d ) limit 1",
+ intval(local_user()),
+ intval(ABOOK_FLAG_SELF)
+ );
+ if($abk)
+ $abook_self_id = $abk[0]['abook_id'];
+
+
+ $tabs = array(
+ array(
+ 'label' => t('Account settings'),
+ 'url' => $a->get_baseurl(true).'/settings/account',
+ 'selected' => ((argv(1) === 'account') ? 'active' : ''),
+ ),
+
+ array(
+ 'label' => t('Channel settings'),
+ 'url' => $a->get_baseurl(true).'/settings/channel',
+ 'selected' => ((argv(1) === 'channel') ? 'active' : ''),
+ ),
+
+ array(
+ 'label' => t('Additional features'),
+ 'url' => $a->get_baseurl(true).'/settings/features',
+ 'selected' => ((argv(1) === 'features') ? 'active' : ''),
+ ),
+
+ array(
+ 'label' => t('Feature settings'),
+ 'url' => $a->get_baseurl(true).'/settings/featured',
+ 'selected' => ((argv(1) === 'featured') ? 'active' : ''),
+ ),
+
+ array(
+ 'label' => t('Display settings'),
+ 'url' => $a->get_baseurl(true).'/settings/display',
+ 'selected' => ((argv(1) === 'display') ? 'active' : ''),
+ ),
+
+ array(
+ 'label' => t('Connected apps'),
+ 'url' => $a->get_baseurl(true) . '/settings/oauth',
+ 'selected' => ((argv(1) === 'oauth') ? 'active' : ''),
+ ),
+
+ array(
+ 'label' => t('Export channel'),
+ 'url' => $a->get_baseurl(true) . '/uexport/basic',
+ 'selected' => ''
+ ),
+
+// array(
+// 'label' => t('Export account'),
+// 'url' => $a->get_baseurl(true) . '/uexport/complete',
+// 'selected' => ''
+// ),
+
+ array(
+ 'label' => t('Automatic Permissions (Advanced)'),
+ 'url' => $a->get_baseurl(true) . '/connedit/' . $abook_self_id,
+ 'selected' => ''
+ ),
+
+
+ );
+
+ if(feature_enabled(local_user(),'premium_channel')) {
+ $tabs[] = array(
+ 'label' => t('Premium Channel Settings'),
+ 'url' => $a->get_baseurl(true) . '/connect/' . $channel['channel_address'],
+ 'selected' => ''
+ );
+
+ }
+
+ if(feature_enabled(local_user(),'channel_sources')) {
+ $tabs[] = array(
+ 'label' => t('Channel Sources'),
+ 'url' => $a->get_baseurl(true) . '/sources',
+ 'selected' => ''
+ );
+
+ }
+
+
+
+ $tabtpl = get_markup_template("generic_links_widget.tpl");
+ return replace_macros($tabtpl, array(
+ '$title' => t('Settings'),
+ '$class' => 'settings-widget',
+ '$items' => $tabs,
+ ));
+
+}
+
+
+function widget_mailmenu($arr) {
+ if (! local_user())
+ return;
+
+ $a = get_app();
+ return replace_macros(get_markup_template('message_side.tpl'), array(
+ '$tabs'=> array(),
+
+ '$check'=>array(
+ 'label' => t('Check Mail'),
+ 'url' => $a->get_baseurl(true) . '/message',
+ 'sel' => (argv(1) == ''),
+ ),
+ '$new'=>array(
+ 'label' => t('New Message'),
+ 'url' => $a->get_baseurl(true) . '/mail/new',
+ 'sel'=> (argv(1) == 'new'),
+ )
+
+ ));
+
+}
+
+function widget_design_tools($arr) {
+ $a = get_app();
+
+ // mod menu doesn't load a profile. For any modules which load a profile, check it.
+ // otherwise local_user() is sufficient for permissions.
+
+ if($a->profile['profile_uid'])
+ if($a->profile['profile_uid'] != local_user())
+ return '';
+
+ if(! local_user())
+ return '';
+
+ return design_tools();
+}
+
+function widget_findpeople($arr) {
+ return findpeople_widget();
+}
+
+
+function widget_photo_albums($arr) {
+ $a = get_app();
+ if(! $a->profile['profile_uid'])
+ return '';
+ $channelx = channelx_by_n($a->profile['profile_uid']);
+ if((! $channelx) || (! perm_is_allowed($a->profile['profile_uid'],get_observer_hash(),'view_photos')))
+ return '';
+ return photos_album_widget($channelx[0],$a->get_observer());
+
+}
+
+
+function widget_vcard($arr) {
+ require_once ('include/Contact.php');
+ return vcard_from_xchan('',get_app()->get_observer());
+}
+
+
+/**
+ * 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();
+}
+
+function widget_dirtags($arr) {
+ return dir_tagblock(z_root() . '/directory',null);
+}
+
+function widget_menu_preview($arr) {
+ if(! get_app()->data['menu_item'])
+ return;
+ require_once('include/menu.php');
+ return menu_render(get_app()->data['menu_item']);
+}
+
+function widget_chatroom_list($arr) {
+ require_once("include/chat.php");
+ $r = chatroom_list(local_user());
+ $channel = get_app()->get_channel();
+ return replace_macros(get_markup_template('chatroomlist.tpl'),array(
+ '$header' => t('Chat Rooms'),
+ '$baseurl' => z_root(),
+ '$nickname' => $channel['channel_address'],
+ '$items' => $r,
+ ));
+}
+
diff --git a/include/zot.php b/include/zot.php
index 77d82f110..b7a22a099 100644
--- a/include/zot.php
+++ b/include/zot.php
@@ -1367,8 +1367,10 @@ function process_delivery($sender,$arr,$deliveries,$relay) {
// remove_community_tag is a no-op if this isn't a community tag activity
remove_community_tag($sender,$arr,$channel['channel_id']);
+
+
$item_id = delete_imported_item($sender,$arr,$channel['channel_id']);
- $result[] = array($d['hash'],'deleted',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>');
+ $result[] = array($d['hash'],(($item_id) ? 'deleted' : 'delete_failed'),$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>');
if($relay && $item_id) {
logger('process_delivery: invoking relay');
@@ -1384,7 +1386,7 @@ function process_delivery($sender,$arr,$deliveries,$relay) {
if((x($arr,'obj_type')) && (activity_match($arr['obj_type'],ACTIVITY_OBJ_EVENT))) {
require_once('include/event.php');
$ev = bbtoevent($arr['body']);
- if(x($ev,'desc') && x($ev,'start')) {
+ if(x($ev,'desc') && x($ev,'start')) {
$ev['event_xchan'] = $arr['author_xchan'];
$ev['uid'] = $channel['channel_id'];
$ev['account'] = $channel['channel_account_id'];
@@ -1524,10 +1526,11 @@ function delete_imported_item($sender,$item,$uid) {
logger('delete_imported_item invoked',LOGGER_DEBUG);
- $r = q("select id from item where ( author_xchan = '%s' or owner_xchan = '%s' )
+ $r = q("select id, item_restrict from item where ( author_xchan = '%s' or owner_xchan = '%s' or source_xchan = '%s' )
and mid = '%s' and uid = %d limit 1",
dbesc($sender['hash']),
dbesc($sender['hash']),
+ dbesc($sender['hash']),
dbesc($item['mid']),
intval($uid)
);
@@ -1536,9 +1539,17 @@ function delete_imported_item($sender,$item,$uid) {
logger('delete_imported_item: failed: ownership issue');
return false;
}
+
+ if($r[0]['item_restrict'] & ITEM_DELETED) {
+ logger('delete_imported_item: item was already deleted');
+ return false;
+ }
require_once('include/items.php');
drop_item($r[0]['id'],false);
+
+ tag_deliver($uid,$r[0]['id']);
+
return $r[0]['id'];
}
@@ -1633,22 +1644,26 @@ function import_directory_profile($hash,$profile,$addr,$ud_flags = 1, $suppress_
$arr = array();
$arr['xprof_hash'] = $hash;
- $arr['xprof_desc'] = (($profile['description']) ? htmlentities($profile['description'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['xprof_desc'] = (($profile['description']) ? htmlspecialchars($profile['description'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_dob'] = datetime_convert('','',$profile['birthday'],'Y-m-d'); // !!!! check this for 0000 year
$arr['xprof_age'] = (($profile['age']) ? intval($profile['age']) : 0);
- $arr['xprof_gender'] = (($profile['gender']) ? htmlentities($profile['gender'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['xprof_marital'] = (($profile['marital']) ? htmlentities($profile['marital'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['xprof_sexual'] = (($profile['sexual']) ? htmlentities($profile['sexual'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['xprof_locale'] = (($profile['locale']) ? htmlentities($profile['locale'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['xprof_region'] = (($profile['region']) ? htmlentities($profile['region'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['xprof_postcode'] = (($profile['postcode']) ? htmlentities($profile['postcode'], ENT_COMPAT,'UTF-8',false) : '');
- $arr['xprof_country'] = (($profile['country']) ? htmlentities($profile['country'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['xprof_gender'] = (($profile['gender']) ? htmlspecialchars($profile['gender'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['xprof_marital'] = (($profile['marital']) ? htmlspecialchars($profile['marital'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['xprof_sexual'] = (($profile['sexual']) ? htmlspecialchars($profile['sexual'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['xprof_locale'] = (($profile['locale']) ? htmlspecialchars($profile['locale'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['xprof_region'] = (($profile['region']) ? htmlspecialchars($profile['region'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['xprof_postcode'] = (($profile['postcode']) ? htmlspecialchars($profile['postcode'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['xprof_country'] = (($profile['country']) ? htmlspecialchars($profile['country'], ENT_COMPAT,'UTF-8',false) : '');
+
+ $arr['xprof_about'] = (($profile['about']) ? htmlspecialchars($profile['about'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['xprof_homepage'] = (($profile['homepage']) ? htmlspecialchars($profile['homepage'], ENT_COMPAT,'UTF-8',false) : '');
+ $arr['xprof_hometown'] = (($profile['hometown']) ? htmlspecialchars($profile['hometown'], ENT_COMPAT,'UTF-8',false) : '');
$clean = array();
if(array_key_exists('keywords',$profile) and is_array($profile['keywords'])) {
import_directory_keywords($hash,$profile['keywords']);
foreach($profile['keywords'] as $kw) {
- $kw = trim(htmlentities($kw,ENT_COMPAT,'UTF-8',false));
+ $kw = trim(htmlspecialchars($kw,ENT_COMPAT,'UTF-8',false));
$kw = trim($kw,',');
$clean[] = $kw;
}
@@ -1692,6 +1707,9 @@ function import_directory_profile($hash,$profile,$addr,$ud_flags = 1, $suppress_
xprof_region = '%s',
xprof_postcode = '%s',
xprof_country = '%s',
+ xprof_about = '%s',
+ xprof_homepage = '%s',
+ xprof_hometown = '%s',
xprof_keywords = '%s'
where xprof_hash = '%s' limit 1",
dbesc($arr['xprof_desc']),
@@ -1704,6 +1722,9 @@ function import_directory_profile($hash,$profile,$addr,$ud_flags = 1, $suppress_
dbesc($arr['xprof_region']),
dbesc($arr['xprof_postcode']),
dbesc($arr['xprof_country']),
+ dbesc($arr['xprof_about']),
+ dbesc($arr['xprof_homepage']),
+ dbesc($arr['xprof_hometown']),
dbesc($arr['xprof_keywords']),
dbesc($arr['xprof_hash'])
);
@@ -1712,7 +1733,7 @@ function import_directory_profile($hash,$profile,$addr,$ud_flags = 1, $suppress_
else {
$update = true;
logger('import_directory_profile: new profile');
- $x = q("insert into xprof (xprof_hash, xprof_desc, xprof_dob, xprof_age, xprof_gender, xprof_marital, xprof_sexual, xprof_locale, xprof_region, xprof_postcode, xprof_country, xprof_keywords) values ('%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ",
+ $x = q("insert into xprof (xprof_hash, xprof_desc, xprof_dob, xprof_age, xprof_gender, xprof_marital, xprof_sexual, xprof_locale, xprof_region, xprof_postcode, xprof_country, xprof_about, xprof_homepage, xprof_hometown, xprof_keywords) values ('%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ",
dbesc($arr['xprof_hash']),
dbesc($arr['xprof_desc']),
dbesc($arr['xprof_dob']),
@@ -1724,6 +1745,9 @@ function import_directory_profile($hash,$profile,$addr,$ud_flags = 1, $suppress_
dbesc($arr['xprof_region']),
dbesc($arr['xprof_postcode']),
dbesc($arr['xprof_country']),
+ dbesc($arr['xprof_about']),
+ dbesc($arr['xprof_homepage']),
+ dbesc($arr['xprof_hometown']),
dbesc($arr['xprof_keywords'])
);
}
@@ -1750,7 +1774,7 @@ function import_directory_keywords($hash,$keywords) {
$clean = array();
foreach($keywords as $kw) {
- $kw = trim(htmlentities($kw,ENT_COMPAT,'UTF-8',false));
+ $kw = trim(htmlspecialchars($kw,ENT_COMPAT,'UTF-8',false));
$kw = trim($kw,',');
$clean[] = $kw;
}
@@ -1849,10 +1873,21 @@ function import_site($arr,$pubkey) {
$access_policy = ACCESS_TIERED;
}
- $directory_url = htmlentities($arr['directory_url'],ENT_COMPAT,'UTF-8',false);
- $url = htmlentities($arr['url'],ENT_COMPAT,'UTF-8',false);
- $sellpage = htmlentities($arr['sellpage'],ENT_COMPAT,'UTF-8',false);
- $site_location = htmlentities($arr['location'],ENT_COMPAT,'UTF-8',false);
+ // don't let insecure sites register as public hubs
+
+ if(strpos($arr['url'],'https://') === false)
+ $access_policy = ACCESS_PRIVATE;
+
+ if($access_policy != ACCESS_PRIVATE) {
+ $x = z_fetch_url($arr['url'] . '/siteinfo/json');
+ if(! $x['success'])
+ $access_policy = ACCESS_PRIVATE;
+ }
+
+ $directory_url = htmlspecialchars($arr['directory_url'],ENT_COMPAT,'UTF-8',false);
+ $url = htmlspecialchars($arr['url'],ENT_COMPAT,'UTF-8',false);
+ $sellpage = htmlspecialchars($arr['sellpage'],ENT_COMPAT,'UTF-8',false);
+ $site_location = htmlspecialchars($arr['location'],ENT_COMPAT,'UTF-8',false);
if($exists) {
if(($siterecord['site_flags'] != $site_directory)