diff --git a/LICENSE b/LICENSE index 1bb0861466..33579fe080 100644 --- a/LICENSE +++ b/LICENSE @@ -1,42 +1,25 @@ -* Friendika -* Copyright (c) 2010, 2011 Mike Macgirvin -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of Friendika nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY Mike Macgirvin ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL Mike Macgirvin BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +The Friendika project is distributed under the following license terms: -Friendika incorporates other software which may be licensed under different -terms and conditions. Some system libraries which are supplied with and -incorporated into Friendika were provided by their respective authors under -the LGPL (Lesser GNU Public License) and may result in legal encumberance if -you make any code changes to these libraries. +* This software is provided for any use with no license terms or restrictions. + +No guarantee is provided. Use at your own risk. + +Components packaged with this software may fall under different license terms. + +cropper - BSD +TwitterOAuth - BSD +markdown - BSD +slinky - BSD +ajax-upload - MIT +simplepie - MIT +LightOpenID - MIT +HTML5 - MIT +jQuery - MIT +TinyMCE - LGPL +phpsec - LGPL +HTMLPurifer - LGPL +Facebook SDK - Apache + +Addons, plugins, and themes may also be provided under their own license terms. -Addon or "plugin" modules (projects by other authors and fully contained within -the 'addon' and 'theme' directories) are licensed under terms provided by the -respective software author or authors of those works, and MAY include copyleft -licenses such as GPLv3, AGPL, and/or commercial licenses. For the purposes of -licensing, addon modules and themes are considered separate standalone works, -where the "work as a whole" is defined as the embodiment of the theme or -addon module. - - diff --git a/addon/LICENSE b/addon/LICENSE index 2e6e056e8c..02cff93203 100644 --- a/addon/LICENSE +++ b/addon/LICENSE @@ -1,5 +1,3 @@ - - Friendika addons/plugins license terms are under the control of the project author or authors. diff --git a/addon/facebook/README b/addon/facebook/README index 42ec01383c..19c5948866 100644 --- a/addon/facebook/README +++ b/addon/facebook/README @@ -15,6 +15,8 @@ Installing the Friendika/Facebook connector $a->config['facebook']['appid'] = 'xxxxxxxxxxx'; $a->config['facebook']['appsecret'] = 'xxxxxxxxxxxxxxx'; Replace with the settings Facebook gives you. + d. Navigate to Set Web->Site URL & Domain -> Website Settings. Set Site URL + to yoursubdomain.yourdomain.com. Set Site Domain to your yourdomain.com. 2. Enable the facebook plugin by including it in .htconfig.php - e.g. $a->config['system']['addon'] = 'plugin1,plugin2,facebook'; 3. Visit the Facebook Settings section of the "Settings->Plugin Settings" page. diff --git a/addon/facebook/facebook.php b/addon/facebook/facebook.php index c54d5b5f09..73518afb2d 100644 --- a/addon/facebook/facebook.php +++ b/addon/facebook/facebook.php @@ -23,6 +23,9 @@ * $a->config['facebook']['appid'] = 'xxxxxxxxxxx'; * $a->config['facebook']['appsecret'] = 'xxxxxxxxxxxxxxx'; * Replace with the settings Facebook gives you. + * d. Navigate to Set Web->Site URL & Domain -> Website Settings. Set + * Site URL to yoursubdomain.yourdomain.com. Set Site Domain to your + * yourdomain.com. * 2. Enable the facebook plugin by including it in .htconfig.php - e.g. * $a->config['system']['addon'] = 'plugin1,plugin2,facebook'; * 3. Visit the Facebook Settings section of the "Settings->Plugin Settings" page. diff --git a/addon/statusnet/statusnet.php b/addon/statusnet/statusnet.php index 9357b0ebd9..63cdd28df6 100644 --- a/addon/statusnet/statusnet.php +++ b/addon/statusnet/statusnet.php @@ -260,7 +260,7 @@ function statusnet_settings(&$a,&$s) { $s .= ''; $s .= ''; $s .= '
'; - $s .= '
'; + $s .= '
'; $s .= '

'.t('Cancel Connection Process').'

'; $s .= '
'; $s .= '

'.t('Current StatusNet API is').': '.$api.'

'; diff --git a/addon/twitter/twitter.php b/addon/twitter/twitter.php index 1dce9d2f66..7f2b2e1c79 100644 --- a/addon/twitter/twitter.php +++ b/addon/twitter/twitter.php @@ -243,8 +243,11 @@ function twitter_post_hook(&$a,&$b) { $msg .= '... ' . $shortlink; } // and now tweet it :-) - if(strlen($msg)) - $tweet->post('statuses/update', array('status' => $msg)); + if(strlen($msg)) { + $result = $tweet->post('statuses/update', array('status' => $msg)); + logger('twitter_post returns: ' . $result); + } + } } } diff --git a/boot.php b/boot.php index 8ff029a5c3..7effe30879 100644 --- a/boot.php +++ b/boot.php @@ -1,12 +1,8 @@ \r\n" ); define ( 'ATOM_TIME', 'Y-m-d\TH:i:s\Z' ); @@ -89,6 +85,7 @@ define ( 'PAGE_FREELOVE', 3 ); * Network and protocol family types */ +define ( 'NETWORK_ZOT', 'zot!'); // Zot! define ( 'NETWORK_DFRN', 'dfrn'); // Friendika, Mistpark, other DFRN implementations define ( 'NETWORK_OSTATUS', 'stat'); // status.net, identi.ca, GNU-social, other OStatus implementations define ( 'NETWORK_FEED', 'feed'); // RSS/Atom feeds with no known "post/notify" protocol @@ -103,6 +100,13 @@ define ( 'NETWORK_FACEBOOK', 'face'); // Facebook API define ( 'MAX_LIKERS', 75); +/** + * Communication timeout + */ + +define ( 'ZCURL_TIMEOUT' , (-1)); + + /** * email notification options */ @@ -117,6 +121,7 @@ define ( 'NOTIFY_MAIL', 0x0010 ); * various namespaces we may need to parse */ +define ( 'NAMESPACE_ZOT', 'http://purl.org/macgirvin/zot' ); define ( 'NAMESPACE_DFRN' , 'http://purl.org/macgirvin/dfrn/1.0' ); define ( 'NAMESPACE_THREAD' , 'http://purl.org/syndication/thread/1.0' ); define ( 'NAMESPACE_TOMB' , 'http://purl.org/atompub/tombstones/1.0' ); @@ -170,20 +175,28 @@ define ( 'GRAVITY_COMMENT', 6); * */ -if (get_magic_quotes_gpc()) { - $process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST); - while (list($key, $val) = each($process)) { - foreach ($val as $k => $v) { - unset($process[$key][$k]); - if (is_array($v)) { - $process[$key][stripslashes($k)] = $v; - $process[] = &$process[$key][stripslashes($k)]; - } else { - $process[$key][stripslashes($k)] = stripslashes($v); - } - } - } - unset($process); +function startup() { + error_reporting(E_ERROR | E_WARNING | E_PARSE); + set_time_limit(0); + ini_set('pcre.backtrack_limit', 250000); + + + if (get_magic_quotes_gpc()) { + $process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST); + while (list($key, $val) = each($process)) { + foreach ($val as $k => $v) { + unset($process[$key][$k]); + if (is_array($v)) { + $process[$key][stripslashes($k)] = $v; + $process[] = &$process[$key][stripslashes($k)]; + } else { + $process[$key][stripslashes($k)] = stripslashes($v); + } + } + } + unset($process); + } + } /* @@ -251,6 +264,8 @@ class App { $this->query_string = ''; + startup(); + $this->scheme = ((isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'])) ? 'https' : 'http' ); if(x($_SERVER,'SERVER_NAME')) { @@ -756,15 +771,17 @@ function post_url($url,$params, $headers = null, &$redirects = 0) { $curl_time = intval(get_config('system','curl_timeout')); curl_setopt($ch, CURLOPT_TIMEOUT, (($curl_time !== false) ? $curl_time : 60)); - if(!is_array($headers)) { - $headers = array('Expect:'); - } else { - if(!in_array('Expect:', $headers)) { - array_push($headers, 'Expect:'); + if(defined('LIGHTTPD')) { + if(!is_array($headers)) { + $headers = array('Expect:'); + } else { + if(!in_array('Expect:', $headers)) { + array_push($headers, 'Expect:'); + } } } - - curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + if($headers) + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $check_cert = get_config('system','verifyssl'); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (($check_cert) ? true : false)); @@ -2056,6 +2073,9 @@ function get_tags($s) { // we might be inside a bbcode color tag - leave it alone continue; } + // ignore strictly numeric tags like #1 + if((strpos($mtch,'#') === 0) && ctype_digit(substr($mtch,1))) + continue; if(substr($mtch,-1,1) === '.') $ret[] = substr($mtch,0,-1); else @@ -2937,3 +2957,15 @@ function return_bytes ($size_str) { } }} +function generate_guid() { + $found = true; + do { + $guid = substr(random_string(),0,16); + $x = q("SELECT `uid` FROM `user` WHERE `guid` = '%s' LIMIT 1", + dbesc($guid) + ); + if(! count($x)) + $found = false; + } while ($found == true ); + return $guid; +} \ No newline at end of file diff --git a/database.sql b/database.sql index 8ea3e42de7..50697845a3 100644 --- a/database.sql +++ b/database.sql @@ -379,6 +379,7 @@ CREATE TABLE IF NOT EXISTS `session` ( CREATE TABLE IF NOT EXISTS `user` ( `uid` int(11) NOT NULL AUTO_INCREMENT, + `guid` char(16) NOT NULL, `username` char(255) NOT NULL, `password` char(255) NOT NULL, `nickname` char(255) NOT NULL, diff --git a/doc/Installing-Connectors.md b/doc/Installing-Connectors.md index e43f17fe3c..c8fc8e7905 100644 --- a/doc/Installing-Connectors.md +++ b/doc/Installing-Connectors.md @@ -129,6 +129,10 @@ $a->config['facebook']['appsecret'] = 'xxxxxxxxxxxxxxx'; Replace with the settings Facebook gives you. +d. Navigate to Set Web->Site URL & Domain -> Website Settings. Set Site URL +to yoursubdomain.yourdomain.com. Set Site Domain to your yourdomain.com. + + Visit the Facebook Settings section of the "Settings->Plugin Settings" page. and click 'Install Facebook Connector'. diff --git a/include/Scrape.php b/include/Scrape.php index fbfec176f8..6726d0b151 100644 --- a/include/Scrape.php +++ b/include/Scrape.php @@ -300,6 +300,8 @@ function probe_url($url) { if(count($links)) { logger('probe_url: found lrdd links: ' . print_r($links,true), LOGGER_DATA); foreach($links as $link) { + if($link['@attributes']['rel'] === NAMESPACE_ZOT) + $zot = unamp($link['@attributes']['href']); if($link['@attributes']['rel'] === NAMESPACE_DFRN) $dfrn = unamp($link['@attributes']['href']); if($link['@attributes']['rel'] === 'salmon') @@ -379,6 +381,25 @@ function probe_url($url) { } } + if(strlen($zot)) { + $s = fetch_url($zot); + if($s) { + $j = json_decode($s); + if($j) { + $network = NETWORK_ZOT; + $vcard = array( + 'fn' => $j->fullname, + 'nick' => $j->nickname, + 'photo' => $j->photo + ); + $profile = $j->url; + $notify = $j->post; + $pubkey = $j->pubkey; + $poll = 'N/A'; + } + } + } + if(strlen($dfrn)) { $ret = scrape_dfrn($dfrn); if(is_array($ret) && x($ret,'dfrn-request')) { @@ -390,7 +411,7 @@ function probe_url($url) { } } - if($network !== NETWORK_DFRN && $network !== NETWORK_MAIL) { + if($network !== NETWORK_ZOT && $network !== NETWORK_DFRN && $network !== NETWORK_MAIL) { $network = NETWORK_OSTATUS; $priority = 0; @@ -549,6 +570,7 @@ function probe_url($url) { $result['priority'] = $priority; $result['network'] = $network; $result['alias'] = $alias; + $result['pubkey'] = $pubkey; logger('probe_url: ' . print_r($result,true), LOGGER_DEBUG); diff --git a/include/bbcode.php b/include/bbcode.php index 7fc1eac1c4..3619015ca9 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -3,6 +3,13 @@ require_once("include/oembed.php"); require_once('include/event.php'); + + +function stripcode_br_cb($s) { + return '[code]' . str_replace('
', '', $s[1]) . '[/code]'; +} + + // BBcode 2 HTML was written by WAY2WEB.net // extended to work with Mistpark/Friendika - Mike Macgirvin @@ -89,9 +96,16 @@ function bbcode($Text,$preserve_nl = false) { $Text = preg_replace("(\[font=(.*?)\](.*?)\[\/font\])","$2",$Text); // Declare the format for [code] layout + + $Text = preg_replace_callback("/\[code\](.*?)\[\/code\]/is",'stripcode_br_cb',$Text); + $CodeLayout = '$1'; // Check for [code] text $Text = preg_replace("/\[code\](.*?)\[\/code\]/is","$CodeLayout", $Text); + + + + // Declare the format for [quote] layout $QuoteLayout = '
$1
'; // Check for [quote] text diff --git a/include/nav.php b/include/nav.php index 3b15c2b8a9..895c321e6a 100644 --- a/include/nav.php +++ b/include/nav.php @@ -30,7 +30,7 @@ function nav(&$a) { $sitelocation = $myident . substr($a->get_baseurl(),strpos($a->get_baseurl(),'//') + 2 ); - // nav links: array of array('href', 'text', 'extra css classes') + // nav links: array of array('href', 'text', 'extra css classes', 'title') $nav = Array(); /** @@ -38,10 +38,10 @@ function nav(&$a) { */ if(local_user()) { - $nav['logout'] = Array('logout',t('Logout'), ""); + $nav['logout'] = Array('logout',t('Logout'), "", t('End this session')); } else { - $nav['login'] = Array('login',t('Login'), ($a->module == 'login'?'nav-selected':'')); + $nav['login'] = Array('login',t('Login'), ($a->module == 'login'?'nav-selected':''), t('Sign in')); } @@ -52,21 +52,21 @@ function nav(&$a) { $homelink = ((x($_SESSION,'visitor_home')) ? $_SESSION['visitor_home'] : ''); if(($a->module != 'home') && (! (local_user()))) - $nav['home'] = array($homelink, t('Home'), ""); + $nav['home'] = array($homelink, t('Home'), "", t('Home Page')); if(($a->config['register_policy'] == REGISTER_OPEN) && (! local_user()) && (! remote_user())) - $nav['register'] = array('register',t('Register'), ""); + $nav['register'] = array('register',t('Register'), "", t('Create an account')); $help_url = $a->get_baseurl() . '/help'; if(! get_config('system','hide_help')) - $nav['help'] = array($help_url, t('Help'), ""); + $nav['help'] = array($help_url, t('Help'), "", t('Help and documentation')); if($a->apps) - $nav['apps'] = array('apps', t('Apps'), ""); + $nav['apps'] = array('apps', t('Apps'), "", t('Addon applications, utilities, games')); - $nav['search'] = array('search', t('Search'), ""); + $nav['search'] = array('search', t('Search'), "", t('Search site content')); $gdirpath = 'directory'; @@ -76,9 +76,9 @@ function nav(&$a) { $gdirpath = $gdir; } elseif(! get_config('system','no_community_page')) - $nav['community'] = array('community', t('Community'), ""); + $nav['community'] = array('community', t('Community'), "", t('Conversations on this site')); - $nav['directory'] = array($gdirpath, t('Directory'), ""); + $nav['directory'] = array($gdirpath, t('Directory'), "", t('People directory')); /** * @@ -88,33 +88,33 @@ function nav(&$a) { if(local_user()) { - $nav['network'] = array('network', t('Network'), ""); + $nav['network'] = array('network', t('Network'), "", t('Conversations from your friends')); - $nav['home'] = array('profile/' . $a->user['nickname'], t('Home'), ""); + $nav['home'] = array('profile/' . $a->user['nickname'], t('Home'), "", t('Your posts and conversations')); /* only show friend requests for normal pages. Other page types have automatic friendship. */ if($_SESSION['page_flags'] == PAGE_NORMAL) { - $nav['notifications'] = array('notifications', t('Notifications'), ""); + $nav['notifications'] = array('notifications', t('Notifications'), "", t('Friend requests')); } - $nav['messages'] = array('message', t('Messages'), ""); + $nav['messages'] = array('message', t('Messages'), "", t('Private mail')); if(is_array($a->identities) && count($a->identities) > 1) { - $nav['manage'] = array('manage', t('Manage'), ""); + $nav['manage'] = array('manage', t('Manage'), "", t('Manage other pages')); } - $nav['settings'] = array('settings', t('Settings'),""); - $nav['profiles'] = array('profiles', t('Profiles'),""); - $nav['contacts'] = array('contacts', t('Contacts'),""); + $nav['settings'] = array('settings', t('Settings'),"", t('Account settings')); + $nav['profiles'] = array('profiles', t('Profiles'),"", t('Manage/edit profiles')); + $nav['contacts'] = array('contacts', t('Contacts'),"", t('Manage/edit friends and contacts')); } /** * Admin page */ if (is_site_admin()){ - $nav['admin'] = array('admin/', t('Admin'), ""); + $nav['admin'] = array('admin/', t('Admin'), "", t('Site setup and configuration')); } diff --git a/include/zotfns.php b/include/zotfns.php new file mode 100644 index 0000000000..b695b6fcb6 --- /dev/null +++ b/include/zotfns.php @@ -0,0 +1,193 @@ + $v) { + if($argstr) + $argstr .= '&'; + $argstr .= $k . '=' . $v; + } + $s = fetch_url($url . '?' . $argstr); + if($s) { + $j = json_decode($s); + if($j) + return($j); + } + return false; +} + +function zot_post($url,$args) { + $s = post_url($url,$args); + if($s) { + $j = json_decode($s); + if($j) + return($j); + } + return false; +} + + +function zot_prv_encode($s,$prvkey) { + $x = ''; + $res = openssl_private_encrypt($s,$x,$prvkey); + return base64url_encode($y); +} +function zot_pub_encode($s,$pubkey) { + $x = ''; + $res = openssl_public_encrypt($s,$x,$pubkey); + return base64url_encode($x); +} + +function zot_prv_decode($s,$prvkey) { + $s = base64url_decode($s); + $x = ''; + openssl_private_decrypt($s,$x,$prvkey); + return $x; +} + +function zot_pub_decode($s,$pubkey) { + $s = base64url_decode($s); + $x = ''; + openssl_public_decrypt($s,$x,$pubkey); + return $x; +} + + +function zot_getzid($url,$myaddress,$myprvkey) { + $ret = array(); + $j = zot_get($url,array('sender' => $myaddress)); + if($j->zid_encoded) + $ret['zid'] = zot_prv_decode($j->zid_encoded,$myprvkey); + if($j->zkey_encoded) + $ret['zkey'] = zot_prv_decode($j->zkey_encoded,$myprvkey); + return $ret; +} + +function zot_post_init($url,$zid,$myprvkey,$theirpubkey) { + $ret = array(); + + $zinit = random_string(32); + + $j = zot_get($url,array('zid' => $zid,'zinit' => $zinit)); + + $a = get_app(); + if(! $a->get_curl_code()) + return ZCURL_TIMEOUT; + if(! $j->zinit) { + logger('zot_post_init: no zinit returned.'); + return false; + } + if(zot_pub_decode($j->zinit,$thierpubkey) !== $zinit) { + logger('zot_post_init: incorrect zinit returned.'); + return false; + } + + if($j->challenge) { + $s = zot_prv_decode($j->challenge,$myprvkey); + $s1 = substr($s,0,strpos($s,'.')); + if($s1 != $zid) { + logger("zot_post_init: incorrect zid returned"); + return false; + } + $ret['result'] = substr($s,strpos($s,'.') + 1); + $ret['perms'] = $j->perms; + } + return $ret; +} + + +function zot_encrypt_data($data,&$key) { + $key = random_string(); + return aes_encrypt($data,$key); +} + + +// encrypt the data prior to calling this function so it only need be done once per message +// regardless of the number of recipients. + +function zot_post_data($url,$zid,$myprvkey,$theirpubkey,$encrypted_data,$key, $intro = false) { + $i = zot_post_init($url,$zid,$myprvkey,$theirpubkey); + if($i === ZCURL_TIMEOUT) + return ZCURL_TIMEOUT; + + if((! $i) || (! array_key_exists('perms',$i)) || (! array_key_exists('result',$i))) + return false; + if((! stristr($i['perms'],'post')) && ($intro === false)) { + logger("zot_post_data: no permission to post: url=$url zid=$zid"); + return false; + } + $p = array(); + $p['zid'] = $zid; + $p['result'] = zot_pub_encode($i['result'],$theirpubkey); + $p['aes_key'] = zot_prv_encode($key,$myprvkey); + $p['data'] = $encrypted_data; + $s = zot_post($url,$p); + $a = get_app(); + if(! $a->get_curl_code()) + return ZCURL_TIMEOUT; + + if($s) { + $j = json_decode($s); + return $j; + } + return false; +} + +function zot_deliver($recipients,$myprvkey,$data) { + + if(is_array($recipients) && count($recipients)) { + + $key = ''; + $encrypted = zot_encrypt_data($data,$key); + + + foreach($recipients as $r) { + $result = zot_post_data( + $r['post'], + $r['zid'], + $myprvkey, + $r['pubkey'], + $encrypted, + $key + ); + if($result === false) { + // post failed + logger('zot_deliver: failed: ' . print_r($r,true)); + } + elseif($result === ZCURL_TIMEOUT) { + // queue for redelivery + } + elseif($result->error) { + // failed at other end + logger('zot_deliver: remote failure: ' . $result->error . ' ' . print_r($r,true)); + } + elseif($result->success) { + logger('zot_deliver: success ' . print_r($r,true, LOGGER_DEBUG)); + } + else + logger('zot_deliver: unknown failure.'); + } + } +} + + +function zot_new_contact($user,$cc) { + + $zid = random_string(32); + $zkey = random_string(32); + + logger("zot_new_contact: zid=$zid zkey=$zkey uid={$user['uid']} " . print_r($cc,true)); + + $ret = array(); + $ret['zid_encoded'] = zot_pub_encode($zid,$cc['pubkey']); + $ret['zkey_encoded'] = zot_pub_encode($zkey,$cc['pubkey']); + return $ret; + + + + + +} \ No newline at end of file diff --git a/index.php b/index.php index 2e24c5b015..3e72baddc5 100644 --- a/index.php +++ b/index.php @@ -1,7 +1,5 @@ page,'aside')) $a->page['aside'] = ''; $a->page['aside'] .= group_side(); - if($a->config['register_policy'] != REGISTER_CLOSED) - $a->page['aside'] .= ''; + $inv = ''; + + if(get_config('system','invitation_only')) { + $x = get_pconfig(local_user(),'system','invites_remaining'); + if($x || is_site_admin()) { + $a->page['aside'] .= '' . $inv; + } + } + elseif($a->config['register_policy'] != REGISTER_CLOSED) + $a->page['aside'] .= $inv; $a->page['aside'] .= '