diff options
Diffstat (limited to 'mod')
-rw-r--r-- | mod/contacts.php | 17 | ||||
-rw-r--r-- | mod/friendika.php | 1 | ||||
-rw-r--r-- | mod/install.php | 2 | ||||
-rw-r--r-- | mod/invite.php | 44 | ||||
-rw-r--r-- | mod/item.php | 8 | ||||
-rw-r--r-- | mod/parse_url.php | 34 | ||||
-rw-r--r-- | mod/receive.php | 215 | ||||
-rw-r--r-- | mod/register.php | 39 | ||||
-rw-r--r-- | mod/settings.php | 16 | ||||
-rw-r--r-- | mod/xrd.php | 15 |
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 |