aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/Contact.php90
-rw-r--r--include/ItemObject.php42
-rw-r--r--include/apps.php431
-rw-r--r--include/auth.php15
-rw-r--r--include/bb2diaspora.php8
-rw-r--r--include/bbcode.php52
-rw-r--r--include/conversation.php2
-rw-r--r--include/datetime.php55
-rw-r--r--include/dir_fns.php2
-rw-r--r--include/event.php256
-rwxr-xr-xinclude/items.php63
-rw-r--r--include/js_strings.php9
-rw-r--r--include/language.php25
-rw-r--r--include/nav.php5
-rw-r--r--include/network.php8
-rwxr-xr-xinclude/plugin.php11
-rw-r--r--include/poller.php3
-rw-r--r--include/reddav.php2
-rw-r--r--include/session.php6
-rwxr-xr-xinclude/text.php6
-rw-r--r--include/widgets.php66
-rw-r--r--include/zot.php72
22 files changed, 1035 insertions, 194 deletions
diff --git a/include/Contact.php b/include/Contact.php
index 540e1169d..ffee5096a 100644
--- a/include/Contact.php
+++ b/include/Contact.php
@@ -141,24 +141,6 @@ function abook_toggle_flag($abook,$flag) {
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
// Included here for completeness, but this is a very dangerous operation.
// It is the caller's responsibility to confirm the requestor's intent and
// authorisation to do this.
@@ -305,6 +287,76 @@ function channel_remove($channel_id, $local = true) {
}
+/**
+ * mark any hubs "offline" that haven't been heard from in more than 30 days
+ * Allow them to redeem themselves if they come back later.
+ * Then go through all those that are newly marked and see if any other hubs
+ * are attached to the controlling xchan that are still alive.
+ * If not, they're dead (although they could come back some day).
+ */
+
+
+function mark_orphan_hubsxchans() {
+
+ $dirmode = intval(get_config('system','directory_mode'));
+ if($dirmode == DIRECTORY_MODE_NORMAL)
+ return;
+
+ $r = q("update hubloc set hubloc_status = (hubloc_status | %d) where not (hubloc_status & %d)
+ and hubloc_connected < utc_timestamp() - interval 36 day",
+ intval(HUBLOC_OFFLINE),
+ intval(HUBLOC_OFFLINE)
+ );
+
+ $r = q("select hubloc_id, hubloc_hash from hubloc where (hubloc_status & %d) and not (hubloc_flags & %d)",
+ intval(HUBLOC_OFFLINE),
+ intval(HUBLOC_FLAGS_ORPHANCHECK)
+ );
+
+ if($r) {
+ foreach($r as $rr) {
+
+ // see if any other hublocs are still alive for this channel
+
+ $x = q("select * from hubloc where hubloc_hash = '%s' and not (hubloc_status & %d)",
+ dbesc($rr['hubloc_hash']),
+ intval(HUBLOC_OFFLINE)
+ );
+ if($x) {
+
+ // yes - if the xchan was marked as an orphan, undo it
+
+ $y = q("update xchan set xchan_flags = (xchan_flags ^ %d) where (xchan_flags & %d) and xchan_hash = '%s' limit 1",
+ intval(XCHAN_FLAGS_ORPHAN),
+ intval(XCHAN_FLAGS_ORPHAN),
+ dbesc($rr['hubloc_hash'])
+ );
+
+ }
+ else {
+
+ // nope - mark the xchan as an orphan
+
+ $y = q("update xchan set xchan_flags = (xchan_flags | %d) where xchan_hash = '%s' limit 1",
+ intval(XCHAN_FLAGS_ORPHAN),
+ dbesc($rr['hubloc_hash'])
+ );
+ }
+
+ // mark that we've checked this entry so we don't need to do it again
+
+ $y = q("update hubloc set hubloc_flags = (hubloc_flags | %d) where hubloc_id = %d limit 1",
+ intval(HUBLOC_FLAGS_ORPHANCHECK),
+ dbesc($rr['hubloc_id'])
+ );
+ }
+ }
+
+}
+
+
+
+
function remove_all_xchan_resources($xchan, $channel_id = 0) {
if(intval($channel_id)) {
@@ -510,7 +562,7 @@ function unmark_for_death($contact) {
}}
function random_profile() {
- $r = q("select xchan_url from xchan where 1 order by rand() limit 1");
+ $r = q("select xchan_url from xchan left join hubloc on hubloc_hash = xchan_hash where hubloc_connected > UTC_TIMESTAMP() - interval 30 day order by rand() limit 1");
if($r)
return $r[0]['xchan_url'];
return '';
diff --git a/include/ItemObject.php b/include/ItemObject.php
index 36070335d..a5870ef91 100644
--- a/include/ItemObject.php
+++ b/include/ItemObject.php
@@ -115,7 +115,7 @@ class Item extends BaseObject {
);
}
- $filer = (($conv->get_profile_owner() == local_user()) ? t("save to folder") : false);
+ $filer = (($conv->get_profile_owner() == local_user()) ? t("Save to Folder") : false);
$profile_avatar = $item['author']['xchan_photo_m'];
$profile_link = chanlink_url($item['author']['xchan_url']);
@@ -125,11 +125,24 @@ class Item extends BaseObject {
$like_count = ((x($alike,$item['mid'])) ? $alike[$item['mid']] : '');
$like_list = ((x($alike,$item['mid'])) ? $alike[$item['mid'] . '-l'] : '');
- $like_button_label = ((x($alike,$item['mid'])) && ($alike[$item['mid']] < 2 ) ? t('like') : t('likes'));
+ if (count($like_list) > MAX_LIKERS) {
+ $like_list_part = array_slice($like_list, 0, MAX_LIKERS);
+ array_push($like_list_part, '<a href="#" data-toggle="modal" data-target="#likeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
+ } else {
+ $like_list_part = '';
+ }
+ $like_button_label = tt('Like','Likes',$like_count,'noun');
+
if (feature_enabled($conv->get_profile_owner(),'dislike')) {
$dislike_count = ((x($dlike,$item['mid'])) ? $dlike[$item['mid']] : '');
$dislike_list = ((x($dlike,$item['mid'])) ? $dlike[$item['mid'] . '-l'] : '');
- $dislike_button_label = ((x($dlike,$item['mid'])) && ($dlike[$item['mid']] < 2) ? t('dislike') : t('dislikes'));
+ $dislike_button_label = tt('Dislike','Dislikes',$dislike_count,'noun');
+ if (count($dislike_list) > MAX_LIKERS) {
+ $dislike_list_part = array_slice($dislike_list, 0, MAX_LIKERS);
+ array_push($dislike_list_part, '<a href="#" data-toggle="modal" data-target="#dislikeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
+ } else {
+ $dislike_list_part = '';
+ }
}
$showlike = ((x($alike,$item['mid'])) ? format_like($alike[$item['mid']],$alike[$item['mid'] . '-l'],'like',$item['mid']) : '');
@@ -151,9 +164,9 @@ class Item extends BaseObject {
// FIXME we don't need all this stuff, some can be done in the template
$star = array(
- 'do' => t("add star"),
- 'undo' => t("remove star"),
- 'toggle' => t("toggle star status"),
+ 'do' => t("Add Star"),
+ 'undo' => t("Remove Star"),
+ 'toggle' => t("Toggle Star Status"),
'classdo' => (($item['item_flags'] & ITEM_STARRED) ? "hidden" : ""),
'classundo' => (($item['item_flags'] & ITEM_STARRED) ? "" : "hidden"),
'isstarred' => (($item['item_flags'] & ITEM_STARRED) ? "starred icon-star" : "unstarred icon-star-empty"),
@@ -174,7 +187,7 @@ class Item extends BaseObject {
// FIXME - check this permission
if($conv->get_profile_owner() == local_user()) {
$tagger = array(
- 'tagit' => t("add tag"),
+ 'tagit' => t("Add Tag"),
'classtagger' => "",
);
}
@@ -187,12 +200,15 @@ class Item extends BaseObject {
}
}
+ $has_event = false;
+ if(($item['obj_type'] === ACTIVITY_OBJ_EVENT) && $conv->get_profile_owner() == local_user())
+ $has_event = true;
if($this->is_commentable()) {
$like = array( t("I like this \x28toggle\x29"), t("like"));
$dislike = array( t("I don't like this \x28toggle\x29"), t("dislike"));
if ($shareable)
- $share = array( t('Share this'), t('share'));
+ $share = array( t('Share This'), t('share'));
}
if(strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC','now - 12 hours')) > 0)
@@ -255,16 +271,22 @@ class Item extends BaseObject {
'star' => ((feature_enabled($conv->get_profile_owner(),'star_posts')) ? $star : ''),
'tagger' => ((feature_enabled($conv->get_profile_owner(),'commtag')) ? $tagger : ''),
'filer' => ((feature_enabled($conv->get_profile_owner(),'filing')) ? $filer : ''),
- 'bookmark' => (($conv->get_profile_owner() == local_user() && $has_bookmarks) ? t('Bookmark Links') : ''),
+ 'bookmark' => (($conv->get_profile_owner() == local_user() && $has_bookmarks) ? t('Save Bookmarks') : ''),
+ 'addtocal' => (($has_event) ? t('Add to Calendar') : ''),
'drop' => $drop,
'multidrop' => ((feature_enabled($conv->get_profile_owner(),'multi_delete')) ? $multidrop : ''),
// end toolbar buttons
'like_count' => $like_count,
'like_list' => $like_list,
+ 'like_list_part' => $like_list_part,
'like_button_label' => $like_button_label,
+ 'like_modal_title' => t('Likes','noun'),
+ 'dislike_modal_title' => t('Dislikes','noun'),
'dislike_count' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_count : ''),
'dislike_list' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list : ''),
+ 'dislike_list_part' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list_part : ''),
'dislike_button_label' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_button_label : ''),
+ 'modal_dismiss' => t('Close'),
'showlike' => $showlike,
'showdislike' => $showdislike,
'comment' => $this->get_comment_box($indent),
@@ -291,7 +313,7 @@ class Item extends BaseObject {
if(($nb_children > 2) || ($thread_level > 1)) {
$result['children'][0]['comment_firstcollapsed'] = true;
$result['children'][0]['num_comments'] = sprintf( tt('%d comment','%d comments',$total_children),$total_children );
- $result['children'][0]['hide_text'] = t('show more');
+ $result['children'][0]['hide_text'] = t('[+] show all');
if($thread_level > 1) {
$result['children'][$nb_children - 1]['comment_lastcollapsed'] = true;
}
diff --git a/include/apps.php b/include/apps.php
new file mode 100644
index 000000000..f7b09c7b6
--- /dev/null
+++ b/include/apps.php
@@ -0,0 +1,431 @@
+<?php /** @file */
+
+/**
+ * apps
+ *
+ */
+
+require_once('include/plugin.php');
+
+function get_system_apps() {
+
+ $ret = array();
+ $files = glob('app/*.apd');
+ if($files) {
+ foreach($files as $f) {
+ $x = parse_app_description($f);
+ if($x) {
+ $ret[] = $x;
+ }
+ }
+ }
+ $files = glob('addon/*/*.apd');
+ if($files) {
+ foreach($files as $f) {
+ $n = basename($f,'.apd');
+ if(plugin_is_installed($n)) {
+ $x = parse_app_description($f);
+ if($x) {
+ $ret[] = $x;
+ }
+ }
+ }
+ }
+ usort($ret,'app_name_compare');
+ return $ret;
+
+}
+
+function app_name_compare($a,$b) {
+ return strcmp($a['name'],$b['name']);
+}
+
+function parse_app_description($f) {
+ $ret = array();
+
+ $baseurl = z_root();
+ $channel = get_app()->get_channel();
+ $address = (($channel) ? $channel['channel_address'] : '');
+
+ //future expansion
+
+ $observer = get_app()->get_observer();
+
+
+ $lines = @file($f);
+ if($lines) {
+ foreach($lines as $x) {
+ if(preg_match('/^([a-zA-Z].*?):(.*?)$/ism',$x,$matches)) {
+ $ret[$matches[1]] = trim(str_replace(array('$baseurl','$nick'),array($baseurl,$address),$matches[2]));
+ }
+ }
+ }
+
+
+
+ if(! $ret['photo'])
+ $ret['photo'] = $baseurl . '/' . get_default_profile_photo(80);
+
+
+ foreach($ret as $k => $v) {
+ if(strpos($v,'http') === 0)
+ $ret[$k] = zid($v);
+ }
+
+ if(array_key_exists('hover',$ret))
+ $ret['hover'] = str_replace(array('\'','"'),array('&#39;','&dquot;'),$ret['hover']);
+
+ if(array_key_exists('requires',$ret)) {
+ $require = trim(strtolower($ret['requires']));
+ switch($require) {
+ case 'nologin':
+ if(local_user())
+ unset($ret);
+ break;
+ case 'admin':
+ if(! is_site_admin())
+ unset($ret);
+ break;
+ case 'local_user':
+ if(! local_user())
+ unset($ret);
+ break;
+ case 'observer':
+ if(! $observer)
+ unset($ret);
+ break;
+ default:
+ if(! local_user() && feature_enabled(local_user(),$require))
+ unset($ret);
+ break;
+
+ }
+// logger('require: ' . print_r($ret,true));
+ }
+ if($ret) {
+ translate_system_apps($ret);
+ return $ret;
+ }
+ return false;
+}
+
+
+function translate_system_apps(&$arr) {
+ $apps = array(
+ 'Site Admin' => t('Site Admin'),
+ 'Bookmarks' => t('Bookmarks'),
+ 'Address Book' => t('Address Book'),
+ 'Login' => t('Login'),
+ 'Channel Select' => t('Channel Select'),
+ 'Matrix' => t('Matrix'),
+ 'Settings' => t('Settings'),
+ 'Files' => t('Files'),
+ 'Webpages' => t('Webpages'),
+ 'Channel Home' => t('Channel Home'),
+ 'Profile' => t('Profile'),
+ 'Photos' => t('Photos'),
+ 'Events' => t('Events'),
+ 'Directory' => t('Directory'),
+ 'Help' => t('Help'),
+ 'Mail' => t('Mail'),
+ 'Mood' => t('Mood'),
+ 'Poke' => t('Poke'),
+ 'Chat' => t('Chat'),
+ 'Search' => t('Search'),
+ 'Probe' => t('Probe'),
+ 'Suggest' => t('Suggest')
+ );
+
+ if(array_key_exists($arr['name'],$apps))
+ $arr['name'] = $apps[$arr['name']];
+
+}
+
+
+// papp is a portable app
+
+function app_render($papp,$mode = 'view') {
+
+ /**
+ * modes:
+ * view: normal mode for viewing an app via bbcode from a conversation or page
+ * provides install/update button if you're logged in locally
+ * list: normal mode for viewing an app on the app page
+ * no buttons are shown
+ * edit: viewing the app page in editing mode provides a delete button
+ */
+
+ $installed = false;
+
+ if(! $papp['photo'])
+ $papp['photo'] = z_root() . '/' . get_default_profile_photo(80);
+
+ if(! $papp)
+ return;
+
+ $papp['papp'] = papp_encode($papp);
+
+ foreach($papp as $k => $v) {
+ if(strpos($v,'http') === 0 && $k != 'papp')
+ $papp[$k] = zid($v);
+ if($k === 'desc')
+ $papp['desc'] = str_replace(array('\'','"'),array('&#39;','&dquot;'),$papp['desc']);
+
+ if($k === 'requires') {
+ $require = trim(strtolower($v));
+ switch($require) {
+ case 'nologin':
+ if(local_user())
+ return '';
+ break;
+ case 'admin':
+ if(! is_site_admin())
+ return '';
+ break;
+ case 'local_user':
+ if(! local_user())
+ return '';
+ break;
+ case 'observer':
+ $observer = get_app()->get_observer();
+ if(! $observer)
+ return '';
+ break;
+ default:
+ if(! local_user() && feature_enabled(local_user(),$require))
+ return '';
+ break;
+
+ }
+
+ }
+ }
+
+ if(local_user()) {
+ $installed = app_installed(local_user(),$papp);
+ }
+
+ $install_action = (($installed) ? t('Update') : t('Install'));
+
+ return replace_macros(get_markup_template('app.tpl'),array(
+ '$app' => $papp,
+ '$purchase' => (($papp['page'] && (! $installed)) ? t('Purchase') : ''),
+ '$install' => ((local_user() && $mode == 'view') ? $install_action : ''),
+ '$edit' => ((local_user() && $installed && $mode == 'edit') ? t('Edit') : ''),
+ '$delete' => ((local_user() && $installed && $mode == 'edit') ? t('Delete') : '')
+ ));
+}
+
+
+function app_install($uid,$app) {
+ $app['uid'] = $uid;
+ if(app_installed($uid,$app))
+ $x = app_update($app);
+ else
+ $x = app_store($app);
+
+ if($x['success'])
+ return $x['app_id'];
+
+ return false;
+}
+
+function app_destroy($uid,$app) {
+ if($uid && $app['guid']) {
+ $r = q("delete from app where app_id = '%s' and app_channel = %d limit 1",
+ dbesc($app['guid']),
+ intval($uid)
+ );
+ }
+}
+
+
+function app_installed($uid,$app) {
+
+ $r = q("select id from app where app_id = '%s' and app_version = '%s' and app_channel = %d limit 1",
+ dbesc((array_key_exists('guid',$app)) ? $app['guid'] : ''),
+ dbesc((array_key_exists('version',$app)) ? $app['version'] : ''),
+ intval($uid)
+ );
+ return(($r) ? true : false);
+
+}
+
+
+function app_list($uid) {
+ $r = q("select * from app where app_channel = %d order by app_name asc",
+ intval($uid)
+ );
+ return($r);
+}
+
+
+function app_decode($s) {
+ $x = base64_decode(str_replace(array('<br />',"\r","\n",' '),array('','','',''),$s));
+ return json_decode($x,true);
+}
+
+
+function app_store($arr) {
+
+ // logger('app_store: ' . print_r($arr,true));
+
+ $darray = array();
+ $ret = array('success' => false);
+
+ $darray['app_url'] = ((x($arr,'url')) ? $arr['url'] : '');
+ $darray['app_channel'] = ((x($arr,'uid')) ? $arr['uid'] : 0);
+
+ if((! $darray['app_url']) || (! $darray['app_channel']))
+ return $ret;
+
+ if($arr['photo'] && ! strstr($arr['photo'],z_root())) {
+ $x = import_profile_photo($arr['photo'],get_observer_hash(),true);
+ $arr['photo'] = $x[1];
+ }
+
+
+ $darray['app_id'] = ((x($arr,'guid')) ? $arr['guid'] : random_string(). '.' . get_app()->get_hostname());
+ $darray['app_sig'] = ((x($arr,'sig')) ? $arr['sig'] : '');
+ $darray['app_author'] = ((x($arr,'author')) ? $arr['author'] : get_observer_hash());
+ $darray['app_name'] = ((x($arr,'name')) ? escape_tags($arr['name']) : t('Unknown'));
+ $darray['app_desc'] = ((x($arr,'desc')) ? escape_tags($arr['desc']) : '');
+ $darray['app_photo'] = ((x($arr,'photo')) ? $arr['photo'] : z_root() . '/' . get_default_profile_photo(80));
+ $darray['app_version'] = ((x($arr,'version')) ? escape_tags($arr['version']) : '');
+ $darray['app_addr'] = ((x($arr,'addr')) ? escape_tags($arr['addr']) : '');
+ $darray['app_price'] = ((x($arr,'price')) ? escape_tags($arr['price']) : '');
+ $darray['app_page'] = ((x($arr,'page')) ? escape_tags($arr['page']) : '');
+ $darray['app_requires'] = ((x($arr,'requires')) ? escape_tags($arr['requires']) : '');
+
+ $r = q("insert into app ( app_id, app_sig, app_author, app_name, app_desc, app_url, app_photo, app_version, app_channel, app_addr, app_price, app_page, app_requires ) values ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s' )",
+ dbesc($darray['app_id']),
+ dbesc($darray['app_sig']),
+ dbesc($darray['app_author']),
+ dbesc($darray['app_name']),
+ dbesc($darray['app_desc']),
+ dbesc($darray['app_url']),
+ dbesc($darray['app_photo']),
+ dbesc($darray['app_version']),
+ intval($darray['app_channel']),
+ dbesc($darray['app_addr']),
+ dbesc($darray['app_price']),
+ dbesc($darray['app_page']),
+ dbesc($darray['app_requires'])
+ );
+ if($r) {
+ $ret['success'] = true;
+ $ret['app_id'] = $darray['app_id'];
+ }
+ return $ret;
+}
+
+
+function app_update($arr) {
+
+ $darray = array();
+ $ret = array('success' => false);
+
+ $darray['app_url'] = ((x($arr,'url')) ? $arr['url'] : '');
+ $darray['app_channel'] = ((x($arr,'uid')) ? $arr['uid'] : 0);
+ $darray['app_id'] = ((x($arr,'guid')) ? $arr['guid'] : 0);
+
+ if((! $darray['app_url']) || (! $darray['app_channel']) || (! $darray['app_id']))
+ return $ret;
+
+ if($arr['photo'] && ! strstr($arr['photo'],z_root())) {
+ $x = import_profile_photo($arr['photo'],get_observer_hash(),true);
+ $arr['photo'] = $x[1];
+ }
+
+ $darray['app_sig'] = ((x($arr,'sig')) ? $arr['sig'] : '');
+ $darray['app_author'] = ((x($arr,'author')) ? $arr['author'] : get_observer_hash());
+ $darray['app_name'] = ((x($arr,'name')) ? escape_tags($arr['name']) : t('Unknown'));
+ $darray['app_desc'] = ((x($arr,'desc')) ? escape_tags($arr['desc']) : '');
+ $darray['app_photo'] = ((x($arr,'photo')) ? $arr['photo'] : z_root() . '/' . get_default_profile_photo(80));
+ $darray['app_version'] = ((x($arr,'version')) ? escape_tags($arr['version']) : '');
+ $darray['app_addr'] = ((x($arr,'addr')) ? escape_tags($arr['addr']) : '');
+ $darray['app_price'] = ((x($arr,'price')) ? escape_tags($arr['price']) : '');
+ $darray['app_page'] = ((x($arr,'page')) ? escape_tags($arr['page']) : '');
+ $darray['app_requires'] = ((x($arr,'requires')) ? escape_tags($arr['requires']) : '');
+
+ $r = q("update app set app_sig = '%s', app_author = '%s', app_name = '%s', app_desc = '%s', app_url = '%s', app_photo = '%s', app_version = '%s', app_addr = '%s', app_price = '%s', app_page = '%s', app_requires = '%s' where app_id = '%s' and app_channel = %d limit 1",
+ dbesc($darray['app_sig']),
+ dbesc($darray['app_author']),
+ dbesc($darray['app_name']),
+ dbesc($darray['app_desc']),
+ dbesc($darray['app_url']),
+ dbesc($darray['app_photo']),
+ dbesc($darray['app_version']),
+ dbesc($darray['app_addr']),
+ dbesc($darray['app_price']),
+ dbesc($darray['app_page']),
+ dbesc($darray['app_requires']),
+ dbesc($darray['app_id']),
+ intval($darray['app_channel'])
+ );
+ if($r) {
+ $ret['success'] = true;
+ $ret['app_id'] = $darray['app_id'];
+ }
+
+ return $ret;
+
+}
+
+
+function app_encode($app,$embed = false) {
+
+ $ret = array();
+
+ if($app['app_id'])
+ $ret['guid'] = $app['app_id'];
+
+ if($app['app_id'])
+ $ret['guid'] = $app['app_id'];
+
+ if($app['app_sig'])
+ $ret['sig'] = $app['app_sig'];
+
+ if($app['app_author'])
+ $ret['author'] = $app['app_author'];
+
+ if($app['app_name'])
+ $ret['name'] = $app['app_name'];
+
+ if($app['app_desc'])
+ $ret['desc'] = $app['app_desc'];
+
+ if($app['app_url'])
+ $ret['url'] = $app['app_url'];
+
+ if($app['app_photo'])
+ $ret['photo'] = $app['app_photo'];
+
+ if($app['app_version'])
+ $ret['version'] = $app['app_version'];
+
+ if($app['app_addr'])
+ $ret['addr'] = $app['app_addr'];
+
+ if($app['app_price'])
+ $ret['price'] = $app['app_price'];
+
+ if($app['app_page'])
+ $ret['page'] = $app['app_page'];
+
+ if($app['app_requires'])
+ $ret['requires'] = $app['app_requires'];
+
+ if(! $embed)
+ return $ret;
+
+ $j = json_encode($ret);
+ return '[app]' . chunk_split(base64_encode($j),72,"\n") . '[/app]';
+
+}
+
+
+function papp_encode($papp) {
+ return chunk_split(base64_encode(json_encode($papp)),72,"\n");
+
+} \ No newline at end of file
diff --git a/include/auth.php b/include/auth.php
index c21705c99..e8f13d0fb 100644
--- a/include/auth.php
+++ b/include/auth.php
@@ -117,13 +117,14 @@ if((isset($_SESSION)) && (x($_SESSION,'authenticated')) && ((! (x($_POST,'auth-p
// first check if we're enforcing that sessions can't change IP address
- $check = get_config('system','paranoia');
- // extra paranoia - if the IP changed, log them out
- if($check && ($_SESSION['addr'] != $_SERVER['REMOTE_ADDR'])) {
- logger('Session address changed. Paranoid setting in effect, blocking session. '
- . $_SESSION['addr'] . ' != ' . $_SERVER['REMOTE_ADDR']);
- nuke_session();
- goaway(z_root());
+ if($_SESSION['addr'] != $_SERVER['REMOTE_ADDR']) {
+ logger('SECURITY: Session IP address changed: ' . $_SESSION['addr'] . ' != ' . $_SERVER['REMOTE_ADDR']);
+ if(get_config('system','paranoia')) {
+ logger('Session address changed. Paranoid setting in effect, blocking session. '
+ . $_SESSION['addr'] . ' != ' . $_SERVER['REMOTE_ADDR']);
+ nuke_session();
+ goaway(z_root());
+ }
}
$r = q("select * from account where account_id = %d limit 1",
diff --git a/include/bb2diaspora.php b/include/bb2diaspora.php
index 8d3089a29..f9ecc564f 100644
--- a/include/bb2diaspora.php
+++ b/include/bb2diaspora.php
@@ -281,6 +281,14 @@ function bb2diaspora($Text,$preserve_nl = false, $fordiaspora = true) {
$Text = preg_replace("/\[img\](.*?)\[\/img\]/", '![' . t('image/photo') . '](' . '$1' . ')', $Text);
$Text = preg_replace("/\[img\=(.*?)\](.*?)\[\/img\]/", '![' . t('image/photo') . '](' . '$2' . ')', $Text);
+ $Text = preg_replace("/\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '[$1]($1)', $Text);
+ $Text = preg_replace("/\#\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '[#$2]($1)', $Text);
+ $Text = preg_replace("/\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '[$2]($1)', $Text);
+
+
+ $Text = preg_replace("/\[zmg\](.*?)\[\/zmg\]/", '![' . t('image/photo') . '](' . '$1' . ')', $Text);
+ $Text = preg_replace("/\[zmg\=(.*?)\](.*?)\[\/zmg\]/", '![' . t('image/photo') . '](' . '$2' . ')', $Text);
+
// Perform MAIL Search
$Text = preg_replace("(\[mail\]([$MAILSearchString]*)\[/mail\])", '[$1](mailto:$1)', $Text);
$Text = preg_replace("/\[mail\=([$MAILSearchString]*)\](.*?)\[\/mail\]/", '[$2](mailto:$1)', $Text);
diff --git a/include/bbcode.php b/include/bbcode.php
index 326676b72..674b5f45a 100644
--- a/include/bbcode.php
+++ b/include/bbcode.php
@@ -63,7 +63,7 @@ function bb_spacefy($st) {
}
// The previously spacefied [noparse][ i ]italic[ /i ][/noparse],
-// now turns back and the [noparse] tags are trimed
+// now turns back and the [noparse] tags are trimmed
// returning [i]italic[/i]
function bb_unspacefy_and_trim($st) {
@@ -166,6 +166,15 @@ function bb_parse_crypt($match) {
}
+function bb_parse_app($match) {
+ require_once('include/apps.php');
+
+ $app = app_decode($match[1]);
+ if($app)
+ return app_render($app);
+
+}
+
function bb_qr($match) {
return '<img class="zrl" src="' . z_root() . '/photo/qr?f=&qr=' . urlencode($match[1]) . '" alt="' . t('QR code') . '" title="' . htmlspecialchars($match[1],ENT_QUOTES,'UTF-8') . '" />';
}
@@ -507,6 +516,30 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
$Text = preg_replace("(\[size=(\d*?)\](.*?)\[\/size\])ism","<span style=\"font-size: $1px;\">$2</span>",$Text);
$Text = preg_replace("(\[size=(.*?)\](.*?)\[\/size\])ism","<span style=\"font-size: $1;\">$2</span>",$Text);
}
+ // Check for h1
+ if (strpos($Text,'[h1]') !== false) {
+ $Text = preg_replace("(\[h1\](.*?)\[\/h1\])ism",'<h1>$1</h1>',$Text);
+ }
+ // Check for h2
+ if (strpos($Text,'[h2]') !== false) {
+ $Text = preg_replace("(\[h2\](.*?)\[\/h2\])ism",'<h2>$1</h2>',$Text);
+ }
+ // Check for h3
+ if (strpos($Text,'[h3]') !== false) {
+ $Text = preg_replace("(\[h3\](.*?)\[\/h3\])ism",'<h3>$1</h3>',$Text);
+ }
+ // Check for h4
+ if (strpos($Text,'[h4]') !== false) {
+ $Text = preg_replace("(\[h4\](.*?)\[\/h4\])ism",'<h4>$1</h4>',$Text);
+ }
+ // Check for h5
+ if (strpos($Text,'[h5]') !== false) {
+ $Text = preg_replace("(\[h5\](.*?)\[\/h5\])ism",'<h5>$1</h5>',$Text);
+ }
+ // Check for h6
+ if (strpos($Text,'[h6]') !== false) {
+ $Text = preg_replace("(\[h6\](.*?)\[\/h6\])ism",'<h6>$1</h6>',$Text);
+ }
// Check for centered text
if (strpos($Text,'[/center]') !== false) {
$Text = preg_replace("(\[center\](.*?)\[\/center\])ism","<div style=\"text-align:center;\">$1</div>",$Text);
@@ -606,24 +639,24 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
// Images
// [img]pathtoimage[/img]
if (strpos($Text,'[/img]') !== false) {
- $Text = preg_replace("/\[img\](.*?)\[\/img\]/ism", '<img src="$1" alt="' . t('Image/photo') . '" />', $Text);
+ $Text = preg_replace("/\[img\](.*?)\[\/img\]/ism", '<img style="max-width=100%;" src="$1" alt="' . t('Image/photo') . '" />', $Text);
}
if (strpos($Text,'[/zmg]') !== false) {
- $Text = preg_replace("/\[zmg\](.*?)\[\/zmg\]/ism", '<img class="zrl" src="$1" alt="' . t('Image/photo') . '" />', $Text);
+ $Text = preg_replace("/\[zmg\](.*?)\[\/zmg\]/ism", '<img class="zrl" style="max-width=100%;" src="$1" alt="' . t('Image/photo') . '" />', $Text);
}
// [img float={left, right}]pathtoimage[/img]
if (strpos($Text,'[/img]') !== false) {
- $Text = preg_replace("/\[img float=left\](.*?)\[\/img\]/ism", '<img src="$1" style="float: left;" alt="' . t('Image/photo') . '" />', $Text);
+ $Text = preg_replace("/\[img float=left\](.*?)\[\/img\]/ism", '<img style="max-width=100%;" src="$1" style="float: left;" alt="' . t('Image/photo') . '" />', $Text);
}
if (strpos($Text,'[/img]') !== false) {
- $Text = preg_replace("/\[img float=right\](.*?)\[\/img\]/ism", '<img src="$1" style="float: right;" alt="' . t('Image/photo') . '" />', $Text);
+ $Text = preg_replace("/\[img float=right\](.*?)\[\/img\]/ism", '<img style="max-width=100%;" src="$1" style="float: right;" alt="' . t('Image/photo') . '" />', $Text);
}
if (strpos($Text,'[/zmg]') !== false) {
- $Text = preg_replace("/\[zmg float=left\](.*?)\[\/zmg\]/ism", '<img class="zrl" src="$1" style="float: left;" alt="' . t('Image/photo') . '" />', $Text);
+ $Text = preg_replace("/\[zmg float=left\](.*?)\[\/zmg\]/ism", '<img style="max-width=100%;" class="zrl" src="$1" style="float: left;" alt="' . t('Image/photo') . '" />', $Text);
}
if (strpos($Text,'[/zmg]') !== false) {
- $Text = preg_replace("/\[zmg float=right\](.*?)\[\/zmg\]/ism", '<img class="zrl" src="$1" style="float: right;" alt="' . t('Image/photo') . '" />', $Text);
+ $Text = preg_replace("/\[zmg float=right\](.*?)\[\/zmg\]/ism", '<img style="max-width=100%;" class="zrl" src="$1" style="float: right;" alt="' . t('Image/photo') . '" />', $Text);
}
// [img=widthxheight]pathtoimage[/img]
@@ -660,6 +693,11 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) {
$Text = preg_replace_callback("/\[crypt (.*?)\](.*?)\[\/crypt\]/ism", 'bb_parse_crypt', $Text);
}
+ if(strpos($Text,'[/app]') !== false) {
+ $Text = preg_replace_callback("/\[app\](.*?)\[\/app\]/ism",'bb_parse_app', $Text);
+ }
+
+
// html5 video and audio
if (strpos($Text,'[/video]') !== false) {
$Text = preg_replace_callback("/\[video\](.*?\.(ogg|ogv|oga|ogm|webm|mp4))\[\/video\]/ism", 'tryzrlvideo', $Text);
diff --git a/include/conversation.php b/include/conversation.php
index 2d72f3489..21ce3bb66 100644
--- a/include/conversation.php
+++ b/include/conversation.php
@@ -255,7 +255,7 @@ function localize_item(&$item){
$A = '[zrl=' . chanlink_url($Alink) . ']' . $Aname . '[/zrl]';
- $txt = t('%1$s is currently %2$s');
+ $txt = t('%1$s is %2$s','mood');
$item['body'] = sprintf($txt, $A, t($verb));
}
diff --git a/include/datetime.php b/include/datetime.php
index c0503fc7d..0214b9e4c 100644
--- a/include/datetime.php
+++ b/include/datetime.php
@@ -443,6 +443,12 @@ function cal($y = 0,$m = 0, $links = false, $class='') {
}
+/**
+ * Return the next birthday, converted from the owner's timezone to UTC.
+ * This makes it globally portable.
+ * If the provided birthday lacks a month and or day, return an empty string.
+ * A missing year is acceptable.
+ */
function z_birthday($dob,$tz,$format="Y-m-d H:i:s") {
@@ -450,8 +456,10 @@ function z_birthday($dob,$tz,$format="Y-m-d H:i:s") {
if(! strlen($tz))
$tz = 'UTC';
+ $birthday = '';
$tmp_dob = substr($dob,5);
- if(intval($tmp_dob)) {
+ $tmp_d = substr($dob,8);
+ if(intval($tmp_dob) && intval($tmp_d)) {
$y = datetime_convert($tz,$tz,'now','Y');
$bd = $y . '-' . $tmp_dob . ' 00:00';
$t_dob = strtotime($bd);
@@ -464,3 +472,48 @@ function z_birthday($dob,$tz,$format="Y-m-d H:i:s") {
return $birthday;
}
+
+/**
+ *
+ * Create a birthday event for any connections with a birthday in the next 1-2 weeks.
+ * Update the year so that we don't create another event until next year.
+ *
+ */
+
+
+function update_birthdays() {
+
+ require_once('include/event.php');
+ require_once('include/permissions.php');
+
+ $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash
+ WHERE abook_dob > utc_timestamp() + interval 7 day and abook_dob < utc_timestamp() + interval 14 day");
+ if($r) {
+ foreach($r as $rr) {
+
+ if(! perm_is_allowed($rr['abook_channel'],$rr['xchan_hash'],'send_stream'))
+ continue;
+
+ $ev = array();
+ $ev['uid'] = $rr['abook_channel'];
+ $ev['account'] = $rr['abook_account'];
+ $ev['event_xchan'] = $rr['xchan_hash'];
+ $ev['start'] = datetime_convert('UTC','UTC', $rr['abook_dob']);
+ $ev['finish'] = datetime_convert('UTC','UTC', $rr['abook_dob'] . ' + 1 day ');
+ $ev['adjust'] = 1;
+ $ev['summary'] = sprintf( t('%1$s\'s birthday'), $rr['xchan_name']);
+ $ev['description'] = sprintf( t('Happy Birthday %1$s'),
+ '[zrl=' . $rr['xchan_url'] . ']' . $rr['xchan_name'] . '[/zrl]') ;
+ $ev['type'] = 'birthday';
+
+ $z = event_store_event($ev);
+ if($z) {
+ $item_id = event_store_item($ev,$z);
+ q("update abook set abook_dob = '%s' where abook_id = %d limit 1",
+ dbesc(intval($rr['abook_dob']) + 1 . substr($rr['abook_dob'],4)),
+ intval($rr['abook_id'])
+ );
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/include/dir_fns.php b/include/dir_fns.php
index a96e7821f..71800cb47 100644
--- a/include/dir_fns.php
+++ b/include/dir_fns.php
@@ -249,7 +249,7 @@ function local_dir_update($uid,$force) {
}
$ud_hash = random_string() . '@' . get_app()->get_hostname();
- update_modtime($hash,$ud_hash,$p[0]['channel_address'] . '@' . get_app()->get_hostname(),(($force) ? (-1) : 1));
+ update_modtime($hash,$ud_hash,$p[0]['channel_address'] . '@' . get_app()->get_hostname(),(($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED));
}
diff --git a/include/event.php b/include/event.php
index 8e6a3fe71..e198fe15c 100644
--- a/include/event.php
+++ b/include/event.php
@@ -128,20 +128,15 @@ function ev_compare($a,$b) {
}
-
-function event_store($arr) {
-
- require_once('include/datetime.php');
- require_once('include/items.php');
- require_once('include/bbcode.php');
-
- $a = get_app();
+function event_store_event($arr) {
$arr['created'] = (($arr['created']) ? $arr['created'] : datetime_convert());
$arr['edited'] = (($arr['edited']) ? $arr['edited'] : datetime_convert());
$arr['type'] = (($arr['type']) ? $arr['type'] : 'event' );
$arr['event_xchan'] = (($arr['event_xchan']) ? $arr['event_xchan'] : '');
-
+
+
+
// Existing event being modified
if($arr['id'] || $arr['event_hash']) {
@@ -161,12 +156,13 @@ function event_store($arr) {
);
}
+
if(! $r)
- return 0;
+ return false;
if($r[0]['edited'] === $arr['edited']) {
// Nothing has changed. Return the ID.
- return $r[0]['id'];
+ return $r[0];
}
$event_hash = $r[0]['event_hash'];
@@ -205,56 +201,6 @@ function event_store($arr) {
intval($r[0]['id']),
intval($arr['uid'])
);
-
- $r = q("SELECT * FROM item left join xchan on author_xchan = xchan_hash WHERE resource_id = '%s' AND resource_type = 'event' and uid = %d LIMIT 1",
- dbesc($event_hash),
- intval($arr['uid'])
- );
-
- if($r) {
-
- $obj = json_encode(array(
- 'type' => ACTIVITY_OBJ_EVENT,
- 'id' => z_root() . '/event/' . $r[0]['resource_id'],
- 'title' => $arr['summary'],
- 'content' => format_event_bbcode($arr),
- 'author' => array(
- 'name' => $r[0]['xchan_name'],
- 'address' => $r[0]['xchan_addr'],
- 'guid' => $r[0]['xchan_guid'],
- 'guid_sig' => $r[0]['xchan_guid_sig'],
- 'link' => array(
- array('rel' => 'alternate', 'type' => 'text/html', 'href' => $r[0]['xchan_url']),
- array('rel' => 'photo', 'type' => $r[0]['xchan_photo_mimetype'], 'href' => $r[0]['xchan_photo_m'])),
- ),
- ));
-
- $private = (($arr['allow_cid'] || $arr['allow_gid'] || $arr['deny_cid'] || $arr['deny_gid']) ? 1 : 0);
-
-
- q("UPDATE item SET title = '%s', body = '%s', object = '%s', allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', edited = '%s', item_flags = %d, item_private = %d WHERE id = %d AND uid = %d LIMIT 1",
- dbesc($arr['summary']),
- dbesc(format_event_bbcode($arr)),
- dbesc($object),
- dbesc($arr['allow_cid']),
- dbesc($arr['allow_gid']),
- dbesc($arr['deny_cid']),
- dbesc($arr['deny_gid']),
- dbesc($arr['edited']),
- intval($r[0]['item_flags']),
- intval($private),
- intval($r[0]['id']),
- intval($arr['uid'])
- );
-
- $item_id = $r[0]['id'];
- }
- else
- $item_id = 0;
-
- call_hooks('event_updated', $arr['id']);
-
- return $item_id;
}
else {
@@ -262,9 +208,6 @@ function event_store($arr) {
$hash = random_string();
- if(! $arr['mid'])
- $arr['mid'] = item_message_id();
-
$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)
@@ -289,37 +232,187 @@ function event_store($arr) {
dbesc($arr['deny_gid'])
);
+ }
- $r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
- dbesc($hash),
+ $r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
+ dbesc($hash),
+ intval($arr['uid'])
+ );
+ if($r)
+ return $r[0];
+
+ return false;
+
+}
+
+function event_addtocal($item_id, $uid) {
+
+ $c = q("select * from channel where channel_id = %d limit 1",
+ intval($uid)
+ );
+
+ if(! $c)
+ return false;
+
+ $channel = $c[0];
+
+ $r = q("select * from item where id = %d and uid = %d limit 1",
+ intval($item_id),
+ intval($channel['channel_id'])
+ );
+
+ if((! $r) || ($r[0]['obj_type'] !== ACTIVITY_OBJ_EVENT))
+ return false;
+
+ $item = $r[0];
+
+ $ev = bbtoevent($r[0]['body']);
+
+ if(x($ev,'summary') && x($ev,'start')) {
+ $ev['event_xchan'] = $item['author_xchan'];
+ $ev['uid'] = $channel['channel_id'];
+ $ev['account'] = $channel['channel_account_id'];
+ $ev['edited'] = $item['edited'];
+ $ev['mid'] = $item['mid'];
+ $ev['private'] = $item['item_private'];
+
+ // is this an edit?
+
+ if($item['resource_type'] === 'event') {
+ $ev['event_hash'] = $item['resource_id'];
+ }
+
+ $event = event_store_event($ev);
+ if($event) {
+ $r = q("update item set resource_id = '%s', resource_type = 'event' where id = %d and uid = %d limit 1",
+ dbesc($event['event_hash']),
+ intval($item['id']),
+ intval($channel['channel_id'])
+ );
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+function event_store_item($arr,$event) {
+
+ require_once('include/datetime.php');
+ require_once('include/items.php');
+ require_once('include/bbcode.php');
+
+ $a = get_app();
+
+ $item = null;
+
+ if($arr['mid'] && $arr['uid']) {
+ $i = q("select * from item where mid = '%s' and uid = %d limit 1",
+ dbesc($arr['mid']),
intval($arr['uid'])
);
- if(count($r))
- $event = $r[0];
+ if($i) {
+ xchan_query($i);
+ $item = fetch_post_tags($i,true);
+ }
+ }
- $z = q("select * from channel where channel_hash = '%s' and channel_id = %d limit 1",
- dbesc($arr['event_xchan']),
+ $item_arr = array();
+ $prefix = '';
+ $birthday = false;
+
+ if($event['type'] === 'birthday') {
+ $prefix = t('This event has been added to your calendar.');
+ $birthday = true;
+
+ // The event is created on your own site by the system, but appears to belong
+ // to the birthday person. It also isn't propagated - so we need to prevent
+ // folks from trying to comment on it. If you're looking at this and trying to
+ // fix it, you'll need to completely change the way birthday events are created
+ // and send them out from the source. This has its own issues.
+
+ $item_arr['comment_policy'] = 'none';
+ }
+
+ $r = q("SELECT * FROM item left join xchan on author_xchan = xchan_hash WHERE resource_id = '%s' AND resource_type = 'event' and uid = %d LIMIT 1",
+ dbesc($event['event_hash']),
+ intval($arr['uid'])
+ );
+
+ if($r) {
+ $obj = json_encode(array(
+ 'type' => ACTIVITY_OBJ_EVENT,
+ 'id' => z_root() . '/event/' . $r[0]['resource_id'],
+ 'title' => $arr['summary'],
+ 'content' => format_event_bbcode($arr),
+ 'author' => array(
+ 'name' => $r[0]['xchan_name'],
+ 'address' => $r[0]['xchan_addr'],
+ 'guid' => $r[0]['xchan_guid'],
+ 'guid_sig' => $r[0]['xchan_guid_sig'],
+ 'link' => array(
+ array('rel' => 'alternate', 'type' => 'text/html', 'href' => $r[0]['xchan_url']),
+ array('rel' => 'photo', 'type' => $r[0]['xchan_photo_mimetype'], 'href' => $r[0]['xchan_photo_m'])),
+ ),
+ ));
+
+ $private = (($arr['allow_cid'] || $arr['allow_gid'] || $arr['deny_cid'] || $arr['deny_gid']) ? 1 : 0);
+
+ q("UPDATE item SET title = '%s', body = '%s', object = '%s', allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', edited = '%s', item_flags = %d, item_private = %d WHERE id = %d AND uid = %d LIMIT 1",
+ dbesc($arr['summary']),
+ dbesc($prefix . format_event_bbcode($arr)),
+ dbesc($object),
+ dbesc($arr['allow_cid']),
+ dbesc($arr['allow_gid']),
+ dbesc($arr['deny_cid']),
+ dbesc($arr['deny_gid']),
+ dbesc($arr['edited']),
+ intval($r[0]['item_flags']),
+ intval($private),
+ intval($r[0]['id']),
intval($arr['uid'])
);
- $wall = (($z) ? true : false);
+ $item_id = $r[0]['id'];
+ call_hooks('event_updated', $event['id']);
+ return $item_id;
+ }
+ else {
+
+ $z = q("select * from channel where channel_hash = '%s' and channel_id = %d limit 1",
+ dbesc($event['event_xchan']),
+ intval($arr['uid'])
+ );
- $item_flags = ITEM_THREAD_TOP;
- if($wall) {
- $item_flags |= ITEM_WALL;
- $item_flags |= ITEM_ORIGIN;
- }
$private = (($arr['allow_cid'] || $arr['allow_gid'] || $arr['deny_cid'] || $arr['deny_gid']) ? 1 : 0);
- $item_arr = array();
+ if($item) {
+ $item_arr['id'] = $item['id'];
+ }
+ else {
+ $wall = (($z) ? true : false);
+
+ $item_flags = ITEM_THREAD_TOP;
+ if($wall) {
+ $item_flags |= ITEM_WALL;
+ $item_flags |= ITEM_ORIGIN;
+ }
+ $item_arr['item_flags'] = $item_flags;
+
+ }
+
+ if(! $arr['mid'])
+ $arr['mid'] = item_message_id();
+
+ $item_arr['aid'] = $z[0]['channel_account_id'];
$item_arr['uid'] = $arr['uid'];
$item_arr['author_xchan'] = $arr['event_xchan'];
$item_arr['mid'] = $arr['mid'];
$item_arr['parent_mid'] = $arr['mid'];
- $item_arr['item_flags'] = $item_flags;
$item_arr['owner_xchan'] = (($wall) ? $z[0]['channel_hash'] : $arr['event_xchan']);
$item_arr['author_xchan'] = $arr['event_xchan'];
@@ -332,10 +425,11 @@ function event_store($arr) {
$item_arr['verb'] = ACTIVITY_POST;
$item_arr['resource_type'] = 'event';
- $item_arr['resource_id'] = $hash;
+ $item_arr['resource_id'] = $event['event_hash'];
$item_arr['obj_type'] = ACTIVITY_OBJ_EVENT;
- $item_arr['body'] = format_event_bbcode($arr);
+
+ $item_arr['body'] = $prefix . format_event_bbcode($arr);
$item_arr['plink'] = z_root() . '/channel/' . $z[0]['channel_address'] . '/?f=&mid=' . $item_arr['mid'];
@@ -361,8 +455,8 @@ function event_store($arr) {
));
}
-
$res = item_store($item_arr);
+
$item_id = $res['item_id'];
call_hooks("event_created", $event['id']);
diff --git a/include/items.php b/include/items.php
index 7a94336be..c0a3a741e 100755
--- a/include/items.php
+++ b/include/items.php
@@ -239,6 +239,31 @@ function red_unescape_codeblock($m) {
}
+function red_zrlify_img_callback($matches) {
+ $m = @parse_url($matches[2]);
+ $zrl = false;
+ if($m['host']) {
+ $r = q("select hubloc_url from hubloc where hubloc_host = '%s' limit 1",
+ dbesc($m['host'])
+ );
+ if($r)
+ $zrl = true;
+ }
+
+ $t = strip_zids($matches[2]);
+ if($t !== $matches[2]) {
+ $zrl = true;
+ $matches[2] = $t;
+ }
+
+ if($zrl)
+ return '[zmg' . $matches[1] . ']' . $matches[2] . '[/zmg]';
+ return $matches[0];
+}
+
+
+
+
/**
* @function post_activity_item($arr)
*
@@ -2309,6 +2334,34 @@ function tag_deliver($uid,$item_id) {
}
+ if (stristr($item['verb'],ACTIVITY_POKE)) {
+ $poke_notify = true;
+
+ if(($item['obj_type'] == "") || ($item['obj_type'] !== ACTIVITY_OBJ_PERSON) || (! $item['object']))
+ $poke_notify = false;
+
+ $obj = json_decode_plus($item['object']);
+ if($obj) {
+ if($obj['id'] !== $u[0]['channel_hash'])
+ $poke_notify = false;
+ }
+
+ $verb = urldecode(substr($item['verb'],strpos($item['verb'],'#')+1));
+ if($poke_notify) {
+ require_once('include/enotify.php');
+ notification(array(
+ 'to_xchan' => $u[0]['channel_hash'],
+ 'from_xchan' => $item['author_xchan'],
+ 'type' => NOTIFY_POKE,
+ 'item' => $item,
+ 'link' => $i[0]['llink'],
+ 'verb' => ACTIVITY_POKE,
+ 'activity' => $verb,
+ 'otype' => 'item'
+ ));
+ }
+ }
+
if($item['obj_type'] === ACTIVITY_OBJ_TAGTERM) {
// We received a community tag activity for a post.
@@ -2413,7 +2466,7 @@ function tag_deliver($uid,$item_id) {
if($terms) {
foreach($terms as $term) {
- if((strcasecmp($term['term'],$u[0]['channel_name']) == 0) && link_compare($term['url'],$link)) {
+ if(link_compare($term['url'],$link)) {
$mention = true;
break;
}
@@ -2449,11 +2502,11 @@ function tag_deliver($uid,$item_id) {
$tagged = false;
$plustagged = false;
- $pattern = '/@\!?\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($u[0]['channel_name'],'/') . '\[\/zrl\]/';
+ $pattern = '/@\!?\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($term['term'],'/') . '\[\/zrl\]/';
if(preg_match($pattern,$body,$matches))
$tagged = true;
- $pattern = '/@\!?\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($u[0]['channel_name'] . '+','/') . '\[\/zrl\]/';
+ $pattern = '/@\!?\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($term['term'] . '+','/') . '\[\/zrl\]/';
if(preg_match($pattern,$body,$matches))
$plustagged = true;
@@ -2582,7 +2635,7 @@ function tgroup_check($uid,$item) {
if($terms) {
foreach($terms as $term) {
- if(($term['term'] == $u[0]['channel_name']) && link_compare($term['url'],$link)) {
+ if(link_compare($term['url'],$link)) {
$mention = true;
break;
}
@@ -2600,7 +2653,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($term['term'] . '+','/') . '\[\/zrl\]/';
if(! preg_match($pattern,$body,$matches)) {
logger('tgroup_check: mention was in a reshare - ignoring');
diff --git a/include/js_strings.php b/include/js_strings.php
index fef84077e..cda66a09c 100644
--- a/include/js_strings.php
+++ b/include/js_strings.php
@@ -4,16 +4,17 @@ function js_strings() {
return replace_macros(get_markup_template('js_strings.tpl'), array(
'$delitem' => t('Delete this item?'),
'$comment' => t('Comment'),
- '$showmore' => t('show more'),
- '$showfewer' => t('show fewer'),
- '$divgrowmore' => t('+ Show More'),
- '$divgrowless' => t('- Show Less'),
+ '$showmore' => t('[+] show all'),
+ '$showfewer' => t('[-] show less'),
+ '$divgrowmore' => t('[+] expand'),
+ '$divgrowless' => t('[-] collapse'),
'$pwshort' => t("Password too short"),
'$pwnomatch' => t("Passwords do not match"),
'$everybody' => t('everybody'),
'$passphrase' => t('Secret Passphrase'),
'$passhint' => t('Passphrase hint'),
'$permschange' => t('Notice: Permissions have changed but have not yet been submitted.'),
+ '$closeAll' => t('close all'),
'$t01' => ((t('timeago.prefixAgo') != 'timeago.prefixAgo') ? t('timeago.prefixAgo') : ''),
'$t02' => ((t('timeago.prefixFromNow') != 'timeago.prefixFromNow') ? t('timeago.prefixFromNow') : ''),
diff --git a/include/language.php b/include/language.php
index b43f5aacc..855d94505 100644
--- a/include/language.php
+++ b/include/language.php
@@ -43,8 +43,6 @@ function get_browser_language() {
arsort($langs, SORT_NUMERIC);
}
}
- else
- $langs['en'] = 1;
return $langs;
}
@@ -65,6 +63,7 @@ function get_best_language() {
if(isset($langs) && count($langs)) {
foreach ($langs as $lang => $v) {
+ $lang = strtolower($lang);
if(file_exists("view/$lang") && is_dir("view/$lang")) {
$preferred = $lang;
break;
@@ -145,25 +144,29 @@ function load_translation_table($lang, $install = false) {
/**
* @brief translate string if translation exists.
*
- * @param s string that should get translated
+ * @param $s string that should get translated
+ * @param $ctx optional context to appear in po file
* @return translated string if exsists, otherwise s
+ *
*/
-function t($s) {
+function t($s,$ctx = '') {
global $a;
- if(x($a->strings,$s)) {
- $t = $a->strings[$s];
+ $cs = $ctx?"__ctx:".$ctx."__ ".$s:$s;
+ if(x($a->strings,$cs)) {
+ $t = $a->strings[$cs];
return is_array($t) ? $t[0] : $t;
}
return $s;
}
-function tt($singular, $plural, $count){
+function tt($singular, $plural, $count, $ctx = ''){
$a = get_app();
- if(x($a->strings,$singular)) {
- $t = $a->strings[$singular];
+ $cs = $ctx?"__ctx:".$ctx."__ ".$singular:$singular;
+ if(x($a->strings,$cs)) {
+ $t = $a->strings[$cs];
$f = 'string_plural_select_' . str_replace('-', '_', $a->language);
if(! function_exists($f))
$f = 'string_plural_select_default';
@@ -210,8 +213,10 @@ function detect_language($s) {
if($min_confidence === false)
$min_confidence = LANGUAGE_DETECT_MIN_CONFIDENCE;
+ // embedded apps have long base64 strings which will trip up the detector.
+ $naked_body = preg_replace('/\[app\](.*?)\[\/app\]/','',$s);
// strip off bbcode
- $naked_body = preg_replace('/\[(.+?)\]/', '', $s);
+ $naked_body = preg_replace('/\[(.+?)\]/', '', $naked_body);
if(mb_strlen($naked_body) < intval($min_length)) {
logger('detect language: string length less than ' . intval($min_length), LOGGER_DATA);
return '';
diff --git a/include/nav.php b/include/nav.php
index a97b434bc..2d0d43d5a 100644
--- a/include/nav.php
+++ b/include/nav.php
@@ -138,8 +138,8 @@ EOT;
if(! get_config('system','hide_help'))
$nav['help'] = array($help_url, t('Help'), "", t('Help and documentation'));
- if(count($a->get_apps()) > 0)
- $nav['apps'] = array('apps', t('Apps'), "", t('Addon applications, utilities, games'));
+
+ $nav['apps'] = array('apps', t('Apps'), "", t('Applications, utilities, links, games'));
$nav['search'] = array('search', t('Search'), "", t('Search site content'));
@@ -221,7 +221,6 @@ EOT;
'$userinfo' => $x['usermenu'],
'$localuser' => local_user(),
'$sel' => $a->nav_sel,
- '$apps' => $a->get_apps(),
'$pleasewait' => t('Please wait...')
));
diff --git a/include/network.php b/include/network.php
index 9f68328b7..03faf9957 100644
--- a/include/network.php
+++ b/include/network.php
@@ -121,8 +121,8 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
if(! $ret['success']) {
$ret['error'] = curl_error($ch);
$ret['debug'] = $curl_info;
- logger('z_fetch_url: error:' . $ret['error'], LOGGER_DEBUG);
- logger('z_fetch_url: debug:' . print_r($curl_info,true), LOGGER_DATA);
+ logger('z_fetch_url: error: ' . $url . ': ' . $ret['error'], LOGGER_DEBUG);
+ logger('z_fetch_url: debug: ' . print_r($curl_info,true), LOGGER_DATA);
}
$ret['body'] = substr($s,strlen($header));
$ret['header'] = $header;
@@ -229,8 +229,8 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) {
if(! $ret['success']) {
$ret['error'] = curl_error($ch);
$ret['debug'] = $curl_info;
- logger('z_post_url: error:' . $ret['error'], LOGGER_DEBUG);
- logger('z_post_url: debug:' . print_r($curl_info,true), LOGGER_DATA);
+ logger('z_post_url: error: ' . $url . ': ' . $ret['error'], LOGGER_DEBUG);
+ logger('z_post_url: debug: ' . print_r($curl_info,true), LOGGER_DATA);
}
$ret['body'] = substr($s,strlen($header));
diff --git a/include/plugin.php b/include/plugin.php
index 9982a48a2..ace00d43a 100755
--- a/include/plugin.php
+++ b/include/plugin.php
@@ -94,6 +94,17 @@ function load_plugin($plugin) {
}
+function plugin_is_installed($name) {
+ $r = q("select name from addon where name = '%s' and installed = 1 limit 1",
+ dbesc($name)
+ );
+ if($r)
+ return true;
+ return false;
+}
+
+
+
// reload all updated plugins
function reload_plugins() {
diff --git a/include/poller.php b/include/poller.php
index 9592c29e4..926deeb47 100644
--- a/include/poller.php
+++ b/include/poller.php
@@ -118,9 +118,12 @@ function poller_run($argv, $argc){
require_once('include/hubloc.php');
prune_hub_reinstalls();
+ require_once('include/Contact.php');
+ mark_orphan_hubsxchans();
}
+ update_birthdays();
// expire any read notifications over a month old
diff --git a/include/reddav.php b/include/reddav.php
index 0650531dd..3c2801e89 100644
--- a/include/reddav.php
+++ b/include/reddav.php
@@ -892,7 +892,7 @@ class RedBrowser extends DAV\Browser\Plugin {
$html .= "
<body>
<h1>Index for " . $this->escapeHTML($path) . "/</h1>
- <table>
+ <table id=\"cloud-index\">
<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>";
diff --git a/include/session.php b/include/session.php
index be1ec5ee7..b531688e2 100644
--- a/include/session.php
+++ b/include/session.php
@@ -11,7 +11,11 @@ $session_expire = 180000;
function new_cookie($time) {
$old_sid = session_id();
- session_set_cookie_params("$time");
+
+// ??? This shouldn't have any effect if called after session_start()
+// We probably need to set the session expiration and change the PHPSESSID cookie.
+
+ session_set_cookie_params($time);
session_regenerate_id(false);
q("UPDATE session SET sid = '%s' WHERE sid = '%s'", dbesc(session_id()), dbesc($old_sid));
diff --git a/include/text.php b/include/text.php
index 0e136fe8e..b5b8ec41a 100755
--- a/include/text.php
+++ b/include/text.php
@@ -810,9 +810,9 @@ function search($s,$id='search-box',$url='/search',$save = false) {
$o = '<div id="' . $id . '">';
$o .= '<form action="' . $a->get_baseurl((stristr($url,'network')) ? true : false) . $url . '" method="get" >';
$o .= '<input type="text" class="icon-search" name="search" id="search-text" placeholder="&#xf002;" value="' . $s .'" onclick="this.submit();" />';
- $o .= '<input type="submit" name="submit" id="search-submit" value="' . t('Search') . '" />';
+ $o .= '<input class="search-submit btn btn-default" type="submit" name="submit" id="search-submit" value="' . t('Search') . '" />';
if(feature_enabled(local_user(),'savedsearch'))
- $o .= '<input type="submit" name="save" id="search-save" value="' . t('Save') . '" />';
+ $o .= '<input class="search-save btn btn-default" type="submit" name="save" id="search-save" value="' . t('Save') . '" />';
$o .= '</form></div>';
return $o;
}
@@ -1482,7 +1482,7 @@ function get_plink($item,$conversation_mode = true) {
if(x($item,$key)) {
return array(
'href' => zid($item[$key]),
- 'title' => t('link to source'),
+ 'title' => t('Link to Source'),
);
}
else {
diff --git a/include/widgets.php b/include/widgets.php
index 1b0e140c0..96bced87f 100644
--- a/include/widgets.php
+++ b/include/widgets.php
@@ -74,6 +74,19 @@ function widget_collections($args) {
}
+function widget_appselect($arr) {
+ return replace_macros(get_markup_template('app_select.tpl'),array(
+ '$title' => t('Apps'),
+ '$system' => t('System'),
+ '$authed' => ((local_user()) ? true : false),
+ '$personal' => t('Personal'),
+ '$new' => t('Create Personal App'),
+ '$edit' => t('Edit Personal App')
+ ));
+}
+
+
+
function widget_suggestions($arr) {
if((! local_user()) || (! feature_enabled(local_user(),'suggest')))
@@ -183,7 +196,7 @@ function widget_savedsearch($arr) {
$a = get_app();
$search = ((x($_GET,'search')) ? $_GET['search'] : '');
-
+
if(x($_GET,'searchsave') && $search) {
$r = q("select * from `term` where `uid` = %d and `type` = %d and `term` = '%s' limit 1",
intval(local_user()),
@@ -251,7 +264,7 @@ function widget_savedsearch($arr) {
$o = replace_macros($tpl, array(
'$title' => t('Saved Searches'),
'$add' => t('add'),
- '$searchbox' => searchbox('','netsearch-box',$srchurl . (($hasq) ? '' : '?f='),true),
+ '$searchbox' => searchbox($search,'netsearch-box',$srchurl . (($hasq) ? '' : '?f='),true),
'$saved' => $saved,
));
@@ -719,4 +732,51 @@ $(document).ready(function() {
EOT;
return $o;
-} \ No newline at end of file
+}
+
+
+/**
+ * @function widget_photo($arr)
+ * widget to display a single photo.
+ * @param array $arr;
+ * 'src' => URL of photo
+ * 'zrl' => true or false, use zid in url
+ * 'style' => CSS string
+ * URL must be an http or https URL
+ */
+
+
+function widget_photo($arr) {
+
+ $style = $zrl = false;
+ $params = '';
+ if(array_key_exists('src',$arr) && isset($arr['src']))
+ $url = $arr['src'];
+
+ if(strpos($url,'http') !== 0)
+ return '';
+
+ if(array_key_exists('style',$arr) && isset($arr['style']))
+ $style = $arr['style'];
+
+ // ensure they can't sneak in an eval(js) function
+
+ if(strpos($style,'(') !== false)
+ return '';
+
+ if(array_key_exists('zrl',$arr) && isset($arr['zrl']))
+ $zrl = (($arr['zrl']) ? true : false);
+
+ if($zrl)
+ $url = zid($url);
+
+ $o = '<div class="widget">';
+
+ $o .= '<img ' . (($zrl) ? ' class="zrl" ' : '')
+ . (($style) ? ' style="' . $style . '"' : '')
+ . ' src="' . $url . '" />';
+
+ $o .= '</div>';
+
+ return $o;
+}
diff --git a/include/zot.php b/include/zot.php
index 9e69aea96..9cdcbf2a4 100644
--- a/include/zot.php
+++ b/include/zot.php
@@ -355,14 +355,29 @@ function zot_refresh($them,$channel = null, $force = false) {
intval(ABOOK_FLAG_SELF)
);
+ if(array_key_exists('profile',$j) && array_key_exists('next_birthday',$j['profile'])) {
+ $next_birthday = datetime_convert('UTC','UTC',$j['profile']['next_birthday']);
+ }
+ else {
+ $next_birthday = '0000-00-00 00:00:00';
+ }
+
if($r) {
+ // if the dob is the same as what we have stored (disregarding the year), keep the one
+ // we have as we may have updated the year after sending a notification; and resetting
+ // to the one we just received would cause us to create duplicated events.
+
+ if(substr($r[0]['abook_dob'],5) == substr($next_birthday,5))
+ $next_birthday = $r[0]['abook_dob'];
+
$current_abook_connected = (($r[0]['abook_flags'] & ABOOK_FLAG_UNCONNECTED) ? 0 : 1);
- $y = q("update abook set abook_their_perms = %d
+ $y = q("update abook set abook_their_perms = %d, abook_dob = '%s'
where abook_xchan = '%s' and abook_channel = %d
and not (abook_flags & %d) limit 1",
intval($their_perms),
+ dbesc($next_birthday),
dbesc($x['hash']),
intval($channel['channel_id']),
intval(ABOOK_FLAG_SELF)
@@ -402,7 +417,7 @@ function zot_refresh($them,$channel = null, $force = false) {
if($z)
$default_perms = intval($z[0]['abook_my_perms']);
- $y = q("insert into abook ( abook_account, abook_channel, abook_xchan, abook_their_perms, abook_my_perms, abook_created, abook_updated, abook_flags ) values ( %d, %d, '%s', %d, %d, '%s', '%s', %d )",
+ $y = q("insert into abook ( abook_account, abook_channel, abook_xchan, abook_their_perms, abook_my_perms, abook_created, abook_updated, abook_dob, abook_flags ) values ( %d, %d, '%s', %d, %d, '%s', '%s', '%s', %d )",
intval($channel['channel_account_id']),
intval($channel['channel_id']),
dbesc($x['hash']),
@@ -410,6 +425,7 @@ function zot_refresh($them,$channel = null, $force = false) {
intval($default_perms),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
+ dbesc($next_birthday),
intval(($default_perms) ? 0 : ABOOK_FLAG_PENDING)
);
@@ -840,6 +856,24 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED) {
intval($r[0]['hubloc_id'])
);
}
+ if($r[0]['hubloc_status'] & HUBLOC_OFFLINE) {
+ q("update hubloc set hubloc_status = (hubloc_status ^ %d) where hubloc_id = %d limit 1",
+ intval(HUBLOC_OFFLINE),
+ intval($r[0]['hubloc_id'])
+ );
+ if($r[0]['hubloc_flags'] & HUBLOC_FLAGS_ORPHANCHECK) {
+ q("update hubloc set hubloc_flags = (hubloc_flags ^ %d) where hubloc_id = %d limit 1",
+ intval(HUBLOC_FLAGS_ORPHANCHECK),
+ intval($r[0]['hubloc_id'])
+ );
+ }
+ q("update xchan set xchan_flags = (xchan_flags ^ %d) where (xchan_flags & %d) and xchan_hash = '%s' limit 1",
+ intval(XCHAN_FLAGS_ORPHAN),
+ intval(XCHAN_FLAGS_ORPHAN),
+ dbesc($xchan_hash)
+ );
+
+ }
// Remove pure duplicates
if(count($r) > 1) {
@@ -1452,37 +1486,6 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false) {
continue;
}
- // for events, extract the event info and create an event linked to an item
-
- 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,'description') && x($ev,'start')) {
- $ev['event_xchan'] = $arr['author_xchan'];
- $ev['uid'] = $channel['channel_id'];
- $ev['account'] = $channel['channel_account_id'];
- $ev['edited'] = $arr['edited'];
- $ev['mid'] = $arr['mid'];
- $ev['private'] = $arr['item_private'];
-
- // is this an edit?
-
- $r = q("SELECT resource_id FROM item where mid = '%s' and uid = %d and resource_type = 'event' limit 1",
- dbesc($arr['mid']),
- intval($channel['channel_id'])
- );
- if($r) {
- $ev['event_hash'] = $r[0]['resource_id'];
- }
-
- $xyz = event_store($ev);
- add_source_route($xyz,$sender['hash']);
-
- $result = array($d['hash'],'event processed',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']);
- continue;
- }
- }
-
$r = q("select id, edited from item where mid = '%s' and uid = %d limit 1",
dbesc($arr['mid']),
intval($channel['channel_id'])
@@ -1501,6 +1504,9 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false) {
$arr['uid'] = $channel['channel_id'];
$item_result = item_store($arr);
$item_id = $item_result['item_id'];
+ $parr = array('item_id' => $item_id,'item' => $arr,'sender' => $sender,'channel' => $channel);
+ call_hooks('activity_received',$parr);
+
add_source_route($item_id,$sender['hash']);
$result[] = array($d['hash'],(($item_id) ? 'posted' : 'storage failed:' . $item_result['message']),$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']);