diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/Contact.php | 90 | ||||
-rw-r--r-- | include/ItemObject.php | 42 | ||||
-rw-r--r-- | include/apps.php | 431 | ||||
-rw-r--r-- | include/auth.php | 15 | ||||
-rw-r--r-- | include/bb2diaspora.php | 8 | ||||
-rw-r--r-- | include/bbcode.php | 52 | ||||
-rw-r--r-- | include/conversation.php | 2 | ||||
-rw-r--r-- | include/datetime.php | 55 | ||||
-rw-r--r-- | include/dir_fns.php | 2 | ||||
-rw-r--r-- | include/event.php | 256 | ||||
-rwxr-xr-x | include/items.php | 63 | ||||
-rw-r--r-- | include/js_strings.php | 9 | ||||
-rw-r--r-- | include/language.php | 25 | ||||
-rw-r--r-- | include/nav.php | 5 | ||||
-rw-r--r-- | include/network.php | 8 | ||||
-rwxr-xr-x | include/plugin.php | 11 | ||||
-rw-r--r-- | include/poller.php | 3 | ||||
-rw-r--r-- | include/reddav.php | 2 | ||||
-rw-r--r-- | include/session.php | 6 | ||||
-rwxr-xr-x | include/text.php | 6 | ||||
-rw-r--r-- | include/widgets.php | 66 | ||||
-rw-r--r-- | include/zot.php | 72 |
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(''','&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(''','&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="" 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']); |