aboutsummaryrefslogtreecommitdiffstats
path: root/mod
diff options
context:
space:
mode:
Diffstat (limited to 'mod')
-rw-r--r--mod/contacts.php17
-rw-r--r--mod/friendika.php1
-rw-r--r--mod/install.php2
-rw-r--r--mod/invite.php44
-rw-r--r--mod/item.php8
-rw-r--r--mod/parse_url.php34
-rw-r--r--mod/receive.php215
-rw-r--r--mod/register.php39
-rw-r--r--mod/settings.php16
-rw-r--r--mod/xrd.php15
10 files changed, 358 insertions, 33 deletions
diff --git a/mod/contacts.php b/mod/contacts.php
index 7a97b53d2..2fc01a0d8 100644
--- a/mod/contacts.php
+++ b/mod/contacts.php
@@ -3,13 +3,26 @@
require_once('include/Contact.php');
function contacts_init(&$a) {
+ if(! local_user())
+ return;
+
require_once('include/group.php');
if(! x($a->page,'aside'))
$a->page['aside'] = '';
$a->page['aside'] .= group_side();
- if($a->config['register_policy'] != REGISTER_CLOSED)
- $a->page['aside'] .= '<div class="side-link" id="side-invite-link" ><a href="invite" >' . t("Invite Friends") . '</a></div>';
+ $inv = '<div class="side-link" id="side-invite-link" ><a href="invite" >' . t("Invite Friends") . '</a></div>';
+
+ if(get_config('system','invitation_only')) {
+ $x = get_pconfig(local_user(),'system','invites_remaining');
+ if($x || is_site_admin()) {
+ $a->page['aside'] .= '<div class="side-link" id="side-invite-remain">'
+ . sprintf( tt('%d invitation available','%d invitations available',$x), $x)
+ . '</div>' . $inv;
+ }
+ }
+ elseif($a->config['register_policy'] != REGISTER_CLOSED)
+ $a->page['aside'] .= $inv;
$a->page['aside'] .= '<div class="side-link" id="side-match-link"><a href="match" >'
diff --git a/mod/friendika.php b/mod/friendika.php
index 8c034c4ac..753a9f478 100644
--- a/mod/friendika.php
+++ b/mod/friendika.php
@@ -39,7 +39,6 @@ function friendika_content(&$a) {
$o .= '<p></p><p>';
- $o .= 'View <a href="LICENSE">License</a>' . '<br /><br />';
$o .= t('This is Friendika version') . ' ' . FRIENDIKA_VERSION . ' ';
$o .= t('running at web location') . ' ' . $a->get_baseurl() . '</p><p>';
diff --git a/mod/install.php b/mod/install.php
index 301630528..970ff6af8 100644
--- a/mod/install.php
+++ b/mod/install.php
@@ -140,7 +140,7 @@ function install_content(&$a) {
'$dbpass' => notags(trim($_POST['dbpass'])),
'$dbdata' => notags(trim($_POST['dbdata'])),
'$phpath' => $phpath,
- '$adminemail' => notags(trim($_POST['adminemail']))
+ '$adminmail' => notags(trim($_POST['adminmail']))
));
return $o;
diff --git a/mod/invite.php b/mod/invite.php
index b52aa19f6..d4eb9c5ef 100644
--- a/mod/invite.php
+++ b/mod/invite.php
@@ -20,6 +20,13 @@ function invite_post(&$a) {
$total = 0;
+ if(get_config('system','invitation_only')) {
+ $invonly = true;
+ $x = get_pconfig(local_user(),'system','invites_remaining');
+ if((! $x) && (! is_site_admin()))
+ return;
+ }
+
foreach($recips as $recip) {
$recip = trim($recip);
@@ -28,9 +35,29 @@ function invite_post(&$a) {
notice( sprintf( t('%s : Not a valid email address.'), $recip) . EOL);
continue;
}
+
+ if($invonly && ($x || is_site_admin())) {
+ $code = autoname(8) . srand(1000,9999);
+ $nmessage = str_replace('$invite_code',$code,$message);
+
+ $r = q("INSERT INTO `register` (`hash`,`created`) VALUES ('%s', '%s') ",
+ dbesc($code),
+ dbesc(datetime_convert())
+ );
+
+ if(! is_site_admin()) {
+ $x --;
+ if($x >= 0)
+ set_pconfig(local_user(),'system','invites_remaining',$x);
+ else
+ return;
+ }
+ }
+ else
+ $nmessage = $message;
$res = mail($recip, sprintf( t('Please join my network on %s'), $a->config['sitename']),
- $message,
+ $nmessage,
"From: " . $a->user['email'] . "\n"
. 'Content-type: text/plain; charset=UTF-8' . "\n"
. 'Content-transfer-encoding: 8bit' );
@@ -56,14 +83,25 @@ function invite_content(&$a) {
}
$tpl = get_markup_template('invite.tpl');
-
+ $invonly = false;
+
+ if(get_config('system','invitation_only')) {
+ $invonly = true;
+ $x = get_pconfig(local_user(),'system','invites_remaining');
+ if((! $x) && (! is_site_admin())) {
+ notice( t('You have no more invitations available') . EOL);
+ return '';
+ }
+ }
+
+
$o = replace_macros($tpl, array(
'$invite' => t('Send invitations'),
'$addr_text' => t('Enter email addresses, one per line:'),
'$msg_text' => t('Your message:'),
'$default_message' => sprintf(t('Please join my social network on %s'), $a->config['sitename']) . "\r\n" . "\r\n"
. t('To accept this invitation, please visit:') . "\r\n" . "\r\n" . $a->get_baseurl()
- . "\r\n" . "\r\n" . t('Once you have registered, please connect with me via my profile page at:')
+ . "\r\n" . "\r\n" . (($invonly) ? t('You will need to supply this invitation code: $invite_code') . "\r\n" . "\r\n" : '') .t('Once you have registered, please connect with me via my profile page at:')
. "\r\n" . "\r\n" . $a->get_baseurl() . '/profile/' . $a->user['nickname'] ,
'$submit' => t('Submit')
));
diff --git a/mod/item.php b/mod/item.php
index 8a4f8293c..f6f665a18 100644
--- a/mod/item.php
+++ b/mod/item.php
@@ -184,12 +184,10 @@ function item_post(&$a) {
if($post_type === 'net-comment') {
if($parent_item !== null) {
- if($parent_item['type'] === 'remote') {
- $post_type = 'remote-comment';
- }
- else {
+ if($parent_item['wall'] == 1)
$post_type = 'wall-comment';
- }
+ else
+ $post_type = 'remote-comment';
}
}
diff --git a/mod/parse_url.php b/mod/parse_url.php
index ec28d7411..46c6b46e9 100644
--- a/mod/parse_url.php
+++ b/mod/parse_url.php
@@ -13,7 +13,7 @@ function parse_url_content(&$a) {
$text = null;
- $template = "<a href=\"%s\" >%s</a>\n%s";
+ $template = "<br /><a href=\"%s\" >%s</a>%s<br />";
$arr = array('url' => $url, 'text' => '');
@@ -39,12 +39,20 @@ function parse_url_content(&$a) {
killme();
}
+ if(strpos($s,'<title>')) {
+ $title = substr($s,strpos($s,'<title>')+7,64);
+ if(strpos($title,'<') !== false)
+ $title = strip_tags(substr($title,0,strpos($title,'<')));
+ }
+
$config = HTMLPurifier_Config::createDefault();
$config->set('Cache.DefinitionImpl', null);
$purifier = new HTMLPurifier($config);
$s = $purifier->purify($s);
+// logger('parse_url: purified: ' . $s, LOGGER_DATA);
+
$dom = @HTML5_Parser::parse($s);
if(! $dom) {
@@ -65,21 +73,27 @@ function parse_url_content(&$a) {
if($divs) {
foreach($divs as $div) {
$class = $div->getAttribute('class');
- if($class && stristr($class,'article')) {
+ if($class && (stristr($class,'article') || stristr($class,'content'))) {
$items = $div->getElementsByTagName('p');
if($items) {
foreach($items as $item) {
- if($item->getElementsByTagName('script'))
- continue;
$text = $item->textContent;
+ if(stristr($text,'<script')) {
+ $text = '';
+ continue;
+ }
$text = strip_tags($text);
- if(strlen($text) < 100)
+ if(strlen($text) < 100) {
+ $text = '';
continue;
+ }
$text = substr($text,0,250) . '...' ;
break;
}
}
}
+ if($text)
+ break;
}
}
@@ -87,12 +101,14 @@ function parse_url_content(&$a) {
$items = $dom->getElementsByTagName('p');
if($items) {
foreach($items as $item) {
- if($item->getElementsByTagName('script'))
- continue;
$text = $item->textContent;
+ if(stristr($text,'<script'))
+ continue;
$text = strip_tags($text);
- if(strlen($text) < 100)
+ if(strlen($text) < 100) {
+ $text = '';
continue;
+ }
$text = substr($text,0,250) . '...' ;
break;
}
@@ -100,7 +116,7 @@ function parse_url_content(&$a) {
}
if(strlen($text)) {
- $text = '<br />' . $text;
+ $text = '<br /><br />' . $text;
}
echo sprintf($template,$url,($title) ? $title : $url,$text);
diff --git a/mod/receive.php b/mod/receive.php
new file mode 100644
index 000000000..6e36109b3
--- /dev/null
+++ b/mod/receive.php
@@ -0,0 +1,215 @@
+<?php
+
+/**
+ * Diaspora endpoint
+ */
+
+
+
+require_once('include/salmon.php');
+require_once('library/simplepie/simplepie.inc');
+
+function receive_return($val) {
+
+ if($val >= 400)
+ $err = 'Error';
+ if($val >= 200 && $val < 300)
+ $err = 'OK';
+
+ logger('mod-diaspora returns ' . $val);
+ header($_SERVER["SERVER_PROTOCOL"] . ' ' . $val . ' ' . $err);
+ killme();
+
+}
+
+function receive_post(&$a) {
+
+ if($a->argc != 3 || $a->argv[1] !== 'users')
+ receive_return(500);
+
+ $guid = $a->argv[2];
+
+ $r = q("SELECT * FROM `user` WHERE `guid` = '%s' LIMIT 1",
+ dbesc($guid)
+ );
+ if(! count($r))
+ salmon_return(500);
+
+ $importer = $r[0];
+
+ $xml = $_POST['xml'];
+
+ logger('mod-diaspora: new salmon ' . $xml, LOGGER_DATA);
+
+ if(! $xml)
+ receive_return(500);
+
+ // parse the xml
+
+ $dom = simplexml_load_string($xml,'SimpleXMLElement',0,NAMESPACE_SALMON_ME);
+
+ // figure out where in the DOM tree our data is hiding
+
+ if($dom->provenance->data)
+ $base = $dom->provenance;
+ elseif($dom->env->data)
+ $base = $dom->env;
+ elseif($dom->data)
+ $base = $dom;
+
+ if(! $base) {
+ logger('mod-diaspora: unable to locate salmon data in xml ');
+ receive_return(400);
+ }
+
+ // Stash the signature away for now. We have to find their key or it won't be good for anything.
+ $signature = base64url_decode($base->sig);
+
+ // unpack the data
+
+ // strip whitespace so our data element will return to one big base64 blob
+ $data = str_replace(array(" ","\t","\r","\n"),array("","","",""),$base->data);
+
+ // stash away some other stuff for later
+
+ $type = $base->data[0]->attributes()->type[0];
+ $keyhash = $base->sig[0]->attributes()->keyhash[0];
+ $encoding = $base->encoding;
+ $alg = $base->alg;
+
+ $signed_data = $data . '.' . base64url_encode($type) . '.' . base64url_encode($encoding) . '.' . base64url_encode($alg);
+
+ // decode the data
+ $data = base64url_decode($data);
+
+ // Remove the xml declaration
+ $data = preg_replace('/\<\?xml[^\?].*\?\>/','',$data);
+
+ // Create a fake feed wrapper so simplepie doesn't choke
+
+ $tpl = get_markup_template('fake_feed.tpl');
+
+ $base = substr($data,strpos($data,'<entry'));
+
+ $feedxml = $tpl . $base . '</feed>';
+
+ logger('mod-diaspora: Processed feed: ' . $feedxml);
+
+ // Now parse it like a normal atom feed to scrape out the author URI
+
+ $feed = new SimplePie();
+ $feed->set_raw_data($feedxml);
+ $feed->enable_order_by_date(false);
+ $feed->init();
+
+ logger('mod-diaspora: Feed parsed.');
+
+ if($feed->get_item_quantity()) {
+ foreach($feed->get_items() as $item) {
+ $author = $item->get_author();
+ $author_link = unxmlify($author->get_link());
+ break;
+ }
+ }
+
+ if(! $author_link) {
+ logger('mod-diaspora: Could not retrieve author URI.');
+ receive_return(400);
+ }
+
+ // Once we have the author URI, go to the web and try to find their public key
+
+ logger('mod-salmon: Fetching key for ' . $author_link );
+
+
+ $key = get_salmon_key($author_link,$keyhash);
+
+ if(! $key) {
+ logger('mod-salmon: Could not retrieve author key.');
+ receive_return(400);
+ }
+
+ // Setup RSA stuff to verify the signature
+
+ set_include_path(get_include_path() . PATH_SEPARATOR . 'library' . PATH_SEPARATOR . 'phpsec');
+
+ require_once('library/phpsec/Crypt/RSA.php');
+
+ $key_info = explode('.',$key);
+
+ $m = base64url_decode($key_info[1]);
+ $e = base64url_decode($key_info[2]);
+
+ logger('mod-salmon: key details: ' . print_r($key_info,true));
+
+ $rsa = new CRYPT_RSA();
+ $rsa->signatureMode = CRYPT_RSA_SIGNATURE_PKCS1;
+ $rsa->setHash('sha256');
+
+ $rsa->modulus = new Math_BigInteger($m, 256);
+ $rsa->k = strlen($rsa->modulus->toBytes());
+ $rsa->exponent = new Math_BigInteger($e, 256);
+
+ $verify = $rsa->verify($signed_data,$signature);
+
+ if(! $verify) {
+ logger('mod-diaspora: Message did not verify. Discarding.');
+ receive_return(400);
+ }
+
+ logger('mod-diaspora: Message verified.');
+
+ /* decrypt the sucker */
+ /*
+ // TODO
+ */
+
+ /*
+ *
+ * If we reached this point, the message is good. Now let's figure out if the author is allowed to send us stuff.
+ *
+ */
+
+ $r = q("SELECT * FROM `contact` WHERE `network` = 'dspr' AND ( `url` = '%s' OR `alias` = '%s')
+ AND `uid` = %d LIMIT 1",
+ dbesc($author_link),
+ dbesc($author_link),
+ intval($importer['uid'])
+ );
+ if(! count($r)) {
+ logger('mod-diaspora: Author unknown to us.');
+ }
+
+ // is this a follower? Or have we ignored the person?
+ // If so we can not accept this post.
+
+ if((count($r)) && (($r[0]['readonly']) || ($r[0]['rel'] == REL_VIP) || ($r[0]['blocked']))) {
+ logger('mod-diaspora: Ignoring this author.');
+ receive_return(202);
+ // NOTREACHED
+ }
+
+ require_once('include/items.php');
+
+ // Placeholder for hub discovery. We shouldn't find any hubs
+ // since we supplied the fake feed header - and it doesn't have any.
+
+ $hub = '';
+
+ /**
+ *
+ * anti-spam measure: consume_feed will accept a follow activity from
+ * this person (and nothing else) if there is no existing contact record.
+ *
+ */
+
+ $contact_rec = ((count($r)) ? $r[0] : null);
+
+ consume_feed($feedxml,$importer,$contact_rec,$hub);
+
+ receive_return(200);
+}
+
+
+
+
diff --git a/mod/register.php b/mod/register.php
index 5fac9d79c..0906395d2 100644
--- a/mod/register.php
+++ b/mod/register.php
@@ -32,7 +32,11 @@ function register_post(&$a) {
break;
}
+ $using_invites = get_config('system','invitation_only');
+ $num_invites = get_config('system','number_invites');
+
+ $invite_id = ((x($_POST,'invite_id')) ? notags(trim($_POST['invite_id'])) : '');
$username = ((x($_POST,'username')) ? notags(trim($_POST['username'])) : '');
$nickname = ((x($_POST,'nickname')) ? notags(trim($_POST['nickname'])) : '');
$email = ((x($_POST,'email')) ? notags(trim($_POST['email'])) : '');
@@ -43,6 +47,19 @@ function register_post(&$a) {
$netpublish = ((strlen(get_config('system','directory_submit_url'))) ? $publish : 0);
$tmp_str = $openid_url;
+
+ if($using_invites) {
+ if(! $invite_id) {
+ notice( t('An invitation is required.') . EOL);
+ return;
+ }
+ $r = q("select * from register where `hash` = '%s' limit 1", dbesc($invite_id));
+ if(! results($r)) {
+ notice( t('Invitation could not be verified.') . EOL);
+ return;
+ }
+ }
+
if((! x($username)) || (! x($email)) || (! x($nickname))) {
if($openid_url) {
if(! validate_url($tmp_str)) {
@@ -181,9 +198,10 @@ function register_post(&$a) {
$spkey = openssl_pkey_get_details($sres);
$spubkey = $spkey["key"];
- $r = q("INSERT INTO `user` ( `username`, `password`, `email`, `openid`, `nickname`,
+ $r = q("INSERT INTO `user` ( `guid`, `username`, `password`, `email`, `openid`, `nickname`,
`pubkey`, `prvkey`, `spubkey`, `sprvkey`, `register_date`, `verified`, `blocked` )
- VALUES ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d )",
+ VALUES ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d )",
+ dbesc(generate_guid()),
dbesc($username),
dbesc($new_password_encoded),
dbesc($email),
@@ -328,7 +346,15 @@ function register_post(&$a) {
}
+ call_hooks('register_account', $newuid);
+
if( $a->config['register_policy'] == REGISTER_OPEN ) {
+
+ if($using_invites && $invite_id) {
+ q("delete * from register where hash = '%s' limit 1", dbesc($invite_id));
+ set_pconfig($newuid,'system','invites_remaining',$num_invites);
+ }
+
$email_tpl = get_intltext_template("register_open_eml.tpl");
$email_tpl = replace_macros($email_tpl, array(
'$sitename' => $a->config['sitename'],
@@ -376,6 +402,10 @@ function register_post(&$a) {
else
push_lang('en');
+ if($using_invites && $invite_id) {
+ q("delete * from register where hash = '%s' limit 1", dbesc($invite_id));
+ set_pconfig($newuid,'system','invites_remaining',$num_invites);
+ }
$email_tpl = get_intltext_template("register_verify_eml.tpl");
$email_tpl = replace_macros($email_tpl, array(
@@ -434,6 +464,7 @@ function register_content(&$a) {
$openid_url = ((x($_POST,'openid_url')) ? $_POST['openid_url'] : ((x($_GET,'openid_url')) ? $_GET['openid_url'] : ''));
$nickname = ((x($_POST,'nickname')) ? $_POST['nickname'] : ((x($_GET,'nickname')) ? $_GET['nickname'] : ''));
$photo = ((x($_POST,'photo')) ? $_POST['photo'] : ((x($_GET,'photo')) ? hex2bin($_GET['photo']) : ''));
+ $invite_id = ((x($_POST,'invite_id')) ? $_POST['invite_id'] : ((x($_GET,'invite_id')) ? $_GET['invite_id'] : ''));
$noid = get_config('system','no_openid');
@@ -476,6 +507,10 @@ function register_content(&$a) {
$o = get_markup_template("register.tpl");
$o = replace_macros($o, array(
'$oidhtml' => $oidhtml,
+ '$invitations' => get_config('system','invitation_only'),
+ '$invite_desc' => t('Membership on this site is by invitation only.'),
+ '$invite_label' => t('Your invitation ID: '),
+ '$invite_id' => $invite_id,
'$realpeople' => $realpeople,
'$regtitle' => t('Registration'),
'$registertext' =>((x($a->config,'register_text'))
diff --git a/mod/settings.php b/mod/settings.php
index e11555687..1b4098de8 100644
--- a/mod/settings.php
+++ b/mod/settings.php
@@ -435,11 +435,6 @@ function settings_content(&$a) {
));
-
-
-
-
-
$invisible = (((! $profile['publish']) && (! $profile['net-publish']))
? true : false);
@@ -495,6 +490,7 @@ function settings_content(&$a) {
'$h_pass' => t('Password Settings'),
'$password1'=> array('npassword', t('New Password:'), '', ''),
'$password2'=> array('confirm', t('Confirm:'), '', t('Leave password fields blank unless changing')),
+ '$oid_enable' => (! get_config('system','no_openid')),
'$openid' => $openid_field,
'$h_basic' => t('Basic Settings'),
@@ -527,11 +523,11 @@ function settings_content(&$a) {
'$h_not' => t('Notification Settings'),
'$lbl_not' => t('Send a notification email when:'),
- '$notify1' => array('notify1', t('You receive an introduction'), ($notify & NOTIFY_INTRO), ''),
- '$notify2' => array('notify1', t('Your introductions are confirmed'), ($notify & NOTIFY_CONFIRM), ''),
- '$notify3' => array('notify1', t('Someone writes on your profile wall'), ($notify & NOTIFY_WALL), ''),
- '$notify4' => array('notify1', t('Someone writes a followup comment'), ($notify & NOTIFY_COMMENT), ''),
- '$notify5' => array('notify1', t('You receive a private message'), ($notify & NOTIFY_MAIL), ''),
+ '$notify1' => array('notify1', t('You receive an introduction'), ($notify & NOTIFY_INTRO), NOTIFY_INTRO, ''),
+ '$notify2' => array('notify2', t('Your introductions are confirmed'), ($notify & NOTIFY_CONFIRM), NOTIFY_CONFIRM, ''),
+ '$notify3' => array('notify3', t('Someone writes on your profile wall'), ($notify & NOTIFY_WALL), NOTIFY_WALL, ''),
+ '$notify4' => array('notify4', t('Someone writes a followup comment'), ($notify & NOTIFY_COMMENT), NOTIFY_COMMENT, ''),
+ '$notify5' => array('notify5', t('You receive a private message'), ($notify & NOTIFY_MAIL), NOTIFY_MAIL, ''),
diff --git a/mod/xrd.php b/mod/xrd.php
index de0c20ea5..accc2f68e 100644
--- a/mod/xrd.php
+++ b/mod/xrd.php
@@ -27,6 +27,20 @@ function xrd_content(&$a) {
header('Access-Control-Allow-Origin: *');
header("Content-type: text/xml");
+ $dspr_enabled = get_config('system','diaspora_enabled');
+
+ if($dspr_enabled) {
+ $tpl = file_get_contents('view/xrd_diaspora.tpl');
+ $dspr = replace_macros($tpl,array(
+ '$baseurl' => $a->get_baseurl(),
+ '$dspr_guid' => $r[0]['guid'],
+ '$dspr_key' => base64_encode($r[0]['pubkey'])
+ ));
+ }
+ else
+ $dspr = '';
+
+
$tpl = file_get_contents('view/xrd_person.tpl');
$o = replace_macros($tpl, array(
@@ -34,6 +48,7 @@ function xrd_content(&$a) {
'$profile_url' => $a->get_baseurl() . '/profile/' . $r[0]['nickname'],
'$atom' => $a->get_baseurl() . '/dfrn_poll/' . $r[0]['nickname'],
'$photo' => $a->get_baseurl() . '/photo/profile/' . $r[0]['uid'] . '.jpg',
+ '$dspr' => $dspr,
'$salmon' => $a->get_baseurl() . '/salmon/' . $r[0]['nickname'],
'$salmen' => $a->get_baseurl() . '/salmon/' . $r[0]['nickname'] . '/mention',
'$modexp' => 'data:application/magic-public-key,' . $salmon_key