aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/Contact.php19
-rw-r--r--include/ItemObject.php9
-rw-r--r--include/account.php1
-rw-r--r--include/acl_selectors.php2
-rw-r--r--include/activities.php2
-rw-r--r--include/api.php3
-rw-r--r--include/attach.php217
-rw-r--r--include/bbcode.php25
-rw-r--r--include/contact_widgets.php3
-rw-r--r--include/conversation.php29
-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.php9
-rw-r--r--include/group.php26
-rw-r--r--include/identity.php132
-rwxr-xr-xinclude/items.php150
-rw-r--r--include/nav.php4
-rw-r--r--include/network.php4
-rw-r--r--include/photo/photo_driver.php54
-rw-r--r--include/photos.php30
-rwxr-xr-xinclude/plugin.php42
-rw-r--r--include/reddav.php953
-rw-r--r--include/security.php2
-rw-r--r--include/taxonomy.php95
-rwxr-xr-xinclude/text.php65
-rw-r--r--include/widgets.php282
-rw-r--r--include/zot.php60
30 files changed, 1906 insertions, 363 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..9a62cee4b 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';
@@ -217,6 +218,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'] > 0) ? sprintf( t('Expires: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['expires'], 'r')):''),
'lock' => $lock,
'verified' => $verified,
'unverified' => $unverified,
@@ -230,7 +232,7 @@ 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 : ''),
@@ -457,6 +459,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..b3dbb7023 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 = '';
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..463d29cf8 100644
--- a/include/api.php
+++ b/include/api.php
@@ -362,7 +362,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']),
diff --git a/include/attach.php b/include/attach.php
index 0c748cba6..a621d2fc4 100644
--- a/include/attach.php
+++ b/include/attach.php
@@ -79,17 +79,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 +188,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 +237,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)
);
@@ -335,8 +330,8 @@ 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 +358,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 +394,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 +424,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 +484,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 +528,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 +571,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,24 +601,25 @@ 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) {
@@ -633,4 +637,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/bbcode.php b/include/bbcode.php
index 271cace73..9f07b71ce 100644
--- a/include/bbcode.php
+++ b/include/bbcode.php
@@ -105,21 +105,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 +132,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="' . urlencode($match[1]) . '" />';
+}
function bb_ShareAttributes($match) {
@@ -273,6 +279,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 +334,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);
}
@@ -418,7 +433,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);
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..a9bf69a3e 100644
--- a/include/conversation.php
+++ b/include/conversation.php
@@ -692,7 +692,7 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $
'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 +782,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 +911,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 +1111,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 +1120,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 +1145,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,15 +1299,18 @@ function prepare_page($item) {
$a = get_app();
$naked = ((get_pconfig($item['uid'],'system','nakedpage')) ? 1 : 0);
+ $observer = $a->get_observer();
+ $zid = ($observer['xchan_addr']);
+
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)
@@ -1457,6 +1465,15 @@ function profile_tabs($a, $is_owner=False, $nickname=Null){
'title' => t('Photo Albums'),
'id' => 'photo-tab',
),
+
+ array(
+ 'label' => t('Files'),
+ 'url' => $a->get_baseurl() . '/cloud/' . $nickname,
+ 'sel' => ((argv(0) == 'cloud') ? 'active' : ''),
+ 'title' => t('Files and Storage'),
+ 'id' => 'files-tab',
+ ),
+
);
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..1f83eb319 100644
--- a/include/features.php
+++ b/include/features.php
@@ -24,9 +24,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 +39,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 +51,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..cdd779df2 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();
@@ -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..30b6e4b6b 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)
);
@@ -655,6 +667,7 @@ function profile_sidebar($profile, $block = 0, $show_connect = true) {
}
}
+
if((x($profile,'address') == 1)
|| (x($profile,'locality') == 1)
|| (x($profile,'region') == 1)
@@ -666,6 +679,10 @@ function profile_sidebar($profile, $block = 0, $show_connect = true) {
$marital = ((x($profile,'marital') == 1) ? t('Status:') : False);
$homepage = ((x($profile,'homepage') == 1) ? t('Homepage:') : False);
+ 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;
}
@@ -688,7 +705,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);
}
@@ -949,44 +966,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;
-
- 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.
+ $things = get_things($a->profile['profile_guid'],$a->profile['profile_uid']);
- $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
));
}
@@ -1035,8 +1023,9 @@ function zid_init(&$a) {
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 +1093,52 @@ 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);
+}
diff --git a/include/items.php b/include/items.php
index dd3cf7644..9a1e5f81b 100755
--- a/include/items.php
+++ b/include/items.php
@@ -243,6 +243,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 +570,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 +590,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 +673,6 @@ function get_item_elements($x) {
$arr['body'] = json_encode(crypto_encapsulate($arr['body'],$key));
}
-
return $arr;
}
@@ -832,8 +837,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;
@@ -876,12 +881,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 +898,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 +963,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 +982,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 +1022,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 +1611,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;
@@ -2149,6 +2156,13 @@ function tag_deliver($uid,$item_id) {
$item = $i[0];
+ 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) {
@@ -2278,7 +2292,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');
@@ -2363,12 +2377,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 +2426,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');
@@ -2444,7 +2459,7 @@ function check_item_source($uid,$item) {
$r = q("select * from source where src_channel_id = %d and src_xchan = '%s' limit 1",
intval($uid),
- dbesc($item['owner_xchan'])
+ dbesc(($item['source_xchan']) ? $item['source_xchan'] : $item['owner_xchan'])
);
if(! $r)
@@ -3711,7 +3726,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
$sql_extra = " AND item.parent IN ( SELECT parent FROM item WHERE (item_flags & " . intval(ITEM_THREAD_TOP) . ") $sql_options ) ";
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)
);
@@ -3928,3 +3943,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/nav.php b/include/nav.php
index f89de2de0..008899c47 100644
--- a/include/nav.php
+++ b/include/nav.php
@@ -165,7 +165,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 +196,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..3fe7f5400 100644
--- a/include/network.php
+++ b/include/network.php
@@ -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/photo/photo_driver.php b/include/photo/photo_driver.php
index 8730b4298..debe1bc38 100644
--- a/include/photo/photo_driver.php
+++ b/include/photo/photo_driver.php
@@ -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 ) 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..5c03b2cdb 100644
--- a/include/photos.php
+++ b/include/photos.php
@@ -102,12 +102,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 +216,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]';
@@ -279,8 +280,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 +320,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 +410,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..d80bcedde 100644
--- a/include/reddav.php
+++ b/include/reddav.php
@@ -1,196 +1,957 @@
<?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 {
+
+ 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;
}
-
- q("delete from attach where id = %d limit 1",
- intval($this->attach['id'])
- );
+ 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');
+
}
function getName() {
- return $this->attach['filename'];
+ logger('RedDirectory::getName returns: ' . basename($this->red_path), LOGGER_DATA);
+ return (basename($this->red_path));
}
- function setName($newName) {
- if((! $newName) || (! perm_is_allowed($this->channel_id,'','view_storage')))
+
+
+ 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 limit 1",
+ intval($this->auth->owner_id)
+ );
+
+
+ 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);
+
+
+ $r = q("update attach set filesize = '%s' where hash = '%s' and uid = %d limit 1",
+ dbesc($size),
+ dbesc($hash),
+ intval($c[0]['channel_id'])
+ );
+
+ $maxfilesize = get_config('system','maxfilesize');
+
+ if(($maxfilesize) && ($size > $maxfilesize)) {
+ attach_delete($c[0]['channel_id'],$hash);
return;
+ }
- $this->attach['filename'] = $newName;
- $r = q("update attach set filename = '%s' where id = %d limit 1",
- dbesc($this->attach['filename']),
- intval($this->attach['id'])
+ $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)) {
+ attach_delete($c[0]['channel_id'],$hash);
+ return;
+ }
+ }
+ }
+
+
+ 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 limit 1",
+ dbesc($this->auth->owner_id)
);
+ 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 getLastModified() {
- return $this->attach['edited'];
+
+ 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);
+ }
+
+ 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' limit 1",
+ dbesc($channel_name)
+ );
+
+ if(! $r)
+ 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;
}
+
+
+
+
}
-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 limit 1",
+ 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, 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'];
}
}
- return $ret;
+
+ $r = q("update attach set filesize = '%s' where hash = '%s' and uid = %d limit 1",
+ dbesc($size),
+ dbesc($this->data['hash']),
+ intval($c[0]['channel_id'])
+ );
- }
+ $maxfilesize = get_config('system','maxfilesize');
- function getChild($name) {
- if(! perm_is_allowed($this->channel_id,'','view_storage')) {
- throw new DAV\Exception\Forbidden('Permission denied.');
+ if(($maxfilesize) && ($size > $maxfilesize)) {
+ attach_delete($c[0]['channel_id'],$this->data['hash']);
return;
}
-// FIXME check revisions
+ $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)) {
+ attach_delete($c[0]['channel_id'],$this->data['hash']);
+ return;
+ }
+ }
+ }
- $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)
+
+ 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) {
- throw new DAV\Exception\NotFound('The file with name: ' . $name . ' could not be found');
- }
+ 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 createFile($name,$data = null) {
+
+ function getContentType() {
+ return $this->data['filetype'];
+ }
+ function getSize() {
+ return $this->data['filesize'];
}
- function createDirectory($name) {
+ function getLastModified() {
+ return $this->data['edited'];
+ }
+ 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;
+ }
+
+ 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 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)
- );
- if($r)
- return true;
- return false;
+function RedChannelList(&$auth) {
+ $ret = array();
+
+ $r = q("select channel_id, channel_address from channel where not (channel_pageflags & %d)",
+ intval(PAGE_REMOVED)
+ );
+
+ 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;
}
-abstract class RedFile extends DAV\Node implements DAV\IFile {
+function RedCollectionData($file,&$auth) {
- private $data;
+ $ret = array();
+ $x = strpos($file,'/cloud');
+ if($x === 0) {
+ $file = substr($file,6);
+ }
- function __construct($data) {
- $this->data = $data;
+ if((! $file) || ($file === '/')) {
+ return RedChannelList($auth);
+ }
+
+ $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) {
+ // 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;
+ }
+ }
+ // This should no longer be needed since we just returned errors for paths not found
- function put($data) {
+ 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);
}
+ return $ret;
- function get() {
+}
+
+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);
}
- function getETag() {
+ if((! $file) || ($file === '/')) {
+ return RedDirectory('/',$auth);
+
+ }
+
+ $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 && ( $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;
+ // final component was a directory.
+ return new RedDirectory('/cloud/' . $file,$auth);
+ }
- function getContentType() {
- return $this->data['filetype'];
+ 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;
- function getSize() {
- return $this->data['filesize'];
+ 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;
+}
+
+class RedBasicAuth extends Sabre\DAV\Auth\Backend\AbstractBasic {
+
+ 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) {
+ require_once('include/auth.php');
+ $record = account_verify_password($email,$pass);
+ 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;
+ }
+
}
+class RedBrowser extends DAV\Browser\Plugin {
+
+ private $auth;
+
+ function __construct(&$auth) {
+
+ $this->auth = $auth;
+
+
+ }
+
+ // 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;
+
+ }
+
+ public function generateDirectoryIndex($path) {
+
+ if($this->auth->timezone)
+ date_default_timezone_set($this->auth->timezone);
+
+ $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>';
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/include/security.php b/include/security.php
index 296fa450f..138efe3ab 100644
--- a/include/security.php
+++ b/include/security.php
@@ -386,7 +386,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/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..f5c440e4a 100755
--- a/include/text.php
+++ b/include/text.php
@@ -781,6 +781,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
@@ -1065,7 +1093,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 +1123,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 +1145,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 +1194,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 +1389,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';
@@ -1889,18 +1921,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..a1ff756ff 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,226 @@ 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) {
+ 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']);
+}
diff --git a/include/zot.php b/include/zot.php
index 77d82f110..7c2cfe019 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,10 @@ 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);
+ $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)