Merge remote-tracking branch 'friendika/master' into newui

This commit is contained in:
fabrixxm 2011-08-17 17:35:37 +02:00
commit bdf42473a0
101 changed files with 9954 additions and 6168 deletions

View File

@ -111,13 +111,13 @@ function facebook_init(&$a) {
$token = substr($token,0,strpos($token,'&'));
set_pconfig($uid,'facebook','access_token',$token);
set_pconfig($uid,'facebook','post','1');
set_pconfig($uid,'facebook','no_linking',1);
fb_get_self($uid);
fb_get_friends($uid);
fb_consume_all($uid);
}
// todo: is this a browser session or a server session? where do we go?
}
}
@ -214,7 +214,7 @@ function fb_get_friends($uid) {
dbesc(($jp->nickname) ? $jp->nickname : strtolower($jp->first_name)),
dbesc('https://graph.facebook.com/' . $jp->id . '/picture'),
dbesc(NETWORK_FACEBOOK),
intval(REL_BUD),
intval(CONTACT_IS_FRIEND),
intval(1),
intval(1)
);
@ -258,6 +258,8 @@ function fb_get_friends($uid) {
}
}
// This is the POST method to the facebook settings page
// Content is posted to Facebook in the function facebook_post_hook()
function facebook_post(&$a) {
@ -298,6 +300,8 @@ function facebook_post(&$a) {
return;
}
// Facebook settings form
function facebook_content(&$a) {
if(! local_user()) {
@ -347,14 +351,18 @@ function facebook_content(&$a) {
$o .= '<form action="facebook" method="post" >';
$post_by_default = get_pconfig(local_user(),'facebook','post_by_default');
$checked = (($post_by_default) ? ' checked="checked" ' : '');
$o .= '<input type="checkbox" name="post_by_default" value="1"' . $checked . '/>' . ' ' . t('Post to Facebook by default') . '<br />';
$o .= '<input type="checkbox" name="post_by_default" value="1"' . $checked . '/>' . ' ' . t('Post to Facebook by default') . EOL;
$no_linking = get_pconfig(local_user(),'facebook','no_linking');
$checked = (($no_linking) ? '' : ' checked="checked" ');
$o .= '<input type="checkbox" name="facebook_linking" value="1"' . $checked . '/>' . ' ' . t('Link all your Facebook friends and conversations') . '<br />';
$o .= '<input type="checkbox" name="facebook_linking" value="1"' . $checked . '/>' . ' ' . t('Link all your Facebook friends and conversations') . EOL ;
$hidden = (($a->user['hidewall'] || get_config('system','block_public')) ? true : false);
if(! $hidden) {
$o .= EOL;
$o .= t('Warning: Your Facebook privacy settings can not be imported.') . EOL;
$o .= t('Linked Facebook items <strong>may</strong> be publicly visible, depending on your privacy settings for this website/account.') . EOL;
}
$o .= '<input type="submit" name="submit" value="' . t('Submit') . '" /></form></div>';
}
@ -522,6 +530,13 @@ function facebook_post_hook(&$a,&$b) {
$fb_enable = (($fb_post && x($_POST,'facebook_enable')) ? intval($_POST['facebook_enable']) : 0);
$fb_token = get_pconfig(local_user(),'facebook','access_token');
// if API is used, default to the chosen settings
if($_POST['api_source'] && intval(get_pconfig(local_user(),'facebook','post_by_default')))
$fb_enable = 1;
logger('facebook: $fb_post: ' . $fb_post . ' $fb_enable: ' . $fb_enable . ' $fb_token: ' . $fb_token,LOGGER_DEBUG);
// post to facebook if it's a public post and we've ticked the 'post to Facebook' box,
@ -564,7 +579,7 @@ function facebook_post_hook(&$a,&$b) {
$msg = preg_replace("/\[img\](.*?)\[\/img\]/is", t('Image: ') . '$1', $msg);
if((strpos($link,$a->get_baseurl()) !== false) && (! $image))
if((strpos($link,z_root()) !== false) && (! $image))
$image = $a->get_baseurl() . '/images/friendika-64.jpg';
$msg = trim(strip_tags(bbcode($msg)));
@ -746,6 +761,8 @@ function fb_consume_all($uid) {
$access_token = get_pconfig($uid,'facebook','access_token');
if(! $access_token)
return;
$s = fetch_url('https://graph.facebook.com/me/feed?access_token=' . $access_token);
if($s) {
$j = json_decode($s);
@ -772,13 +789,12 @@ function fb_consume_stream($uid,$j,$wall = false) {
intval($uid)
);
$user = q("SELECT `nickname` FROM `user` WHERE `uid` = %d LIMIT 1",
$user = q("SELECT `nickname`, `blockwall` FROM `user` WHERE `uid` = %d LIMIT 1",
intval($uid)
);
if(count($user))
$my_local_url = $a->get_baseurl() . '/profile/' . $user[0]['nickname'];
$self_id = get_pconfig($uid,'facebook','self_id');
if(! count($j->data) || (! strlen($self_id)))
return;

View File

@ -298,10 +298,10 @@ class qqFileUploader {
return array('error' => t('Uploaded file is empty'));
}
if ($size > $this->sizeLimit) {
// if ($size > $this->sizeLimit) {
return array('error' => t('Uploaded file is too large'));
}
// return array('error' => t('Uploaded file is too large'));
// }
$maximagesize = get_config('system','maximagesize');

View File

@ -1,7 +1,7 @@
<?php
/**
* Name: StatusNet Connector
* Version: 1.0
* Version: 1.0.2
* Author: Tobias Diekershoff <https://diekershoff.homeunix.net/friendika/profile/tobias>
*/
@ -51,6 +51,57 @@ class StatusNetOAuth extends TwitterOAuth {
parent::__construct($consumer_key, $consumer_secret, $oauth_token, $oauth_token_secret);
$this->host = $apipath;
}
/**
* Make an HTTP request
*
* @return API results
*
* Copied here from the twitteroauth library and complemented by applying the proxy settings of friendika
*/
function http($url, $method, $postfields = NULL) {
$this->http_info = array();
$ci = curl_init();
/* Curl settings */
$prx = get_config('system','proxy');
logger('Proxy SN: '.$prx);
if(strlen($prx)) {
curl_setopt($ci, CURLOPT_HTTPPROXYTUNNEL, 1);
curl_setopt($ci, CURLOPT_PROXY, $prx);
$prxusr = get_config('system','proxyuser');
if(strlen($prxusr))
curl_setopt($ci, CURLOPT_PROXYUSERPWD, $prxusr);
}
curl_setopt($ci, CURLOPT_USERAGENT, $this->useragent);
curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, $this->connecttimeout);
curl_setopt($ci, CURLOPT_TIMEOUT, $this->timeout);
curl_setopt($ci, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ci, CURLOPT_HTTPHEADER, array('Expect:'));
curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, $this->ssl_verifypeer);
curl_setopt($ci, CURLOPT_HEADERFUNCTION, array($this, 'getHeader'));
curl_setopt($ci, CURLOPT_HEADER, FALSE);
switch ($method) {
case 'POST':
curl_setopt($ci, CURLOPT_POST, TRUE);
if (!empty($postfields)) {
curl_setopt($ci, CURLOPT_POSTFIELDS, $postfields);
}
break;
case 'DELETE':
curl_setopt($ci, CURLOPT_CUSTOMREQUEST, 'DELETE');
if (!empty($postfields)) {
$url = "{$url}?{$postfields}";
}
}
curl_setopt($ci, CURLOPT_URL, $url);
$response = curl_exec($ci);
$this->http_code = curl_getinfo($ci, CURLINFO_HTTP_CODE);
$this->http_info = array_merge($this->http_info, curl_getinfo($ci));
$this->url = $url;
curl_close ($ci);
return $response;
}
}
function statusnet_install() {
@ -276,7 +327,7 @@ function statusnet_settings(&$a,&$s) {
$connection = new StatusNetOAuth($api,$ckey,$csecret,$otoken,$osecret);
$details = $connection->get('account/verify_credentials');
$s .= '<div id="statusnet-info" ><img id="statusnet-avatar" src="'.$details->profile_image_url.'" /><p id="statusnet-info-block">'. t('Currently connected to: ') .'<a href="'.$details->statusnet_profile_url.'" target="_statusnet">'.$details->screen_name.'</a><br /><em>'.$details->description.'</em></p></div>';
$s .= '<p>'. t('If enabled all your <strong>public</strong> postings will be posted to the associated StatusNet account.') .'</p>';
$s .= '<p>'. t('If enabled all your <strong>public</strong> postings can be posted to the associated StatusNet account. You can choose to do so by default (here) or for every posting separately in the posting options when writing the entry.') .'</p>';
$s .= '<div id="statusnet-enable-wrapper">';
$s .= '<label id="statusnet-enable-label" for="statusnet-checkbox">'. t('Allow posting to StatusNet') .'</label>';
$s .= '<input id="statusnet-checkbox" type="checkbox" name="statusnet-enable" value="1" ' . $checked . '/>';
@ -322,6 +373,9 @@ function statusnet_post_hook(&$a,&$b) {
$statusnet_post = get_pconfig(local_user(),'statusnet','post');
$statusnet_enable = (($statusnet_post && x($_POST,'statusnet_enable')) ? intval($_POST['statusnet_enable']) : 0);
// if API is used, default to the chosen settings
if($_POST['api_source'] && intval(get_pconfig(local_user(),'statusnet','post_by_default')))
$statusnet_enable = 1;
if($statusnet_enable && $statusnet_post) {
require_once('include/bbcode.php');
@ -402,10 +456,10 @@ function statusnet_plugin_admin(&$a, &$o){
/* empty form to add new site */
$id++;
$sitesform[] = Array(
'sitename' => Array("sitename[$id]", "Site name", "", ""),
'apiurl' => Array("apiurl[$id]", "Api url", "", ""),
'secret' => Array("secret[$id]", "Secret", "", ""),
'key' => Array("key[$id]", "Key", "", ""),
'sitename' => Array("sitename[$id]", t("Site name"), "", ""),
'apiurl' => Array("apiurl[$id]", t("API URL"), "", ""),
'secret' => Array("secret[$id]", t("Consumer Secret"), "", ""),
'key' => Array("key[$id]", t("Consumer Key"), "", ""),
);

View File

@ -1,7 +1,7 @@
<?php
/**
* Name: Twitter Connector
* Version: 1.0
* Version: 1.0.1
* Author: Tobias Diekershoff <https://diekershoff.homeunix.net/friendika/profile/tobias>
*/
@ -87,7 +87,8 @@ function twitter_settings_post ($a,$post) {
*/
del_pconfig( local_user(), 'twitter', 'consumerkey' );
del_pconfig( local_user(), 'twitter', 'consumersecret' );
del_pconfig( local_user(), 'twitter', 'post' );
del_pconfig( local_user(), 'twitter', 'post' );
del_pconfig( local_user(), 'twitter', 'post_by_default' );
} else {
if (isset($_POST['twitter-pin'])) {
// if the user supplied us with a PIN from Twitter, let the magic of OAuth happen
@ -105,11 +106,13 @@ function twitter_settings_post ($a,$post) {
set_pconfig(local_user(),'twitter', 'oauthsecret', $token['oauth_token_secret']);
set_pconfig(local_user(),'twitter', 'post', 1);
// reload the Addon Settings page, if we don't do it see Bug #42
header('Location: '.$a->get_baseurl().'/settings/addon');
goaway($a->get_baseurl().'/settings/addon');
} else {
// if no PIN is supplied in the POST variables, the user has changed the setting
// to post a tweet for every new __public__ posting to the wall
set_pconfig(local_user(),'twitter','post',intval($_POST['twitter-enable']));
set_pconfig(local_user(),'twitter','post_by_default',intval($_POST['twitter-default']));
info( t('Twitter settings updated.') . EOL);
}}
}
function twitter_settings(&$a,&$s) {
@ -127,6 +130,9 @@ function twitter_settings(&$a,&$s) {
$osecret = get_pconfig(local_user(), 'twitter', 'oauthsecret' );
$enabled = get_pconfig(local_user(), 'twitter', 'post');
$checked = (($enabled) ? ' checked="checked" ' : '');
$defenabled = get_pconfig(local_user(),'twitter','post_by_default');
$defchecked = (($defenabled) ? ' checked="checked" ' : '');
$s .= '<div class="settings-block">';
$s .= '<h3>'. t('Twitter Posting Settings') .'</h3>';
@ -172,11 +178,15 @@ function twitter_settings(&$a,&$s) {
$connection = new TwitterOAuth($ckey,$csecret,$otoken,$osecret);
$details = $connection->get('account/verify_credentials');
$s .= '<div id="twitter-info" ><img id="twitter-avatar" src="'.$details->profile_image_url.'" /><p id="twitter-info-block">'. t('Currently connected to: ') .'<a href="https://twitter.com/'.$details->screen_name.'" target="_twitter">'.$details->screen_name.'</a><br /><em>'.$details->description.'</em></p></div>';
$s .= '<p>'. t('If enabled all your <strong>public</strong> postings will be posted to the associated Twitter account as well.') .'</p>';
$s .= '<p>'. t('If enabled all your <strong>public</strong> postings can be posted to the associated Twitter account. You can choose to do so by default (here) or for every posting separately in the posting options when writing the entry.') .'</p>';
$s .= '<div id="twitter-enable-wrapper">';
$s .= '<label id="twitter-enable-label" for="twitter-checkbox">'. t('Send public postings to Twitter'). '</label>';
$s .= '<label id="twitter-enable-label" for="twitter-checkbox">'. t('Allow posting to Twitter'). '</label>';
$s .= '<input id="twitter-checkbox" type="checkbox" name="twitter-enable" value="1" ' . $checked . '/>';
$s .= '<div class="clear"></div>';
$s .= '<label id="twitter-default-label" for="twitter-default">'. t('Send public postings to Twitter by default') .'</label>';
$s .= '<input id="twitter-default" type="checkbox" name="twitter-default" value="1" ' . $defchecked . '/>';
$s .= '</div><div class="clear"></div>';
$s .= '<div id="twitter-disconnect-wrapper">';
$s .= '<label id="twitter-disconnect-label" for="twitter-disconnect">'. t('Clear OAuth configuration') .'</label>';
$s .= '<input id="twitter-disconnect" type="checkbox" name="twitter-disconnect" value="1" />';
@ -215,6 +225,10 @@ function twitter_post_hook(&$a,&$b) {
$twitter_post = intval(get_pconfig(local_user(),'twitter','post'));
$twitter_enable = (($twitter_post && x($_POST,'twitter_enable')) ? intval($_POST['twitter_enable']) : 0);
// if API is used, default to the chosen settings
if($_POST['api_source'] && intval(get_pconfig(local_user(),'twitter','post_by_default')))
$twitter_enable = 1;
if($twitter_post && $twitter_enable) {
logger('Posting to Twitter', LOGGER_DEBUG);
require_once('library/twitteroauth.php');

2086
boot.php

File diff suppressed because it is too large Load Diff

View File

@ -160,6 +160,7 @@ CREATE TABLE IF NOT EXISTS `intro` (
CREATE TABLE IF NOT EXISTS `item` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`guid` char(64) NOT NULL,
`uri` char(255) NOT NULL,
`uid` int(10) unsigned NOT NULL DEFAULT '0',
`contact-id` int(10) unsigned NOT NULL DEFAULT '0',
@ -208,6 +209,7 @@ CREATE TABLE IF NOT EXISTS `item` (
`deleted` tinyint(1) NOT NULL DEFAULT '0',
`last-child` tinyint(1) unsigned NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
KEY `guid` (`guid`),
KEY `uri` (`uri`),
KEY `uid` (`uid`),
KEY `contact-id` (`contact-id`),
@ -573,3 +575,9 @@ CREATE TABLE IF NOT EXISTS `attach` (
`deny_gid` MEDIUMTEXT NOT NULL
) ENGINE = MYISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `guid` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`guid` CHAR( 64 ) NOT NULL ,
INDEX ( `guid` )
) ENGINE = MYISAM DEFAULT CHARSET=utf8;

BIN
images/diaspora.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 461 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 770 B

After

Width:  |  Height:  |  Size: 756 B

View File

@ -1,6 +1,7 @@
<?php
require_once('library/HTML5/Parser.php');
require_once('include/crypto.php');
if(! function_exists('scrape_dfrn')) {
function scrape_dfrn($url) {
@ -171,6 +172,8 @@ function scrape_vcard($url) {
// Pull out hCard profile elements
$largest_photo = 0;
$items = $dom->getElementsByTagName('*');
foreach($items as $item) {
if(attribute_contains($item->getAttribute('class'), 'vcard')) {
@ -179,8 +182,13 @@ function scrape_vcard($url) {
if(attribute_contains($x->getAttribute('class'),'fn'))
$ret['fn'] = $x->textContent;
if((attribute_contains($x->getAttribute('class'),'photo'))
|| (attribute_contains($x->getAttribute('class'),'avatar')))
$ret['photo'] = $x->getAttribute('src');
|| (attribute_contains($x->getAttribute('class'),'avatar'))) {
$size = intval($x->getAttribute('width'));
if(($size > $largest_photo) || (! $largest_photo)) {
$ret['photo'] = $x->getAttribute('src');
$largest_photo = $size;
}
}
if((attribute_contains($x->getAttribute('class'),'nickname'))
|| (attribute_contains($x->getAttribute('class'),'uid')))
$ret['nick'] = $x->textContent;
@ -290,12 +298,23 @@ function probe_url($url) {
return $result;
$diaspora = false;
$diaspora_base = '';
$diaspora_guid = '';
$diaspora_key = '';
$email_conversant = false;
$twitter = ((strpos($url,'twitter.com') !== false) ? true : false);
$at_addr = ((strpos($url,'@') !== false) ? true : false);
if(! $twitter) {
$links = lrdd($url);
if(strpos($url,'mailto:') !== false && $at_addr) {
$url = str_replace('mailto:','',$url);
$links = array();
}
else
$links = lrdd($url);
if(count($links)) {
logger('probe_url: found lrdd links: ' . print_r($links,true), LOGGER_DATA);
@ -312,8 +331,19 @@ function probe_url($url) {
$hcard = unamp($link['@attributes']['href']);
if($link['@attributes']['rel'] === 'http://webfinger.net/rel/profile-page')
$profile = unamp($link['@attributes']['href']);
if($link['@attributes']['rel'] === 'http://joindiaspora.com/seed_location')
if($link['@attributes']['rel'] === 'http://joindiaspora.com/seed_location') {
$diaspora_base = unamp($link['@attributes']['href']);
$diaspora = true;
}
if($link['@attributes']['rel'] === 'http://joindiaspora.com/guid') {
$diaspora_guid = unamp($link['@attributes']['href']);
$diaspora = true;
}
if($link['@attributes']['rel'] === 'diaspora-public-key') {
$diaspora_key = base64_decode(unamp($link['@attributes']['href']));
$pubkey = rsatopem($diaspora_key);
$diaspora = true;
}
}
// Status.Net can have more than one profile URL. We need to match the profile URL
@ -411,8 +441,17 @@ function probe_url($url) {
}
}
if($diaspora && $diaspora_base && $diaspora_guid) {
$notify = $diaspora_base . 'receive/post/' . $diaspora_guid;
if(strpos($url,'@'))
$addr = str_replace('acct:', '', $url);
}
if($network !== NETWORK_ZOT && $network !== NETWORK_DFRN && $network !== NETWORK_MAIL) {
$network = NETWORK_OSTATUS;
if($diaspora)
$network = NETWORK_DIASPORA;
else
$network = NETWORK_OSTATUS;
$priority = 0;
if($hcard) {
@ -429,13 +468,6 @@ function probe_url($url) {
logger('probe_url: scrape_vcard: ' . print_r($vcard,true), LOGGER_DATA);
}
if(! $profile) {
if($diaspora)
$profile = $hcard;
else
$profile = $url;
}
if($twitter) {
logger('twitter: setup');
$tid = basename($url);
@ -451,10 +483,18 @@ function probe_url($url) {
if(x($vcard,'nick'))
$vcard['fn'] = $vcard['nick'];
$check_feed = false;
if(((! isset($vcard)) && (! $poll)) || ($twitter)) {
if($twitter || ! $poll)
$check_feed = true;
if((! isset($vcard)) || (! $profile))
$check_feed = true;
if(($at_addr) && (! count($links)))
$check_feed = false;
$feedret = scrape_feed($url);
if($check_feed) {
$feedret = scrape_feed(($poll) ? $poll : $url);
logger('probe_url: scrape_feed returns: ' . print_r($feedret,true), LOGGER_DATA);
if(count($feedret) && ($feedret['feed_atom'] || $feedret['feed_rss'])) {
$poll = ((x($feedret,'feed_atom')) ? unamp($feedret['feed_atom']) : unamp($feedret['feed_rss']));
@ -488,6 +528,8 @@ function probe_url($url) {
if(strpos($vcard['fn'],'@') !== false)
$vcard['fn'] = substr($vcard['fn'],0,strpos($vcard['fn'],'@'));
$email = unxmlify($author->get_email());
if(! $profile && $author->get_link())
$profile = trim(unxmlify($author->get_link()));
if(! $vcard['photo']) {
$rawtags = $feed->get_feed_tags( SIMPLEPIE_NAMESPACE_ATOM_10, 'author');
if($rawtags) {
@ -508,6 +550,8 @@ function probe_url($url) {
if(strpos($vcard['fn'],'@') !== false)
$vcard['fn'] = substr($vcard['fn'],0,strpos($vcard['fn'],'@'));
$email = unxmlify($author->get_email());
if(! $profile && $author->get_link())
$profile = trim(unxmlify($author->get_link()));
}
if(! $vcard['photo']) {
$rawmedia = $item->get_item_tags('http://search.yahoo.com/mrss/','thumbnail');
@ -545,8 +589,10 @@ function probe_url($url) {
if(strpos($vcard['nick'],' '))
$vcard['nick'] = trim(substr($vcard['nick'],0,strpos($vcard['nick'],' ')));
}
$network = 'feed';
$priority = 2;
if(! $network)
$network = 'feed';
if(! $priority)
$priority = 2;
}
}
@ -554,8 +600,12 @@ function probe_url($url) {
$a = get_app();
$vcard['photo'] = $a->get_baseurl() . '/images/default-profile.jpg' ;
}
if(! $profile)
$profile = $url;
$vcard['fn'] = notags($vcard['fn']);
$vcard['nick'] = notags($vcard['nick']);
$vcard['nick'] = str_replace(' ','',notags($vcard['nick']));
$result['name'] = $vcard['fn'];

View File

@ -153,6 +153,9 @@ ACL.prototype.updateview = function(){
$('#jot-perms-icon').removeClass('lock').addClass('unlock');
$('#jot-public').show();
$('.profile-jot-net input').attr('disabled', false);
if(editor != false) {
$('#profile-jot-desc').html(ispublic);
}
} else {
that.showall.removeClass("selected");
@ -160,6 +163,7 @@ ACL.prototype.updateview = function(){
$('#jot-perms-icon').removeClass('unlock').addClass('lock');
$('#jot-public').hide();
$('.profile-jot-net input').attr('disabled', 'disabled');
$('#profile-jot-desc').html('&nbsp;');
}
$("#acl-list-content .acl-list-item").each(function(){

View File

@ -96,7 +96,7 @@ function contact_selector($selname, $selclass, $preselected = false, $options) {
$sql_extra = '';
if($x['mutual']) {
$sql_extra .= sprintf(" AND `rel` = %d ", intval(REL_BUD));
$sql_extra .= sprintf(" AND `rel` = %d ", intval(CONTACT_IS_FRIEND));
}
if(intval($x['exclude']))
@ -163,7 +163,7 @@ function contact_select($selname, $selclass, $preselected = false, $size = 4, $p
$sql_extra = '';
if($privmail || $celeb) {
$sql_extra .= sprintf(" AND `rel` = %d ", intval(REL_BUD));
$sql_extra .= sprintf(" AND `rel` = %d ", intval(CONTACT_IS_FRIEND));
}
if($privmail) {

View File

@ -10,10 +10,9 @@
$API = Array();
function api_date($str){
//Wed May 23 06:01:13 +0000 2007
return datetime_convert('UTC', 'UTC', $str, "D M d h:i:s +0000 Y" );
return datetime_convert('UTC', 'UTC', $str, "D M d H:i:s +0000 Y" );
}
@ -112,6 +111,10 @@
api_login($a);
}
load_contact_links(local_user());
logger('API call for ' . $a->user['username'] . ': ' . $a->query_string);
logger('API parameters: ' . print_r($_REQUEST,true));
$type="json";
if (strpos($a->query_string, ".xml")>0) $type="xml";
if (strpos($a->query_string, ".json")>0) $type="json";
@ -145,7 +148,26 @@
//echo "<pre>"; var_dump($r); die();
}
}
return false;
$r = '<status><error>not implemented</error></status>';
switch($type){
case "xml":
header ("Content-Type: text/xml");
return '<?xml version="1.0" encoding="UTF-8"?>'."\n".$r;
break;
case "json":
header ("Content-Type: application/json");
return json_encode(array('error' => 'not implemented'));
break;
case "rss":
header ("Content-Type: application/rss+xml");
return '<?xml version="1.0" encoding="UTF-8"?>'."\n".$r;
break;
case "atom":
header ("Content-Type: application/atom+xml");
return '<?xml version="1.0" encoding="UTF-8"?>'."\n".$r;
break;
}
}
/**
@ -157,7 +179,9 @@
$arr['$rss'] = array(
'alternate' => $user_info['url'],
'self' => $a->get_baseurl(). "/". $a->query_string,
'base' => $a->get_baseurl(),
'updated' => api_date(null),
'atom_updated' => datetime_convert('UTC','UTC','now',ATOM_TIME),
'language' => $user_info['language'],
'logo' => $a->get_baseurl()."/images/friendika-32.png",
);
@ -168,9 +192,10 @@
/**
* Returns user info array.
*/
function api_get_user(&$a, $contact_id=Null){
function api_get_user(&$a, $contact_id = Null){
$user = null;
$extra_query = "";
if(!is_null($contact_id)){
$user=$contact_id;
$extra_query = "AND `contact`.`id` = %d ";
@ -185,7 +210,7 @@
$extra_query = "AND `contact`.`nick` = '%s' ";
}
if (is_null($user)){
if (is_null($user) && $a->argc > 3){
list($user, $null) = explode(".",$a->argv[3]);
if(is_numeric($user)){
$user = intval($user);
@ -196,17 +221,17 @@
}
}
if ($user==='') {
if (! $user) {
if (local_user()===false) {
api_login($a); return False;
} else {
$user = $_SESSION['uid'];
$extra_query = "AND `contact`.`uid` = %d ";
$extra_query = "AND `contact`.`uid` = %d AND `contact`.`self` = 1 ";
}
}
logger('api_user: ' . $extra_query . ' ' , $user);
// user info
$uinfo = q("SELECT *, `contact`.`id` as `cid` FROM `contact`
WHERE 1
@ -217,43 +242,135 @@
return False;
}
// count public wall messages
$r = q("SELECT COUNT(`id`) as `count` FROM `item`
WHERE `uid` = %d
AND `type`='wall'
AND `allow_cid`='' AND `allow_gid`='' AND `deny_cid`='' AND `deny_gid`=''",
intval($uinfo[0]['uid'])
);
$countitms = $r[0]['count'];
if($uinfo[0]['self']) {
$usr = q("select * from user where uid = %d limit 1",
intval(local_user())
);
$profile = q("select * from profile where uid = %d and `is-default` = 1 limit 1",
intval(local_user())
);
// count public wall messages
$r = q("SELECT COUNT(`id`) as `count` FROM `item`
WHERE `uid` = %d
AND `type`='wall'
AND `allow_cid`='' AND `allow_gid`='' AND `deny_cid`='' AND `deny_gid`=''",
intval($uinfo[0]['uid'])
);
$countitms = $r[0]['count'];
}
else {
$r = q("SELECT COUNT(`id`) as `count` FROM `item`
WHERE `contact-id` = %d
AND `allow_cid`='' AND `allow_gid`='' AND `deny_cid`='' AND `deny_gid`=''",
intval($uinfo[0]['id'])
);
$countitms = $r[0]['count'];
}
// count friends
$r = q("SELECT COUNT(`id`) as `count` FROM `contact`
WHERE `uid` = %d
WHERE `uid` = %d AND `rel` IN ( %d, %d )
AND `self`=0 AND `blocked`=0",
intval($uinfo[0]['uid'])
intval($uinfo[0]['uid']),
intval(CONTACT_IS_SHARING),
intval(CONTACT_IS_FRIEND)
);
$countfriends = $r[0]['count'];
$r = q("SELECT COUNT(`id`) as `count` FROM `contact`
WHERE `uid` = %d AND `rel` IN ( %d, %d )
AND `self`=0 AND `blocked`=0",
intval($uinfo[0]['uid']),
intval(CONTACT_IS_FOLLOWER),
intval(CONTACT_IS_FRIEND)
);
$countfollowers = $r[0]['count'];
$r = q("SELECT count(`id`) as `count` FROM item where starred = 1 and uid = %d and deleted = 0",
intval($uinfo[0]['uid'])
);
$starred = $r[0]['count'];
if(! $uinfo[0]['self']) {
$countfriends = 0;
$countfollowers = 0;
$starred = 0;
}
$ret = Array(
'uid' => $uinfo[0]['uid'],
'id' => $uinfo[0]['cid'],
'uid' => intval($uinfo[0]['uid']),
'id' => intval($uinfo[0]['cid']),
'name' => $uinfo[0]['name'],
'screen_name' => $uinfo[0]['nick'],
'location' => '', //$uinfo[0]['default-location'],
'screen_name' => (($uinfo[0]['nick']) ? $uinfo[0]['nick'] : $uinfo[0]['name']),
'location' => ($usr) ? $usr[0]['default-location'] : '',
'profile_image_url' => $uinfo[0]['micro'],
'url' => $uinfo[0]['url'],
'contact_url' => $a->get_baseurl()."/contacts/".$uinfo[0]['cid'],
'protected' => false, #
'friends_count' => $countfriends,
'protected' => false,
'friends_count' => intval($countfriends),
'created_at' => api_date($uinfo[0]['name-date']),
'utc_offset' => "+00:00",
'time_zone' => 'UTC', //$uinfo[0]['timezone'],
'geo_enabled' => false,
'statuses_count' => intval($countitms), #XXX: fix me
'lang' => 'en', #XXX: fix me
'description' => (($profile) ? $profile[0]['pdesc'] : ''),
'followers_count' => intval($countfollowers),
'favourites_count' => intval($starred),
'contributors_enabled' => false,
'follow_request_sent' => false,
'profile_background_color' => 'cfe8f6',
'profile_text_color' => '000000',
'profile_link_color' => 'FF8500',
'profile_sidebar_fill_color' =>'AD0066',
'profile_sidebar_border_color' => 'AD0066',
'profile_background_image_url' => '',
'profile_background_tile' => false,
'profile_use_background_image' => false,
'notifications' => false,
'following' => '', #XXX: fix me
'verified' => true, #XXX: fix me
#'status' => null
);
return $ret;
}
function api_item_get_user(&$a, $item) {
// The author is our direct contact, in a conversation with us.
if(link_compare($item['url'],$item['author-link'])) {
return api_get_user($a,$item['cid']);
}
else {
// The author may be a contact of ours, but is replying to somebody else.
// Figure out if we know him/her.
$normalised = normalise_link((strlen($item['author-link'])) ? $item['author-link'] : $item['url']);
if(($normalised != 'mailbox') && (x($a->contacts[$normalised])))
return api_get_user($a,$a->contacts[$normalised]['id']);
}
// We don't know this person directly.
$ret = array(
'uid' => 0,
'id' => 0,
'name' => $item['author-name'],
'screen_name' => $item['author_name'],
'location' => '', //$uinfo[0]['default-location'],
'profile_image_url' => $item['author-avatar'],
'url' => $item['author-link'],
'contact_url' => 0,
'protected' => false, #
'friends_count' => 0,
'created_at' => '',
'utc_offset' => 0, #XXX: fix me
'time_zone' => '', //$uinfo[0]['timezone'],
'geo_enabled' => false,
'statuses_count' => $countitms, #XXX: fix me
'statuses_count' => 0,
'lang' => 'en', #XXX: fix me
'description' => '',
'followers_count' => $countfriends, #XXX: fix me
'followers_count' => 0,
'favourites_count' => 0,
'contributors_enabled' => false,
'follow_request_sent' => false,
@ -272,7 +389,6 @@
);
return $ret;
}
/**
@ -281,7 +397,7 @@
function api_xmlify($val){
if (is_bool($val)) return $val?"true":"false";
if (is_array($val)) return array_map('api_xmlify', $val);
return xmlify($val);
return xmlify((string) $val);
}
/**
@ -289,9 +405,11 @@
*/
function api_apply_template($templatename, $type, $data){
$a = get_app();
switch($type){
case "rss":
case "atom":
case "rss":
case "xml":
$data = api_xmlify($data);
$tpl = get_markup_template("api_".$templatename."_".$type.".tpl");
@ -323,20 +441,39 @@
api_register_func('api/account/verify_credentials','api_account_verify_credentials', true);
/**
* get data from $_POST or $_GET
*/
function requestdata($k){
if (isset($_POST[$k])){
return $_POST[$k];
}
if (isset($_GET[$k])){
return $_GET[$k];
}
return null;
}
// TODO - media uploads
function api_statuses_update(&$a, $type) {
if (local_user()===false) return false;
$user_info = api_get_user($a);
// convert $_POST array items to the form we use for web posts.
$_POST['body'] = urldecode($_POST['status']);
$_POST['parent'] = $_POST['in_reply_to_status_id'];
if($_POST['lat'] && $_POST['long'])
$_POST['coord'] = sprintf("%s %s",$_POST['lat'],$_POST['long']);
// logger('api_post: ' . print_r($_POST,true));
$_POST['body'] = urldecode(requestdata('status'));
$parent = requestdata('in_reply_to_status_id');
if(ctype_digit($parent))
$_POST['parent'] = $parent;
else
$_POST['parent_uri'] = $parent;
if(requestdata('lat') && requestdata('long'))
$_POST['coord'] = sprintf("%s %s",requestdata('lat'),requestdata('long'));
$_POST['profile_uid'] = local_user();
if($_POST['parent'])
if(requestdata('parent'))
$_POST['type'] = 'net-comment';
else
$_POST['type'] = 'wall';
@ -473,7 +610,7 @@
$user_info = api_get_user($a);
// get last newtork messages
$sql_extra = " AND `item`.`parent` IN ( SELECT `parent` FROM `item` WHERE `id` = `parent` ) ";
// $sql_extra = " AND `item`.`parent` IN ( SELECT `parent` FROM `item` WHERE `id` = `parent` ) ";
$r = q("SELECT `item`.*, `item`.`id` AS `item_id`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
@ -485,42 +622,13 @@
AND `contact`.`id` = `item`.`contact-id`
AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
$sql_extra
ORDER BY `item`.`created` DESC LIMIT %d ,%d ",
ORDER BY `item`.`received` DESC LIMIT %d ,%d ",
intval($user_info['uid']),
0,20
);
$ret = Array();
foreach($r as $item) {
$status_user = (($item['cid']==$user_info['id'])?$user_info: api_get_user($a,$item['cid']));
$status = array(
'created_at'=> api_date($item['created']),
'published' => datetime_convert('UTC','UTC',$item['created'],ATOM_TIME),
'updated' => datetime_convert('UTC','UTC',$item['edited'],ATOM_TIME),
'id' => $item['id'],
'text' => strip_tags(bbcode($item['body'])),
'html' => bbcode($item['body']),
'source' => (($item['app']) ? $item['app'] : 'web'),
'url' => ($item['plink']!=''?$item['plink']:$item['author-link']),
'truncated' => False,
'in_reply_to_status_id' => ($item['parent']!=$item['id']?$item['parent']:''),
'in_reply_to_user_id' => '',
'favorited' => false,
'in_reply_to_screen_name' => '',
'geo' => '',
'coordinates' => $item['coord'],
'place' => $item['location'],
'contributors' => '',
'annotations' => '',
'entities' => '',
'user' => $status_user ,
'objecttype' => $item['object-type'],
'verb' => $item['verb'],
'self' => $a->get_baseurl()."/api/statuses/show/".$ite['id'].".".$type,
'edit' => $a->get_baseurl()."/api/statuses/show/".$ite['id'].".".$type,
);
$ret[]=$status;
};
$ret = api_format_items($r,$user_info);
$data = array('$statuses' => $ret);
switch($type){
@ -533,8 +641,129 @@
}
api_register_func('api/statuses/home_timeline','api_statuses_home_timeline', true);
api_register_func('api/statuses/friends_timeline','api_statuses_home_timeline', true);
api_register_func('api/statuses/user_timeline','api_statuses_home_timeline', true);
# TODO: user_timeline should be profile view
function api_statuses_user_timeline(&$a, $type){
if (local_user()===false) return false;
$user_info = api_get_user($a);
// get last newtork messages
// $sql_extra = " AND `item`.`parent` IN ( SELECT `parent` FROM `item` WHERE `id` = `parent` ) ";
$r = q("SELECT `item`.*, `item`.`id` AS `item_id`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
`contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
FROM `item`, `contact`
WHERE `item`.`uid` = %d
AND `item`.`visible` = 1 AND `item`.`deleted` = 0
AND `item`.`wall` = 1
AND `contact`.`id` = `item`.`contact-id`
AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
$sql_extra
ORDER BY `item`.`received` DESC LIMIT %d ,%d ",
intval($user_info['uid']),
0,20
);
$ret = api_format_items($r,$user_info);
$data = array('$statuses' => $ret);
switch($type){
case "atom":
case "rss":
$data = api_rss_extra($a, $data, $user_info);
}
return api_apply_template("timeline", $type, $data);
}
api_register_func('api/statuses/user_timeline','api_statuses_user_timeline', true);
function api_favorites(&$a, $type){
if (local_user()===false) return false;
$user_info = api_get_user($a);
// get last newtork messages
// $sql_extra = " AND `item`.`parent` IN ( SELECT `parent` FROM `item` WHERE `id` = `parent` ) ";
$r = q("SELECT `item`.*, `item`.`id` AS `item_id`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
`contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
FROM `item`, `contact`
WHERE `item`.`uid` = %d
AND `item`.`visible` = 1 AND `item`.`deleted` = 0
AND `item`.`starred` = 1
AND `contact`.`id` = `item`.`contact-id`
AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
$sql_extra
ORDER BY `item`.`received` DESC LIMIT %d ,%d ",
intval($user_info['uid']),
0,20
);
$ret = api_format_items($r,$user_info);
$data = array('$statuses' => $ret);
switch($type){
case "atom":
case "rss":
$data = api_rss_extra($a, $data, $user_info);
}
return api_apply_template("timeline", $type, $data);
}
api_register_func('api/favorites','api_favorites', true);
function api_format_items($r,$user_info) {
//logger('api_format_items: ' . print_r($r,true));
//logger('api_format_items: ' . print_r($user_info,true));
$a = get_app();
$ret = Array();
foreach($r as $item) {
$status_user = (($item['cid']==$user_info['id'])?$user_info: api_item_get_user($a,$item));
$status = array(
'created_at'=> api_date($item['created']),
'published' => datetime_convert('UTC','UTC',$item['created'],ATOM_TIME),
'updated' => datetime_convert('UTC','UTC',$item['edited'],ATOM_TIME),
'id' => intval($item['id']),
'message_id' => $item['uri'],
'text' => strip_tags(bbcode($item['body'])),
'statusnet_html' => bbcode($item['body']),
'source' => (($item['app']) ? $item['app'] : 'web'),
'url' => ($item['plink']!=''?$item['plink']:$item['author-link']),
'truncated' => False,
'in_reply_to_status_id' => ($item['parent']!=$item['id']? intval($item['parent']):''),
'in_reply_to_user_id' => '',
'favorited' => $item['starred'] ? true : false,
'in_reply_to_screen_name' => '',
'geo' => '',
'coordinates' => $item['coord'],
'place' => $item['location'],
'contributors' => '',
'annotations' => '',
'entities' => '',
'user' => $status_user ,
'objecttype' => (($item['object-type']) ? $item['object-type'] : ACTIVITY_OBJ_NOTE),
'verb' => (($item['verb']) ? $item['verb'] : ACTIVITY_POST),
'self' => $a->get_baseurl()."/api/statuses/show/".$item['id'].".".$type,
'edit' => $a->get_baseurl()."/api/statuses/show/".$item['id'].".".$type,
);
$ret[]=$status;
};
return $ret;
}
function api_account_rate_limit_status(&$a,$type) {
@ -550,3 +779,93 @@
}
api_register_func('api/account/rate_limit_status','api_account_rate_limit_status',true);
function api_statusnet_config(&$a,$type) {
$name = $a->config['sitename'];
$server = $a->get_hostname();
$logo = $a->get_baseurl() . '/images/friendika-64.png';
$email = $a->config['admin_email'];
$closed = (($a->config['register_policy'] == REGISTER_CLOSED) ? 'true' : 'false');
$private = (($a->config['system']['block_public']) ? 'true' : 'false');
$textlimit = (string) (($a->config['max_import_size']) ? $a->config['max_import_size'] : 200000);
if($a->config['api_import_size'])
$texlimit = string($a->config['api_import_size']);
$ssl = (($a->config['system']['have_ssl']) ? 'true' : 'false');
$sslserver = (($ssl === 'true') ? str_replace('http:','https:',$a->get_baseurl()) : '');
$config = array(
'site' => array('name' => $name,'server' => $server, 'theme' => 'default', 'path' => '',
'logo' => $logo, 'fancy' => 'true', 'language' => 'en', 'email' => $email, 'broughtby' => '',
'broughtbyurl' => '', 'timezone' => 'UTC', 'closed' => $closed, 'inviteonly' => 'false',
'private' => $private, 'textlimit' => $textlimit, 'sslserver' => $sslserver, 'ssl' => $ssl,
'shorturllength' => '30'
),
);
return api_apply_template('config', $type, array('$config' => $config));
}
api_register_func('api/statusnet/config','api_statusnet_config',false);
function api_statusnet_version(&$a,$type) {
// liar
if($type === 'xml') {
header("Content-type: application/xml");
echo '<?xml version="1.0" encoding="UTF-8"?>' . "\r\n" . '<version>0.9.7</version>' . "\r\n";
killme();
}
elseif($type === 'json') {
header("Content-type: application/json");
echo '"0.9.7"';
killme();
}
}
api_register_func('api/statusnet/version','api_statusnet_version',false);
function api_ff_ids(&$a,$type,$qtype) {
if(! local_user())
return false;
if($qtype == 'friends')
$sql_extra = sprintf(" AND ( `rel` = %d OR `rel` = %d ) ", intval(CONTACT_IS_SHARING), intval(CONTACT_IS_FRIEND));
if($qtype == 'followers')
$sql_extra = sprintf(" AND ( `rel` = %d OR `rel` = %d ) ", intval(CONTACT_IS_FOLLOWER), intval(CONTACT_IS_FRIEND));
$r = q("SELECT id FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 $sql_extra",
intval(local_user())
);
if(is_array($r)) {
if($type === 'xml') {
header("Content-type: application/xml");
echo '<?xml version="1.0" encoding="UTF-8"?>' . "\r\n" . '<ids>' . "\r\n";
foreach($r as $rr)
echo '<id>' . $rr['id'] . '</id>' . "\r\n";
echo '</ids>' . "\r\n";
killme();
}
elseif($type === 'json') {
$ret = array();
header("Content-type: application/json");
foreach($r as $rr) $ret[] = $rr['id'];
echo json_encode($ret);
killme();
}
}
}
function api_friends_ids(&$a,$type) {
api_ff_ids($a,$type,'friends');
}
function api_followers_ids(&$a,$type) {
api_ff_ids($a,$type,'followers');
}
api_register_func('api/friends/ids','api_friends_ids',true);
api_register_func('api/followers/ids','api_followers_ids',true);

View File

@ -1,7 +1,7 @@
<?php
if(!function_exists('mime_content_type')) {
function mime_content_type($filename) {
function z_mime_content_type($filename) {
$mime_types = array(
@ -61,8 +61,9 @@ function mime_content_type($filename) {
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
);
if(strpos($filename,'.') !== false) {
$ext = strtolower(array_pop(explode('.',$filename)));
$dot = strpos($filename,'.');
if($dot !== false) {
$ext = strtolower(substr($filename,$dot+1));
if (array_key_exists($ext, $mime_types)) {
return $mime_types[$ext];
}
@ -76,5 +77,5 @@ function mime_content_type($filename) {
else {
return 'application/octet-stream';
}
}}
}

View File

@ -25,7 +25,7 @@ if((isset($_SESSION)) && (x($_SESSION,'authenticated')) && ((! (x($_POST,'auth-p
nuke_session();
info( t('Logged out.') . EOL);
goaway($a->get_baseurl());
goaway(z_root());
}
if(x($_SESSION,'visitor_id') && (! x($_SESSION,'uid'))) {
@ -45,7 +45,7 @@ if((isset($_SESSION)) && (x($_SESSION,'authenticated')) && ((! (x($_POST,'auth-p
// extra paranoia - if the IP changed, log them out
if($check && ($_SESSION['addr'] != $_SERVER['REMOTE_ADDR'])) {
nuke_session();
goaway($a->get_baseurl());
goaway(z_root());
}
$r = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1",
@ -54,7 +54,7 @@ if((isset($_SESSION)) && (x($_SESSION,'authenticated')) && ((! (x($_POST,'auth-p
if(! count($r)) {
nuke_session();
goaway($a->get_baseurl());
goaway(z_root());
}
// initialise user environment
@ -118,7 +118,7 @@ else {
if(($noid) || (strpos($temp_string,'@')) || (! validate_url($temp_string))) {
$a = get_app();
notice( t('Login failed.') . EOL);
goaway($a->get_baseurl());
goaway(z_root());
// NOTREACHED
}
@ -143,7 +143,7 @@ else {
if($a->config['register_policy'] == REGISTER_CLOSED) {
$a = get_app();
notice( t('Login failed.') . EOL);
goaway($a->get_baseurl());
goaway(z_root());
// NOTREACHED
}
// new account
@ -196,7 +196,7 @@ else {
if((! $record) || (! count($record))) {
logger('authenticate: failed login attempt: ' . trim($_POST['openid_url']));
notice( t('Login failed.') . EOL );
goaway($a->get_baseurl());
goaway(z_root());
}
$_SESSION['uid'] = $record['uid'];

218
include/config.php Normal file
View File

@ -0,0 +1,218 @@
<?php
/**
*
* Arbitrary configuration storage
* Note:
* Please do not store booleans - convert to 0/1 integer values
* The get_?config() functions return boolean false for keys that are unset,
* and this could lead to subtle bugs.
*
* There are a few places in the code (such as the admin panel) where boolean
* configurations need to be fixed as of 10/08/2011.
*/
// retrieve a "family" of config variables from database to cached storage
if(! function_exists('load_config')) {
function load_config($family) {
global $a;
$r = q("SELECT * FROM `config` WHERE `cat` = '%s'",
dbesc($family)
);
if(count($r)) {
foreach($r as $rr) {
$k = $rr['k'];
if ($rr['cat'] === 'config') {
$a->config[$k] = $rr['v'];
} else {
$a->config[$family][$k] = $rr['v'];
}
}
}
}}
// get a particular config variable given the family name
// and key. Returns false if not set.
// $instore is only used by the set_config function
// to determine if the key already exists in the DB
// If a key is found in the DB but doesn't exist in
// local config cache, pull it into the cache so we don't have
// to hit the DB again for this item.
if(! function_exists('get_config')) {
function get_config($family, $key, $instore = false) {
global $a;
if(! $instore) {
if(isset($a->config[$family][$key])) {
if($a->config[$family][$key] === '!<unset>!') {
return false;
}
return $a->config[$family][$key];
}
}
$ret = q("SELECT `v` FROM `config` WHERE `cat` = '%s' AND `k` = '%s' LIMIT 1",
dbesc($family),
dbesc($key)
);
if(count($ret)) {
// manage array value
$val = (preg_match("|^a:[0-9]+:{.*}$|", $ret[0]['v'])?unserialize( $ret[0]['v']):$ret[0]['v']);
$a->config[$family][$key] = $val;
return $val;
}
else {
$a->config[$family][$key] = '!<unset>!';
}
return false;
}}
// Store a config value ($value) in the category ($family)
// under the key ($key)
// Return the value, or false if the database update failed
if(! function_exists('set_config')) {
function set_config($family,$key,$value) {
global $a;
// manage array value
$dbvalue = (is_array($value)?serialize($value):$value);
if(get_config($family,$key,true) === false) {
$a->config[$family][$key] = $value;
$ret = q("INSERT INTO `config` ( `cat`, `k`, `v` ) VALUES ( '%s', '%s', '%s' ) ",
dbesc($family),
dbesc($key),
dbesc($dbvalue)
);
if($ret)
return $value;
return $ret;
}
$ret = q("UPDATE `config` SET `v` = '%s' WHERE `cat` = '%s' AND `k` = '%s' LIMIT 1",
dbesc($dbvalue),
dbesc($family),
dbesc($key)
);
$a->config[$family][$key] = $value;
if($ret)
return $value;
return $ret;
}}
if(! function_exists('load_pconfig')) {
function load_pconfig($uid,$family) {
global $a;
$r = q("SELECT * FROM `pconfig` WHERE `cat` = '%s' AND `uid` = %d",
dbesc($family),
intval($uid)
);
if(count($r)) {
foreach($r as $rr) {
$k = $rr['k'];
$a->config[$uid][$family][$k] = $rr['v'];
}
}
}}
if(! function_exists('get_pconfig')) {
function get_pconfig($uid,$family, $key, $instore = false) {
global $a;
if(! $instore) {
if(isset($a->config[$uid][$family][$key])) {
if($a->config[$uid][$family][$key] === '!<unset>!') {
return false;
}
return $a->config[$uid][$family][$key];
}
}
$ret = q("SELECT `v` FROM `pconfig` WHERE `uid` = %d AND `cat` = '%s' AND `k` = '%s' LIMIT 1",
intval($uid),
dbesc($family),
dbesc($key)
);
if(count($ret)) {
$a->config[$uid][$family][$key] = $ret[0]['v'];
return $ret[0]['v'];
}
else {
$a->config[$uid][$family][$key] = '!<unset>!';
}
return false;
}}
if(! function_exists('del_config')) {
function del_config($family,$key) {
global $a;
if(x($a->config[$family],$key))
unset($a->config[$family][$key]);
$ret = q("DELETE FROM `config` WHERE `cat` = '%s' AND `k` = '%s' LIMIT 1",
dbesc($cat),
dbesc($key)
);
return $ret;
}}
// Same as above functions except these are for personal config storage and take an
// additional $uid argument.
if(! function_exists('set_pconfig')) {
function set_pconfig($uid,$family,$key,$value) {
global $a;
if(get_pconfig($uid,$family,$key,true) === false) {
$a->config[$uid][$family][$key] = $value;
$ret = q("INSERT INTO `pconfig` ( `uid`, `cat`, `k`, `v` ) VALUES ( %d, '%s', '%s', '%s' ) ",
intval($uid),
dbesc($family),
dbesc($key),
dbesc($value)
);
if($ret)
return $value;
return $ret;
}
$ret = q("UPDATE `pconfig` SET `v` = '%s' WHERE `uid` = %d AND `cat` = '%s' AND `k` = '%s' LIMIT 1",
dbesc($value),
intval($uid),
dbesc($family),
dbesc($key)
);
$a->config[$uid][$family][$key] = $value;
if($ret)
return $value;
return $ret;
}}
if(! function_exists('del_pconfig')) {
function del_pconfig($uid,$family,$key) {
global $a;
if(x($a->config[$uid][$family],$key))
unset($a->config[$uid][$family][$key]);
$ret = q("DELETE FROM `pconfig` WHERE `uid` = %d AND `cat` = '%s' AND `k` = '%s' LIMIT 1",
intval($uid),
dbesc($family),
dbesc($key)
);
return $ret;
}}

View File

@ -283,14 +283,14 @@ function conversation(&$a, $items, $mode, $update) {
continue;
$toplevelpost = (($item['id'] == $item['parent']) ? true : false);
$toplevelprivate = false;
// Take care of author collapsing and comment collapsing
// If a single author has more than 3 consecutive top-level posts, squash the remaining ones.
// If there are more than two comments, squash all but the last 2.
if($toplevelpost) {
$toplevelprivate = (($toplevelpost && $item['private']) ? true : false);
$item_writeable = (($item['writable'] || $item['self']) ? true : false);
if($blowhard == $item['cid'] && (! $item['self']) && ($mode != 'profile') && ($mode != 'notes')) {
@ -312,9 +312,12 @@ function conversation(&$a, $items, $mode, $update) {
$comments_seen = 0;
$comments_collapsed = false;
}
else
else {
// prevent private email from leaking into public conversation
if((! $toplevelpost) && (! toplevelprivate) && ($item['private']) && ($profile_owner != local_user()))
continue;
$comments_seen ++;
}
$override_comment_box = ((($page_writeable) && ($item_writeable)) ? true : false);
$show_comment_box = ((($page_writeable) && ($item_writeable) && ($comments_seen == $comments[$item['parent']])) ? true : false);
@ -347,7 +350,7 @@ function conversation(&$a, $items, $mode, $update) {
if(($toplevelpost) && (! $item['self']) && ($mode !== 'profile')) {
if($item['type'] === 'wall') {
if($item['wall']) {
// On the network page, I am the owner. On the display page it will be the profile owner.
// This will have been stored in $a->page_contact by our calling page.
@ -359,7 +362,7 @@ function conversation(&$a, $items, $mode, $update) {
$template = $wallwall;
$commentww = 'ww';
}
if(($item['type'] === 'remote') && (strlen($item['owner-link'])) && ($item['owner-link'] != $item['author-link'])) {
if((! $item['wall']) && (strlen($item['owner-link'])) && ($item['owner-link'] != $item['author-link'])) {
// Could be anybody.
@ -444,7 +447,7 @@ function conversation(&$a, $items, $mode, $update) {
$profile_link = '';
$normalised = normalise_link((strlen($item['author-link'])) ? $item['author-link'] : $item['url']);
if(($normalised != 'mailbox') && (x($a->contacts[$normalised])))
if(($normalised != 'mailbox') && (x($a->contacts,$normalised)))
$profile_avatar = $a->contacts[$normalised]['thumb'];
else
$profile_avatar = (((strlen($item['author-avatar'])) && $diff_author) ? $item['author-avatar'] : $thumb);
@ -533,33 +536,6 @@ function conversation(&$a, $items, $mode, $update) {
return $o;
}
if(! function_exists('load_contact_links')) {
function load_contact_links($uid) {
$a = get_app();
$ret = array();
if(! $uid || x($a->contacts,'empty'))
return;
$r = q("SELECT `id`,`network`,`url`,`thumb` FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 ",
intval($uid)
);
if(count($r)) {
foreach($r as $rr){
$url = normalise_link($rr['url']);
$ret[$url] = $rr;
}
}
else
$ret['empty'] = true;
$a->contacts = $ret;
return;
}}
function best_link_url($item,&$sparkle) {
$a = get_app();

43
include/cronhooks.php Normal file
View File

@ -0,0 +1,43 @@
<?php
require_once("boot.php");
function cronhooks_run($argv, $argc){
global $a, $db;
if(is_null($a)) {
$a = new App;
}
if(is_null($db)) {
@include(".htconfig.php");
require_once("dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
};
require_once('include/session.php');
require_once('include/datetime.php');
load_config('config');
load_config('system');
$a->set_baseurl(get_config('system','url'));
load_hooks();
logger('cronhooks: start');
$d = datetime_convert();
call_hooks('cron', $d);
return;
}
if (array_search(__file__,get_included_files())===0){
cronhooks_run($argv,$argc);
killme();
}

184
include/crypto.php Normal file
View File

@ -0,0 +1,184 @@
<?php
require_once('library/ASNValue.class.php');
require_once('library/asn1.php');
function rsa_sign($data,$key) {
$sig = '';
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
openssl_sign($data,$sig,$key,'sha256');
}
else {
if(strlen($key) < 1024 || extension_loaded('gmp')) {
require_once('library/phpsec/Crypt/RSA.php');
$rsa = new CRYPT_RSA();
$rsa->signatureMode = CRYPT_RSA_SIGNATURE_PKCS1;
$rsa->setHash('sha256');
$rsa->loadKey($key);
$sig = $rsa->sign($data);
}
else {
logger('rsa_sign: insecure algorithm used. Please upgrade PHP to 5.3');
openssl_private_encrypt(hex2bin('3031300d060960864801650304020105000420') . hash('sha256',$data,true), $sig, $key);
}
}
return $sig;
}
function rsa_verify($data,$sig,$key) {
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
$verify = openssl_verify($data,$sig,$key,'sha256');
}
else {
if(strlen($key) <= 300 || extension_loaded('gmp')) {
require_once('library/phpsec/Crypt/RSA.php');
$rsa = new CRYPT_RSA();
$rsa->signatureMode = CRYPT_RSA_SIGNATURE_PKCS1;
$rsa->setHash('sha256');
$rsa->loadKey($key);
$verify = $rsa->verify($data,$sig);
}
else {
// fallback sha256 verify for PHP < 5.3 and large key lengths
$rawsig = '';
openssl_public_decrypt($sig,$rawsig,$key);
$verify = (($rawsig && substr($rawsig,-32) === hash('sha256',$data,true)) ? true : false);
}
}
return $verify;
}
function DerToPem($Der, $Private=false)
{
//Encode:
$Der = base64_encode($Der);
//Split lines:
$lines = str_split($Der, 65);
$body = implode("\n", $lines);
//Get title:
$title = $Private? 'RSA PRIVATE KEY' : 'PUBLIC KEY';
//Add wrapping:
$result = "-----BEGIN {$title}-----\n";
$result .= $body . "\n";
$result .= "-----END {$title}-----\n";
return $result;
}
function DerToRsa($Der)
{
//Encode:
$Der = base64_encode($Der);
//Split lines:
$lines = str_split($Der, 65);
$body = implode("\n", $lines);
//Get title:
$title = 'RSA PUBLIC KEY';
//Add wrapping:
$result = "-----BEGIN {$title}-----\n";
$result .= $body . "\n";
$result .= "-----END {$title}-----\n";
return $result;
}
function pkcs8_encode($Modulus,$PublicExponent) {
//Encode key sequence
$modulus = new ASNValue(ASNValue::TAG_INTEGER);
$modulus->SetIntBuffer($Modulus);
$publicExponent = new ASNValue(ASNValue::TAG_INTEGER);
$publicExponent->SetIntBuffer($PublicExponent);
$keySequenceItems = array($modulus, $publicExponent);
$keySequence = new ASNValue(ASNValue::TAG_SEQUENCE);
$keySequence->SetSequence($keySequenceItems);
//Encode bit string
$bitStringValue = $keySequence->Encode();
$bitStringValue = chr(0x00) . $bitStringValue; //Add unused bits byte
$bitString = new ASNValue(ASNValue::TAG_BITSTRING);
$bitString->Value = $bitStringValue;
//Encode body
$bodyValue = "\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00" . $bitString->Encode();
$body = new ASNValue(ASNValue::TAG_SEQUENCE);
$body->Value = $bodyValue;
//Get DER encoded public key:
$PublicDER = $body->Encode();
return $PublicDER;
}
function pkcs1_encode($Modulus,$PublicExponent) {
//Encode key sequence
$modulus = new ASNValue(ASNValue::TAG_INTEGER);
$modulus->SetIntBuffer($Modulus);
$publicExponent = new ASNValue(ASNValue::TAG_INTEGER);
$publicExponent->SetIntBuffer($PublicExponent);
$keySequenceItems = array($modulus, $publicExponent);
$keySequence = new ASNValue(ASNValue::TAG_SEQUENCE);
$keySequence->SetSequence($keySequenceItems);
//Encode bit string
$bitStringValue = $keySequence->Encode();
return $bitStringValue;
}
function metopem($m,$e) {
$der = pkcs8_encode($m,$e);
$key = DerToPem($der,false);
return $key;
}
function pubrsatome($key,&$m,&$e) {
require_once('library/asn1.php');
require_once('include/salmon.php');
$lines = explode("\n",$key);
unset($lines[0]);
unset($lines[count($lines)]);
$x = base64_decode(implode('',$lines));
$r = ASN_BASE::parseASNString($x);
$m = base64url_decode($r[0]->asnData[0]->asnData);
$e = base64url_decode($r[0]->asnData[1]->asnData);
}
function rsatopem($key) {
pubrsatome($key,$m,$e);
return(metopem($m,$e));
}
function pemtorsa($key) {
pemtome($key,$m,$e);
return(metorsa($m,$e));
}
function pemtome($key,&$m,&$e) {
require_once('include/salmon.php');
$lines = explode("\n",$key);
unset($lines[0]);
unset($lines[count($lines)]);
$x = base64_decode(implode('',$lines));
$r = ASN_BASE::parseASNString($x);
$m = base64url_decode($r[0]->asnData[1]->asnData[0]->asnData[0]->asnData);
$e = base64url_decode($r[0]->asnData[1]->asnData[0]->asnData[1]->asnData);
}
function metorsa($m,$e) {
$der = pkcs1_encode($m,$e);
$key = DerToRsa($der);
return $key;
}
function salmon_key($pubkey) {
pemtome($pubkey,$m,$e);
return 'RSA' . '.' . base64url_encode($m,true) . '.' . base64url_encode($e,true) ;
}

View File

@ -84,12 +84,47 @@ function datetime_convert($from = 'UTC', $to = 'UTC', $s = 'now', $fmt = "Y-m-d
function dob($dob) {
list($year,$month,$day) = sscanf($dob,'%4d-%2d-%2d');
$y = datetime_convert('UTC',date_default_timezone_get(),'now','Y');
$o = datesel('',1920,$y,true,$year,$month,$day);
$f = get_config('system','birthday_input_format');
if(! $f)
$f = 'ymd';
$o = datesel($f,'',1920,$y,true,$year,$month,$day);
return $o;
}
function datesel_format($f) {
$o = '';
if(strlen($f)) {
for($x = 0; $x < strlen($f); $x ++) {
switch($f[$x]) {
case 'y':
if(strlen($o))
$o .= '-';
$o .= t('year');
break;
case 'm':
if(strlen($o))
$o .= '-';
$o .= t('month');
break;
case 'd':
if(strlen($o))
$o .= '-';
$o .= t('day');
break;
default:
break;
}
}
}
return $o;
}
// returns a date selector.
// $f = format string, e.g. 'ymd' or 'mdy'
// $pre = prefix (if needed) for HTML name and class fields
// $ymin = first year shown in selector dropdown
// $ymax = last year shown in selector dropdown
@ -99,41 +134,53 @@ function dob($dob) {
// $d = already selected day
if(! function_exists('datesel')) {
function datesel($pre,$ymin,$ymax,$allow_blank,$y,$m,$d) {
function datesel($f,$pre,$ymin,$ymax,$allow_blank,$y,$m,$d) {
$o = '';
$o .= "<select name=\"{$pre}year\" class=\"{$pre}year\" size=\"1\">";
if($allow_blank) {
$sel = (($y == '0000') ? " selected=\"selected\" " : "");
$o .= "<option value=\"0000\" $sel ></option>";
}
if($ymax > $ymin) {
for($x = $ymax; $x >= $ymin; $x --) {
$sel = (($x == $y) ? " selected=\"selected\" " : "");
$o .= "<option value=\"$x\" $sel>$x</option>";
if(strlen($f)) {
for($z = 0; $z < strlen($f); $z ++) {
if($f[$z] === 'y') {
$o .= "<select name=\"{$pre}year\" class=\"{$pre}year\" size=\"1\">";
if($allow_blank) {
$sel = (($y == '0000') ? " selected=\"selected\" " : "");
$o .= "<option value=\"0000\" $sel ></option>";
}
if($ymax > $ymin) {
for($x = $ymax; $x >= $ymin; $x --) {
$sel = (($x == $y) ? " selected=\"selected\" " : "");
$o .= "<option value=\"$x\" $sel>$x</option>";
}
}
else {
for($x = $ymax; $x <= $ymin; $x ++) {
$sel = (($x == $y) ? " selected=\"selected\" " : "");
$o .= "<option value=\"$x\" $sel>$x</option>";
}
}
}
elseif($f[$z] == 'm') {
$o .= "</select> <select name=\"{$pre}month\" class=\"{$pre}month\" size=\"1\">";
for($x = (($allow_blank) ? 0 : 1); $x <= 12; $x ++) {
$sel = (($x == $m) ? " selected=\"selected\" " : "");
$y = (($x) ? $x : '');
$o .= "<option value=\"$x\" $sel>$y</option>";
}
}
elseif($f[$z] == 'd') {
$o .= "</select> <select name=\"{$pre}day\" class=\"{$pre}day\" size=\"1\">";
for($x = (($allow_blank) ? 0 : 1); $x <= 31; $x ++) {
$sel = (($x == $d) ? " selected=\"selected\" " : "");
$y = (($x) ? $x : '');
$o .= "<option value=\"$x\" $sel>$y</option>";
}
}
}
}
else {
for($x = $ymax; $x <= $ymin; $x ++) {
$sel = (($x == $y) ? " selected=\"selected\" " : "");
$o .= "<option value=\"$x\" $sel>$x</option>";
}
}
$o .= "</select> <select name=\"{$pre}month\" class=\"{$pre}month\" size=\"1\">";
for($x = (($allow_blank) ? 0 : 1); $x <= 12; $x ++) {
$sel = (($x == $m) ? " selected=\"selected\" " : "");
$y = (($x) ? $x : '');
$o .= "<option value=\"$x\" $sel>$y</option>";
}
$o .= "</select> <select name=\"{$pre}day\" class=\"{$pre}day\" size=\"1\">";
for($x = (($allow_blank) ? 0 : 1); $x <= 31; $x ++) {
$sel = (($x == $d) ? " selected=\"selected\" " : "");
$y = (($x) ? $x : '');
$o .= "<option value=\"$x\" $sel>$y</option>";
}
$o .= "</select>";
return $o;

815
include/diaspora.php Normal file
View File

@ -0,0 +1,815 @@
<?php
require_once('include/crypto.php');
require_once('include/items.php');
function get_diaspora_key($uri) {
$key = '';
logger('Fetching diaspora key for: ' . $uri);
$arr = lrdd($uri);
if(is_array($arr)) {
foreach($arr as $a) {
if($a['@attributes']['rel'] === 'diaspora-public-key') {
$key = base64_decode($a['@attributes']['href']);
}
}
}
else {
return '';
}
if($key)
return rsatopem($key);
return '';
}
function diaspora_base_message($type,$data) {
$tpl = get_markup_template('diaspora_' . $type . '.tpl');
if(! $tpl)
return '';
return replace_macros($tpl,$data);
}
function diaspora_msg_build($msg,$user,$contact,$prvkey,$pubkey) {
$a = get_app();
$inner_aes_key = random_string(32);
$b_inner_aes_key = base64_encode($inner_aes_key);
$inner_iv = random_string(32);
$b_inner_iv = base64_encode($inner_iv);
$outer_aes_key = random_string(32);
$b_outer_aes_key = base64_encode($outer_aes_key);
$outer_iv = random_string(32);
$b_outer_iv = base64_encode($outer_iv);
$handle = 'acct:' . $user['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3);
$padded_data = pkcs5_pad($msg,16);
$inner_encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $inner_aes_key, $padded_data, MCRYPT_MODE_CBC, $inner_iv);
$b64_data = base64_encode($inner_encrypted);
$b64url_data = base64url_encode($b64_data);
$b64url_stripped = str_replace(array("\n","\r"," ","\t"),array('','','',''),$b64url_data);
$lines = str_split($b64url_stripped,60);
$data = implode("\n",$lines);
$data = $data . (($data[-1] != "\n") ? "\n" : '') ;
$type = 'application/atom+xml';
$encoding = 'base64url';
$alg = 'RSA-SHA256';
$signable_data = $data . '.' . base64url_encode($type) . "\n" . '.'
. base64url_encode($encoding) . "\n" . '.' . base64url_encode($alg) . "\n";
$signature = rsa_sign($signable_data,$prvkey);
$sig = base64url_encode($signature);
$decrypted_header = <<< EOT
<decrypted_header>
<iv>$b_inner_iv</iv>
<aes_key>$b_inner_aes_key</aes_key>
<author>
<name>{$user['username']}</name>
<uri>$handle</uri>
</author>
</decrypted_header>
EOT;
$decrypted_header = pkcs5_pad($decrypted_header,16);
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $outer_aes_key, $decrypted_header, MCRYPT_MODE_CBC, $outer_iv);
$outer_json = json_encode(array('iv' => $b_outer_iv,'key' => $b_outer_aes_key));
$encrypted_outer_key_bundle = '';
openssl_public_encrypt($outer_json,$encrypted_outer_key_bundle,$pubkey);
$b64_encrypted_outer_key_bundle = base64_encode($encrypted_outer_key_bundle);
$encrypted_header_json_object = json_encode(array('aes_key' => base64_encode($encrypted_outer_key_bundle),
'ciphertext' => base64_encode($ciphertext)));
$encrypted_header = '<encrypted_header>' . base64_encode($encrypted_header_json_object) . '</encrypted_header>';
$magic_env = <<< EOT
<?xml version='1.0' encoding='UTF-8'?>
<entry xmlns='http://www.w3.org/2005/Atom'>
$encrypted_header
<me:env xmlns:me="http://salmon-protocol.org/ns/magic-env">
<me:encoding>base64url</me:encoding>
<me:alg>RSA-SHA256</me:alg>
<me:data type="application/atom+xml">$data</me:data>
<me:sig>$sig</me:sig>
</me:env>
</entry>
EOT;
return $magic_env;
}
/**
*
* diaspora_decode($importer,$xml)
* array $importer -> from user table
* string $xml -> urldecoded Diaspora salmon
*
* Returns array
* 'message' -> decoded Diaspora XML message
* 'author' -> author diaspora handle
* 'key' -> author public key (converted to pkcs#8)
*
* Author and key are used elsewhere to save a lookup for verifying replies and likes
*/
function diaspora_decode($importer,$xml) {
$basedom = parse_xml_string($xml);
$atom = $basedom->children(NAMESPACE_ATOM1);
// Diaspora devs: This is kind of sucky - 'encrypted_header' does not belong in the atom namespace
$encrypted_header = json_decode(base64_decode($atom->encrypted_header));
$encrypted_aes_key_bundle = base64_decode($encrypted_header->aes_key);
$ciphertext = base64_decode($encrypted_header->ciphertext);
$outer_key_bundle = '';
openssl_private_decrypt($encrypted_aes_key_bundle,$outer_key_bundle,$importer['prvkey']);
$j_outer_key_bundle = json_decode($outer_key_bundle);
$outer_iv = base64_decode($j_outer_key_bundle->iv);
$outer_key = base64_decode($j_outer_key_bundle->key);
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $outer_key, $ciphertext, MCRYPT_MODE_CBC, $outer_iv);
$decrypted = pkcs5_unpad($decrypted);
/**
* $decrypted now contains something like
*
* <decrypted_header>
* <iv>8e+G2+ET8l5BPuW0sVTnQw==</iv>
* <aes_key>UvSMb4puPeB14STkcDWq+4QE302Edu15oaprAQSkLKU=</aes_key>
* <author>
* <name>Ryan Hughes</name>
* <uri>acct:galaxor@diaspora.pirateship.org</uri>
* </author>
* </decrypted_header>
*/
logger('decrypted: ' . $decrypted);
$idom = parse_xml_string($decrypted,false);
$inner_iv = base64_decode($idom->iv);
$inner_aes_key = base64_decode($idom->aes_key);
$author_link = str_replace('acct:','',$idom->author->uri);
$dom = $basedom->children(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 ');
http_status_exit(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);
// Add back the 60 char linefeeds
// Diaspora devs: This completely violates the entire principle of salmon magic signatures,
// which was to have a message signing format that was completely ambivalent to linefeeds
// and transport whitespace mangling, and base64 wrapping rules. Guess what? PHP and Ruby
// use different linelengths for base64 output.
$lines = str_split($data,60);
$data = implode("\n",$lines);
// 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;
// Diaspora devs: I can't even begin to tell you how sucky this is. Read the freaking spec.
$signed_data = $data . (($data[-1] != "\n") ? "\n" : '') . '.' . base64url_encode($type) . "\n" . '.' . base64url_encode($encoding) . "\n" . '.' . base64url_encode($alg) . "\n";
// decode the data
$data = base64url_decode($data);
// Now pull out the inner encrypted blob
$inner_encrypted = base64_decode($data);
$inner_decrypted =
$inner_decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $inner_aes_key, $inner_encrypted, MCRYPT_MODE_CBC, $inner_iv);
$inner_decrypted = pkcs5_unpad($inner_decrypted);
if(! $author_link) {
logger('mod-diaspora: Could not retrieve author URI.');
http_status_exit(400);
}
// Once we have the author URI, go to the web and try to find their public key
// *** or look it up locally ***
logger('mod-diaspora: Fetching key for ' . $author_link );
// Get diaspora public key (pkcs#1) and convert to pkcs#8
$key = get_diaspora_key($author_link);
if(! $key) {
logger('mod-diaspora: Could not retrieve author key.');
http_status_exit(400);
}
$verify = rsa_verify($signed_data,$signature,$key);
if(! $verify) {
logger('mod-diaspora: Message did not verify. Discarding.');
http_status_exit(400);
}
logger('mod-diaspora: Message verified.');
return array('message' => $inner_decrypted, 'author' => $author_link, 'key' => $key);
}
function diaspora_get_contact_by_handle($uid,$handle) {
$r = q("SELECT * FROM `contact` WHERE `network` = '%s' AND `uid` = %d AND `addr` = '%s' LIMIT 1",
dbesc(NETWORK_DIASPORA),
intval($uid),
dbesc($handle)
);
if($r && count($r))
return $r[0];
return false;
}
function find_person_by_handle($handle) {
// we don't care about the uid, we just want to save an expensive webfinger probe
$r = q("select * from contact where network = '%s' and addr = '%s' LIMIT 1",
dbesc(NETWORK_DIASPORA),
dbesc($handle)
);
if(count($r))
return $r[0];
$r = probe_url($handle);
// need to cached this, perhaps in fcontact
if(count($r))
return ($r);
return false;
}
function diaspora_request($importer,$xml) {
$sender_handle = unxmlify($xml->sender_handle);
$recipient_handle = unxmlify($xml->recipient_handle);
if(! $sender_handle || ! $recipient_handle)
return;
$contact = diaspora_get_contact_by_handle($importer['uid'],$sender_handle);
if($contact) {
// perhaps we were already sharing with this person. Now they're sharing with us.
// That makes us friends.
if($contact['rel'] == CONTACT_IS_FOLLOWER) {
q("UPDATE `contact` SET `rel` = %d WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval(CONTACT_IS_FRIEND),
intval($contact['id']),
intval($importer['uid'])
);
}
// send notification?
return;
}
require_once('include/Scrape.php');
$ret = probe_url($sender_handle);
if((! count($ret)) || ($ret['network'] != NETWORK_DIASPORA)) {
logger('diaspora_request: Cannot resolve diaspora handle ' . $sender_handle . ' for ' . $recipient_handle);
return;
}
$r = q("INSERT INTO `contact` (`uid`, `network`,`addr`,`created`,`url`,`name`,`nick`,`photo`,`pubkey`,`notify`,`poll`,`blocked`,`priority`)
VALUES ( %d, '%s', '%s', '%s','%s','%s','%s','%s','%s','%s','%s',%d,%d) ",
intval($importer['uid']),
dbesc($ret['network']),
dbesc($ret['addr']),
datetime_convert(),
dbesc($ret['url']),
dbesc($ret['name']),
dbesc($ret['nick']),
dbesc($ret['photo']),
dbesc($ret['pubkey']),
dbesc($ret['notify']),
dbesc($ret['poll']),
1,
2
);
// find the contact record we just created
$contact_record = diaspora_get_contact_by_handle($importer['uid'],$sender_handle);
$hash = random_string() . (string) time(); // Generate a confirm_key
if($contact_record) {
$ret = q("INSERT INTO `intro` ( `uid`, `contact-id`, `blocked`, `knowyou`, `note`, `hash`, `datetime`,`blocked`)
VALUES ( %d, %d, 1, %d, '%s', '%s', '%s', 0 )",
intval($importer['uid']),
intval($contact_record['id']),
0,
dbesc( t('Sharing notification from Diaspora network')),
dbesc($hash),
dbesc(datetime_convert())
);
}
return;
}
function diaspora_post($importer,$xml) {
$guid = notags(unxmlify($xml->guid));
$diaspora_handle = notags(unxmlify($xml->diaspora_handle));
$contact = diaspora_get_contact_by_handle($importer['uid'],$diaspora_handle);
if(! $contact)
return;
if(($contact['rel'] == CONTACT_IS_FOLLOWER) || ($contact['blocked']) || ($contact['readonly'])) {
logger('diaspora_post: Ignoring this author.');
http_status_exit(202);
// NOTREACHED
}
$message_id = $diaspora_handle . ':' . $guid;
$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `guid` = '%s' LIMIT 1",
intval($importer['uid']),
dbesc($message_id),
dbesc($guid)
);
if(count($r))
return;
// allocate a guid on our system - we aren't fixing any collisions.
// we're ignoring them
$g = q("select * from guid where guid = '%s' limit 1",
dbesc($guid)
);
if(! count($g)) {
q("insert into guid ( guid ) values ( '%s' )",
dbesc($guid)
);
}
$created = unxmlify($xml->created_at);
$private = ((unxmlify($xml->public) == 'false') ? 1 : 0);
$body = unxmlify($xml->raw_message);
require_once('library/HTMLPurifier.auto.php');
require_once('include/html2bbcode.php');
$maxlen = get_max_import_size();
if($maxlen && (strlen($body) > $maxlen))
$body = substr($body,0, $maxlen);
if((strpos($body,'<') !== false) || (strpos($body,'>') !== false)) {
$body = preg_replace('#<object[^>]+>.+?' . 'http://www.youtube.com/((?:v|cp)/[A-Za-z0-9\-_=]+).+?</object>#s',
'[youtube]$1[/youtube]', $body);
$body = preg_replace('#<iframe[^>].+?' . 'http://www.youtube.com/embed/([A-Za-z0-9\-_=]+).+?</iframe>#s',
'[youtube]$1[/youtube]', $body);
$body = oembed_html2bbcode($body);
$config = HTMLPurifier_Config::createDefault();
$config->set('Cache.DefinitionImpl', null);
$purifier = new HTMLPurifier($config);
$body = $purifier->purify($body);
$body = html2bbcode($body);
}
$datarray = array();
$datarray['uid'] = $importer['uid'];
$datarray['contact-id'] = $contact['id'];
$datarray['wall'] = 0;
$datarray['guid'] = $guid;
$datarray['uri'] = $datarray['parent-uri'] = $message_id;
$datarray['created'] = $datarray['edited'] = datetime_convert('UTC','UTC',$created);
$datarray['private'] = $private;
$datarray['parent'] = 0;
$datarray['owner-name'] = $contact['name'];
$datarray['owner-link'] = $contact['url'];
$datarray['owner-avatar'] = $contact['thumb'];
$datarray['author-name'] = $contact['name'];
$datarray['author-link'] = $contact['url'];
$datarray['author-avatar'] = $contact['thumb'];
$datarray['body'] = $body;
item_store($datarray);
return;
}
function diaspora_comment($importer,$xml,$msg) {
$guid = notags(unxmlify($xml->guid));
$parent_guid = notags(unxmlify($xml->parent_guid));
$diaspora_handle = notags(unxmlify($xml->diaspora_handle));
$target_type = notags(unxmlify($xml->target_type));
$text = unxmlify($xml->text);
$author_signature = notags(unxmlify($xml->author_signature));
$parent_author_signature = (($xml->parent_author_signature) ? notags(unxmlify($xml->parent_author_signature)) : '');
$text = $xml->text;
$contact = diaspora_get_contact_by_handle($importer['uid'],$msg['author']);
if(! $contact)
return;
if(($contact['rel'] == CONTACT_IS_FOLLOWER) || ($contact['blocked']) || ($contact['readonly'])) {
logger('diaspora_comment: Ignoring this author.');
http_status_exit(202);
// NOTREACHED
}
$r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
intval($importer['uid']),
dbesc($parent_guid)
);
if(! count($r)) {
logger('diaspora_comment: parent item not found: ' . $guid);
return;
}
$parent_item = $r[0];
$author_signed_data = $guid . ';' . $parent_guid . ';' . $text . ';' . $diaspora_handle;
$author_signature = base64_decode($author_signature);
if(stricmp($diaspora_handle,$msg['author']) == 0) {
$person = $contact;
$key = $msg['key'];
}
else {
$person = find_person_by_handle($diaspora_handle);
if(is_array($person) && x($person,'pubkey'))
$key = $person['pubkey'];
else {
logger('diaspora_comment: unable to find author details');
return;
}
}
if(! rsa_verify($author_signed_data,$author_signature,$key)) {
logger('diaspora_comment: verification failed.');
return;
}
if($parent_author_signature) {
$owner_signed_data = $guid . ';' . $parent_guid . ';' . $text . ';' . $msg['author'];
$parent_author_signature = base64_decode($parent_author_signature);
$key = $msg['key'];
if(! rsa_verify($owner_signed_data,$parent_author_signature,$key)) {
logger('diaspora_comment: owner verification failed.');
return;
}
}
// Phew! Everything checks out. Now create an item.
require_once('library/HTMLPurifier.auto.php');
require_once('include/html2bbcode.php');
$body = $text;
$maxlen = get_max_import_size();
if($maxlen && (strlen($body) > $maxlen))
$body = substr($body,0, $maxlen);
if((strpos($body,'<') !== false) || (strpos($body,'>') !== false)) {
$body = preg_replace('#<object[^>]+>.+?' . 'http://www.youtube.com/((?:v|cp)/[A-Za-z0-9\-_=]+).+?</object>#s',
'[youtube]$1[/youtube]', $body);
$body = preg_replace('#<iframe[^>].+?' . 'http://www.youtube.com/embed/([A-Za-z0-9\-_=]+).+?</iframe>#s',
'[youtube]$1[/youtube]', $body);
$body = oembed_html2bbcode($body);
$config = HTMLPurifier_Config::createDefault();
$config->set('Cache.DefinitionImpl', null);
$purifier = new HTMLPurifier($config);
$body = $purifier->purify($body);
$body = html2bbcode($body);
}
$message_id = $diaspora_handle . ':' . $guid;
$datarray = array();
$datarray['uid'] = $importer['uid'];
$datarray['contact-id'] = $contact['id'];
$datarray['wall'] = $parent_item['wall'];
$datarray['gravity'] = GRAVITY_COMMENT;
$datarray['guid'] = $guid;
$datarray['uri'] = $message_id;
$datarray['parent-uri'] = $parent_item['uri'];
// No timestamps for comments? OK, we'll the use current time.
$datarray['created'] = $datarray['edited'] = datetime_convert();
$datarray['private'] = $parent_item['private'];
$datarray['owner-name'] = $contact['name'];
$datarray['owner-link'] = $contact['url'];
$datarray['owner-avatar'] = $contact['thumb'];
$datarray['author-name'] = $person['name'];
$datarray['author-link'] = $person['url'];
$datarray['author-avatar'] = ((x($person,'thumb')) ? $person['thumb'] : $person['photo']);
$datarray['body'] = $body;
item_store($datarray);
return;
}
function diaspora_like($importer,$xml,$msg) {
$guid = notags(unxmlify($xml->guid));
$parent_guid = notags(unxmlify($xml->parent_guid));
$diaspora_handle = notags(unxmlify($xml->diaspora_handle));
$target_type = notags(unxmlify($xml->target_type));
$positive = notags(unxmlify($xml->positive));
$author_signature = notags(unxmlify($xml->author_signature));
$parent_author_signature = (($xml->parent_author_signature) ? notags(unxmlify($xml->parent_author_signature)) : '');
// likes on comments not supported here and likes on photos not supported by Diaspora
if($target_type !== 'Post')
return;
$contact = diaspora_get_contact_by_handle($importer['uid'],$msg['author']);
if(! $contact)
return;
if(($contact['rel'] == CONTACT_IS_FOLLOWER) || ($contact['blocked']) || ($contact['readonly'])) {
logger('diaspora_like: Ignoring this author.');
http_status_exit(202);
// NOTREACHED
}
$r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
intval($importer['uid']),
dbesc($parent_guid)
);
if(! count($r)) {
logger('diaspora_like: parent item not found: ' . $guid);
return;
}
$parent_item = $r[0];
$r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '$s' LIMIT 1",
intval($importer['uid']),
dbesc($guid)
);
if(count($r)) {
if($positive === 'true') {
logger('diaspora_like: duplicate like: ' . $guid);
return;
}
if($positive === 'false') {
q("UPDATE `item` SET `deleted` = 1 WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($r[0]['id']),
intval($importer['uid'])
);
// FIXME
// send notification via proc_run()
return;
}
}
if($positive === 'false') {
logger('diaspora_like: unlike received with no corresponding like');
return;
}
$author_signed_data = $guid . ';' . $parent_guid . ';' . $target_type . ';' . $positive . ';' . $diaspora_handle;
$author_signature = base64_decode($author_signature);
if(stricmp($diaspora_handle,$msg['author']) == 0) {
$person = $contact;
$key = $msg['key'];
}
else {
$person = find_person_by_handle($diaspora_handle);
if(is_array($person) && x($person,'pubkey'))
$key = $person['pubkey'];
else {
logger('diaspora_comment: unable to find author details');
return;
}
}
if(! rsa_verify($author_signed_data,$author_signature,$key)) {
logger('diaspora_like: verification failed.');
return;
}
if($parent_author_signature) {
$owner_signed_data = $guid . ';' . $parent_guid . ';' . $target_type . ';' . $positive . ';' . $msg['author'];
$parent_author_signature = base64_decode($parent_author_signature);
$key = $msg['key'];
if(! rsa_verify($owner_signed_data,$parent_author_signature,$key)) {
logger('diaspora_like: owner verification failed.');
return;
}
}
// Phew! Everything checks out. Now create an item.
$uri = $diaspora_handle . ':' . $guid;
$activity = ACTIVITY_LIKE;
$post_type = (($parent_item['resource-id']) ? t('photo') : t('status'));
$objtype = (($parent_item['resource-id']) ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE );
$link = xmlify('<link rel="alternate" type="text/html" href="' . $a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $parent_item['id'] . '" />' . "\n") ;
$body = $parent_item['body'];
$obj = <<< EOT
<object>
<type>$objtype</type>
<local>1</local>
<id>{$parent_item['uri']}</id>
<link>$link</link>
<title></title>
<content>$body</content>
</object>
EOT;
$bodyverb = t('%1$s likes %2$s\'s %3$s');
$arr = array();
$arr['uri'] = $uri;
$arr['uid'] = $importer['uid'];
$arr['contact-id'] = $contact['id'];
$arr['type'] = 'activity';
$arr['wall'] = $parent_item['wall'];
$arr['gravity'] = GRAVITY_LIKE;
$arr['parent'] = $parent_item['id'];
$arr['parent-uri'] = $parent_item['uri'];
$datarray['owner-name'] = $contact['name'];
$datarray['owner-link'] = $contact['url'];
$datarray['owner-avatar'] = $contact['thumb'];
$datarray['author-name'] = $person['name'];
$datarray['author-link'] = $person['url'];
$datarray['author-avatar'] = ((x($person,'thumb')) ? $person['thumb'] : $person['photo']);
$ulink = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]';
$alink = '[url=' . $parent_item['author-link'] . ']' . $parent_item['author-name'] . '[/url]';
$plink = '[url=' . $a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $parent_item['id'] . ']' . $post_type . '[/url]';
$arr['body'] = sprintf( $bodyverb, $ulink, $alink, $plink );
$arr['private'] = $parent_item['private'];
$arr['verb'] = $activity;
$arr['object-type'] = $objtype;
$arr['object'] = $obj;
$arr['visible'] = 1;
$arr['unseen'] = 1;
$arr['last-child'] = 0;
$post_id = item_store($arr);
// FIXME send notification
}
function diaspora_retraction($importer,$xml) {
$guid = notags(unxmlify($xml->guid));
$diaspora_handle = notags(unxmlify($xml->diaspora_handle));
$contact = diaspora_get_contact_by_handle($importer['uid'],$diaspora_handle);
if(! $contact)
return;
// if(($contact['rel'] == CONTACT_IS_FOLLOWER) || ($contact['blocked']) || ($contact['readonly'])) {
// logger('diaspora_retraction: Ignoring this author.');
// http_status_exit(202);
// // NOTREACHED
// }
}
function diaspora_share($me,$contact) {
$a = get_app();
$myaddr = $me['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3);
$theiraddr = $contact['addr'];
$tpl = get_markup_template('diaspora_share.tpl');
$msg = replace_macros($tpl, array(
'$sender' => myaddr,
'$recipient' => $theiraddr
));
$slap = 'xml=' . urlencode(diaspora_msg_build($msg,$me,$contact,$me['prvkey'],$contact['pubkey']));
post_url($contact['notify'],$slap);
$return_code = $a->get_curl_code();
return $return_code;
}
function diaspora_send_status($item,$owner,$contact) {
$a = get_app();
$myaddr = $owner['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3);
$theiraddr = $contact['addr'];
require_once('include/bbcode.php');
$body = xmlify(bbcode($item['body']));
$public = (($item['private']) ? 'false' : 'true');
require_once('include/datetime.php');
$created = datetime_convert('UTC','UTC',$item['created'],'Y-m-d h:i:s \U\T\C');
$tpl = get_markup_template('diaspora_post.tpl');
$msg = replace_macros($tpl, array(
'$body' => $body,
'$guid' => $item['guid'],
'$handle' => xmlify($myaddr),
'$public' => $public,
'$created' => $created
));
logger('diaspora_send_status: base message: ' . $msg, LOGGER_DATA);
$slap = 'xml=' . urlencode(diaspora_msg_build($msg,$owner,$contact,$owner['uprvkey'],$contact['pubkey']));
post_url($contact['notify'],$slap);
$return_code = $a->get_curl_code();
logger('diaspora_send_status: returns: ' . $return_code);
return $return_code;
}

View File

@ -197,6 +197,7 @@ function event_store($arr) {
$arr['type'] = (($arr['type']) ? $arr['type'] : 'event' );
$arr['cid'] = ((intval($arr['cid'])) ? intval($arr['cid']) : 0);
$arr['uri'] = (x($arr,'uri') ? $arr['uri'] : item_new_uri($a->get_hostname(),$arr['uid']));
$arr['private'] = ((x($arr,'private')) ? intval($arr['private']) : 0);
if($arr['cid'])
$c = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
@ -275,7 +276,7 @@ function event_store($arr) {
$object .= '</object>' . "\n";
q("UPDATE `item` SET `body` = '%s', `object` = '%s', `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s', `edited` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1",
q("UPDATE `item` SET `body` = '%s', `object` = '%s', `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s', `edited` = '%s', `private` = %d WHERE `id` = %d AND `uid` = %d LIMIT 1",
dbesc(format_event_bbcode($arr)),
dbesc($object),
dbesc($arr['allow_cid']),
@ -283,6 +284,7 @@ function event_store($arr) {
dbesc($arr['deny_cid']),
dbesc($arr['deny_gid']),
dbesc($arr['edited']),
intval($arr['private']),
intval($r[0]['id']),
intval($arr['uid'])
);
@ -341,10 +343,11 @@ function event_store($arr) {
$item_arr['author-link'] = $contact['url'];
$item_arr['author-avatar'] = $contact['thumb'];
$item_arr['title'] = '';
$item_arr['allow_cid'] = $str_contact_allow;
$item_arr['allow_gid'] = $str_group_allow;
$item_arr['deny_cid'] = $str_contact_deny;
$item_arr['deny_gid'] = $str_group_deny;
$item_arr['allow_cid'] = $arr['allow_cid'];
$item_arr['allow_gid'] = $arr['allow_gid'];
$item_arr['deny_cid'] = $arr['deny_cid'];
$item_arr['deny_gid'] = $arr['deny_gid'];
$item_arr['private'] = $arr['private'];
$item_arr['last-child'] = 1;
$item_arr['visible'] = 1;
$item_arr['verb'] = ACTIVITY_POST;

View File

@ -136,7 +136,7 @@ function group_public_members($gid) {
function group_side($every="contacts",$each="group",$edit = false, $group_id = 0) {
function group_side($every="contacts",$each="group",$edit = false, $group_id = 0, $cid = 0) {
$o = '';
@ -160,10 +160,19 @@ EOT;
$r = q("SELECT * FROM `group` WHERE `deleted` = 0 AND `uid` = %d ORDER BY `name` ASC",
intval($_SESSION['uid'])
);
if($cid) {
$member_of = groups_containing(local_user(),$cid);
}
if(count($r)) {
foreach($r as $rr) {
$selected = (($group_id == $rr['id']) ? ' class="group-selected" ' : '');
$o .= ' <li class="sidebar-group-li">' . (($edit) ? "<a href=\"group/{$rr['id']}\" title=\"" . t('Edit') . "\" ><img src=\"images/spencil.gif\" alt=\"" . t('Edit') . "\"></a> " : "") . "<a href=\"$each/{$rr['id']}\" $selected >{$rr['name']}</a></li>\r\n";
$o .= ' <li class="sidebar-group-li">'
. (($edit) ? "<a href=\"group/{$rr['id']}\" title=\"" . t('Edit')
. "\" ><img src=\"images/spencil.gif\" alt=\"" . t('Edit') . "\"></a> " : "")
. (($cid) ? '<input type="checkbox" class="' . (($selected) ? 'ticked' : 'unticked') . '" onclick="contactgroupChangeMember(' . $rr['id'] . ',' . $cid . ');return true;" '
. ((in_array($rr['id'],$member_of)) ? ' checked="checked" ' : '') . '/>' : '')
. "<a href=\"$each/{$rr['id']}\" $selected >{$rr['name']}</a></li>\r\n";
}
}
$o .= " </ul>\r\n </div>";
@ -204,3 +213,18 @@ function member_of($c) {
}
function groups_containing($uid,$c) {
$r = q("SELECT `gid` FROM `group_member` WHERE `uid` = %d AND `group_member`.`contact-id` = %d ",
intval($uid),
intval($c)
);
$ret = array();
if(count($r)) {
foreach($r as $rr)
$ret[] = $rr['gid'];
}
return $ret;
}

View File

@ -6,7 +6,6 @@ require_once('include/salmon.php');
function get_feed_for(&$a, $dfrn_id, $owner_nick, $last_update, $direction = 0) {
// default permissions - anonymous user
if(! strlen($owner_nick))
@ -113,7 +112,7 @@ function get_feed_for(&$a, $dfrn_id, $owner_nick, $last_update, $direction = 0)
$items = $r;
$feed_template = get_markup_template('atom_feed.tpl');
$feed_template = get_markup_template(($dfrn_id) ? 'atom_feed_dfrn.tpl' : 'atom_feed.tpl');
$atom = '';
@ -154,6 +153,9 @@ function get_feed_for(&$a, $dfrn_id, $owner_nick, $last_update, $direction = 0)
if($dfrn_id === '') {
$type = 'html';
// catch any email that's in a public conversation and make sure it doesn't leak
if($item['private'])
continue;
}
else {
$type = 'text';
@ -485,7 +487,6 @@ function get_atom_elements($feed,$item) {
if((x($res,'verb')) && ($res['verb'] === 'http://ostatus.org/schema/1.0/unfollow'))
$res['verb'] = ACTIVITY_UNFOLLOW;
$cats = $item->get_categories();
if($cats) {
$tag_arr = array();
@ -520,7 +521,7 @@ function get_atom_elements($feed,$item) {
if(! $type)
$type = 'application/octet-stream';
$att_arr[] = '[attach]href="' . $link . '" size="' . $len . '" type="' . $type . '" title="' . $title . '"[/attach]';
$att_arr[] = '[attach]href="' . $link . '" length="' . $len . '" type="' . $type . '" title="' . $title . '"[/attach]';
}
$res['attach'] = implode(',', $att_arr);
}
@ -720,6 +721,13 @@ function item_store($arr,$force_parent = false) {
if($r[0]['uri'] != $r[0]['parent-uri']) {
$arr['thr-parent'] = $arr['parent-uri'];
$arr['parent-uri'] = $r[0]['parent-uri'];
$z = q("SELECT `id` FROM `item` WHERE `uri` = '%s' AND `parent-uri` = '%s' AND `uid` = %d LIMIT 1",
dbesc($r[0]['parent-uri']),
dbesc($r[0]['parent-uri']),
intval($arr['uid'])
);
if($z && count($z))
$r = $z;
}
$parent_id = $r[0]['id'];
@ -749,6 +757,8 @@ function item_store($arr,$force_parent = false) {
}
}
$arr['guid'] = get_guid();
call_hooks('post_remote',$arr);
dbesc_array($arr);
@ -917,7 +927,7 @@ function dfrn_deliver($owner,$contact,$atom, $dissolve = false) {
$postvars['dissolve'] = '1';
if((($contact['rel']) && ($contact['rel'] != REL_FAN) && (! $contact['blocked'])) || ($owner['page-flags'] == PAGE_COMMUNITY)) {
if((($contact['rel']) && ($contact['rel'] != CONTACT_IS_SHARING) && (! $contact['blocked'])) || ($owner['page-flags'] == PAGE_COMMUNITY)) {
$postvars['data'] = $atom;
$postvars['perm'] = 'rw';
}
@ -997,6 +1007,11 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $secure_fee
require_once('library/simplepie/simplepie.inc');
if(! strlen($xml)) {
logger('consume_feed: empty input');
return;
}
$feed = new SimplePie();
$feed->set_raw_data($xml);
if($datedir)
@ -1023,7 +1038,9 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $secure_fee
if(count($hubs))
$hub = implode(',', $hubs);
$rawtags = $feed->get_feed_tags( SIMPLEPIE_NAMESPACE_ATOM_10, 'author');
$rawtags = $feed->get_feed_tags( NAMESPACE_DFRN, 'owner');
if(! $rawtags)
$rawtags = $feed->get_feed_tags( SIMPLEPIE_NAMESPACE_ATOM_10, 'author');
if($rawtags) {
$elems = $rawtags[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10];
if($elems['name'][0]['attribs'][NAMESPACE_DFRN]['updated']) {
@ -1349,6 +1366,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $secure_fee
$ev['uid'] = $importer['uid'];
$ev['uri'] = $item_id;
$ev['edited'] = $datarray['edited'];
$ev['private'] = $datarray['private'];
if(is_array($contact))
$ev['cid'] = $contact['id'];
@ -1444,9 +1462,9 @@ function new_follower($importer,$contact,$datarray,$item) {
$nick = $rawtag[0]['child'][NAMESPACE_POCO]['preferredUsername'][0]['data'];
if(is_array($contact)) {
if($contact['network'] == 'stat' && $contact['rel'] == REL_FAN) {
if($contact['network'] == 'stat' && $contact['rel'] == CONTACT_IS_SHARING) {
$r = q("UPDATE `contact` SET `rel` = %d WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval(REL_BUD),
intval(CONTACT_IS_FRIEND),
intval($contact['id']),
intval($importer['uid'])
);
@ -1468,12 +1486,12 @@ function new_follower($importer,$contact,$datarray,$item) {
dbesc($nick),
dbesc($photo),
dbesc('stat'),
intval(REL_VIP)
intval(CONTACT_IS_FOLLOWER)
);
$r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `url` = '%s' AND `pending` = 1 AND `rel` = %d LIMIT 1",
intval($importer['uid']),
dbesc($url),
intval(REL_VIP)
intval(CONTACT_IS_FOLLOWER)
);
if(count($r))
$contact_record = $r[0];
@ -1518,9 +1536,9 @@ function new_follower($importer,$contact,$datarray,$item) {
function lose_follower($importer,$contact,$datarray,$item) {
if(($contact['rel'] == REL_BUD) || ($contact['rel'] == REL_FAN)) {
if(($contact['rel'] == CONTACT_IS_FRIEND) || ($contact['rel'] == CONTACT_IS_SHARING)) {
q("UPDATE `contact` SET `rel` = %d WHERE `id` = %d LIMIT 1",
intval(REL_FAN),
intval(CONTACT_IS_SHARING),
intval($contact['id'])
);
}
@ -1726,11 +1744,11 @@ function item_getfeedattach($item) {
if(count($arr)) {
foreach($arr as $r) {
$matches = false;
$cnt = preg_match('|\[attach\]href=\"(.*?)\" size=\"(.*?)\" type=\"(.*?)\" title=\"(.*?)\"\[\/attach\]|',$r,$matches);
$cnt = preg_match('|\[attach\]href=\"(.*?)\" length=\"(.*?)\" type=\"(.*?)\" title=\"(.*?)\"\[\/attach\]|',$r,$matches);
if($cnt) {
$ret .= '<link rel="enclosure" href="' . xmlify($matches[1]) . '" type="' . xmlify($matches[3]) . '" ';
if(intval($matches[2]))
$ret .= 'size="' . intval($matches[2]) . '" ';
$ret .= 'length="' . intval($matches[2]) . '" ';
if($matches[4] !== ' ')
$ret .= 'title="' . xmlify(trim($matches[4])) . '" ';
$ret .= ' />' . "\r\n";

View File

@ -194,7 +194,8 @@
else {
$('#' + ident + ' ' + '.wall-item-ago').replaceWith($(this).find('.wall-item-ago'));
$('#' + ident + ' ' + '.wall-item-comment-wrapper').replaceWith($(this).find('.wall-item-comment-wrapper'));
if($('#' + ident + ' ' + '.comment-edit-text-empty').length)
$('#' + ident + ' ' + '.wall-item-comment-wrapper').replaceWith($(this).find('.wall-item-comment-wrapper'));
$('#' + ident + ' ' + '.wall-item-like').replaceWith($(this).find('.wall-item-like'));
$('#' + ident + ' ' + '.wall-item-dislike').replaceWith($(this).find('.wall-item-dislike'));
$('#' + ident + ' ' + '.my-comment-photo').each(function() {
@ -361,6 +362,14 @@
});
}
function contactgroupChangeMember(gid,cid) {
$('body').css('cursor', 'wait');
$.get('contactgroup/' + gid + '/' + cid, function(data) {
$('body').css('cursor', 'auto');
});
}
function checkboxhighlight(box) {
if($(box).is(':checked')) {
$(box).addClass('checkeditem');
@ -414,3 +423,4 @@ Array.prototype.remove = function(item) {
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};

695
include/network.php Normal file
View File

@ -0,0 +1,695 @@
<?php
// curl wrapper. If binary flag is true, return binary
// results.
if(! function_exists('fetch_url')) {
function fetch_url($url,$binary = false, &$redirects = 0, $timeout = 0) {
$a = get_app();
$ch = curl_init($url);
if(($redirects > 8) || (! $ch))
return false;
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch, CURLOPT_USERAGENT, "Friendika");
if(intval($timeout)) {
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
}
else {
$curl_time = intval(get_config('system','curl_timeout'));
curl_setopt($ch, CURLOPT_TIMEOUT, (($curl_time !== false) ? $curl_time : 60));
}
// by default we will allow self-signed certs
// but you can override this
$check_cert = get_config('system','verifyssl');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (($check_cert) ? true : false));
$prx = get_config('system','proxy');
if(strlen($prx)) {
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
curl_setopt($ch, CURLOPT_PROXY, $prx);
$prxusr = get_config('system','proxyuser');
if(strlen($prxusr))
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $prxusr);
}
if($binary)
curl_setopt($ch, CURLOPT_BINARYTRANSFER,1);
$a->set_curl_code(0);
// don't let curl abort the entire application
// if it throws any errors.
$s = @curl_exec($ch);
$base = $s;
$curl_info = curl_getinfo($ch);
$http_code = $curl_info['http_code'];
$header = '';
// Pull out multiple headers, e.g. proxy and continuation headers
// allow for HTTP/2.x without fixing code
while(preg_match('/^HTTP\/[1-2].+? [1-5][0-9][0-9]/',$base)) {
$chunk = substr($base,0,strpos($base,"\r\n\r\n")+4);
$header .= $chunk;
$base = substr($base,strlen($chunk));
}
if($http_code == 301 || $http_code == 302 || $http_code == 303 || $http_code == 307) {
$matches = array();
preg_match('/(Location:|URI:)(.*?)\n/', $header, $matches);
$url = trim(array_pop($matches));
$url_parsed = @parse_url($url);
if (isset($url_parsed)) {
$redirects++;
return fetch_url($url,$binary,$redirects,$timeout);
}
}
$a->set_curl_code($http_code);
$body = substr($s,strlen($header));
$a->set_curl_headers($header);
curl_close($ch);
return($body);
}}
// post request to $url. $params is an array of post variables.
if(! function_exists('post_url')) {
function post_url($url,$params, $headers = null, &$redirects = 0, $timeout = 0) {
$a = get_app();
$ch = curl_init($url);
if(($redirects > 8) || (! $ch))
return false;
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$params);
curl_setopt($ch, CURLOPT_USERAGENT, "Friendika");
if(intval($timeout)) {
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
}
else {
$curl_time = intval(get_config('system','curl_timeout'));
curl_setopt($ch, CURLOPT_TIMEOUT, (($curl_time !== false) ? $curl_time : 60));
}
if(defined('LIGHTTPD')) {
if(!is_array($headers)) {
$headers = array('Expect:');
} else {
if(!in_array('Expect:', $headers)) {
array_push($headers, 'Expect:');
}
}
}
if($headers)
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$check_cert = get_config('system','verifyssl');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (($check_cert) ? true : false));
$prx = get_config('system','proxy');
if(strlen($prx)) {
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
curl_setopt($ch, CURLOPT_PROXY, $prx);
$prxusr = get_config('system','proxyuser');
if(strlen($prxusr))
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $prxusr);
}
$a->set_curl_code(0);
// don't let curl abort the entire application
// if it throws any errors.
$s = @curl_exec($ch);
$base = $s;
$curl_info = curl_getinfo($ch);
$http_code = $curl_info['http_code'];
$header = '';
// Pull out multiple headers, e.g. proxy and continuation headers
// allow for HTTP/2.x without fixing code
while(preg_match('/^HTTP\/[1-2].+? [1-5][0-9][0-9]/',$base)) {
$chunk = substr($base,0,strpos($base,"\r\n\r\n")+4);
$header .= $chunk;
$base = substr($base,strlen($chunk));
}
if($http_code == 301 || $http_code == 302 || $http_code == 303) {
$matches = array();
preg_match('/(Location:|URI:)(.*?)\n/', $header, $matches);
$url = trim(array_pop($matches));
$url_parsed = @parse_url($url);
if (isset($url_parsed)) {
$redirects++;
return post_url($url,$params,$headers,$redirects,$timeout);
}
}
$a->set_curl_code($http_code);
$body = substr($s,strlen($header));
$a->set_curl_headers($header);
curl_close($ch);
return($body);
}}
// Generic XML return
// Outputs a basic dfrn XML status structure to STDOUT, with a <status> variable
// of $st and an optional text <message> of $message and terminates the current process.
if(! function_exists('xml_status')) {
function xml_status($st, $message = '') {
$xml_message = ((strlen($message)) ? "\t<message>" . xmlify($message) . "</message>\r\n" : '');
if($st)
logger('xml_status returning non_zero: ' . $st . " message=" . $message);
header( "Content-type: text/xml" );
echo '<?xml version="1.0" encoding="UTF-8"?>'."\r\n";
echo "<result>\r\n\t<status>$st</status>\r\n$xml_message</result>\r\n";
killme();
}}
if(! function_exists('http_status_exit')) {
function http_status_exit($val) {
if($val >= 400)
$err = 'Error';
if($val >= 200 && $val < 300)
$err = 'OK';
logger('http_status_exit ' . $val);
header($_SERVER["SERVER_PROTOCOL"] . ' ' . $val . ' ' . $err);
killme();
}}
// convert an XML document to a normalised, case-corrected array
// used by webfinger
if(! function_exists('convert_xml_element_to_array')) {
function convert_xml_element_to_array($xml_element, &$recursion_depth=0) {
// If we're getting too deep, bail out
if ($recursion_depth > 512) {
return(null);
}
if (!is_string($xml_element) &&
!is_array($xml_element) &&
(get_class($xml_element) == 'SimpleXMLElement')) {
$xml_element_copy = $xml_element;
$xml_element = get_object_vars($xml_element);
}
if (is_array($xml_element)) {
$result_array = array();
if (count($xml_element) <= 0) {
return (trim(strval($xml_element_copy)));
}
foreach($xml_element as $key=>$value) {
$recursion_depth++;
$result_array[strtolower($key)] =
convert_xml_element_to_array($value, $recursion_depth);
$recursion_depth--;
}
if ($recursion_depth == 0) {
$temp_array = $result_array;
$result_array = array(
strtolower($xml_element_copy->getName()) => $temp_array,
);
}
return ($result_array);
} else {
return (trim(strval($xml_element)));
}
}}
// Given an email style address, perform webfinger lookup and
// return the resulting DFRN profile URL, or if no DFRN profile URL
// is located, returns an OStatus subscription template (prefixed
// with the string 'stat:' to identify it as on OStatus template).
// If this isn't an email style address just return $s.
// Return an empty string if email-style addresses but webfinger fails,
// or if the resultant personal XRD doesn't contain a supported
// subscription/friend-request attribute.
if(! function_exists('webfinger_dfrn')) {
function webfinger_dfrn($s) {
if(! strstr($s,'@')) {
return $s;
}
$links = webfinger($s);
logger('webfinger_dfrn: ' . $s . ':' . print_r($links,true), LOGGER_DATA);
if(count($links)) {
foreach($links as $link)
if($link['@attributes']['rel'] === NAMESPACE_DFRN)
return $link['@attributes']['href'];
foreach($links as $link)
if($link['@attributes']['rel'] === NAMESPACE_OSTATUSSUB)
return 'stat:' . $link['@attributes']['template'];
}
return '';
}}
// Given an email style address, perform webfinger lookup and
// return the array of link attributes from the personal XRD file.
// On error/failure return an empty array.
if(! function_exists('webfinger')) {
function webfinger($s) {
$host = '';
if(strstr($s,'@')) {
$host = substr($s,strpos($s,'@') + 1);
}
if(strlen($host)) {
$tpl = fetch_lrdd_template($host);
logger('webfinger: lrdd template: ' . $tpl);
if(strlen($tpl)) {
$pxrd = str_replace('{uri}', urlencode('acct:' . $s), $tpl);
logger('webfinger: pxrd: ' . $pxrd);
$links = fetch_xrd_links($pxrd);
if(! count($links)) {
// try with double slashes
$pxrd = str_replace('{uri}', urlencode('acct://' . $s), $tpl);
logger('webfinger: pxrd: ' . $pxrd);
$links = fetch_xrd_links($pxrd);
}
return $links;
}
}
return array();
}}
if(! function_exists('lrdd')) {
function lrdd($uri) {
$a = get_app();
// default priority is host priority, host-meta first
$priority = 'host';
// All we have is an email address. Resource-priority is irrelevant
// because our URI isn't directly resolvable.
if(strstr($uri,'@')) {
return(webfinger($uri));
}
// get the host meta file
$host = @parse_url($uri);
if($host) {
$url = ((x($host,'scheme')) ? $host['scheme'] : 'http') . '://';
$url .= $host['host'] . '/.well-known/host-meta' ;
}
else
return array();
logger('lrdd: constructed url: ' . $url);
$xml = fetch_url($url);
$headers = $a->get_curl_headers();
if (! $xml)
return array();
logger('lrdd: host_meta: ' . $xml, LOGGER_DATA);
$h = parse_xml_string($xml);
if(! $h)
return array();
$arr = convert_xml_element_to_array($h);
if(isset($arr['xrd']['property'])) {
$property = $arr['crd']['property'];
if(! isset($property[0]))
$properties = array($property);
else
$properties = $property;
foreach($properties as $prop)
if((string) $prop['@attributes'] === 'http://lrdd.net/priority/resource')
$priority = 'resource';
}
// save the links in case we need them
$links = array();
if(isset($arr['xrd']['link'])) {
$link = $arr['xrd']['link'];
if(! isset($link[0]))
$links = array($link);
else
$links = $link;
}
// do we have a template or href?
if(count($links)) {
foreach($links as $link) {
if($link['@attributes']['rel'] && attribute_contains($link['@attributes']['rel'],'lrdd')) {
if(x($link['@attributes'],'template'))
$tpl = $link['@attributes']['template'];
elseif(x($link['@attributes'],'href'))
$href = $link['@attributes']['href'];
}
}
}
if((! isset($tpl)) || (! strpos($tpl,'{uri}')))
$tpl = '';
if($priority === 'host') {
if(strlen($tpl))
$pxrd = str_replace('{uri}', urlencode($uri), $tpl);
elseif(isset($href))
$pxrd = $href;
if(isset($pxrd)) {
logger('lrdd: (host priority) pxrd: ' . $pxrd);
$links = fetch_xrd_links($pxrd);
return $links;
}
$lines = explode("\n",$headers);
if(count($lines)) {
foreach($lines as $line) {
if((stristr($line,'link:')) && preg_match('/<([^>].*)>.*rel\=[\'\"]lrdd[\'\"]/',$line,$matches)) {
return(fetch_xrd_links($matches[1]));
break;
}
}
}
}
// priority 'resource'
$html = fetch_url($uri);
$headers = $a->get_curl_headers();
logger('lrdd: headers=' . $headers, LOGGER_DEBUG);
// don't try and parse raw xml as html
if(! strstr($html,'<?xml')) {
require_once('library/HTML5/Parser.php');
$dom = @HTML5_Parser::parse($html);
if($dom) {
$items = $dom->getElementsByTagName('link');
foreach($items as $item) {
$x = $item->getAttribute('rel');
if($x == "lrdd") {
$pagelink = $item->getAttribute('href');
break;
}
}
}
}
if(isset($pagelink))
return(fetch_xrd_links($pagelink));
// next look in HTTP headers
$lines = explode("\n",$headers);
if(count($lines)) {
foreach($lines as $line) {
// TODO alter the following regex to support multiple relations (space separated)
if((stristr($line,'link:')) && preg_match('/<([^>].*)>.*rel\=[\'\"]lrdd[\'\"]/',$line,$matches)) {
$pagelink = $matches[1];
break;
}
// don't try and run feeds through the html5 parser
if(stristr($line,'content-type:') && ((stristr($line,'application/atom+xml')) || (stristr($line,'application/rss+xml'))))
return array();
if(stristr($html,'<rss') || stristr($html,'<feed'))
return array();
}
}
if(isset($pagelink))
return(fetch_xrd_links($pagelink));
// If we haven't found any links, return the host xrd links (which we have already fetched)
if(isset($links))
return $links;
return array();
}}
// Given a host name, locate the LRDD template from that
// host. Returns the LRDD template or an empty string on
// error/failure.
if(! function_exists('fetch_lrdd_template')) {
function fetch_lrdd_template($host) {
$tpl = '';
$url1 = 'https://' . $host . '/.well-known/host-meta' ;
$url2 = 'http://' . $host . '/.well-known/host-meta' ;
$links = fetch_xrd_links($url1);
logger('fetch_lrdd_template from: ' . $url1);
logger('template (https): ' . print_r($links,true));
if(! count($links)) {
logger('fetch_lrdd_template from: ' . $url2);
$links = fetch_xrd_links($url2);
logger('template (http): ' . print_r($links,true));
}
if(count($links)) {
foreach($links as $link)
if($link['@attributes']['rel'] && $link['@attributes']['rel'] === 'lrdd')
$tpl = $link['@attributes']['template'];
}
if(! strpos($tpl,'{uri}'))
$tpl = '';
return $tpl;
}}
// Given a URL, retrieve the page as an XRD document.
// Return an array of links.
// on error/failure return empty array.
if(! function_exists('fetch_xrd_links')) {
function fetch_xrd_links($url) {
$xrd_timeout = intval(get_config('system','xrd_timeout'));
$redirects = 0;
$xml = fetch_url($url,false,$redirects,(($xrd_timeout) ? $xrd_timeout : 30));
logger('fetch_xrd_links: ' . $xml, LOGGER_DATA);
if ((! $xml) || (! stristr($xml,'<xrd')))
return array();
$h = parse_xml_string($xml);
if(! $h)
return array();
$arr = convert_xml_element_to_array($h);
$links = array();
if(isset($arr['xrd']['link'])) {
$link = $arr['xrd']['link'];
if(! isset($link[0]))
$links = array($link);
else
$links = $link;
}
if(isset($arr['xrd']['alias'])) {
$alias = $arr['xrd']['alias'];
if(! isset($alias[0]))
$aliases = array($alias);
else
$aliases = $alias;
if(count($aliases)) {
foreach($aliases as $alias) {
$links[]['@attributes'] = array('rel' => 'alias' , 'href' => $alias);
}
}
}
logger('fetch_xrd_links: ' . print_r($links,true), LOGGER_DATA);
return $links;
}}
// Take a URL from the wild, prepend http:// if necessary
// and check DNS to see if it's real
// return true if it's OK, false if something is wrong with it
if(! function_exists('validate_url')) {
function validate_url(&$url) {
if(substr($url,0,4) != 'http')
$url = 'http://' . $url;
$h = @parse_url($url);
if(($h) && (dns_get_record($h['host'], DNS_A + DNS_CNAME + DNS_PTR))) {
return true;
}
return false;
}}
// checks that email is an actual resolvable internet address
if(! function_exists('validate_email')) {
function validate_email($addr) {
if(! strpos($addr,'@'))
return false;
$h = substr($addr,strpos($addr,'@') + 1);
if(($h) && (dns_get_record($h, DNS_A + DNS_CNAME + DNS_PTR + DNS_MX))) {
return true;
}
return false;
}}
// Check $url against our list of allowed sites,
// wildcards allowed. If allowed_sites is unset return true;
// If url is allowed, return true.
// otherwise, return false
if(! function_exists('allowed_url')) {
function allowed_url($url) {
$h = @parse_url($url);
if(! $h) {
return false;
}
$str_allowed = get_config('system','allowed_sites');
if(! $str_allowed)
return true;
$found = false;
$host = strtolower($h['host']);
// always allow our own site
if($host == strtolower($_SERVER['SERVER_NAME']))
return true;
$fnmatch = function_exists('fnmatch');
$allowed = explode(',',$str_allowed);
if(count($allowed)) {
foreach($allowed as $a) {
$pat = strtolower(trim($a));
if(($fnmatch && fnmatch($pat,$host)) || ($pat == $host)) {
$found = true;
break;
}
}
}
return $found;
}}
// check if email address is allowed to register here.
// Compare against our list (wildcards allowed).
// Returns false if not allowed, true if allowed or if
// allowed list is not configured.
if(! function_exists('allowed_email')) {
function allowed_email($email) {
$domain = strtolower(substr($email,strpos($email,'@') + 1));
if(! $domain)
return false;
$str_allowed = get_config('system','allowed_email');
if(! $str_allowed)
return true;
$found = false;
$fnmatch = function_exists('fnmatch');
$allowed = explode(',',$str_allowed);
if(count($allowed)) {
foreach($allowed as $a) {
$pat = strtolower(trim($a));
if(($fnmatch && fnmatch($pat,$domain)) || ($pat == $domain)) {
$found = true;
break;
}
}
}
return $found;
}}
if(! function_exists('gravatar_img')) {
function gravatar_img($email) {
$size = 175;
$opt = 'identicon'; // psuedo-random geometric pattern if not found
$rating = 'pg';
$hash = md5(trim(strtolower($email)));
$url = 'http://www.gravatar.com/avatar/' . $hash . '.jpg'
. '?s=' . $size . '&d=' . $opt . '&r=' . $rating;
logger('gravatar: ' . $email . ' ' . $url);
return $url;
}}
if(! function_exists('parse_xml_string')) {
function parse_xml_string($s,$strict = true) {
if($strict) {
if(! strstr($s,'<?xml'))
return false;
$s2 = substr($s,strpos($s,'<?xml'));
}
else
$s2 = $s;
libxml_use_internal_errors(true);
$x = @simplexml_load_string($s2);
if(! $x) {
logger('libxml: parse: error: ' . $s2, LOGGER_DATA);
foreach(libxml_get_errors() as $err)
logger('libxml: parse: ' . $err->code." at ".$err->line.":".$err->column." : ".$err->message, LOGGER_DATA);
libxml_clear_errors();
}
return $x;
}}

View File

@ -50,8 +50,10 @@ function notifier_run($argv, $argc){
$recipients = array();
$url_recipients = array();
if($cmd === 'mail') {
$normal_mode = true;
if($cmd === 'mail') {
$normal_mode = false;
$message = q("SELECT * FROM `mail` WHERE `id` = %d LIMIT 1",
intval($item_id)
);
@ -64,6 +66,7 @@ function notifier_run($argv, $argc){
}
elseif($cmd === 'expire') {
$normal_mode = false;
$expire = true;
$items = q("SELECT * FROM `item` WHERE `uid` = %d AND `wall` = 1
AND `deleted` = 1 AND `changed` > UTC_TIMESTAMP - INTERVAL 10 MINUTE",
@ -75,6 +78,7 @@ function notifier_run($argv, $argc){
return;
}
elseif($cmd === 'suggest') {
$normal_mode = false;
$suggest = q("SELECT * FROM `fsuggest` WHERE `id` = %d LIMIT 1",
intval($item_id)
);
@ -95,7 +99,7 @@ function notifier_run($argv, $argc){
return;
}
$parent_item = $r[0];
$target_item = $r[0];
$parent_id = intval($r[0]['parent']);
$uid = $r[0]['uid'];
$updated = $r[0]['edited'];
@ -119,7 +123,8 @@ function notifier_run($argv, $argc){
$top_level = true;
}
$r = q("SELECT `contact`.*, `user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`,
$r = q("SELECT `contact`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`,
`user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`,
`user`.`page-flags`, `user`.`prvnets`
FROM `contact` LEFT JOIN `user` ON `user`.`uid` = `contact`.`uid`
WHERE `contact`.`uid` = %d AND `contact`.`self` = 1 LIMIT 1",
@ -145,7 +150,7 @@ function notifier_run($argv, $argc){
$parent = $items[0];
if($parent['type'] === 'remote' && (! $expire)) {
if($parent['wall'] == 0 && (! $expire)) {
// local followup to remote post
$followup = true;
$notify_hub = false; // not public
@ -289,6 +294,11 @@ function notifier_run($argv, $argc){
if(! $item['parent'])
continue;
// private emails may be in included in public conversations. Filter them.
if(($notify_hub) && $item['private'])
continue;
$contact = get_item_contact($item,$contacts);
if(! $contact)
continue;
@ -311,9 +321,9 @@ function notifier_run($argv, $argc){
$mail_disabled = ((function_exists('imap_open') && (! get_config('system','imap_disabled'))) ? 0 : 1);
if(! $mail_disabled) {
if((! strlen($parent_item['allow_cid'])) && (! strlen($parent_item['allow_gid']))
&& (! strlen($parent_item['deny_cid'])) && (! strlen($parent_item['deny_gid']))
&& (intval($parent_item['pubmail']))) {
if((! strlen($target_item['allow_cid'])) && (! strlen($target_item['allow_gid']))
&& (! strlen($target_item['deny_cid'])) && (! strlen($target_item['deny_gid']))
&& (intval($target_item['pubmail']))) {
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `network` = '%s'",
intval($uid),
dbesc(NETWORK_MAIL)
@ -346,7 +356,7 @@ function notifier_run($argv, $argc){
$deliver_status = 0;
switch($contact['network']) {
case 'dfrn':
case NETWORK_DFRN:
logger('notifier: dfrndelivery: ' . $contact['name']);
$deliver_status = dfrn_deliver($owner,$contact,$atom);
@ -364,7 +374,7 @@ function notifier_run($argv, $argc){
);
}
break;
case 'stat':
case NETWORK_OSTATUS:
// Do not send to otatus if we are not configured to send to public networks
if($owner['prvnets'])
@ -414,7 +424,7 @@ function notifier_run($argv, $argc){
}
break;
case 'mail':
case NETWORK_MAIL:
if(get_config('system','dfrn_only'))
break;
@ -491,9 +501,34 @@ function notifier_run($argv, $argc){
mail($addr, $subject, $message, $headers);
}
break;
case 'feed':
case 'face':
case 'dspr':
case NETWORK_DIASPORA:
if(get_config('system','dfrn_only') || (! get_config('diaspora_enabled')) || (! $normal_mode))
break;
if($target_item['deleted']) {
// diaspora delete, (check for like)
break;
}
elseif($followup) {
// send to owner to relay
break;
}
elseif($target_item['parent'] != $target_item['id']) {
// we are the relay
break;
}
elseif($top_level) {
diaspora_send_status($target_item,$owner,$contact);
break;
}
break;
case NETWORK_FEED:
case NETWORK_FACEBOOK:
if(get_config('system','dfrn_only'))
break;
default:
@ -504,7 +539,7 @@ function notifier_run($argv, $argc){
// send additional slaps to mentioned remote tags (@foo@example.com)
if($slap && count($url_recipients) && $followup && $notify_hub && (! $expire)) {
if($slap && count($url_recipients) && ($followup || $top_level) && $notify_hub && (! $expire)) {
if(! get_config('system','dfrn_only')) {
foreach($url_recipients as $url) {
if($url) {
@ -542,7 +577,7 @@ function notifier_run($argv, $argc){
*
*/
$max_allowed = ((get_config('system','maxpubdeliver') === false) ? 150 : intval(get_config('system','maxpubdeliver')));
$max_allowed = ((get_config('system','maxpubdeliver') === false) ? 999 : intval(get_config('system','maxpubdeliver')));
/**
*
@ -552,10 +587,10 @@ function notifier_run($argv, $argc){
*/
$r = q("SELECT `id`, `name` FROM `contact`
WHERE `network` = 'dfrn' AND `uid` = %d AND `blocked` = 0 AND `pending` = 0
WHERE `network` = NETWORK_DFRN AND `uid` = %d AND `blocked` = 0 AND `pending` = 0
AND `rel` != %d ",
intval($owner['uid']),
intval(REL_FAN)
intval(CONTACT_IS_SHARING)
);
if((count($r)) && (($max_allowed == 0) || (count($r) < $max_allowed))) {

View File

@ -7,6 +7,7 @@ function oembed_replacecb($matches){
function oembed_fetch_url($embedurl){
$r = q("SELECT v FROM `cache` WHERE k='%s'",
dbesc($embedurl));
@ -16,7 +17,10 @@ function oembed_fetch_url($embedurl){
$txt = "";
// try oembed autodiscovery
$html_text = fetch_url($embedurl);
$redirects = 0;
$html_text = fetch_url($embedurl, false, $redirects, 15);
if(! $html_text)
return;
$dom = @DOMDocument::loadHTML($html_text);
if ($dom){
$xpath = new DOMXPath($dom);

199
include/plugin.php Normal file
View File

@ -0,0 +1,199 @@
<?php
// install and uninstall plugin
if (! function_exists('uninstall_plugin')){
function uninstall_plugin($plugin){
logger("Addons: uninstalling " . $plugin);
q("DELETE FROM `addon` WHERE `name` = '%s' LIMIT 1",
dbesc($plugin)
);
@include_once('addon/' . $plugin . '/' . $plugin . '.php');
if(function_exists($plugin . '_uninstall')) {
$func = $plugin . '_uninstall';
$func();
}
}}
if (! function_exists('install_plugin')){
function install_plugin($plugin){
logger("Addons: installing " . $plugin);
$t = filemtime('addon/' . $plugin . '/' . $plugin . '.php');
@include_once('addon/' . $plugin . '/' . $plugin . '.php');
if(function_exists($plugin . '_install')) {
$func = $plugin . '_install';
$func();
$plugin_admin = (function_exists($plugin."_plugin_admin")?1:0);
$r = q("INSERT INTO `addon` (`name`, `installed`, `timestamp`, `plugin_admin`) VALUES ( '%s', 1, %d , %d ) ",
dbesc($plugin),
intval($t),
$plugin_admin
);
}
}}
// reload all updated plugins
if(! function_exists('reload_plugins')) {
function reload_plugins() {
$plugins = get_config('system','addon');
if(strlen($plugins)) {
$r = q("SELECT * FROM `addon` WHERE `installed` = 1");
if(count($r))
$installed = $r;
else
$installed = array();
$parr = explode(',',$plugins);
if(count($parr)) {
foreach($parr as $pl) {
$pl = trim($pl);
$t = filemtime('addon/' . $pl . '/' . $pl . '.php');
foreach($installed as $i) {
if(($i['name'] == $pl) && ($i['timestamp'] != $t)) {
logger('Reloading plugin: ' . $i['name']);
@include_once('addon/' . $pl . '/' . $pl . '.php');
if(function_exists($pl . '_uninstall')) {
$func = $pl . '_uninstall';
$func();
}
if(function_exists($pl . '_install')) {
$func = $pl . '_install';
$func();
}
q("UPDATE `addon` SET `timestamp` = %d WHERE `id` = %d LIMIT 1",
intval($t),
intval($i['id'])
);
}
}
}
}
}
}}
if(! function_exists('register_hook')) {
function register_hook($hook,$file,$function) {
$r = q("SELECT * FROM `hook` WHERE `hook` = '%s' AND `file` = '%s' AND `function` = '%s' LIMIT 1",
dbesc($hook),
dbesc($file),
dbesc($function)
);
if(count($r))
return true;
$r = q("INSERT INTO `hook` (`hook`, `file`, `function`) VALUES ( '%s', '%s', '%s' ) ",
dbesc($hook),
dbesc($file),
dbesc($function)
);
return $r;
}}
if(! function_exists('unregister_hook')) {
function unregister_hook($hook,$file,$function) {
$r = q("DELETE FROM `hook` WHERE `hook` = '%s' AND `file` = '%s' AND `function` = '%s' LIMIT 1",
dbesc($hook),
dbesc($file),
dbesc($function)
);
return $r;
}}
if(! function_exists('load_hooks')) {
function load_hooks() {
$a = get_app();
$a->hooks = array();
$r = q("SELECT * FROM `hook` WHERE 1");
if(count($r)) {
foreach($r as $rr) {
$a->hooks[] = array($rr['hook'], $rr['file'], $rr['function']);
}
}
}}
if(! function_exists('call_hooks')) {
function call_hooks($name, &$data = null) {
$a = get_app();
if(count($a->hooks)) {
foreach($a->hooks as $hook) {
if($hook[HOOK_HOOK] === $name) {
@include_once($hook[HOOK_FILE]);
if(function_exists($hook[HOOK_FUNCTION])) {
$func = $hook[HOOK_FUNCTION];
$func($a,$data);
}
}
}
}
}}
/*
* parse plugin comment in search of plugin infos.
* like
*
* * Name: Plugin
* * Description: A plugin which plugs in
* * Version: 1.2.3
* * Author: John <profile url>
* * Author: Jane <email>
* *
*/
if (! function_exists('get_plugin_info')){
function get_plugin_info($plugin){
if (!is_file("addon/$plugin/$plugin.php")) return false;
$f = file_get_contents("addon/$plugin/$plugin.php");
$r = preg_match("|/\*.*\*/|msU", $f, $m);
$info=Array(
'name' => $plugin,
'description' => "",
'author' => array(),
'version' => ""
);
if ($r){
$ll = explode("\n", $m[0]);
foreach( $ll as $l ) {
$l = trim($l,"\t\n\r */");
if ($l!=""){
list($k,$v) = array_map("trim", explode(":",$l,2));
$k= strtolower($k);
if ($k=="author"){
$r=preg_match("|([^<]+)<([^>]+)>|", $v, $m);
if ($r) {
$info['author'][] = array('name'=>$m[1], 'link'=>$m[2]);
} else {
$info['author'][] = array('name'=>$v);
}
} else {
if (array_key_exists($k,$info)){
$info[$k]=$v;
}
}
}
}
}
return $info;
}}

View File

@ -80,15 +80,14 @@ function poller_run($argv, $argc){
$d = datetime_convert();
if(! $restart)
call_hooks('cron', $d);
proc_run('php','include/cronhooks.php');
$contacts = q("SELECT `id` FROM `contact`
WHERE ( `rel` = %d OR `rel` = %d ) AND `poll` != ''
$sql_extra
AND `self` = 0 AND `blocked` = 0 AND `readonly` = 0 ORDER BY RAND()",
intval(REL_FAN),
intval(REL_BUD)
intval(CONTACT_IS_SHARING),
intval(CONTACT_IS_FRIEND)
);
if(! count($contacts)) {
@ -101,7 +100,7 @@ function poller_run($argv, $argc){
intval($c['id'])
);
if(! count($res))
if((! $res) || (! count($res)))
continue;
foreach($res as $contact) {
@ -312,7 +311,7 @@ function poller_run($argv, $argc){
// Will only do this once per notify-enabled OStatus contact
// or if relationship changes
$stat_writeable = ((($contact['notify']) && ($contact['rel'] == REL_VIP || $contact['rel'] == REL_BUD)) ? 1 : 0);
$stat_writeable = ((($contact['notify']) && ($contact['rel'] == CONTACT_IS_FOLLOWER || $contact['rel'] == CONTACT_IS_FRIEND)) ? 1 : 0);
if($stat_writeable != $contact['writable']) {
q("UPDATE `contact` SET `writable` = %d WHERE `id` = %d LIMIT 1",
@ -323,7 +322,7 @@ function poller_run($argv, $argc){
// Are we allowed to import from this person?
if($contact['rel'] == REL_VIP || $contact['blocked'] || $contact['readonly'])
if($contact['rel'] == CONTACT_IS_FOLLOWER || $contact['blocked'] || $contact['readonly'])
continue;
$xml = fetch_url($contact['poll']);
@ -421,6 +420,10 @@ function poller_run($argv, $argc){
$datarray['contact-id'] = $contact['id'];
if($datarray['parent-uri'] === $datarray['uri'])
$datarray['private'] = 1;
if(! get_pconfig($importer_uid,'system','allow_public_email_replies')) {
$datarray['private'] = 1;
$datarray['allow_cid'] = '<' . $contact['id'] . '>';
}
$datarray['author-name'] = $contact['name'];
$datarray['author-link'] = 'mailbox';
$datarray['author-avatar'] = $contact['photo'];
@ -440,7 +443,8 @@ function poller_run($argv, $argc){
}
}
elseif($contact['network'] === NETWORK_FACEBOOK) {
// TODO: work in progress
// This is picked up by the Facebook plugin on a cron hook.
// Ignored here.
}
if($xml) {
@ -463,7 +467,7 @@ function poller_run($argv, $argc){
consume_feed($xml,$importer,$contact,$hub,1);
if((strlen($hub)) && ($hub_update) && (($contact['rel'] == REL_BUD) || (($contact['network'] === NETWORK_OSTATUS) && (! $contact['readonly'])))) {
if((strlen($hub)) && ($hub_update) && (($contact['rel'] == CONTACT_IS_FRIEND) || (($contact['network'] === NETWORK_OSTATUS) && (! $contact['readonly'])))) {
logger('poller: subscribing to hub(s) : ' . $hub . ' contact name : ' . $contact['name'] . ' local user : ' . $importer['name']);
$hubs = explode(',', $hub);
if(count($hubs)) {

View File

@ -1,53 +1,8 @@
<?php
require_once('library/asn1.php');
function salmon_key($pubkey) {
$lines = explode("\n",$pubkey);
unset($lines[0]);
unset($lines[count($lines)]);
$x = base64_decode(implode('',$lines));
$r = ASN_BASE::parseASNString($x);
$m = $r[0]->asnData[1]->asnData[0]->asnData[0]->asnData;
$e = $r[0]->asnData[1]->asnData[0]->asnData[1]->asnData;
require_once('include/crypto.php');
return 'RSA' . '.' . $m . '.' . $e ;
}
function base64url_encode($s, $strip_padding = false) {
$s = strtr(base64_encode($s),'+/','-_');
if($strip_padding)
$s = str_replace('=','',$s);
return $s;
}
function base64url_decode($s) {
/*
* // Placeholder for new rev of salmon which strips base64 padding.
* // PHP base64_decode handles the un-padded input without requiring this step
* // Uncomment if you find you need it.
*
* $l = strlen($s);
* if(! strpos($s,'=')) {
* $m = $l % 4;
* if($m == 2)
* $s .= '==';
* if($m == 3)
* $s .= '=';
* }
*
*/
return base64_decode(strtr($s,'-_','+/'));
}
function get_salmon_key($uri,$keyhash) {
$ret = array();
@ -141,28 +96,20 @@ EOT;
$data_type = 'application/atom+xml';
$encoding = 'base64url';
$algorithm = 'RSA-SHA256';
$keyhash = base64url_encode(hash('sha256',salmon_key($owner['spubkey'])));
// Setup RSA stuff to PKCS#1 sign the data
set_include_path(get_include_path() . PATH_SEPARATOR . 'library/phpsec');
require_once('library/phpsec/Crypt/RSA.php');
$rsa = new CRYPT_RSA();
$rsa->signatureMode = CRYPT_RSA_SIGNATURE_PKCS1;
$rsa->setHash('sha256');
$rsa->loadKey($owner['sprvkey']);
$keyhash = base64url_encode(hash('sha256',salmon_key($owner['spubkey'])),true);
// precomputed base64url encoding of data_type, encoding, algorithm concatenated with periods
$precomputed = '.YXBwbGljYXRpb24vYXRvbSt4bWw=.YmFzZTY0dXJs.UlNBLVNIQTI1Ng==';
$signature = base64url_encode($rsa->sign($data . $precomputed));
$signature = base64url_encode(rsa_sign(str_replace('=','',$data . $precomputed),true),$owner['sprvkey']);
$signature2 = base64url_encode($rsa->sign($data));
$signature2 = base64url_encode(rsa_sign($data . $precomputed),$owner['sprvkey']);
$signature3 = base64url_encode(rsa_sign($data),$owner['sprvkey']);
$salmon_tpl = get_markup_template('magicsig.tpl');
$salmon = replace_macros($salmon_tpl,array(
'$data' => $data,
'$encoding' => $encoding,
@ -184,11 +131,11 @@ EOT;
if($return_code > 299) {
logger('slapper: compliant salmon failed. Falling back to status.net hack');
logger('slapper: compliant salmon failed. Falling back to status.net hack2');
// Entirely likely that their salmon implementation is
// non-compliant. Let's try once more, this time only signing
// the data, without the precomputed blob
// the data, without stripping '=' chars
$salmon = replace_macros($salmon_tpl,array(
'$data' => $data,
@ -205,6 +152,30 @@ EOT;
));
$return_code = $a->get_curl_code();
if($return_code > 299) {
logger('slapper: compliant salmon failed. Falling back to status.net hack3');
// Entirely likely that their salmon implementation is
// non-compliant. Let's try once more, this time only signing
// the data, without the precomputed blob
$salmon = replace_macros($salmon_tpl,array(
'$data' => $data,
'$encoding' => $encoding,
'$algorithm' => $algorithm,
'$keyhash' => $keyhash,
'$signature' => $signature3
));
// slap them
post_url($url,$salmon, array(
'Content-type: application/magic-envelope+xml',
'Content-length: ' . strlen($salmon)
));
$return_code = $a->get_curl_code();
}
}
logger('slapper returned ' . $return_code);
if(! $return_code)

View File

@ -28,8 +28,8 @@ function can_write_wall(&$a,$owner) {
AND `user`.`blockwall` = 0 AND `readonly` = 0 AND ( `contact`.`rel` IN ( %d , %d ) OR `user`.`page-flags` = %d ) LIMIT 1",
intval($owner),
intval(remote_user()),
intval(REL_VIP),
intval(REL_BUD),
intval(CONTACT_IS_FOLLOWER),
intval(CONTACT_IS_FRIEND),
intval(PAGE_COMMUNITY)
);
if(count($r)) {

954
include/text.php Normal file
View File

@ -0,0 +1,954 @@
<?php
// This is our template processor.
// $s is the string requiring macro substitution.
// $r is an array of key value pairs (search => replace)
// returns substituted string.
// WARNING: this is pretty basic, and doesn't properly handle search strings that are substrings of each other.
// For instance if 'test' => "foo" and 'testing' => "bar", testing could become either bar or fooing,
// depending on the order in which they were declared in the array.
require_once("include/template_processor.php");
if(! function_exists('replace_macros')) {
function replace_macros($s,$r) {
global $t;
return $t->replace($s,$r);
}}
// random string, there are 86 characters max in text mode, 128 for hex
// output is urlsafe
define('RANDOM_STRING_HEX', 0x00 );
define('RANDOM_STRING_TEXT', 0x01 );
if(! function_exists('random_string')) {
function random_string($size = 64,$type = RANDOM_STRING_HEX) {
// generate a bit of entropy and run it through the whirlpool
$s = hash('whirlpool', (string) rand() . uniqid(rand(),true) . (string) rand(),(($type == RANDOM_STRING_TEXT) ? true : false));
$s = (($type == RANDOM_STRING_TEXT) ? str_replace("\n","",base64url_encode($s,true)) : $s);
return(substr($s,0,$size));
}}
/**
* This is our primary input filter.
*
* The high bit hack only involved some old IE browser, forget which (IE5/Mac?)
* that had an XSS attack vector due to stripping the high-bit on an 8-bit character
* after cleansing, and angle chars with the high bit set could get through as markup.
*
* This is now disabled because it was interfering with some legitimate unicode sequences
* and hopefully there aren't a lot of those browsers left.
*
* Use this on any text input where angle chars are not valid or permitted
* They will be replaced with safer brackets. This may be filtered further
* if these are not allowed either.
*
*/
if(! function_exists('notags')) {
function notags($string) {
return(str_replace(array("<",">"), array('[',']'), $string));
// High-bit filter no longer used
// return(str_replace(array("<",">","\xBA","\xBC","\xBE"), array('[',']','','',''), $string));
}}
// use this on "body" or "content" input where angle chars shouldn't be removed,
// and allow them to be safely displayed.
if(! function_exists('escape_tags')) {
function escape_tags($string) {
return(htmlspecialchars($string));
}}
// generate a string that's random, but usually pronounceable.
// used to generate initial passwords
if(! function_exists('autoname')) {
function autoname($len) {
$vowels = array('a','a','ai','au','e','e','e','ee','ea','i','ie','o','ou','u');
if(mt_rand(0,5) == 4)
$vowels[] = 'y';
$cons = array(
'b','bl','br',
'c','ch','cl','cr',
'd','dr',
'f','fl','fr',
'g','gh','gl','gr',
'h',
'j',
'k','kh','kl','kr',
'l',
'm',
'n',
'p','ph','pl','pr',
'qu',
'r','rh',
's','sc','sh','sm','sp','st',
't','th','tr',
'v',
'w','wh',
'x',
'z','zh'
);
$midcons = array('ck','ct','gn','ld','lf','lm','lt','mb','mm', 'mn','mp',
'nd','ng','nk','nt','rn','rp','rt');
$noend = array('bl', 'br', 'cl','cr','dr','fl','fr','gl','gr',
'kh', 'kl','kr','mn','pl','pr','rh','tr','qu','wh');
$start = mt_rand(0,2);
if($start == 0)
$table = $vowels;
else
$table = $cons;
$word = '';
for ($x = 0; $x < $len; $x ++) {
$r = mt_rand(0,count($table) - 1);
$word .= $table[$r];
if($table == $vowels)
$table = array_merge($cons,$midcons);
else
$table = $vowels;
}
$word = substr($word,0,$len);
foreach($noend as $noe) {
if((strlen($word) > 2) && (substr($word,-2) == $noe)) {
$word = substr($word,0,-1);
break;
}
}
if(substr($word,-1) == 'q')
$word = substr($word,0,-1);
return $word;
}}
// escape text ($str) for XML transport
// returns escaped text.
if(! function_exists('xmlify')) {
function xmlify($str) {
$buffer = '';
for($x = 0; $x < strlen($str); $x ++) {
$char = $str[$x];
switch( $char ) {
case "\r" :
break;
case "&" :
$buffer .= '&amp;';
break;
case "'" :
$buffer .= '&apos;';
break;
case "\"" :
$buffer .= '&quot;';
break;
case '<' :
$buffer .= '&lt;';
break;
case '>' :
$buffer .= '&gt;';
break;
case "\n" :
$buffer .= "\n";
break;
default :
$buffer .= $char;
break;
}
}
$buffer = trim($buffer);
return($buffer);
}}
// undo an xmlify
// pass xml escaped text ($s), returns unescaped text
if(! function_exists('unxmlify')) {
function unxmlify($s) {
$ret = str_replace('&amp;','&', $s);
$ret = str_replace(array('&lt;','&gt;','&quot;','&apos;'),array('<','>','"',"'"),$ret);
return $ret;
}}
// convenience wrapper, reverse the operation "bin2hex"
if(! function_exists('hex2bin')) {
function hex2bin($s) {
if(! ctype_xdigit($s)) {
logger('hex2bin: illegal input: ' . print_r(debug_backtrace(), true));
return($s);
}
return(pack("H*",$s));
}}
// Automatic pagination.
// To use, get the count of total items.
// Then call $a->set_pager_total($number_items);
// Optionally call $a->set_pager_itemspage($n) to the number of items to display on each page
// Then call paginate($a) after the end of the display loop to insert the pager block on the page
// (assuming there are enough items to paginate).
// When using with SQL, the setting LIMIT %d, %d => $a->pager['start'],$a->pager['itemspage']
// will limit the results to the correct items for the current page.
// The actual page handling is then accomplished at the application layer.
if(! function_exists('paginate')) {
function paginate(&$a) {
$o = '';
$stripped = preg_replace('/(&page=[0-9]*)/','',$a->query_string);
$stripped = str_replace('q=','',$stripped);
$stripped = trim($stripped,'/');
$pagenum = $a->pager['page'];
$url = $a->get_baseurl() . '/' . $stripped;
if($a->pager['total'] > $a->pager['itemspage']) {
$o .= '<div class="pager">';
if($a->pager['page'] != 1)
$o .= '<span class="pager_prev">'."<a href=\"$url".'&page='.($a->pager['page'] - 1).'">' . t('prev') . '</a></span> ';
$o .= "<span class=\"pager_first\"><a href=\"$url"."&page=1\">" . t('first') . "</a></span> ";
$numpages = $a->pager['total'] / $a->pager['itemspage'];
$numstart = 1;
$numstop = $numpages;
if($numpages > 14) {
$numstart = (($pagenum > 7) ? ($pagenum - 7) : 1);
$numstop = (($pagenum > ($numpages - 7)) ? $numpages : ($numstart + 14));
}
for($i = $numstart; $i <= $numstop; $i++){
if($i == $a->pager['page'])
$o .= '<span class="pager_current">'.(($i < 10) ? '&nbsp;'.$i : $i);
else
$o .= "<span class=\"pager_n\"><a href=\"$url"."&page=$i\">".(($i < 10) ? '&nbsp;'.$i : $i)."</a>";
$o .= '</span> ';
}
if(($a->pager['total'] % $a->pager['itemspage']) != 0) {
if($i == $a->pager['page'])
$o .= '<span class="pager_current">'.(($i < 10) ? '&nbsp;'.$i : $i);
else
$o .= "<span class=\"pager_n\"><a href=\"$url"."&page=$i\">".(($i < 10) ? '&nbsp;'.$i : $i)."</a>";
$o .= '</span> ';
}
$lastpage = (($numpages > intval($numpages)) ? intval($numpages)+1 : $numpages);
$o .= "<span class=\"pager_last\"><a href=\"$url"."&page=$lastpage\">" . t('last') . "</a></span> ";
if(($a->pager['total'] - ($a->pager['itemspage'] * $a->pager['page'])) > 0)
$o .= '<span class="pager_next">'."<a href=\"$url"."&page=".($a->pager['page'] + 1).'">' . t('next') . '</a></span>';
$o .= '</div>'."\r\n";
}
return $o;
}}
// Turn user/group ACLs stored as angle bracketed text into arrays
if(! function_exists('expand_acl')) {
function expand_acl($s) {
// turn string array of angle-bracketed elements into numeric array
// e.g. "<1><2><3>" => array(1,2,3);
$ret = array();
if(strlen($s)) {
$t = str_replace('<','',$s);
$a = explode('>',$t);
foreach($a as $aa) {
if(intval($aa))
$ret[] = intval($aa);
}
}
return $ret;
}}
// Used to wrap ACL elements in angle brackets for storage
if(! function_exists('sanitise_acl')) {
function sanitise_acl(&$item) {
if(intval($item))
$item = '<' . intval(notags(trim($item))) . '>';
else
unset($item);
}}
// Convert an ACL array to a storable string
if(! function_exists('perms2str')) {
function perms2str($p) {
$ret = '';
$tmp = $p;
if(is_array($tmp)) {
array_walk($tmp,'sanitise_acl');
$ret = implode('',$tmp);
}
return $ret;
}}
// generate a guaranteed unique (for this domain) item ID for ATOM
// safe from birthday paradox
if(! function_exists('item_new_uri')) {
function item_new_uri($hostname,$uid) {
do {
$dups = false;
$hash = random_string();
$uri = "urn:X-dfrn:" . $hostname . ':' . $uid . ':' . $hash;
$r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' LIMIT 1",
dbesc($uri));
if(count($r))
$dups = true;
} while($dups == true);
return $uri;
}}
// Generate a guaranteed unique photo ID.
// safe from birthday paradox
if(! function_exists('photo_new_resource')) {
function photo_new_resource() {
do {
$found = false;
$resource = hash('md5',uniqid(mt_rand(),true));
$r = q("SELECT `id` FROM `photo` WHERE `resource-id` = '%s' LIMIT 1",
dbesc($resource)
);
if(count($r))
$found = true;
} while($found == true);
return $resource;
}}
// wrapper to load a view template, checking for alternate
// languages before falling back to the default
// obsolete, deprecated.
if(! function_exists('load_view_file')) {
function load_view_file($s) {
global $lang, $a;
if(! isset($lang))
$lang = 'en';
$b = basename($s);
$d = dirname($s);
if(file_exists("$d/$lang/$b"))
return file_get_contents("$d/$lang/$b");
$theme = current_theme();
if(file_exists("$d/theme/$theme/$b"))
return file_get_contents("$d/theme/$theme/$b");
return file_get_contents($s);
}}
if(! function_exists('get_intltext_template')) {
function get_intltext_template($s) {
global $lang;
if(! isset($lang))
$lang = 'en';
if(file_exists("view/$lang/$s"))
return file_get_contents("view/$lang/$s");
elseif(file_exists("view/en/$s"))
return file_get_contents("view/en/$s");
else
return file_get_contents("view/$s");
}}
if(! function_exists('get_markup_template')) {
function get_markup_template($s) {
$theme = current_theme();
if(file_exists("view/theme/$theme/$s"))
return file_get_contents("view/theme/$theme/$s");
else
return file_get_contents("view/$s");
}}
// for html,xml parsing - let's say you've got
// an attribute foobar="class1 class2 class3"
// and you want to find out if it contains 'class3'.
// you can't use a normal sub string search because you
// might match 'notclass3' and a regex to do the job is
// possible but a bit complicated.
// pass the attribute string as $attr and the attribute you
// are looking for as $s - returns true if found, otherwise false
if(! function_exists('attribute_contains')) {
function attribute_contains($attr,$s) {
$a = explode(' ', $attr);
if(count($a) && in_array($s,$a))
return true;
return false;
}}
if(! function_exists('logger')) {
function logger($msg,$level = 0) {
$debugging = get_config('system','debugging');
$loglevel = intval(get_config('system','loglevel'));
$logfile = get_config('system','logfile');
if((! $debugging) || (! $logfile) || ($level > $loglevel))
return;
@file_put_contents($logfile, datetime_convert() . ':' . session_id() . ' ' . $msg . "\n", FILE_APPEND);
return;
}}
if(! function_exists('activity_match')) {
function activity_match($haystack,$needle) {
if(($haystack === $needle) || ((basename($needle) === $haystack) && strstr($needle,NAMESPACE_ACTIVITY_SCHEMA)))
return true;
return false;
}}
// Pull out all #hashtags and @person tags from $s;
// We also get @person@domain.com - which would make
// the regex quite complicated as tags can also
// end a sentence. So we'll run through our results
// and strip the period from any tags which end with one.
// Returns array of tags found, or empty array.
if(! function_exists('get_tags')) {
function get_tags($s) {
$ret = array();
// ignore anything in a code block
$s = preg_replace('/\[code\](.*?)\[\/code\]/sm','',$s);
// Match full names against @tags including the space between first and last
// We will look these up afterward to see if they are full names or not recognisable.
if(preg_match_all('/(@[^ \x0D\x0A,:?]+ [^ \x0D\x0A,:?]+)([ \x0D\x0A,:?]|$)/',$s,$match)) {
foreach($match[1] as $mtch) {
if(strstr($mtch,"]")) {
// we might be inside a bbcode color tag - leave it alone
continue;
}
if(substr($mtch,-1,1) === '.')
$ret[] = substr($mtch,0,-1);
else
$ret[] = $mtch;
}
}
// Otherwise pull out single word tags. These can be @nickname, @first_last
// and #hash tags.
if(preg_match_all('/([@#][^ \x0D\x0A,:?]+)([ \x0D\x0A,:?]|$)/',$s,$match)) {
foreach($match[1] as $mtch) {
if(strstr($mtch,"]")) {
// 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
$ret[] = $mtch;
}
}
return $ret;
}}
// quick and dirty quoted_printable encoding
if(! function_exists('qp')) {
function qp($s) {
return str_replace ("%","=",rawurlencode($s));
}}
if(! function_exists('get_mentions')) {
function get_mentions($item) {
$o = '';
if(! strlen($item['tag']))
return $o;
$arr = explode(',',$item['tag']);
foreach($arr as $x) {
$matches = null;
if(preg_match('/@\[url=([^\]]*)\]/',$x,$matches)) {
$o .= "\t\t" . '<link rel="mentioned" href="' . $matches[1] . '" />' . "\r\n";
$o .= "\t\t" . '<link rel="ostatus:attention" href="' . $matches[1] . '" />' . "\r\n";
}
}
return $o;
}}
if(! function_exists('contact_block')) {
function contact_block() {
$o = '';
$a = get_app();
$shown = get_pconfig($a->profile['uid'],'system','display_friend_count');
if(! $shown)
$shown = 24;
if((! is_array($a->profile)) || ($a->profile['hide-friends']))
return $o;
$r = q("SELECT COUNT(*) AS `total` FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 and `pending` = 0",
intval($a->profile['uid'])
);
if(count($r)) {
$total = intval($r[0]['total']);
}
if(! $total) {
$o .= '<h4 class="contact-h4">' . t('No contacts') . '</h4>';
return $o;
}
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 and `pending` = 0 ORDER BY RAND() LIMIT %d",
intval($a->profile['uid']),
intval($shown)
);
if(count($r)) {
$o .= '<h4 class="contact-h4">' . sprintf( tt('%d Contact','%d Contacts', $total),$total) . '</h4><div id="contact-block">';
foreach($r as $rr) {
$o .= micropro($rr,true,'mpfriend');
}
$o .= '</div><div id="contact-block-end"></div>';
$o .= '<div id="viewcontacts"><a id="viewcontacts-link" href="viewcontacts/' . $a->profile['nickname'] . '">' . t('View Contacts') . '</a></div>';
}
$arr = array('contacts' => $r, 'output' => $o);
call_hooks('contact_block_end', $arr);
return $o;
}}
if(! function_exists('micropro')) {
function micropro($contact, $redirect = false, $class = '', $textmode = false) {
if($class)
$class = ' ' . $class;
$url = $contact['url'];
$sparkle = '';
if($redirect) {
$a = get_app();
$redirect_url = $a->get_baseurl() . '/redir/' . $contact['id'];
if(local_user() && ($contact['uid'] == local_user()) && ($contact['network'] === 'dfrn')) {
$url = $redirect_url;
$sparkle = ' sparkle';
}
}
$click = ((x($contact,'click')) ? ' onclick="' . $contact['click'] . '" ' : '');
if($click)
$url = '';
if($textmode) {
return '<div class="contact-block-textdiv' . $class . '"><a class="contact-block-link' . $class . $sparkle
. (($click) ? ' fakelink' : '') . '" '
. (($url) ? ' href="' . $url . '"' : '') . $click
. '" title="' . $contact['name'] . ' [' . $contact['url'] . ']" alt="' . $contact['name']
. '" >'. $contact['name'] . '</a></div>' . "\r\n";
}
else {
return '<div class="contact-block-div' . $class . '"><a class="contact-block-link' . $class . $sparkle
. (($click) ? ' fakelink' : '') . '" '
. (($url) ? ' href="' . $url . '"' : '') . $click . ' ><img class="contact-block-img' . $class . $sparkle . '" src="'
. $contact['micro'] . '" title="' . $contact['name'] . ' [' . $contact['url'] . ']" alt="' . $contact['name']
. '" /></a></div>' . "\r\n";
}
}}
if(! function_exists('search')) {
function search($s,$id='search-box',$url='/search') {
$a = get_app();
$o = '<div id="' . $id . '">';
$o .= '<form action="' . $a->get_baseurl() . $url . '" method="get" >';
$o .= '<input type="text" name="search" id="search-text" value="' . $s .'" />';
$o .= '<input type="submit" name="submit" id="search-submit" value="' . t('Search') . '" />';
$o .= '</form></div>';
return $o;
}}
if(! function_exists('valid_email')) {
function valid_email($x){
if(preg_match('/^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)+$/',$x))
return true;
return false;
}}
if(! function_exists('aes_decrypt')) {
function aes_decrypt($val,$ky)
{
$key="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
for($a=0;$a<strlen($ky);$a++)
$key[$a%16]=chr(ord($key[$a%16]) ^ ord($ky[$a]));
$mode = MCRYPT_MODE_ECB;
$enc = MCRYPT_RIJNDAEL_128;
$dec = @mcrypt_decrypt($enc, $key, $val, $mode, @mcrypt_create_iv( @mcrypt_get_iv_size($enc, $mode), MCRYPT_DEV_URANDOM ) );
return rtrim($dec,(( ord(substr($dec,strlen($dec)-1,1))>=0 and ord(substr($dec, strlen($dec)-1,1))<=16)? chr(ord( substr($dec,strlen($dec)-1,1))):null));
}}
if(! function_exists('aes_encrypt')) {
function aes_encrypt($val,$ky)
{
$key="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
for($a=0;$a<strlen($ky);$a++)
$key[$a%16]=chr(ord($key[$a%16]) ^ ord($ky[$a]));
$mode=MCRYPT_MODE_ECB;
$enc=MCRYPT_RIJNDAEL_128;
$val=str_pad($val, (16*(floor(strlen($val) / 16)+(strlen($val) % 16==0?2:1))), chr(16-(strlen($val) % 16)));
return mcrypt_encrypt($enc, $key, $val, $mode, mcrypt_create_iv( mcrypt_get_iv_size($enc, $mode), MCRYPT_DEV_URANDOM));
}}
/**
*
* Function: linkify
*
* Replace naked text hyperlink with HTML formatted hyperlink
*
*/
if(! function_exists('linkify')) {
function linkify($s) {
$s = preg_replace("/(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\.\=\_\~\#\'\%\$\!\+]*)/", ' <a href="$1" target="external-link">$1</a>', $s);
return($s);
}}
/**
*
* Function: smilies
*
* Description:
* Replaces text emoticons with graphical images
*
* @Parameter: string $s
*
* Returns string
*/
if(! function_exists('smilies')) {
function smilies($s) {
$a = get_app();
return str_replace(
array( '&lt;3', '&lt;/3', '&lt;\\3', ':-)', ':)', ';-)', ':-(', ':(', ':-P', ':P', ':-"', ':-x', ':-X', ':-D', '8-|', '8-O',
'~friendika', 'Diaspora*' ),
array(
'<img src="' . $a->get_baseurl() . '/images/smiley-heart.gif" alt="<3" />',
'<img src="' . $a->get_baseurl() . '/images/smiley-brokenheart.gif" alt="</3" />',
'<img src="' . $a->get_baseurl() . '/images/smiley-brokenheart.gif" alt="<\\3" />',
'<img src="' . $a->get_baseurl() . '/images/smiley-smile.gif" alt=":-)" />',
'<img src="' . $a->get_baseurl() . '/images/smiley-smile.gif" alt=":)" />',
'<img src="' . $a->get_baseurl() . '/images/smiley-wink.gif" alt=";-)" />',
'<img src="' . $a->get_baseurl() . '/images/smiley-frown.gif" alt=":-(" />',
'<img src="' . $a->get_baseurl() . '/images/smiley-frown.gif" alt=":(" />',
'<img src="' . $a->get_baseurl() . '/images/smiley-tongue-out.gif" alt=":-P" />',
'<img src="' . $a->get_baseurl() . '/images/smiley-tongue-out.gif" alt=":P" />',
'<img src="' . $a->get_baseurl() . '/images/smiley-kiss.gif" alt=":-\"" />',
'<img src="' . $a->get_baseurl() . '/images/smiley-kiss.gif" alt=":-x" />',
'<img src="' . $a->get_baseurl() . '/images/smiley-kiss.gif" alt=":-X" />',
'<img src="' . $a->get_baseurl() . '/images/smiley-laughing.gif" alt=":-D" />',
'<img src="' . $a->get_baseurl() . '/images/smiley-surprised.gif" alt="8-|" />',
'<img src="' . $a->get_baseurl() . '/images/smiley-surprised.gif" alt="8-O" />',
'<a href="http://project.friendika.com">~friendika <img src="' . $a->get_baseurl() . '/images/friendika-16.png" alt="~friendika" /></a>',
'<a href="http://joindiaspora.com">Diaspora<img src="' . $a->get_baseurl() . '/images/diaspora.png" alt="Diaspora*" /></a>',
), $s);
}}
if(! function_exists('day_translate')) {
function day_translate($s) {
$ret = str_replace(array('Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'),
array( t('Monday'), t('Tuesday'), t('Wednesday'), t('Thursday'), t('Friday'), t('Saturday'), t('Sunday')),
$s);
$ret = str_replace(array('January','February','March','April','May','June','July','August','September','October','November','December'),
array( t('January'), t('February'), t('March'), t('April'), t('May'), t('June'), t('July'), t('August'), t('September'), t('October'), t('November'), t('December')),
$ret);
return $ret;
}}
if(! function_exists('normalise_link')) {
function normalise_link($url) {
$ret = str_replace(array('https:','//www.'), array('http:','//'), $url);
return(rtrim($ret,'/'));
}}
/**
*
* Compare two URLs to see if they are the same, but ignore
* slight but hopefully insignificant differences such as if one
* is https and the other isn't, or if one is www.something and
* the other isn't - and also ignore case differences.
*
* Return true if the URLs match, otherwise false.
*
*/
if(! function_exists('link_compare')) {
function link_compare($a,$b) {
if(strcasecmp(normalise_link($a),normalise_link($b)) === 0)
return true;
return false;
}}
// Given an item array, convert the body element from bbcode to html and add smilie icons.
// If attach is true, also add icons for item attachments
if(! function_exists('prepare_body')) {
function prepare_body($item,$attach = false) {
$s = prepare_text($item['body']);
if(! $attach)
return $s;
$arr = explode(',',$item['attach']);
if(count($arr)) {
$s .= '<div class="body-attach">';
foreach($arr as $r) {
$matches = false;
$icon = '';
$cnt = preg_match('|\[attach\]href=\"(.*?)\" length=\"(.*?)\" type=\"(.*?)\" title=\"(.*?)\"\[\/attach\]|',$r,$matches);
if($cnt) {
$icontype = strtolower(substr($matches[3],0,strpos($matches[3],'/')));
switch($icontype) {
case 'video':
case 'audio':
case 'image':
case 'text':
$icon = '<div class="attachtype type-' . $icontype . '"></div>';
break;
default:
$icon = '<div class="attachtype type-unkn"></div>';
break;
}
$title = ((strlen(trim($matches[4]))) ? escape_tags(trim($matches[4])) : escape_tags($matches[1]));
$title .= ' ' . $matches[2] . ' ' . t('bytes');
$s .= '<a href="' . strip_tags($matches[1]) . '" title="' . $title . '" class="attachlink" target="external-link" >' . $icon . '</a>';
}
}
$s .= '<div class="clear"></div></div>';
}
return $s;
}}
// Given a text string, convert from bbcode to html and add smilie icons.
if(! function_exists('prepare_text')) {
function prepare_text($text) {
require_once('include/bbcode.php');
$s = smilies(bbcode($text));
return $s;
}}
/**
* return atom link elements for all of our hubs
*/
if(! function_exists('feed_hublinks')) {
function feed_hublinks() {
$hub = get_config('system','huburl');
$hubxml = '';
if(strlen($hub)) {
$hubs = explode(',', $hub);
if(count($hubs)) {
foreach($hubs as $h) {
$h = trim($h);
if(! strlen($h))
continue;
$hubxml .= '<link rel="hub" href="' . xmlify($h) . '" />' . "\n" ;
}
}
}
return $hubxml;
}}
/* return atom link elements for salmon endpoints */
if(! function_exists('feed_salmonlinks')) {
function feed_salmonlinks($nick) {
$a = get_app();
$salmon = '<link rel="salmon" href="' . xmlify($a->get_baseurl() . '/salmon/' . $nick) . '" />' . "\n" ;
// old style links that status.net still needed as of 12/2010
$salmon .= ' <link rel="http://salmon-protocol.org/ns/salmon-replies" href="' . xmlify($a->get_baseurl() . '/salmon/' . $nick) . '" />' . "\n" ;
$salmon .= ' <link rel="http://salmon-protocol.org/ns/salmon-mention" href="' . xmlify($a->get_baseurl() . '/salmon/' . $nick) . '" />' . "\n" ;
return $salmon;
}}
if(! function_exists('get_plink')) {
function get_plink($item) {
$a = get_app();
$plink = (((x($item,'plink')) && (! $item['private'])) ? '<div class="wall-item-links-wrapper"><a href="'
. $item['plink'] . '" title="' . t('link to source') . '" target="external-link" class="icon remote-link"></a></div>' : '');
return $plink;
}}
if(! function_exists('unamp')) {
function unamp($s) {
return str_replace('&amp;', '&', $s);
}}
if(! function_exists('lang_selector')) {
function lang_selector() {
global $lang;
$o = '<div id="lang-select-icon" class="icon language" title="' . t('Select an alternate language') . '" onclick="openClose(\'language-selector\');" ></div>';
$o .= '<div id="language-selector" style="display: none;" >';
$o .= '<form action="" method="post" ><select name="system_language" onchange="this.form.submit();" >';
$langs = glob('view/*/strings.php');
if(is_array($langs) && count($langs)) {
if(! in_array('view/en/strings.php',$langs))
$langs[] = 'view/en/';
asort($langs);
foreach($langs as $l) {
$ll = substr($l,5);
$ll = substr($ll,0,strrpos($ll,'/'));
$selected = (($ll === $lang) ? ' selected="selected" ' : '');
$o .= '<option value="' . $ll . '"' . $selected . '>' . $ll . '</option>';
}
}
$o .= '</select></form></div>';
return $o;
}}
if(! function_exists('return_bytes')) {
function return_bytes ($size_str) {
switch (substr ($size_str, -1))
{
case 'M': case 'm': return (int)$size_str * 1048576;
case 'K': case 'k': return (int)$size_str * 1024;
case 'G': case 'g': return (int)$size_str * 1073741824;
default: return $size_str;
}
}}
function generate_user_guid() {
$found = true;
do {
$guid = random_string(16);
$x = q("SELECT `uid` FROM `user` WHERE `guid` = '%s' LIMIT 1",
dbesc($guid)
);
if(! count($x))
$found = false;
} while ($found == true );
return $guid;
}
function pkcs5_pad ($text, $blocksize)
{
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
function pkcs5_unpad($text)
{
$pad = ord($text{strlen($text)-1});
if ($pad > strlen($text)) return false;
if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false;
return substr($text, 0, -1 * $pad);
}
function base64url_encode($s, $strip_padding = false) {
$s = strtr(base64_encode($s),'+/','-_');
if($strip_padding)
$s = str_replace('=','',$s);
return $s;
}
function base64url_decode($s) {
/*
* // Placeholder for new rev of salmon which strips base64 padding.
* // PHP base64_decode handles the un-padded input without requiring this step
* // Uncomment if you find you need it.
*
* $l = strlen($s);
* if(! strpos($s,'=')) {
* $m = $l % 4;
* if($m == 2)
* $s .= '==';
* if($m == 3)
* $s .= '=';
* }
*
*/
return base64_decode(strtr($s,'-_','+/'));
}
function cc_license() {
return '<div class="cc-license">' . t('Shared content is covered by the <a href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0</a> license.') . '</div>';
}

View File

@ -194,12 +194,18 @@ if(strlen($a->module)) {
*/
if(! $a->module_loaded) {
// Stupid browser tried to pre-fetch our ACL img template. Don't log the event or return anything - just quietly exit.
if((x($_SERVER,'QUERY_STRING')) && strpos($_SERVER['QUERY_STRING'],'{0}') !== false) {
killme();
}
if((x($_SERVER,'QUERY_STRING')) && ($_SERVER['QUERY_STRING'] === 'q=internal_error.html') && isset($dreamhost_error_hack)) {
logger('index.php: dreamhost_error_hack invoked. Original URI =' . $_SERVER['REQUEST_URI']);
goaway($a->get_baseurl() . $_SERVER['REQUEST_URI']);
}
logger('index.php: page not found: ' . $_SERVER['REQUEST_URI'] . ' QUERY: ' . $_SERVER['QUERY_STRING'], LOGGER_DEBUG);
logger('index.php: page not found: ' . $_SERVER['REQUEST_URI'] . ' ADDRESS: ' . $_SERVER['REMOTE_ADDR'] . ' QUERY: ' . $_SERVER['QUERY_STRING'], LOGGER_DEBUG);
header($_SERVER["SERVER_PROTOCOL"] . ' 404 ' . t('Not Found'));
notice( t('Page not found.' ) . EOL);
}

169
library/ASNValue.class.php Normal file
View File

@ -0,0 +1,169 @@
<?php
//-----------------------------------------------------------------------------
// ASNValue class by A.Oliinyk
// contact@pumka.net
//-----------------------------------------------------------------------------
class ASNValue
{
const TAG_INTEGER = 0x02;
const TAG_BITSTRING = 0x03;
const TAG_SEQUENCE = 0x30;
public $Tag;
public $Value;
function __construct($Tag=0x00, $Value='')
{
$this->Tag = $Tag;
$this->Value = $Value;
}
function Encode()
{
//Write type
$result = chr($this->Tag);
//Write size
$size = strlen($this->Value);
if ($size < 127) {
//Write size as is
$result .= chr($size);
}
else {
//Prepare length sequence
$sizeBuf = self::IntToBin($size);
//Write length sequence
$firstByte = 0x80 + strlen($sizeBuf);
$result .= chr($firstByte) . $sizeBuf;
}
//Write value
$result .= $this->Value;
return $result;
}
function Decode(&$Buffer)
{
//Read type
$this->Tag = self::ReadByte($Buffer);
//Read first byte
$firstByte = self::ReadByte($Buffer);
if ($firstByte < 127) {
$size = $firstByte;
}
else if ($firstByte > 127) {
$sizeLen = $firstByte - 0x80;
//Read length sequence
$size = self::BinToInt(self::ReadBytes($Buffer, $sizeLen));
}
else {
throw new Exception("Invalid ASN length value");
}
$this->Value = self::ReadBytes($Buffer, $size);
}
protected static function ReadBytes(&$Buffer, $Length)
{
$result = substr($Buffer, 0, $Length);
$Buffer = substr($Buffer, $Length);
return $result;
}
protected static function ReadByte(&$Buffer)
{
return ord(self::ReadBytes($Buffer, 1));
}
protected static function BinToInt($Bin)
{
$len = strlen($Bin);
$result = 0;
for ($i=0; $i<$len; $i++) {
$curByte = self::ReadByte($Bin);
$result += $curByte << (($len-$i-1)*8);
}
return $result;
}
protected static function IntToBin($Int)
{
$result = '';
do {
$curByte = $Int % 256;
$result .= chr($curByte);
$Int = ($Int - $curByte) / 256;
} while ($Int > 0);
$result = strrev($result);
return $result;
}
function SetIntBuffer($Value)
{
if (strlen($Value) > 1) {
$firstByte = ord($Value{0});
if ($firstByte & 0x80) { //first bit set
$Value = chr(0x00) . $Value;
}
}
$this->Value = $Value;
}
function GetIntBuffer()
{
$result = $this->Value;
if (ord($result{0}) == 0x00) {
$result = substr($result, 1);
}
return $result;
}
function SetInt($Value)
{
$Value = self::IntToBin($Value);
$this->SetIntBuffer($Value);
}
function GetInt()
{
$result = $this->GetIntBuffer();
$result = self::BinToInt($result);
return $result;
}
function SetSequence($Values)
{
$result = '';
foreach ($Values as $item) {
$result .= $item->Encode();
}
$this->Value = $result;
}
function GetSequence()
{
$result = array();
$seq = $this->Value;
while (strlen($seq)) {
$val = new ASNValue();
$val->Decode($seq);
$result[] = $val;
}
return $result;
}
}

View File

@ -187,7 +187,6 @@ class ASN_BASE {
return new ASN_BOOLEAN((bool)$data);
case ASN_INTEGER:
return new ASN_INTEGER(strtr(base64_encode($data),'+/','-_'));
// return new ASN_INTEGER(ord($data));
case ASN_BIT_STR:
return new ASN_BIT_STR(self::parseASNString($data, $level+1, $maxLevels));
case ASN_OCTET_STR:
@ -290,9 +289,3 @@ class ASN_BASE {
}
function accum($s) {
$result = strtr(base64_encode($s),'+/=','-_,');
return $result;
}

View File

@ -5517,6 +5517,7 @@ class SimplePie_Item
$type = null;
$url = null;
$width = null;
$title = $title_parent;
$url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
if (isset($link['attribs']['']['type']))
@ -5527,9 +5528,13 @@ class SimplePie_Item
{
$length = ceil($link['attribs']['']['length']);
}
if (isset($link['attribs']['']['title']))
{
$title = $this->sanitize($link['attribs']['']['title'], SIMPLEPIE_CONSTRUCT_TEXT);
}
// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
$this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
$this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title, $width);
}
}

View File

@ -192,8 +192,8 @@ function admin_page_site_post(&$a){
$no_community_page = !((x($_POST,'no_community_page')) ? True : False);
$verifyssl = ((x($_POST,'verifyssl')) ? True : False);
$proxyuser = ((x($_POST,'proxyuser')) ? notags(trim($_POST['global_search_url'])) : '');
$proxy = ((x($_POST,'proxy')) ? notags(trim($_POST['global_search_url'])) : '');
$proxyuser = ((x($_POST,'proxyuser')) ? notags(trim($_POST['proxyuser'])) : '');
$proxy = ((x($_POST,'proxy')) ? notags(trim($_POST['proxy'])) : '');
$timeout = ((x($_POST,'timeout')) ? intval(trim($_POST['timeout'])) : 60);
$dfrn_only = ((x($_POST,'dfrn_only')) ? True : False);
$ostatus_disabled = !((x($_POST,'ostatus_disabled')) ? True : False);
@ -234,7 +234,7 @@ function admin_page_site_post(&$a){
set_config('system','no_gravatar', $no_gravatar);
set_config('system','no_regfullname', $no_regfullname);
set_config('system','no_community_page', $no_community_page);
set_config('system','proxy', $no_utf);
set_config('system','no_utf', $no_utf);
set_config('system','verifyssl', $verifyssl);
set_config('system','proxyuser', $proxyuser);
set_config('system','proxy', $proxy);
@ -322,7 +322,7 @@ function admin_page_site(&$a) {
'$no_openid' => array('no_openid', t("OpenID support"), !get_config('system','no_openid'), "OpenID support for registration and logins."),
'$no_gravatar' => array('no_gravatar', t("Gravatar support"), !get_config('system','no_gravatar'), "Search new user's photo on Gravatar."),
'$no_regfullname' => array('no_regfullname', t("Fullname check"), !get_config('system','no_regfullname'), "Force users to register with a space between firstname and lastname in Full name, as an antispam measure"),
'$no_utf' => array('no_utf', t("UTF-8 Regular expressions"), !get_config('system','proxy'), "Use PHP UTF8 regular expressions"),
'$no_utf' => array('no_utf', t("UTF-8 Regular expressions"), !get_config('system','no_utf'), "Use PHP UTF8 regular expressions"),
'$no_community_page' => array('no_community_page', t("Show Community Page"), !get_config('system','no_community_page'), "Display a Community page showing all recent public postings on this site."),
'$ostatus_disabled' => array('ostatus_disabled', t("Enable OStatus support"), !get_config('system','ostatus_disable'), "Provide built-in OStatus \x28identi.ca, status.net, etc.\x29 compatibility. All communications in OStatus are public, so privacy warnings will be occasionally displayed."),
'$dfrn_only' => array('dfrn_only', t('Only allow Friendika contacts'), get_config('system','dfrn_only'), "All contacts must use Friendika protocols. All other built-in communication protocols disabled."),

50
mod/contactgroup.php Normal file
View File

@ -0,0 +1,50 @@
<?php
require_once('include/group.php');
function contactgroup_content(&$a) {
if(! local_user()) {
killme();
}
if(($a->argc > 2) && intval($a->argv[1]) && intval($a->argv[2])) {
$r = q("SELECT `id` FROM `contact` WHERE `id` = %d AND `uid` = %d and `self` = 0 and `blocked` = 0 AND `pending` = 0 LIMIT 1",
intval($a->argv[2]),
intval(local_user())
);
if(count($r))
$change = intval($a->argv[2]);
}
if(($a->argc > 1) && (intval($a->argv[1]))) {
$r = q("SELECT * FROM `group` WHERE `id` = %d AND `uid` = %d AND `deleted` = 0 LIMIT 1",
intval($a->argv[1]),
intval(local_user())
);
if(! count($r)) {
killme();
}
$group = $r[0];
$members = group_get_members($group['id']);
$preselected = array();
if(count($members)) {
foreach($members as $member)
$preselected[] = $member['id'];
}
if($change) {
if(in_array($change,$preselected)) {
group_rmv_member(local_user(),$group['name'],$change);
}
else {
group_add_member(local_user(),$group['name'],$change);
}
}
}
killme();
}

View File

@ -6,10 +6,22 @@ function contacts_init(&$a) {
if(! local_user())
return;
$contact_id = 0;
if(($a->argc == 2) && intval($a->argv[1])) {
$contact_id = intval($a->argv[1]);
$r = q("SELECT * FROM `contact` WHERE `uid` = %d and `id` = %d LIMIT 1",
intval(local_user()),
intval($contact_id)
);
if(! count($r)) {
$contact_id = 0;
}
}
require_once('include/group.php');
if(! x($a->page,'aside'))
$a->page['aside'] = '';
$a->page['aside'] .= group_side();
$a->page['aside'] .= group_side('contacts','group',false,0,$contact_id);
$inv = '<div class="side-link" id="side-invite-link" ><a href="invite" >' . t("Invite Friends") . '</a></div>';
@ -237,16 +249,16 @@ function contacts_content(&$a) {
$tpl = get_markup_template("contact_edit.tpl");
switch($r[0]['rel']) {
case REL_BUD:
case CONTACT_IS_FRIEND:
$dir_icon = 'images/lrarrow.gif';
$alt_text = t('Mutual Friendship');
break;
case REL_VIP;
case CONTACT_IS_FOLLOWER;
$dir_icon = 'images/larrow.gif';
$alt_text = t('is a fan of yours');
break;
case REL_FAN;
case CONTACT_IS_SHARING;
$dir_icon = 'images/rarrow.gif';
$alt_text = t('you are a fan of');
break;
@ -264,13 +276,6 @@ function contacts_content(&$a) {
}
$grps = '';
$member_of = member_of($r[0]['id']);
if(is_array($member_of) && count($member_of)) {
$grps = t('Member of: ') . EOL . '<ul>';
foreach($member_of as $member)
$grps .= '<li><a href="group/' . $member['id'] . '" title="' . t('Edit') . '" ><img src="images/spencil.gif" alt="' . t('Edit') . '" /></a> <a href="network/' . $member['id'] . '">' . $member['name'] . '</a></li>';
$grps .= '</ul>';
}
$insecure = '<div id="profile-edit-insecure"><p><img src="images/unlock_icon.gif" alt="' . t('Privacy Unavailable') . '" />&nbsp;'
. t('Private communications are not available for this contact.') . '</p></div>';
@ -314,7 +319,7 @@ function contacts_content(&$a) {
'$contact_id' => $r[0]['id'],
'$block_text' => (($r[0]['blocked']) ? t('Unblock this contact') : t('Block this contact') ),
'$ignore_text' => (($r[0]['readonly']) ? t('Unignore this contact') : t('Ignore this contact') ),
'$insecure' => (($r[0]['network'] !== NETWORK_DFRN && $r[0]['network'] !== NETWORK_MAIL && $r[0]['network'] !== NETWORK_FACEBOOK) ? $insecure : ''),
'$insecure' => (($r[0]['network'] !== NETWORK_DFRN && $r[0]['network'] !== NETWORK_MAIL && $r[0]['network'] !== NETWORK_FACEBOOK && $r[0]['network'] !== NETWORK_DIASPORA) ? $insecure : ''),
'$info' => $r[0]['info'],
'$blocked' => (($r[0]['blocked']) ? '<div id="block-message">' . t('Currently blocked') . '</div>' : ''),
'$ignored' => (($r[0]['readonly']) ? '<div id="ignore-message">' . t('Currently ignored') . '</div>' : ''),
@ -363,7 +368,7 @@ function contacts_content(&$a) {
$search = dbesc($search.'*');
$sql_extra .= ((strlen($search)) ? " AND MATCH `name` AGAINST ('$search' IN BOOLEAN MODE) " : "");
$sql_extra2 = ((($sort_type > 0) && ($sort_type <= REL_BUD)) ? sprintf(" AND `rel` = %d ",intval($sort_type)) : '');
$sql_extra2 = ((($sort_type > 0) && ($sort_type <= CONTACT_IS_FRIEND)) ? sprintf(" AND `rel` = %d ",intval($sort_type)) : '');
$r = q("SELECT COUNT(*) AS `total` FROM `contact`
@ -387,15 +392,15 @@ function contacts_content(&$a) {
continue;
switch($rr['rel']) {
case REL_BUD:
case CONTACT_IS_FRIEND:
$dir_icon = 'images/lrarrow.gif';
$alt_text = t('Mutual Friendship');
break;
case REL_VIP;
case CONTACT_IS_FOLLOWER;
$dir_icon = 'images/larrow.gif';
$alt_text = t('is a fan of yours');
break;
case REL_FAN;
case CONTACT_IS_SHARING;
$dir_icon = 'images/rarrow.gif';
$alt_text = t('you are a fan of');
break;

View File

@ -123,9 +123,12 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
$dfrn_confirm = $contact['confirm'];
$aes_allow = $contact['aes_allow'];
$network = ((strlen($contact['issued-id'])) ? 'dfrn' : 'stat');
$network = ((strlen($contact['issued-id'])) ? NETWORK_DFRN : NETWORK_OSTATUS);
if($network === 'dfrn') {
if($contact['network'])
$network = $contact['network'];
if($network === NETWORK_DFRN) {
/**
*
@ -298,19 +301,19 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
*
*/
require_once("Photo.php");
require_once('include/Photo.php');
$photos = import_profile_photo($contact['photo'],$uid,$contact_id);
logger('dfrn_confirm: confirm - imported photos');
if($network === 'dfrn') {
if($network === NETWORK_DFRN) {
$new_relation = REL_VIP;
if(($relation == REL_FAN) || ($duplex))
$new_relation = REL_BUD;
$new_relation = CONTACT_IS_FOLLOWER;
if(($relation == CONTACT_IS_SHARING) || ($duplex))
$new_relation = CONTACT_IS_FRIEND;
if(($relation == REL_FAN) && ($duplex))
if(($relation == CONTACT_IS_SHARING) && ($duplex))
$duplex = 0;
$r = q("UPDATE `contact` SET `photo` = '%s',
@ -337,21 +340,29 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
);
}
else {
// $network !== 'dfrn'
$notify = '';
$poll = '';
// $network !== NETWORK_DFRN
$arr = lrdd($contact['url']);
if(count($arr)) {
foreach($arr as $link) {
if($link['@attributes']['rel'] === 'salmon')
$notify = $link['@attributes']['href'];
if($link['@attributes']['rel'] === NAMESPACE_FEED)
$poll = $link['@attributes']['href'];
$network = (($contact['network']) ? $contact['network'] : NETWORK_OSTATUS);
$notify = (($contact['notify']) ? $contact['notify'] : '');
$poll = (($contact['poll']) ? $contact['poll'] : '');
if((! $contact['notify']) || (! $contact['poll'])) {
$arr = lrdd($contact['url']);
if(count($arr)) {
foreach($arr as $link) {
if($link['@attributes']['rel'] === 'salmon')
$notify = $link['@attributes']['href'];
if($link['@attributes']['rel'] === NAMESPACE_FEED)
$poll = $link['@attributes']['href'];
}
}
}
$new_relation = $contact['rel'];
if($network === NETWORK_DIASPORA && $duplex)
$new_relation = CONTACT_IS_FRIEND;
$r = q("DELETE FROM `intro` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($intro_id),
intval($uid)
@ -368,7 +379,8 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
`poll` = '%s',
`blocked` = 0,
`pending` = 0,
`network` = 'stat'
`network` = '%s',
`rel` = %d
WHERE `id` = %d LIMIT 1
",
dbesc($photos[0]),
@ -379,6 +391,8 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
dbesc(datetime_convert()),
dbesc($notify),
dbesc($poll),
dbesc($network),
intval($new_relation),
intval($contact_id)
);
}
@ -401,7 +415,13 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
$r = q("SELECT `hide-friends` FROM `profile` WHERE `uid` = %d AND `is-default` = 1 LIMIT 1",
intval($uid)
);
if((count($r)) && ($r[0]['hide-friends'] == 0) && (is_array($contact)) && isset($new_relation) && ($new_relation == REL_BUD)) {
if((count($r)) && ($r[0]['hide-friends'] == 0) && (is_array($contact)) && isset($new_relation) && ($new_relation == CONTACT_IS_FRIEND)) {
if($r[0]['network'] === NETWORK_DIASPORA) {
require_once('include/diaspora.php');
$ret = diaspora_share($user[0],$r[0]);
logger('mod_follow: diaspora_share returns: ' . $ret);
}
require_once('include/items.php');
@ -528,12 +548,22 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
dbesc($decrypted_source_url),
intval($local_uid)
);
if(! count($ret)) {
// this is either a bogus confirmation (?) or we deleted the original introduction.
$message = t('Contact record was not found for you on our site.');
xml_status(3,$message);
return; // NOTREACHED
if(strstr($decrypted_source_url,'http:'))
$newurl = str_replace('http:','https:',$decrypted_source_url);
else
$newurl = str_replace('https:','http:',$decrypted_source_url);
$ret = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d LIMIT 1",
dbesc($newurl),
intval($local_uid)
);
if(! count($r)) {
// this is either a bogus confirmation (?) or we deleted the original introduction.
$message = t('Contact record was not found for you on our site.');
xml_status(3,$message);
return; // NOTREACHED
}
}
$relation = $ret[0]['rel'];
@ -592,11 +622,11 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
logger('dfrn_confirm: request - photos imported');
$new_relation = REL_FAN;
if(($relation == REL_VIP) || ($duplex))
$new_relation = REL_BUD;
$new_relation = CONTACT_IS_SHARING;
if(($relation == CONTACT_IS_FOLLOWER) || ($duplex))
$new_relation = CONTACT_IS_FRIEND;
if(($relation == REL_VIP) && ($duplex))
if(($relation == CONTACT_IS_FOLLOWER) && ($duplex))
$duplex = 0;
$r = q("UPDATE `contact` SET
@ -639,7 +669,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
if((count($r)) && ($r[0]['notify-flags'] & NOTIFY_CONFIRM)) {
push_lang($r[0]['language']);
$tpl = (($new_relation == REL_BUD)
$tpl = (($new_relation == CONTACT_IS_FRIEND)
? get_intltext_template('friend_complete_eml.tpl')
: get_intltext_template('intro_complete_eml.tpl'));
@ -672,7 +702,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
// somebody arrived here by mistake or they are fishing. Send them to the homepage.
goaway($a->get_baseurl());
goaway(z_root());
// NOTREACHED
}

View File

@ -704,6 +704,7 @@ function dfrn_notify_post(&$a) {
$ev['uid'] = $importer['uid'];
$ev['uri'] = $item_id;
$ev['edited'] = $datarray['edited'];
$ev['private'] = $datarray['private'];
$r = q("SELECT * FROM `event` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
dbesc($item_id),

View File

@ -61,7 +61,7 @@ function dfrn_poll_init(&$a) {
$my_id = '0:' . $dfrn_id;
break;
default:
goaway($a->get_baseurl());
goaway(z_root());
break; // NOTREACHED
}
@ -100,7 +100,7 @@ function dfrn_poll_init(&$a) {
$profile = $r[0]['nickname'];
goaway((strlen($destination_url)) ? $destination_url : $a->get_baseurl() . '/profile/' . $profile);
}
goaway($a->get_baseurl());
goaway(z_root());
}
@ -297,7 +297,7 @@ function dfrn_poll_post(&$a) {
$my_id = '0:' . $dfrn_id;
break;
default:
goaway($a->get_baseurl());
goaway(z_root());
break; // NOTREACHED
}
@ -420,7 +420,7 @@ function dfrn_poll_content(&$a) {
$my_id = '0:' . $dfrn_id;
break;
default:
goaway($a->get_baseurl());
goaway(z_root());
break; // NOTREACHED
}

View File

@ -48,7 +48,7 @@ function dfrn_request_post(&$a) {
if($_POST['cancel']) {
goaway($a->get_baseurl());
goaway(z_root());
}
@ -190,7 +190,7 @@ function dfrn_request_post(&$a) {
// invalid/bogus request
notice( t('Unrecoverable protocol error.') . EOL );
goaway($a->get_baseurl());
goaway(z_root());
return; // NOTREACHED
}
@ -309,7 +309,7 @@ function dfrn_request_post(&$a) {
notice( t('You have already introduced yourself here.') . EOL );
return;
}
elseif($ret[0]['rel'] == REL_BUD) {
elseif($ret[0]['rel'] == CONTACT_IS_FRIEND) {
notice( sprintf( t('Apparently you are already friends with %s.'), $a->profile['name']) . EOL);
return;
}
@ -445,7 +445,7 @@ function dfrn_request_post(&$a) {
*
* OStatus network
* Check contact existence
* Try and scrape together enough information to create a contact record, with us as REL_VIP
* Try and scrape together enough information to create a contact record, with us as CONTACT_IS_FOLLOWER
* Substitute our user's feed URL into $url template
* Send the subscriber home to subscribe
*
@ -602,7 +602,7 @@ function dfrn_request_content(&$a) {
$myaddr = $a->get_baseurl() . '/profile/' . $a->user['nickname'];
}
else {
$myaddr = $a->user['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3 );
$myaddr = $a->user['nickname'] . '@' . substr(z_root(), strpos(z_root(),'://') + 3 );
}
}
elseif(x($_GET,'addr')) {

View File

@ -114,7 +114,7 @@ function display_content(&$a) {
}
$o .= '<div class="cc-license">' . t('Shared content is covered by the <a href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0</a> license.') . '</div>';
$o .= cc_license();
return $o;
}

View File

@ -297,6 +297,12 @@ function events_content(&$a) {
$fhour = ((x($orig_event)) ? datetime_convert('UTC', $tz, $fdt, 'H') : 0);
$fminute = ((x($orig_event)) ? datetime_convert('UTC', $tz, $fdt, 'i') : 0);
$f = get_config('system','event_input_format');
if(! $f)
$f = 'ymd';
$dateformat = datesel_format($f);
$timeformat = t('hour:minute');
require_once('include/acl_selectors.php');
@ -306,14 +312,14 @@ function events_content(&$a) {
'$cid' => $cid,
'$uri' => $uri,
'$e_text' => t('Event details'),
'$e_desc' => t('Format is year-month-day hour:minute. Starting date and Description are required.'),
'$e_desc' => sprintf( t('Format is %s %s. Starting date and Description are required.'),$dateformat,$timeformat),
'$s_text' => t('Event Starts:') . ' <span class="required">*</span> ',
'$s_dsel' => datesel('start',$syear+5,$syear,false,$syear,$smonth,$sday),
'$s_dsel' => datesel($f,'start',$syear+5,$syear,false,$syear,$smonth,$sday),
'$s_tsel' => timesel('start',$shour,$sminute),
'$n_text' => t('Finish date/time is not known or not relevant'),
'$n_checked' => $n_checked,
'$f_text' => t('Event Finishes:'),
'$f_dsel' => datesel('finish',$fyear+5,$fyear,false,$fyear,$fmonth,$fday),
'$f_dsel' => datesel($f,'finish',$fyear+5,$fyear,false,$fyear,$fmonth,$fday),
'$f_tsel' => timesel('finish',$fhour,$fminute),
'$a_text' => t('Adjust for viewer timezone'),
'$a_checked' => $a_checked,

View File

@ -58,7 +58,7 @@ function follow_post(&$a) {
}
if($ret['network'] === NETWORK_OSTATUS && get_config('system','ostatus_disabled')) {
notice( t('Communication options with this network have been restricted.') . EOL);
notice( t('The profile address specified belongs to a network which has been disabled on this site.') . EOL);
$ret['notify'] = '';
}
@ -71,6 +71,9 @@ function follow_post(&$a) {
$writeable = 1;
}
if($ret['network'] === NETWORK_DIASPORA)
$writeable = 1;
// check if we already have a contact
// the poll url is more reliable than the profile url, as we may have
// indirect links or webfinger links
@ -82,15 +85,20 @@ function follow_post(&$a) {
if(count($r)) {
// update contact
if($r[0]['rel'] == REL_VIP) {
if($r[0]['rel'] == CONTACT_IS_FOLLOWER || ($network === NETWORK_DIASPORA && $r[0]['rel'] == CONTACT_IS_SHARING)) {
q("UPDATE `contact` SET `rel` = %d , `readonly` = 0 WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval(REL_BUD),
intval(CONTACT_IS_FRIEND),
intval($r[0]['id']),
intval(local_user())
);
}
}
else {
$new_relation = (($ret['network'] === NETWORK_MAIL) ? CONTACT_IS_FRIEND : CONTACT_IS_SHARING);
if($ret['network'] === NETWORK_DIASPORA)
$new_relation = CONTACT_IS_FOLLOWER;
// create contact record
$r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `addr`, `alias`, `notify`, `poll`, `name`, `nick`, `photo`, `network`, `rel`, `priority`,
`writable`, `blocked`, `readonly`, `pending` )
@ -106,7 +114,7 @@ function follow_post(&$a) {
dbesc($ret['nick']),
dbesc($ret['photo']),
dbesc($ret['network']),
intval(($ret['network'] === NETWORK_MAIL) ? REL_BUD : REL_FAN),
intval($new_relation),
intval($ret['priority']),
intval($writeable)
);
@ -175,10 +183,16 @@ function follow_post(&$a) {
intval(local_user())
);
if((count($r)) && (x($contact,'notify')) && (strlen($contact['notify']))) {
require_once('include/salmon.php');
slapper($r[0],$contact['notify'],$slap);
if(count($r)) {
if(($contact['network'] == NETWORK_OSTATUS) && (strlen($contact['notify']))) {
require_once('include/salmon.php');
slapper($r[0],$contact['notify'],$slap);
}
if($contact['network'] == NETWORK_DIASPORA) {
require_once('include/diaspora.php');
$ret = diaspora_share($a->user,$r[0]);
logger('mod_follow: diaspora_share returns: ' . $ret);
}
}
goaway($_SESSION['return_url']);

View File

@ -16,7 +16,7 @@ function friendika_init(&$a) {
$data = Array(
'version' => FRIENDIKA_VERSION,
'url' => $a->get_baseurl(),
'url' => z_root(),
'plugins' => $a->plugins,
'register_policy' => $register_policy[$a->config['register_policy']],
'admin' => $admin,
@ -40,7 +40,7 @@ function friendika_content(&$a) {
$o .= '<p></p><p>';
$o .= t('This is Friendika version') . ' ' . FRIENDIKA_VERSION . ' ';
$o .= t('running at web location') . ' ' . $a->get_baseurl() . '</p><p>';
$o .= t('running at web location') . ' ' . z_root() . '</p><p>';
$o .= t('Shared content within the Friendika network is provided under the <a href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 license</a>') . '</p><p>';

50
mod/hcard.php Normal file
View File

@ -0,0 +1,50 @@
<?php
function hcard_init(&$a) {
if((get_config('system','block_public')) && (! local_user()) && (! remote_user()))
return;
if($a->argc > 1)
$which = $a->argv[1];
else {
notice( t('No profile') . EOL );
$a->error = 404;
return;
}
$profile = 0;
if((local_user()) && ($a->argc > 2) && ($a->argv[2] === 'view')) {
$which = $a->user['nickname'];
$profile = $a->argv[1];
}
profile_load($a,$which,$profile);
if((x($a->profile,'page-flags')) && ($a->profile['page-flags'] == PAGE_COMMUNITY)) {
$a->page['htmlhead'] .= '<meta name="friendika.community" content="true" />';
}
if(x($a->profile,'openidserver'))
$a->page['htmlhead'] .= '<link rel="openid.server" href="' . $a->profile['openidserver'] . '" />' . "\r\n";
if(x($a->profile,'openid')) {
$delegate = ((strstr($a->profile['openid'],'://')) ? $a->profile['openid'] : 'http://' . $a->profile['openid']);
$a->page['htmlhead'] .= '<link rel="openid.delegate" href="' . $delegate . '" />' . "\r\n";
}
$keywords = ((x($a->profile,'pub_keywords')) ? $a->profile['pub_keywords'] : '');
$keywords = str_replace(array(',',' ',',,'),array(' ',',',','),$keywords);
if(strlen($keywords))
$a->page['htmlhead'] .= '<meta name="keywords" content="' . $keywords . '" />' . "\r\n" ;
$a->page['htmlhead'] .= '<meta name="dfrn-global-visibility" content="' . (($a->profile['net-publish']) ? 'true' : 'false') . '" />' . "\r\n" ;
$a->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $a->get_baseurl() . '/dfrn_poll/' . $which .'" />' . "\r\n" ;
$uri = urlencode('acct:' . $a->profile['nickname'] . '@' . $a->get_hostname() . (($a->path) ? '/' . $a->path : ''));
$a->page['htmlhead'] .= '<link rel="lrdd" type="application/xrd+xml" href="' . $a->get_baseurl() . '/xrd/?uri=' . $uri . '" />' . "\r\n";
header('Link: <' . $a->get_baseurl() . '/xrd/?uri=' . $uri . '>; rel="lrdd"; type="application/xrd+xml"', false);
$dfrn_pages = array('request', 'confirm', 'notify', 'poll');
foreach($dfrn_pages as $dfrn)
$a->page['htmlhead'] .= "<link rel=\"dfrn-{$dfrn}\" href=\"".$a->get_baseurl()."/dfrn_{$dfrn}/{$which}\" />\r\n";
}

View File

@ -9,7 +9,9 @@ function load_doc_file($s) {
$d = dirname($s);
if(file_exists("$d/$lang/$b"))
return file_get_contents("$d/$lang/$b");
return file_get_contents($s);
if(file_exists($s))
return file_get_contents($s);
return '';
}}
@ -31,6 +33,11 @@ function help_content(&$a) {
$a->page['title'] = t('Help');
}
if(! strlen($text)) {
header($_SERVER["SERVER_PROTOCOL"] . ' 404 ' . t('Not Found'));
notice( t('Page not found.' ) . EOL);
return;
}
return Markdown($text);

View File

@ -1,11 +1,10 @@
<?php
function hostxrd($baseurl) {
function hostxrd_init(&$a) {
header('Access-Control-Allow-Origin: *');
header("Content-type: text/xml");
$tpl = file_get_contents('view/xrd_host.tpl');
echo str_replace('$domain',$baseurl,$tpl);
echo str_replace(array('$zroot','$domain'),array(z_root(),z_path()),$tpl);
session_write_close();
exit();

View File

@ -123,15 +123,15 @@ function install_content(&$a) {
$o .= replace_macros($tpl, array(
'$lbl_01' => t('Friendika Social Network'),
'$lbl_02' => t('Installation'),
'$lbl_03' => t('In order to install Friendika we need to know how to contact your database.'),
'$lbl_03' => t('In order to install Friendika we need to know how to connect to your database.'),
'$lbl_04' => t('Please contact your hosting provider or site administrator if you have questions about these settings.'),
'$lbl_05' => t('The database you specify below must already exist. If it does not, please create it before continuing.'),
'$lbl_05' => t('The database you specify below should already exist. If it does not, please create it before continuing.'),
'$lbl_06' => t('Database Server Name'),
'$lbl_07' => t('Database Login Name'),
'$lbl_08' => t('Database Login Password'),
'$lbl_09' => t('Database Name'),
'$lbl_10' => t('Please select a default timezone for your website'),
'$lbl_11' => t('Site administrator email address. Your account email address will need match this.'),
'$lbl_11' => t('Site administrator email address. Your account email address must match this in order to use the web admin panel.'),
'$baseurl' => $a->get_baseurl(),
'$tzselect' => ((x($_POST,'timezone')) ? select_timezone($_POST['timezone']) : select_timezone()),
'$submit' => t('Submit'),

View File

@ -6,6 +6,8 @@
* text stuff. This function handles status, wall-to-wall status,
* local comments, and remote coments - that are posted on this site
* (as opposed to being delivered in a feed).
* Also processed here are posts and comments coming through the
* statusnet/twitter API.
* All of these become an "item" which is our basic unit of
* information.
* Posts that originate externally or do not fall into the above
@ -33,22 +35,61 @@ function item_post(&$a) {
call_hooks('post_local_start', $_POST);
$api_source = ((x($_POST,'api_source') && $_POST['api_source']) ? true : false);
/**
* Is this a reply to something?
*/
$parent = ((x($_POST,'parent')) ? intval($_POST['parent']) : 0);
$parent_uri = ((x($_POST,'parent_uri')) ? trim($_POST['parent_uri']) : '');
$parent_item = null;
$parent_contact = null;
$thr_parent = '';
$parid = 0;
$r = false;
if($parent) {
$r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1",
intval($parent)
);
if(! count($r)) {
if($parent || $parent_uri) {
if(! x($_POST,'type'))
$_POST['type'] = 'net-comment';
if($parent) {
$r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1",
intval($parent)
);
}
elseif($parent_uri && local_user()) {
// This is coming from an API source, and we are logged in
$r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
dbesc($parent_uri),
intval(local_user())
);
}
// if this isn't the real parent of the conversation, find it
if($r !== false && count($r)) {
$parid = $r[0]['parent'];
if($r[0]['id'] != $r[0]['parent']) {
$r = q("SELECT * FROM `item` WHERE `id` = `parent` AND `parent` = %d LIMIT 1",
intval($parid)
);
}
}
if(($r === false) || (! count($r))) {
notice( t('Unable to locate original post.') . EOL);
if(x($_POST,'return'))
goaway($a->get_baseurl() . "/" . $_POST['return'] );
killme();
}
$parent_item = $r[0];
$parent = $r[0]['id'];
// multi-level threading - preserve the info but re-parent to our single level threading
if(($parid) && ($parid != $parent))
$thr_parent = $parent_uri;
if($parent_item['contact-id'] && $uid) {
$r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($parent_item['contact-id']),
@ -59,6 +100,8 @@ function item_post(&$a) {
}
}
if($parent) logger('mod_post: parent=' . $parent);
$profile_uid = ((x($_POST,'profile_uid')) ? intval($_POST['profile_uid']) : 0);
$post_id = ((x($_POST['post_id'])) ? intval($_POST['post_id']) : 0);
$app = ((x($_POST['source'])) ? strip_tags($_POST['source']) : '');
@ -135,6 +178,20 @@ function item_post(&$a) {
$pubmail_enable = ((x($_POST,'pubmail_enable') && intval($_POST['pubmail_enable']) && (! $private)) ? 1 : 0);
// if using the API, we won't see pubmail_enable - figure out if it should be set
if($api_source && $profile_uid && $profile_uid == local_user() && (! $private)) {
$mail_disabled = ((function_exists('imap_open') && (! get_config('system','imap_disabled'))) ? 0 : 1);
if(! $mail_disabled) {
$r = q("SELECT * FROM `mailacct` WHERE `uid` = %d AND `server` != '' LIMIT 1",
intval(local_user())
);
if(count($r) && intval($r[0]['pubmail']))
$pubmail_enabled = true;
}
}
if(! strlen($body)) {
info( t('Empty post discarded.') . EOL );
if(x($_POST,'return'))
@ -180,6 +237,8 @@ function item_post(&$a) {
$contact_record = $r[0];
}
$post_type = notags(trim($_POST['type']));
if($post_type === 'net-comment') {
@ -259,6 +318,10 @@ function item_post(&$a) {
if(count($r)) {
$r = q("UPDATE `attach` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s'
WHERE `uid` = %d AND `id` = %d LIMIT 1",
dbesc($str_contact_allow),
dbesc($str_group_allow),
dbesc($str_contact_deny),
dbesc($str_group_deny),
intval($profile_uid),
intval($attach)
);
@ -391,7 +454,7 @@ function item_post(&$a) {
if(count($r)) {
if(strlen($attachments))
$attachments .= ',';
$attachments .= '[attach]href="' . $a->get_baseurl() . '/attach/' . $r[0]['id'] . '" size="' . $r[0]['filesize'] . '" type="' . $r[0]['filetype'] . '" title="' . (($r[0]['filename']) ? $r[0]['filename'] : ' ') . '"[/attach]';
$attachments .= '[attach]href="' . $a->get_baseurl() . '/attach/' . $r[0]['id'] . '" length="' . $r[0]['filesize'] . '" type="' . $r[0]['filetype'] . '" title="' . (($r[0]['filename']) ? $r[0]['filename'] : '') . '"[/attach]';
}
$body = str_replace($match[1],'',$body);
}
@ -443,6 +506,7 @@ function item_post(&$a) {
$datarray['private'] = $private;
$datarray['pubmail'] = $pubmail_enable;
$datarray['attach'] = $attachments;
$datarray['thr-parent'] = $thr_parent;
/**
* These fields are for the convenience of plugins...
@ -456,6 +520,9 @@ function item_post(&$a) {
if($orig_post)
$datarray['edit'] = true;
else
$datarray['guid'] = get_guid();
call_hooks('post_local',$datarray);
@ -479,10 +546,11 @@ function item_post(&$a) {
$post_id = 0;
$r = q("INSERT INTO `item` (`uid`,`type`,`wall`,`gravity`,`contact-id`,`owner-name`,`owner-link`,`owner-avatar`,
`author-name`, `author-link`, `author-avatar`, `created`, `edited`, `received`, `changed`, `uri`, `title`, `body`, `app`, `location`, `coord`,
$r = q("INSERT INTO `item` (`guid`, `uid`,`type`,`wall`,`gravity`,`contact-id`,`owner-name`,`owner-link`,`owner-avatar`,
`author-name`, `author-link`, `author-avatar`, `created`, `edited`, `received`, `changed`, `uri`, `thr-parent`, `title`, `body`, `app`, `location`, `coord`,
`tag`, `inform`, `verb`, `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid`, `private`, `pubmail`, `attach` )
VALUES( %d, '%s', %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s' )",
VALUES( '%s', %d, '%s', %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s' )",
dbesc($datarray['guid']),
intval($datarray['uid']),
dbesc($datarray['type']),
intval($datarray['wall']),
@ -499,6 +567,7 @@ function item_post(&$a) {
dbesc($datarray['received']),
dbesc($datarray['changed']),
dbesc($datarray['uri']),
dbesc($datarray['thr-parent']),
dbesc($datarray['title']),
dbesc($datarray['body']),
dbesc($datarray['app']),
@ -731,12 +800,16 @@ function item_post(&$a) {
}
logger('post_complete');
// figure out how to return, depending on from whence we came
if($api_source)
return;
if((x($_POST,'return')) && strlen($_POST['return'])) {
logger('return: ' . $_POST['return']);
goaway($a->get_baseurl() . "/" . $_POST['return'] );
}
if($_POST['api_source'])
return;
$json = array('success' => 1);
if(x($_POST,'jsreload') && strlen($_POST['jsreload']))
$json['reload'] = $a->get_baseurl() . '/' . $_POST['jsreload'];

View File

@ -3,6 +3,8 @@
function login_content(&$a) {
if(x($_SESSION,'theme'))
unset($_SESSION['theme']);
if(local_user())
goaway(z_root());
return login(($a->config['register_policy'] == REGISTER_CLOSED) ? false : true);
}

View File

@ -5,7 +5,7 @@ function lostpass_post(&$a) {
$email = notags(trim($_POST['login-name']));
if(! $email)
goaway($a->get_baseurl());
goaway(z_root());
$r = q("SELECT * FROM `user` WHERE ( `email` = '%s' OR `nickname` = '%s' ) AND `verified` = 1 AND `blocked` = 0 LIMIT 1",
dbesc($email),
@ -14,7 +14,7 @@ function lostpass_post(&$a) {
if(! count($r)) {
notice( t('No valid account found.') . EOL);
goaway($a->get_baseurl());
goaway(z_root());
}
$uid = $r[0]['uid'];
@ -46,7 +46,7 @@ function lostpass_post(&$a) {
. 'Content-transfer-encoding: 8bit' );
goaway($a->get_baseurl());
goaway(z_root());
}
@ -62,7 +62,7 @@ function lostpass_content(&$a) {
);
if(! count($r)) {
notice( t("Request could not be verified. \x28You may have previously submitted it.\x29 Password reset failed.") . EOL);
goaway($a->get_baseurl());
goaway(z_root());
return;
}
$uid = $r[0]['uid'];

View File

@ -297,9 +297,8 @@ function network_content(&$a, $update = 0) {
$o .= conversation($a,$r,$mode,$update);
if(! $update) {
$o .= paginate($a);
$o .= '<div class="cc-license">' . t('Shared content is covered by the <a href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0</a> license.') . '</div>';
$o .= cc_license();
}
return $o;

View File

@ -3,7 +3,7 @@
function notifications_post(&$a) {
if(! local_user()) {
goaway($a->get_baseurl());
goaway(z_root());
}
$request_id = (($a->argc > 1) ? $a->argv[1] : 0);
@ -60,7 +60,7 @@ function notifications_content(&$a) {
if(! local_user()) {
notice( t('Permission denied.') . EOL);
goaway($a->get_baseurl());
return;
}
$o = '';
@ -122,23 +122,25 @@ function notifications_content(&$a) {
continue;
}
$friend_selected = (($rr['network'] !== 'stat') ? ' checked="checked" ' : ' disabled ');
$fan_selected = (($rr['network'] === 'stat') ? ' checked="checked" disabled ' : '');
$friend_selected = (($rr['network'] !== NETWORK_OSTATUS) ? ' checked="checked" ' : ' disabled ');
$fan_selected = (($rr['network'] === NETWORK_OSTATUS) ? ' checked="checked" disabled ' : '');
$dfrn_tpl = get_markup_template('netfriend.tpl');
$knowyou = '';
$dfrn_text = '';
if($rr['network'] !== 'stat') {
$knowyou = t('Claims to be known to you: ') . (($rr['knowyou']) ? t('yes') : t('no'));
if($rr['network'] === NETWORK_DFRN || $rr['network'] === NETWORK_DIASPORA) {
if($rr['network'] === NETWORK_DFRN)
$knowyou = t('Claims to be known to you: ') . (($rr['knowyou']) ? t('yes') : t('no'));
else
$knowyou = '';
$dfrn_text = replace_macros($dfrn_tpl,array(
'$intro_id' => $rr['intro_id'],
'$friend_selected' => $friend_selected,
'$fan_selected' => $fan_selected,
'$approve_as' => t('Approve as: '),
'$as_friend' => t('Friend'),
'$as_fan' => t('Fan/Admirer')
'$as_fan' => (($rr['network'] == NETWORK_DIASPORA) ? t('Sharer') : t('Fan/Admirer'))
));
}
@ -146,7 +148,7 @@ function notifications_content(&$a) {
$o .= replace_macros($tpl,array(
'$str_notifytype' => t('Notification type: '),
'$notify_type' => (($rr['network'] !== 'stat') ? t('Friend/Connect Request') : t('New Follower')),
'$notify_type' => (($rr['network'] !== NETWORK_OSTATUS) ? t('Friend/Connect Request') : t('New Follower')),
'$dfrn_text' => $dfrn_text,
'$dfrn_id' => $rr['issued-id'],
'$uid' => $_SESSION['uid'],

View File

@ -8,7 +8,7 @@ function openid_content(&$a) {
$noid = get_config('system','no_openid');
if($noid)
goaway($a->get_baseurl());
goaway(z_root());
if((x($_GET,'openid_mode')) && (x($_SESSION,'openid'))) {
$openid = new LightOpenID;
@ -49,7 +49,7 @@ function openid_content(&$a) {
if($a->config['register_policy'] != REGISTER_CLOSED)
goaway($a->get_baseurl() . '/register' . $args);
else
goaway($a->get_baseurl());
goaway(z_root());
// NOTREACHED
}
@ -60,7 +60,7 @@ function openid_content(&$a) {
);
if(! count($r)) {
notice( t('Login failed.') . EOL );
goaway($a->get_baseurl());
goaway(z_root());
}
unset($_SESSION['openid']);
@ -116,10 +116,10 @@ function openid_content(&$a) {
if(($a->module !== 'home') && isset($_SESSION['return_url']))
goaway($a->get_baseurl() . '/' . $_SESSION['return_url']);
else
goaway($a->get_baseurl());
goaway(z_root());
}
}
notice( t('Login failed.') . EOL);
goaway($a->get_baseurl());
goaway(z_root());
// NOTREACHED
}

View File

@ -116,7 +116,7 @@ function parse_url_content(&$a) {
}
if(strlen($text)) {
$text = '<br /><br />' . $text;
$text = '<br /><br /><blockquote>' . $text . '</blockquote><br />';
}
echo sprintf($template,$url,($title) ? $title : $url,$text);

View File

@ -5,6 +5,11 @@ require_once('include/security.php');
function photo_init(&$a) {
switch($a->argc) {
case 4:
$person = $a->argv[3];
$customres = intval($a->argv[2]);
$type = $a->argv[1];
break;
case 3:
$person = $a->argv[2];
$type = $a->argv[1];
@ -29,6 +34,7 @@ function photo_init(&$a) {
switch($type) {
case 'profile':
case 'custom':
$resolution = 4;
break;
case 'micro':
@ -113,6 +119,15 @@ function photo_init(&$a) {
// NOTREACHED
}
if(intval($customres) && $customres > 0 && $customres < 500) {
require_once('include/Photo.php');
$ph = new Photo($data);
if($ph->is_valid()) {
$ph->scaleImageSquare($customres);
$data = $ph->imageString();
}
}
header("Content-type: image/jpeg");
echo $data;
killme();

View File

@ -903,7 +903,7 @@ function photos_content(&$a) {
$album = hex2bin($datum);
$r = q("SELECT `resource-id`, max(`scale`) AS `scale` FROM `photo` WHERE `uid` = %d AND `album` = '%s'
$sql_extra GROUP BY `resource-id`",
AND `scale` <= 4 $sql_extra GROUP BY `resource-id`",
intval($owner_uid),
dbesc($album)
);
@ -913,7 +913,7 @@ function photos_content(&$a) {
}
$r = q("SELECT `resource-id`, `id`, `filename`, max(`scale`) AS `scale`, `desc` FROM `photo` WHERE `uid` = %d AND `album` = '%s'
$sql_extra GROUP BY `resource-id` ORDER BY `created` DESC LIMIT %d , %d",
AND `scale` <= 4 $sql_extra GROUP BY `resource-id` ORDER BY `created` DESC LIMIT %d , %d",
intval($owner_uid),
dbesc($album),
intval($a->pager['start']),

24
mod/probe.php Normal file
View File

@ -0,0 +1,24 @@
<?php
require_once('include/Scrape.php');
function probe_content(&$a) {
$o .= '<h3>Probe Diagnostic</h3>';
$o .= '<form action="probe" method="get">';
$o .= 'Lookup address: <input type="text" style="width: 250px;" name="addr" value="' . $_GET['addr'] .'" />';
$o .= '<input type="submit" name="submit" value="Submit" /></form>';
$o .= '<br /><br />';
if(x($_GET,'addr')) {
$addr = trim($_GET['addr']);
$res = probe_url($addr);
$o .= '<pre>';
$o .= str_replace("\n",'<br />',print_r($res,true));
$o .= '</pre>';
}
return $o;
}

View File

@ -21,7 +21,7 @@ function profile_init(&$a) {
profile_load($a,$which,$profile);
if((x($a->profile,'page-flags')) && ($a->profile['page-flags'] & PAGE_COMMUNITY)) {
if((x($a->profile,'page-flags')) && ($a->profile['page-flags'] == PAGE_COMMUNITY)) {
$a->page['htmlhead'] .= '<meta name="friendika.community" content="true" />';
}
if(x($a->profile,'openidserver'))
@ -236,9 +236,8 @@ function profile_content(&$a, $update = 0) {
$o .= conversation($a,$r,'profile',$update);
if(! $update) {
$o .= paginate($a);
$o .= '<div class="cc-license">' . t('Shared content is covered by the <a href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0</a> license.') . '</div>';
$o .= cc_license();
}
return $o;

View File

@ -361,6 +361,9 @@ function profiles_content(&$a) {
$a->page['htmlhead'] .= replace_macros($tpl, array('$baseurl' => $a->get_baseurl()));
$a->page['htmlhead'] .= "<script type=\"text/javascript\" src=\"include/country.js\" ></script>";
$f = get_config('system','birthday_input_format');
if(! $f)
$f = 'ymd';
$is_default = (($r[0]['is-default']) ? 1 : 0);
$tpl = get_markup_template("profile_edit.tpl");
@ -375,7 +378,7 @@ function profiles_content(&$a) {
'$lbl_fullname' => t('Your Full Name:'),
'$lbl_title' => t('Title/Description:'),
'$lbl_gender' => t('Your Gender:'),
'$lbl_bd' => t("Birthday \x28y/m/d\x29:"),
'$lbl_bd' => sprintf( t("Birthday \x28%s\x29:"),datesel_format($f)),
'$lbl_address' => t('Street Address:'),
'$lbl_city' => t('Locality/City:'),
'$lbl_zip' => t('Postal/Zip Code:'),
@ -466,7 +469,7 @@ function profiles_content(&$a) {
'$id' => $rr['id'],
'$alt' => t('Profile Image'),
'$profile_name' => $rr['profile-name'],
'$visible' => (($rr['is-default']) ? '<strong>' . t('Visible to everybody') . '</strong>'
'$visible' => (($rr['is-default']) ? '<strong>' . t('visible to everybody') . '</strong>'
: '<a href="' . $a->get_baseurl() . '/profperm/' . $rr['id'] . '" />' . t('Edit visibility') . '</a>')
));
}

View File

@ -111,8 +111,8 @@ function pubsub_post(&$a) {
AND ( `rel` = %d OR `rel` = %d ) AND `blocked` = 0 AND `readonly` = 0 LIMIT 1",
intval($contact_id),
intval($importer['uid']),
intval(REL_FAN),
intval(REL_BUD)
intval(CONTACT_IS_SHARING),
intval(CONTACT_IS_FRIEND)
);
if(! count($r)) {

View File

@ -6,25 +6,14 @@
require_once('include/salmon.php');
require_once('library/simplepie/simplepie.inc');
require_once('include/crypto.php');
require_once('include/diaspora.php');
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);
http_status_exit(500);
$guid = $a->argv[2];
@ -32,183 +21,51 @@ function receive_post(&$a) {
dbesc($guid)
);
if(! count($r))
salmon_return(500);
http_status_exit(500);
$importer = $r[0];
$xml = $_POST['xml'];
// It is an application/x-www-form-urlencoded
$xml = urldecode($_POST['xml']);
logger('mod-diaspora: new salmon ' . $xml, LOGGER_DATA);
if(! $xml)
receive_return(500);
http_status_exit(500);
// parse the xml
$msg = diaspora_decode($importer,$xml);
$dom = simplexml_load_string($xml,'SimpleXMLElement',0,NAMESPACE_SALMON_ME);
logger('mod-diaspora: decoded msg: ' . print_r($msg,true), LOGGER_DATA);
// figure out where in the DOM tree our data is hiding
if(! is_array($msg))
http_status_exit(500);
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);
$parsed_xml = parse_xml_string($msg['message'],false);
$xmlbase = $parsed_xml->post;
if($xmlbase->request) {
diaspora_request($importer,$xmlbase->request);
}
elseif($xmlbase->status_message) {
diaspora_post($importer,$xmlbase->status_message);
}
elseif($xmlbase->comment) {
diaspora_comment($importer,$xmlbase->comment,$msg);
}
elseif($xmlbase->like) {
diaspora_like($importer,$xmlbase->like,$msg);
}
elseif($xmlbase->retraction) {
diaspora_retraction($importer,$xmlbase->retraction,$msg);
}
else {
logger('mod-diaspora: unknown message type: ' . print_r($xmlbase,true));
}
// 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);
http_status_exit(200);
// NOTREACHED
}

View File

@ -3,7 +3,7 @@
function redir_init(&$a) {
if((! local_user()) || (! ($a->argc == 2)) || (! intval($a->argv[1])))
goaway($a->get_baseurl());
goaway(z_root());
$cid = $a->argv[1];
$url = ((x($_GET,'url')) ? $_GET['url'] : '');
@ -13,7 +13,7 @@ function redir_init(&$a) {
);
if((! count($r)) || ($r[0]['network'] !== 'dfrn'))
goaway($a->get_baseurl());
goaway(z_root());
$dfrn_id = $orig_id = (($r[0]['issued-id']) ? $r[0]['issued-id'] : $r[0]['dfrn-id']);

View File

@ -201,7 +201,7 @@ function register_post(&$a) {
$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', '%s', %d, %d )",
dbesc(generate_guid()),
dbesc(generate_user_guid()),
dbesc($username),
dbesc($new_password_encoded),
dbesc($email),
@ -373,7 +373,7 @@ function register_post(&$a) {
if($res) {
info( t('Registration successful. Please check your email for further instructions.') . EOL ) ;
goaway($a->get_baseurl());
goaway(z_root());
}
else {
notice( t('Failed to send email message. Here is the message that failed.') . $email_tpl . EOL );
@ -382,7 +382,7 @@ function register_post(&$a) {
elseif($a->config['register_policy'] == REGISTER_APPROVE) {
if(! strlen($a->config['admin_email'])) {
notice( t('Your registration can not be processed.') . EOL);
goaway($a->get_baseurl());
goaway(z_root());
}
$hash = random_string();
@ -428,7 +428,7 @@ function register_post(&$a) {
if($res) {
info( t('Your registration is pending approval by the site owner.') . EOL ) ;
goaway($a->get_baseurl());
goaway(z_root());
}
}
@ -501,7 +501,7 @@ function register_content(&$a) {
}
$license = t('Shared content is covered by the <a href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0</a> license.');
$license = cc_license();
$o = get_markup_template("register.tpl");

View File

@ -29,7 +29,7 @@ function removeme_post(&$a) {
function removeme_content(&$a) {
if(! local_user())
goaway($a->get_baseurl());
goaway(z_root());
$hash = random_string();

View File

@ -5,6 +5,7 @@
// complicated process to try and sort out.
require_once('include/salmon.php');
require_once('include/crypto.php');
require_once('library/simplepie/simplepie.inc');
function salmon_return($val) {
@ -33,7 +34,7 @@ function salmon_post(&$a) {
dbesc($nick)
);
if(! count($r))
salmon_return(500);
http_status_exit(500);
$importer = $r[0];
@ -52,7 +53,7 @@ function salmon_post(&$a) {
if(! $base) {
logger('mod-salmon: unable to locate salmon data in xml ');
salmon_return(400);
http_status_exit(400);
}
// Stash the signature away for now. We have to find their key or it won't be good for anything.
@ -72,12 +73,16 @@ function salmon_post(&$a) {
$encoding = $base->encoding;
$alg = $base->alg;
// If we're talking to status.net or one of their ilk, they aren't following the magic envelope spec
// and only signed the data element. We'll be nice and let them validate anyway.
// Salmon magic signatures have evolved and there is no way of knowing ahead of time which
// flavour we have. We'll try and verify it regardless.
$stnet_signed_data = $data;
$signed_data = $data . '.' . base64url_encode($type) . '.' . base64url_encode($encoding) . '.' . base64url_encode($alg);
$compliant_format = str_replace('=','',$signed_data);
// decode the data
$data = base64url_decode($data);
@ -113,7 +118,7 @@ function salmon_post(&$a) {
if(! $author_link) {
logger('mod-salmon: Could not retrieve author URI.');
salmon_return(400);
http_status_exit(400);
}
// Once we have the author URI, go to the web and try to find their public key
@ -125,44 +130,35 @@ function salmon_post(&$a) {
if(! $key) {
logger('mod-salmon: Could not retrieve author key.');
salmon_return(400);
http_status_exit(400);
}
// Setup RSA stuff to verify the signature
set_include_path(get_include_path() . PATH_SEPARATOR . 'library/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));
logger('mod-salmon: key details: ' . print_r($key_info,true), LOGGER_DEBUG);
$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);
$pubkey = metopem($m,$e);
// We should have everything we need now. Let's see if it verifies.
// If it fails with the proper data format, try again using just the data
// (e.g. status.net)
$verify = $rsa->verify($signed_data,$signature);
$verify = rsa_verify($compliant_format,$signature,$pubkey);
if(! $verify) {
logger('mod-salmon: message did not verify using protocol. Trying statusnet hack.');
$verify = $rsa->verify($stnet_signed_data,$signature);
logger('mod-salmon: message did not verify using protocol. Trying padding hack.');
$verify = rsa_verify($signed_data,$signature,$pubkey);
}
if(! $verify) {
logger('mod-salmon: message did not verify using padding. Trying old statusnet hack.');
$verify = rsa_verify($stnet_signed_data,$signature,$pubkey);
}
if(! $verify) {
logger('mod-salmon: Message did not verify. Discarding.');
salmon_return(400);
http_status_exit(400);
}
logger('mod-salmon: Message verified.');
@ -187,9 +183,9 @@ function salmon_post(&$a) {
// 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']))) {
if((count($r)) && (($r[0]['readonly']) || ($r[0]['rel'] == CONTACT_IS_FOLLOWER) || ($r[0]['blocked']))) {
logger('mod-salmon: Ignoring this author.');
salmon_return(202);
http_status_exit(202);
// NOTREACHED
}
@ -211,7 +207,7 @@ function salmon_post(&$a) {
consume_feed($feedxml,$importer,$contact_rec,$hub);
salmon_return(200);
http_status_exit(200);
}

View File

@ -91,6 +91,7 @@ function search_content(&$a) {
$o .= conversation($a,$r,'search',false);
$o .= paginate($a);
$o .= cc_license();
return $o;
}

View File

@ -60,11 +60,11 @@ function wall_attach_post(&$a) {
}
$filedata = @file_get_contents($src);
$mimetype = mime_content_type($src);
$mimetype = z_mime_content_type($filename);
if((! strlen($mimetype)) || ($mimetype === 'application/octet-stream') && function_exists('mime_content_type'))
$mimetype = mime_content_type($filename);
$hash = random_string();
$created = datetime_convert();
$r = q("INSERT INTO `attach` ( `uid`, `hash`, `filename`, `filetype`, `filesize`, `data`, `created`, `edited`, `allow_cid`, `allow_gid`,`deny_cid`, `deny_gid` )
VALUES ( %d, '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
intval($page_owner_uid),

View File

@ -1,8 +1,8 @@
<?php
require_once('salmon.php');
require_once('include/crypto.php');
function xrd_content(&$a) {
function xrd_init(&$a) {
$uri = urldecode(notags(trim($_GET['uri'])));
@ -27,25 +27,23 @@ function xrd_content(&$a) {
header('Access-Control-Allow-Origin: *');
header("Content-type: text/xml");
$dspr_enabled = get_config('system','diaspora_enabled');
if($dspr_enabled) {
if(get_config('system','diaspora_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'])
'$dspr_key' => base64_encode(pemtorsa($r[0]['pubkey']))
));
}
else
$dspr = '';
$tpl = file_get_contents('view/xrd_person.tpl');
$o = replace_macros($tpl, array(
'$accturi' => $uri,
'$profile_url' => $a->get_baseurl() . '/profile/' . $r[0]['nickname'],
'$hcard_url' => $a->get_baseurl() . '/hcard/' . $r[0]['nickname'],
'$atom' => $a->get_baseurl() . '/dfrn_poll/' . $r[0]['nickname'],
'$photo' => $a->get_baseurl() . '/photo/profile/' . $r[0]['uid'] . '.jpg',
'$dspr' => $dspr,
@ -58,7 +56,7 @@ function xrd_content(&$a) {
$arr = array('user' => $r[0], 'xml' => $o);
call_hooks('personal_xrd', $arr);
echo $o;
echo $arr['xml'];
killme();
}

View File

@ -1,6 +1,6 @@
<?php
define( 'UPDATE_VERSION' , 1076 );
define( 'UPDATE_VERSION' , 1079 );
/**
*
@ -624,3 +624,25 @@ function update_1075() {
}
}
}
function update_1076() {
q("CREATE TABLE `guid` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`guid` CHAR( 16 ) NOT NULL , INDEX ( `guid` ) ) ENGINE = MYISAM ");
}
// There was a typo in 1076 so we'll try again in 1077 to make sure
// We'll also make it big enough to allow for future growth, I seriously
// doubt Diaspora will be able to leave guids at 16 bytes,
// and we can also use the same structure for our own larger guids
function update_1077() {
q("CREATE TABLE IF NOT EXISTS `guid` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`guid` CHAR( 16 ) NOT NULL , INDEX ( `guid` ) ) ENGINE = MYISAM ");
q("ALTER TABLE `guid` CHANGE `guid` `guid` CHAR( 64 ) NOT NULL");
}
function update_1078() {
q("ALTER TABLE `item` ADD `guid` CHAR( 64 ) NOT NULL AFTER `id` , ADD INDEX ( `guid` ) ");
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<config>
<site>
<name>$sitedesc</name>
<server>$sitename</server>
<name>$config.site.name</name>
<server>$config.site.server</server>
<theme>default</theme>
<path></path>
<logo>$sitelogo</logo>
<logo>$config.site.logo</logo>
<fancy>true</fancy>
<language>en</language>
<email>$adminemail</email>
<email>$config.site.email</email>
<broughtby></broughtby>
<broughtbyurl></broughtbyurl>
<timezone>UTC</timezone>
<closed>$siteclosed</closed>
<closed>$config.site.closed</closed>
<inviteonly>false</inviteonly>
<private>$siteprivate</private>
<textlimit>$textlimit</textlimit>
<ssl>$has_ssl</ssl>
<sslserver>$ssl_server</sslserver>
<private>$config.site.private</private>
<textlimit>$config.site.textlimit</textlimit>
<ssl>$config.site.ssl</ssl>
<sslserver>$config.site.sslserver</sslserver>
<shorturllength>30</shorturllength>
</site>

View File

@ -1,10 +1,10 @@
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:georss="http://www.georss.org/georss" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:media="http://purl.org/syndication/atommedia" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:statusnet="http://status.net/schema/api/1/">
<generator uri="http://status.net" version="0.9.7">StatusNet</generator>
<id>tag:friendika:PublicTimeline</id>
<title>Network on Friendika</title>
<subtitle>Your network updates on Friendika</subtitle>
<id>$rss.self</id>
<title>Friendika</title>
<subtitle>Friendika API feed</subtitle>
<logo>$rss.logo</logo>
<updated>$rss.updated</updated>
<updated>$rss.atom_updated</updated>
<link type="text/html" rel="alternate" href="$rss.alternate"/>
<link type="application/atom+xml" rel="self" href="$rss.self"/>
@ -53,28 +53,17 @@
{{ for $statuses as $status }}
<entry>
<activity:object-type>$status.objecttype</activity:object-type>
<id>$status.id</id>
<id>$status.message_id</id>
<title>$status.text</title>
<content type="html">$status.html</content>
<content type="html">$status.statusnet_html</content>
<link rel="alternate" type="text/html" href="$status.url"/>
<activity:verb>$status.verb</activity:verb>
<published>$status.published</published>
<updated>$status.updated</updated>
<!--
<source>
<id>http://identi.ca/api/statuses/user_timeline/397830.atom</id>
<title>Sin Mobopolitan</title>
<link rel="alternate" type="text/html" href="http://identi.ca/mobopolitan"/>
<link rel="self" type="application/atom+xml" href="http://identi.ca/api/statuses/user_timeline/397830.atom"/>
<link rel="license" href="http://creativecommons.org/licenses/by/3.0/"/>
<icon>http://avatar.identi.ca/397830-96-20110312195623.jpeg</icon>
<updated>2011-04-21T18:39:32+00:00</updated>
</source>
-->
<link rel="self" type="application/atom+xml" href="$status.self"/>
<link rel="edit" type="application/atom+xml" href="$status.edit"/>
<statusnet:notice_info local_id="$status.id" source="$status.source" favorite="false" repeated="false">
<statusnet:notice_info local_id="$status.id" source="$status.source" >
</statusnet:notice_info>
<author>
@ -82,10 +71,8 @@
<uri>$status.user.url</uri>
<name>$status.user.name</name>
<link rel="alternate" type="text/html" href="$status.user.url"/>
<link rel="avatar" type="image/jpeg" media:width="106" media:height="106" href="$status.user.profile_image_url"/>
<link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="$status.user.profile_image_url"/>
<link rel="avatar" type="image/jpeg" media:width="48" media:height="48" href="$status.user.profile_image_url"/>
<link rel="avatar" type="image/jpeg" media:width="24" media:height="24" href="$status.user.profile_image_url"/>
<georss:point/>
<poco:preferredUsername>$status.user.screen_name</poco:preferredUsername>
<poco:displayName>$status.user.name</poco:displayName>
@ -95,29 +82,7 @@
<poco:value>$status.user.url</poco:value>
<poco:primary>true</poco:primary>
</poco:urls>
<!-- <statusnet:profile_info local_id="123710" following="true" blocking="false"></statusnet:profile_info> -->
</author>
<!--Deprecation warning: activity:actor is present only for backward compatibility. It will be removed in the next version of StatusNet.-->
<activity:actor>
<activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type>
<id>$status.user.contact_url</id>
<title>$status.user.name</title>
<link rel="alternate" type="text/html" href="$status.user.url"/>
<link rel="avatar" type="image/jpeg" media:width="106" media:height="106" href="$status.user.profile_image_url"/>
<link rel="avatar" type="image/jpeg" media:width="96" media:height="96" href="$status.user.profile_image_url"/>
<link rel="avatar" type="image/jpeg" media:width="48" media:height="48" href="$status.user.profile_image_url"/>
<link rel="avatar" type="image/jpeg" media:width="24" media:height="24" href="$status.user.profile_image_url"/>
<georss:point/>
<poco:preferredUsername>$status.user.screen_name</poco:preferredUsername>
<poco:displayName>$status.user.name</poco:displayName>
<poco:address />
<poco:urls>
<poco:type>homepage</poco:type>
<poco:value>$status.user.url</poco:value>
<poco:primary>true</poco:primary>
</poco:urls>
<!-- <statusnet:profile_info local_id="123710" following="true" blocking="false"></statusnet:profile_info> -->
</activity:actor>
<link rel="ostatus:conversation" href="$status.url"/>
</entry>

View File

@ -4,6 +4,7 @@
<created_at>$status.created_at</created_at>
<id>$status.id</id>
<text>$status.text</text>
<statusnet_html>$status.statusnet_html</statusnet_html>
<source>$status.source</source>
<truncated>$status.truncated</truncated>
<url>$status.url</url>

View File

@ -7,7 +7,7 @@
<profile_image_url>$user.profile_image_url</profile_image_url>
<url>$user.url</url>
<protected>$user.protected</protected>
<followers_count>$user.followers</followers_count>
<followers_count>$user.followers_count</followers_count>
<profile_background_color>$user.profile_background_color</profile_background_color>
<profile_text_color>$user.profile_text_color</profile_text_color>
<profile_link_color>$user.profile_link_color</profile_link_color>
@ -21,10 +21,10 @@
<profile_background_image_url>$user.profile_background_image_url</profile_background_image_url>
<profile_background_tile>$user.profile_background_tile</profile_background_tile>
<profile_use_background_image>$user.profile_use_background_image</profile_use_background_image>
<notifications></notifications>
<notifications>$user.notifications</notifications>
<geo_enabled>$user.geo_enabled</geo_enabled>
<verified>$user.verified</verified>
<following></following>
<following>$user.following</following>
<statuses_count>$user.statuses_count</statuses_count>
<lang>$user.lang</lang>
<contributors_enabled>$user.contributors_enabled</contributors_enabled>

View File

@ -19,10 +19,10 @@
<updated>$feed_updated</updated>
<author>
<dfrn:owner>
<name dfrn:updated="$namdate" >$name</name>
<uri dfrn:updated="$uridate" >$profile_page</uri>
<link rel="photo" type="image/jpeg" dfrn:updated="$picdate" media:width="175" media:height="175" href="$photo" />
<link rel="avatar" type="image/jpeg" dfrn:updated="$picdate" media:width="175" media:height="175" href="$photo" />
$birthday
</author>
</dfrn:owner>

28
view/atom_feed_dfrn.tpl Normal file
View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8" ?>
<feed xmlns="http://www.w3.org/2005/Atom"
xmlns:thr="http://purl.org/syndication/thread/1.0"
xmlns:at="http://purl.org/atompub/tombstones/1.0"
xmlns:media="http://purl.org/syndication/atommedia"
xmlns:dfrn="http://purl.org/macgirvin/dfrn/1.0"
xmlns:as="http://activitystrea.ms/spec/1.0/"
xmlns:georss="http://www.georss.org/georss"
xmlns:poco="http://portablecontacts.net/spec/1.0"
xmlns:ostatus="http://ostatus.org/schema/1.0"
xmlns:statusnet="http://status.net/schema/api/1/" >
<id>$feed_id</id>
<title>$feed_title</title>
<generator uri="http://friendika.com" version="$version">Friendika</generator>
<link rel="license" href="http://creativecommons.org/licenses/by/3.0/" />
$hub
$salmon
<updated>$feed_updated</updated>
<author>
<name dfrn:updated="$namdate" >$name</name>
<uri dfrn:updated="$uridate" >$profile_page</uri>
<link rel="photo" type="image/jpeg" dfrn:updated="$picdate" media:width="175" media:height="175" href="$photo" />
<link rel="avatar" type="image/jpeg" dfrn:updated="$picdate" media:width="175" media:height="175" href="$photo" />
$birthday
</author>

File diff suppressed because it is too large Load Diff

View File

@ -24,6 +24,30 @@ $a->strings["Help:"] = "Hilfe:";
$a->strings["Help"] = "Hilfe";
$a->strings["File exceeds size limit of %d"] = "Die Datei ist größer als das erlaubte Limit von %d";
$a->strings["File upload failed."] = "Upload der Datei fehlgeschlagen.";
$a->strings["Friend suggestion sent."] = "Kontaktvorschlag gesendet.";
$a->strings["Suggest Friends"] = "Kontakte vorschlagen";
$a->strings["Suggest a friend for %s"] = "Schlage %s einen Kontakt vor";
$a->strings["Status"] = "Status";
$a->strings["Profile"] = "Profil";
$a->strings["Photos"] = "Bilder";
$a->strings["Events"] = "Veranstaltungen";
$a->strings["Personal Notes"] = "Persönliche Notizen";
$a->strings["Create New Event"] = "Neue Veranstaltung erstellen";
$a->strings["Previous"] = "Vorherige";
$a->strings["Next"] = "Nächste";
$a->strings["l, F j"] = "l, F j";
$a->strings["Edit event"] = "Veranstaltung bearbeiten";
$a->strings["link to source"] = "Link zum original Posting";
$a->strings["hour:minute"] = "Stunde:Minute";
$a->strings["Event details"] = "Veranstaltungsdetails";
$a->strings["Format is %s %s. Starting date and Description are required."] = "Format ist %s %s. Anfangsdatum und Beschreibung sind notwendig.";
$a->strings["Event Starts:"] = "Veranstaltungsbeginn:";
$a->strings["Finish date/time is not known or not relevant"] = "Enddatum/-zeit ist nicht bekannt oder nicht relevant";
$a->strings["Event Finishes:"] = "Veranstaltungsende:";
$a->strings["Adjust for viewer timezone"] = "An Zeitzone des Betrachters anpassen";
$a->strings["Description:"] = "Beschreibung";
$a->strings["Location:"] = "Ort:";
$a->strings["Share this event"] = "Veranstaltung teilen";
$a->strings["Cancel"] = "Abbrechen";
$a->strings["Tag removed"] = "Tag entfernt";
$a->strings["Remove Item Tag"] = "Gegenstands Tag entfernen";
@ -32,6 +56,7 @@ $a->strings["Remove"] = "Entfernen";
$a->strings["%s welcomes %s"] = "%s heißt %s herzlich willkommen";
$a->strings["Photo Albums"] = "Fotoalben";
$a->strings["Contact Photos"] = "Kontaktbilder";
$a->strings["everybody"] = "jeder";
$a->strings["Contact information unavailable"] = "Kontakt Informationen nicht verfügbar";
$a->strings["Profile Photos"] = "Profilbilder";
$a->strings["Album not found."] = "Album nicht gefunden.";
@ -41,10 +66,12 @@ $a->strings["was tagged in a"] = "was tagged in a";
$a->strings["photo"] = "Foto";
$a->strings["by"] = "von";
$a->strings["Image exceeds size limit of "] = "Die Bildgröße übersteigt das Limit von ";
$a->strings["Image file is empty."] = "Bilddatei ist leer.";
$a->strings["Unable to process image."] = "Konnte das Bild nicht bearbeiten.";
$a->strings["Image upload failed."] = "Hochladen des Bildes gescheitert.";
$a->strings["Public access denied."] = "Öffentlicher Zugriff verweigert.";
$a->strings["No photos selected"] = "Keine Bilder ausgewählt";
$a->strings["Access to this item is restricted."] = "Zugriff zu diesem Eintrag wurde eingeschrängt.";
$a->strings["Upload Photos"] = "Bilder hochladen";
$a->strings["New album name: "] = "Name des neuen Albums: ";
$a->strings["or existing album name: "] = "oder existierender Albumname: ";
@ -55,9 +82,7 @@ $a->strings["Photo not available"] = "Foto nicht verfügbar";
$a->strings["Edit photo"] = "Foto bearbeiten";
$a->strings["Use as profile photo"] = "Als Profilbild verwenden";
$a->strings["Private Message"] = "Private Nachricht";
$a->strings["<< Prev"] = "<< Vorherige";
$a->strings["View Full Size"] = "Betrachte Originalgröße";
$a->strings["Next >>"] = "Nächste >>";
$a->strings["Tags: "] = "Tags: ";
$a->strings["[Remove any tag]"] = "[Tag entfernen]";
$a->strings["New album name"] = "Name des neuen Albums";
@ -74,6 +99,10 @@ $a->strings["Delete"] = "Löschen";
$a->strings["Recent Photos"] = "Neuste Fotos";
$a->strings["Upload New Photos"] = "Weitere Fotos hochladen";
$a->strings["View Album"] = "Album betrachten";
$a->strings["Not available."] = "Nicht verfügbar.";
$a->strings["Community"] = "Gemeinschaft";
$a->strings["No results."] = "Keine Ergebnisse.";
$a->strings["Shared content is covered by the <a href=\"http://creativecommons.org/licenses/by/3.0/\">Creative Commons Attribution 3.0</a> license."] = "Geteilte Inhalte innerhalb des Friendika Netzwerks sind unter der <a href=\"http://creativecommons.org/licenses/by/3.0/\">Creative Commons Attribution 3.0</a> verfügbar.";
$a->strings["Item not found"] = "Beitrag nicht gefunden";
$a->strings["Edit post"] = "Beitrag bearbeiten";
$a->strings["Post to Email"] = "An Email senden";
@ -92,8 +121,8 @@ $a->strings["Public post"] = "Öffentlicher Beitrag";
$a->strings["Example: bob@example.com, mary@example.com"] = "Z.B.: bob@example.com, mary@example.com";
$a->strings["This introduction has already been accepted."] = "Diese Vorstellung wurde bereits abgeschlossen.";
$a->strings["Profile location is not valid or does not contain profile information."] = "Profil Adresse ist ungültig oder stellt einige Profildaten nicht zur Verfügung.";
$a->strings["Warning: profile location has no identifiable owner name."] = "Warning: profile location has no identifiable owner name.";
$a->strings["Warning: profile location has no profile photo."] = "Warning: profile location has no profile photo.";
$a->strings["Warning: profile location has no identifiable owner name."] = "Warnung: Es konnte kein Name des Besitzers von der angegebenen Profiladresse gefunden werden.";
$a->strings["Warning: profile location has no profile photo."] = "Warnung: Es konnte kein Profilbild bei der angegebenen Profiladresse gefunden werden.";
$a->strings["%d required parameter was not found at the given location"] = array(
0 => "",
1 => "",
@ -123,7 +152,7 @@ $a->strings["Administrator"] = "Administrator";
$a->strings["Friend/Connection Request"] = "Freundschafts/Kontakt Anfrage";
$a->strings["Examples: jojo@demo.friendika.com, http://demo.friendika.com/profile/jojo, testuser@identi.ca"] = "Beispiele: jojo@demo.friendika.com, http://demo.friendika.com/profile/jojo, testuser@identi.ca";
$a->strings["Please answer the following:"] = "Bitte beantworte folgende Fragen:";
$a->strings["Does \$name know you?"] = "Kennt \$name dich?";
$a->strings["Does %s know you?"] = "Kennt %s dich?";
$a->strings["Yes"] = "Ja";
$a->strings["No"] = "Nein";
$a->strings["Add a personal note:"] = "Eine persönliche Notiz anfügen:";
@ -146,14 +175,15 @@ $a->strings["You may need to import the file \"database.sql\" manually using php
$a->strings["Welcome to Friendika."] = "Willkommen bei Friendika.";
$a->strings["Friendika Social Network"] = "Friendika Soziales Netzwerk";
$a->strings["Installation"] = "Installation";
$a->strings["In order to install Friendika we need to know how to contact your database."] = "Um Friendika installieren zu können müssen wir wissen, wie wir die Datenbank erreichen können.";
$a->strings["In order to install Friendika we need to know how to connect to your database."] = "Um Friendika installieren zu können, müssen wir wissen wie wir deine MySQL Datenbank erreichen.";
$a->strings["Please contact your hosting provider or site administrator if you have questions about these settings."] = "Bitte kontaktiere den Hosting Provider oder den Administrator der Seite falls du Fragen zu diesen Einstellungen haben solltest.";
$a->strings["The database you specify below must already exist. If it does not, please create it before continuing."] = "Die Datenbank die du hier angibst muss bereits existieren. Wenn dies noch nicht der Fall ist lege sie bitte an bevor du fortfährst.";
$a->strings["The database you specify below should already exist. If it does not, please create it before continuing."] = "Die Datenbank die du unten angibst sollte bereits existieren. Ist dies noch nicht der Fall erzeuge sie bitte bevor du mit der Installation vorfährst.";
$a->strings["Database Server Name"] = "Datenbank Server";
$a->strings["Database Login Name"] = "Datenbank Nutzer";
$a->strings["Database Login Password"] = "Datenbank Passwort";
$a->strings["Database Name"] = "Datenbank Name";
$a->strings["Please select a default timezone for your website"] = "Bitte wähle die standard Zeitzone deiner Webseite";
$a->strings["Site administrator email address. Your account email address must match this in order to use the web admin panel."] = "Email Adresse des Seiten Administrators. Die Email Adresse deines Accounts muss mit dieser übereinstimmen, damit du das Administrationspanel nutzen kannst.";
$a->strings["Could not find a command line version of PHP in the web server PATH."] = "Konnte keine Kommandozeilenversion von PHP im PATH des Servers finden.";
$a->strings["This is required. Please adjust the configuration file .htconfig.php accordingly."] = "Diese wird von Friendika benötigt. Bitte passe die Konfigurationsdatei .htconfig.php entsprechend an.";
$a->strings["The command line version of PHP on your system does not have \"register_argc_argv\" enabled."] = "Die Kommandozeilenversion von PHP auf deinem System hat \"register_argc_argv\" nicht aktiviert.";
@ -165,13 +195,16 @@ $a->strings["Error: libCURL PHP module required but not installed."] = "Fehler:
$a->strings["Error: GD graphics PHP module with JPEG support required but not installed."] = "Fehler: Das GD Graphikmodul für PHP mit JPEG Unterstützung ist nicht installiert.";
$a->strings["Error: openssl PHP module required but not installed."] = "Fehler: Das openssl Modul von PHP ist nict installiert.";
$a->strings["Error: mysqli PHP module required but not installed."] = "Fehler: Das mysqli Modul von PHP ist nicht installiert.";
$a->strings["Error: mb_string PHP module required but not installed."] = "Fehler: mb_string PHP Module wird benötigt ist aber nicht installiert.";
$a->strings["The web installer needs to be able to create a file called \".htconfig.php\ in the top folder of your web server and it is unable to do so."] = "Der Installationswizzard muss in der Lage sein eine Datei im Stammverzeichnis deines Webservers anzuliegen ist allerdings derzeit nicht in der Lage dies zu tun.";
$a->strings["This is most often a permission setting, as the web server may not be able to write files in your folder - even if you can."] = "In den meisten Fällen ist dies ein Problem mit den Schreibrechten, der Webserver könnte keine Schreiberlaubnis haben, selbst wenn du sie hast.";
$a->strings["Please check with your site documentation or support people to see if this situation can be corrected."] = "Bitte überprüfe die Einstellungen und frage im Zweifelsfall dein Support Team um diese Situations zu beheben.";
$a->strings["If not, you may be required to perform a manual installation. Please see the file \"INSTALL.txt\" for instructions."] = "Sollte dies nicht möglich sein musst du die Installation manuell durchführen. Lies dazu bitte in der Datei \"INSTALL.txt\".";
$a->strings["The database configuration file \".htconfig.php\" could not be written. Please use the enclosed text to create a configuration file in your web server root."] = "Die Konfigurationsdatei \".htconfig.php\" konnte nicht angelegt werden. Bitte verwende den angefügten Text um die Datei im Stammverzeichnis deiner Friendika Installation zu erzeugen.";
$a->strings["Errors encountered creating database tables."] = "Fehler aufgetreten wärend der Erzeugung der Datenbank Tabellen.";
$a->strings["[Embedded content - reload page to view]"] = "[Eingebetteter Inhalt - Seite neu laden zum Betrachten]";
$a->strings["Profile Match"] = "Profil Übereinstimmungen";
$a->strings["No keywords to match. Please add keywords to your default profile."] = "Keine Schlüsselwörter zum Abgleichen gefunden. Bitte füge einige Schlüsselwörter zu deinem Standardprofil hinzu.";
$a->strings["No matches"] = "Keine Übereinstimmungen";
$a->strings["Remote privacy information not available."] = "Entfernte Privatsphäreneinstellungen nicht verfügbar.";
$a->strings["Visible to:"] = "Sichtbar für:";
@ -182,21 +215,24 @@ $a->strings["Ignore"] = "Ignorieren";
$a->strings["Pending Friend/Connect Notifications"] = "Anstehende Freundschafts/Kontakt Benachrichtigungen";
$a->strings["Show Ignored Requests"] = "Zeige ignorierte Anfragen";
$a->strings["Hide Ignored Requests"] = "Verberge ignorierte Anfragen";
$a->strings["Notification type: "] = "Benachrichtigungs Typ: ";
$a->strings["Friend Suggestion"] = "Kontakt Vorschlag";
$a->strings["suggested by %s"] = "vorgeschlagen von %s";
$a->strings["Approve"] = "Genehmigen";
$a->strings["Claims to be known to you: "] = "Behauptet dich zu kennen: ";
$a->strings["yes"] = "ja";
$a->strings["no"] = "nein";
$a->strings["Approve as: "] = "Genehmigen als: ";
$a->strings["Friend"] = "Freund";
$a->strings["Fan/Admirer"] = "Fan/Verehrer";
$a->strings["Notification type: "] = "Benachrichtigungs Typ: ";
$a->strings["Friend/Connect Request"] = "Kontakt-/Freundschaftsanfrage";
$a->strings["New Follower"] = "Neuer Bewunderer";
$a->strings["Approve"] = "Genehmigen";
$a->strings["No notifications."] = "Keine Benachrichtigungen.";
$a->strings["User registrations waiting for confirm"] = "Neuanmeldungen die auf deine Bestätigung warten";
$a->strings["Deny"] = "Verwehren";
$a->strings["No registrations."] = "Keine Neuanmeldungen.";
$a->strings["Invite Friends"] = "Freunde einladen";
$a->strings["%d invitation available"] = array(
0 => "%d Einladung verfügbar",
1 => "%d Einladungen verfügbar",
);
$a->strings["Find People With Shared Interests"] = "Finde Personen die deine Interessen teilen";
$a->strings["Connect/Follow"] = "Verbinden/Folgen";
$a->strings["Example: bob@example.com, http://example.com/barbara"] = "Beispiel: bob@example.com, http://example.com/barbara";
@ -218,6 +254,7 @@ $a->strings["Private communications are not available for this contact."] = "Pri
$a->strings["Never"] = "Niemals";
$a->strings["(Update was successful)"] = "(Aktualisierung war erfolgreich)";
$a->strings["(Update was not successful)"] = "(Aktualisierung war nicht erfolgreich)";
$a->strings["Suggest friends"] = "Kontakte vorschlagen";
$a->strings["Contact Editor"] = "Kontakt Editor";
$a->strings["Profile Visibility"] = "Profil Anzeige";
$a->strings["Please choose the profile you would like to display to %s when viewing your profile securely."] = "Bitte wähle eines deiner Profile das angezeitgt werden soll, wenn %s dein Profil aufruft.";
@ -226,7 +263,7 @@ $a->strings["Online Reputation"] = "Online Ruf";
$a->strings["Occasionally your friends may wish to inquire about this person's online legitimacy."] = "Es könnte sein, dass deine Freunde etwas über den Ruf einer Peron erfahren möchten.";
$a->strings["You may help them choose whether or not to interact with this person by providing a <em>reputation</em> to guide them."] = "Du kannst ihnen bei der Entscheidung helfen ob sie mit einer Person interagieren sollten oder nicht indem du Informationen über den <em>Ruf</em> der Person anbietest.";
$a->strings["Please take a moment to elaborate on this selection if you feel it could be helpful to others."] = "Bitte nimm dir einen Moment und fülle diesen Punkt aus wenn du denkst das es anderen helfen könnte.";
$a->strings["Visit \$name's profile"] = "Besuche das Profil von \$name";
$a->strings["Visit %s's profile [%s]"] = "Besuche %ss Profil [%s]";
$a->strings["Block/Unblock contact"] = "Kontakt blockieren/freischalten";
$a->strings["Ignore contact"] = "Ignoriere den Kontakt";
$a->strings["Repair contact URL settings"] = "URL Einstellungen des Kontakts reparieren";
@ -247,8 +284,8 @@ $a->strings["Show Blocked Connections"] = "Zeige geblockte Verbindungen";
$a->strings["Hide Blocked Connections"] = "Verstecke geblockte Verbindungen";
$a->strings["Finding: "] = "Funde: ";
$a->strings["Find"] = "Finde";
$a->strings["Visit \$username's profile"] = "Besuche das Profil von \$username";
$a->strings["Edit contact"] = "Kontakt bearbeiten";
$a->strings["No valid account found."] = "Kein gültiger Account gefunden.";
$a->strings["Password reset request issued. Check your email."] = "Zurücksetzen des Passworts eingeleitet. Bitte überprüfe deine Email.";
$a->strings["Password reset requested at %s"] = "Anfrage zum Zurücksetzen des Passworts auf %s erhalten";
$a->strings["Request could not be verified. (You may have previously submitted it.) Password reset failed."] = "Anfrage konnte nicht verifiziert werden. (Eventuell hast du bereits ähnliche Anfrage gestellt.) Zurücksetzen des Passworts gescheitert.";
@ -266,30 +303,39 @@ $a->strings["Passwords do not match. Password unchanged."] = "Die Passwörter st
$a->strings["Empty passwords are not allowed. Password unchanged."] = "Leere Passwörter sind nicht erlaubt. Passwort bleibt unverändert.";
$a->strings["Password changed."] = "Passwort ändern.";
$a->strings["Password update failed. Please try again."] = "Aktualisierung des Passworts gescheitert, bitte versuche es noch einmal.";
$a->strings["Failed to connect with email account using the settings provided."] = "Konnte das Email Konto mit den angegebenen Einstellungen nicht erreichen.";
$a->strings[" Please use a shorter name."] = " Bitte verwende einen kürzeren Namen.";
$a->strings[" Name too short."] = " Name ist zu kurz.";
$a->strings[" Not valid email."] = " Keine gültige EMail.";
$a->strings[" Cannot change to that email."] = " Cannot change to that email.";
$a->strings["Settings updated."] = "Einstellungen aktualisiert.";
$a->strings["Plugin Settings"] = "Plugin Einstellungen";
$a->strings["Account Settings"] = "Account Einstellungen";
$a->strings["Account settings"] = "Account Einstellungen";
$a->strings["Plugin settings"] = "Plugin Einstellungen";
$a->strings["No Plugin settings configured"] = "Keine Erweiterungen konfiguriert";
$a->strings["Plugin Settings"] = "Plugin Einstellungen";
$a->strings["Normal Account"] = "Normaler Account";
$a->strings["This account is a normal personal profile"] = "Dieser Account ist ein normales persönliches Profil";
$a->strings["Soapbox Account"] = "Sandkasten Accunt";
$a->strings["Soapbox Account"] = "Sandkasten Account";
$a->strings["Automatically approve all connection/friend requests as read-only fans"] = "Freundschaftsanfragen werden automatisch als Nurlese-Fans akzeptiert";
$a->strings["Community/Celebrity Account"] = "Gemeinschafts/Berühmtheiten Account";
$a->strings["Automatically approve all connection/friend requests as read-write fans"] = "Freundschaftsanfragen werden automatisch als Lese-und-Schreib-Fans akzeptiert";
$a->strings["Automatic Friend Account"] = "Automatischer Freundes Account";
$a->strings["Automatically approve all connection/friend requests as friends"] = "Freundschaftsanfragen werden automatisch als Freund akzeptiert";
$a->strings["OpenID: "] = "OpenID: ";
$a->strings["&nbsp;(Optional) Allow this OpenID to login to this account."] = "&nbsp;(Optional) Erlaube dieser OpenID sich für diesen Account anzumelden.";
$a->strings["Publish your default profile in site directory?"] = "Dein Standard-Profil im Verzeichnis dieser Seite veröffentliche?";
$a->strings["Publish your default profile in global social directory?"] = "Dein Standard-Profil im weltweiten Verzeichnis veröffentlichen?";
$a->strings["OpenID:"] = "OpenID:";
$a->strings["(Optional) Allow this OpenID to login to this account."] = "(Optional) Erlaube die Anmeldung für diesen Account mit dieser OpenID.";
$a->strings["Publish your default profile in your local site directory?"] = "Veröffentliche dein Standardprofil im Verzeichnis der lokalen Seite?";
$a->strings["Publish your default profile in the global social directory?"] = "Veröffentliche dein Standardprofil im weltweiten Verzeichnis?";
$a->strings["Hide your contact/friend list from viewers of your default profile?"] = "Verberge die Liste deiner Kontakte vor Betrachtern des Standardprofils.";
$a->strings["Hide profile details and all your messages from unknown viewers?"] = "Profildetails und all deine Beiträge vor unbekannten Besuchern verbergen?";
$a->strings["Profile is <strong>not published</strong>."] = "Profil ist <strong>nicht veröffentlicht</strong>.";
$a->strings["or"] = "oder";
$a->strings["Your Identity Address is"] = "Die Adresse deines Profils lautet:";
$a->strings["Account Settings"] = "Account Einstellungen";
$a->strings["Export Personal Data"] = "Perönliche Daten exportieren";
$a->strings["Password Settings"] = "Passwort Einstellungen";
$a->strings["New Password:"] = "Neues Passwort:";
$a->strings["Confirm:"] = "Bestätigen:";
$a->strings["Leave password fields blank unless changing"] = "Lass die Passwort-Felder leer außer du willst das Passwort ändern";
$a->strings["Basic Settings"] = "Grundeinstellungen";
$a->strings["Full Name:"] = "Kompletter Name:";
$a->strings["Email Address:"] = "Email Adresse:";
@ -300,9 +346,11 @@ $a->strings["Display Theme:"] = "Theme:";
$a->strings["Security and Privacy Settings"] = "Sicherheits und Privatsphären Einstellungen";
$a->strings["Maximum Friend Requests/Day:"] = "Maximale Anzahl von Freundschaftsanfragen/Tag:";
$a->strings["(to prevent spam abuse)"] = "(um SPAM zu vermeiden)";
$a->strings["Default Post Permissions"] = "Grundeinstellung für Veröffentlichungen";
$a->strings["(click to open/close)"] = "(klicke zum öffnen/schließen)";
$a->strings["Allow friends to post to your profile page:"] = "Erlaube es Freunden Beiträge auf deiner Pinnwand zu posten:";
$a->strings["Automatically expire (delete) posts older than"] = "Automatisch Beiträge verfallen lassen (löschen) die älter sind als";
$a->strings["days"] = "Tage";
$a->strings["Automatically expire posts after days:"] = "Einträge verfallen automatisch nach Tagen:";
$a->strings["If empty, posts will not expire. Expired posts will be deleted"] = "Wenn leer verfallen Einträge nie automatisch. Verfallene Einträge werden gelöscht.";
$a->strings["Notification Settings"] = "Benachrichtigungs Einstellungen";
$a->strings["Send a notification email when:"] = "Benachrichtigungs-Email senden wenn:";
$a->strings["You receive an introduction"] = "Du eine Vorstellung erhälst";
@ -310,29 +358,27 @@ $a->strings["Your introductions are confirmed"] = "Eine deiner Vorstellungen ang
$a->strings["Someone writes on your profile wall"] = "Jemand etwas auf deiner Pinnwand postet";
$a->strings["Someone writes a followup comment"] = "Jemand einen Kommentar verfasst";
$a->strings["You receive a private message"] = "Du eine private Nachricht erhälst";
$a->strings["Password Settings"] = "Passwort Einstellungen";
$a->strings["Leave password fields blank unless changing"] = "Lass die Passwort-Felder leer außer du willst das Passwort ändern";
$a->strings["New Password:"] = "Neues Passwort:";
$a->strings["Confirm:"] = "Bestätigen:";
$a->strings["Advanced Page Settings"] = "Erweiterte Seiten Einstellungen";
$a->strings["Default Post Permissions"] = "Grundeinstellung für Veröffentlichungen";
$a->strings["(click to open/close)"] = "(klicke zum öffnen/schließen)";
$a->strings["Email/Mailbox Setup"] = "Email/Postfach Einstellungen";
$a->strings["If you wish to communicate with email contacts using this service (optional), please specify how to connect to your mailbox."] = "Wenn du mit Email Kontakten über diesen Service kommunizieren möchtest (optional) gib bitte die Einstellungen für dein Postfach an.";
$a->strings["Last successful email check:"] = "Letzter erfolgreicher Email Check";
$a->strings["Email access is disabled on this site."] = "Zugriff auf Emails für diese Seite deaktiviert.";
$a->strings["IMAP server name:"] = "IMAP Server Name:";
$a->strings["IMAP port:"] = "IMAP Port:";
$a->strings["Security (TLS or SSL):"] = "Sicherheit (TLS oder SSL)";
$a->strings["Security:"] = "Sicherheit:";
$a->strings["None"] = "Keine";
$a->strings["Email login name:"] = "Email Login Name:";
$a->strings["Email password:"] = "Email Passwort:";
$a->strings["Reply-to address (Optional):"] = "Reply-to Adresse (Optional)";
$a->strings["Reply-to address:"] = "Reply-to Adresse:";
$a->strings["Send public posts to all email contacts:"] = "Sende öffentliche Einträge an alle Email Kontakte:";
$a->strings["Email access is disabled on this site."] = "Zugriff auf Emails für diese Seite deaktiviert.";
$a->strings["Advanced Page Settings"] = "Erweiterte Seiten Einstellungen";
$a->strings["Welcome back %s"] = "Willkommen zurück %s";
$a->strings["Manage Identities and/or Pages"] = "Verwalte Identitäten und/oder Seiten";
$a->strings["(Toggle between different identities or community/group pages which share your account details.)"] = "(Wähle zwischen verschiedenen Identitäten oder Gemeinschafts/Gruppen Seiten die deine Accountdetails teilen.)";
$a->strings["Select an identity to manage: "] = "Wähle eine Identität zum Verwalten: ";
$a->strings["Normal View"] = "Normale Ansicht";
$a->strings["New Item View"] = "Neue Einträge";
$a->strings["View Conversations"] = "Unterhaltungen anzeigen";
$a->strings["View New Items"] = "Neue Einträge anzeigen";
$a->strings["View Any Items"] = "Alle Einträge anzeigen";
$a->strings["View Starred Items"] = "Gesternte Einträge anzeigen";
$a->strings["Warning: This group contains %s member from an insecure network."] = array(
0 => "",
1 => "",
@ -344,9 +390,21 @@ $a->strings["Group: "] = "Gruppe: ";
$a->strings["Contact: "] = "Kontakt ";
$a->strings["Private messages to this person are at risk of public disclosure."] = "Private Nachrichten an diese Person könnten an die Öffentlichkeit gelangen.";
$a->strings["Invalid contact."] = "Ungültiger Kontakt.";
$a->strings["Shared content is covered by the <a href=\"http://creativecommons.org/licenses/by/3.0/\">Creative Commons Attribution 3.0</a> license."] = "Geteilte Inhalte innerhalb des Friendika Netzwerks sind unter der <a href=\"http://creativecommons.org/licenses/by/3.0/\">Creative Commons Attribution 3.0</a> verfügbar.";
$a->strings["Private Notes"] = "Privater Beitrag";
$a->strings["Save"] = "Speichern";
$a->strings["Welcome to Friendika"] = "Willkommen bei Friendika";
$a->strings["New Member Checklist"] = "Checkliste für neue Mitglieder";
$a->strings["We would like to offer some tips and links to help make your experience enjoyable. Click any item to visit the relevant page."] = "Wir möchten dir einige Tipps und Links anbieten um deine Erfahrung mit Friendika so angenehm wie möglich zu machen. Klicke einfach einen Aspekt an um weitere Informationen zu erhalten.";
$a->strings["On your <em>Settings</em> page - change your initial password. Also make a note of your Identity Address. This will be useful in making friends."] = "Ändere dein anfängliches Passwort auf der <em>Einstellungen</em> Seite. Bei dieser Gelegenheit solltest du dir die Adresse deines Profils merken, diese wird benötigt um mit Anderen in Kontakt zu treten.";
$a->strings["Review the other settings, particularly the privacy settings. An unpublished directory listing is like having an unlisted phone number. In general, you should probably publish your listing - unless all of your friends and potential friends know exactly how to find you."] = "Überprüfe die restlichen Einstellungen, insbesondere die Einstellungen zur Privatsphäre. Wenn du dein Profil nicht veröffentlichst ist das wie wenn niemand deine Telefonnummer kennt. Im Allgemeinen solltest du es veröffentlichen - außer all deine Freunde und potentiellen Freunde wissen wie man dich findet.";
$a->strings["Upload a profile photo if you have not done so already. Studies have shown that people with real photos of themselves are ten times more likely to make friends than people who do not."] = "Lade ein Profilbild hoch falls du es noch nicht getan hast. Studien haben gezeigt, das es zehnmal wahrscheinlicher ist neue Freunde zu finden, wenn du ein Bild von dir selbst verwendest als wenn du dies nicht tust.";
$a->strings["Authorise the Facebook Connector if you currently have a Facebook account and we will (optionally) import all your Facebook friends and conversations."] = "Richte die Verbindung zu Facebook ein, wenn du im Augenblick ein Facebook Konto hast und (optional) deine Facebook Freunde und Unterhaltungen importieren willst.";
$a->strings["Enter your email access information on your Settings page if you wish to import and interact with friends or mailing lists from your email INBOX"] = "Gib deine Email Daten in deinen Einstellungen an, wenn du mit deinen Email-Kontakten / Email-Listen interagieren möchtest.";
$a->strings["Edit your <strong>default</strong> profile to your liking. Review the settings for hiding your list of friends and hiding the profile from unknown visitors."] = "Editiere dein <strong>Standard</strong> Profil nach deinen Vorlieben. Überprüfe die Einstellungen zum Verbergen deiner Freundesliste vor unbekannten Betrachtern des Profils.";
$a->strings["Set some public keywords for your default profile which describe your interests. We may be able to find other people with similar interests and suggest friendships."] = "Trage ein paar öffentliche Stichwörter in dein Standardprofil ein die deine Interessen beschreiben. Eventuell sind wir in der Lage Leute zu finden, die deine Interessen teilen und können dir dann Kontakte vorschlagen.";
$a->strings["Your Contacts page is your gateway to managing friendships and connecting with friends on other networks. Typically you enter their address or site URL in the <em>Connect</em> dialog."] = "Deine Kontakte Seite ist die zentrale Stelle um deine Freundschaften zu koordinieren und neuen Kontakte, auch von anderen Netzwerken, zu folgen. Normalerweise gibst du einfach die URL der Seite in den <em>Verbinden</em> Dialog ein.";
$a->strings["The Directory page lets you find other people in this network or other federated sites. Look for a <em>Connect</em> or <em>Follow</em> link on their profile page. Provide your own Identity Address if requested."] = "Über die Verzeichnisseite kannst du andere Personen auf diesem Server oder anderen verteilten Seiten finden. Halte nach einem <em>Verbinden</em> oder <em>Folgen</em> Link auf deren Profilseiten Ausschau und gib deine eigene Profiladresse an falls du danach gefragt wirst.";
$a->strings["Once you have made some friends, organize them into private conversation groups from the sidebar of your Contacts page and then you can interact with each group privately on your Network page."] = "Sobald du einige Freunde gefunden hast, organisiere sie in Gruppen zur privaten Kommunikation im Seitenmenü der Kontakte-Seite. Du kannst dann mit jeder dieser Gruppen von der Netzwerkseite aus privat interagieren.";
$a->strings["Our <strong>help</strong> pages may be consulted for detail on other program features and resources."] = "Unsere <strong>Hilfe</strong> Seiten können herangezogen werden um weitere Einzelheiten zu andern Programm Features zu erhalten.";
$a->strings["Item not available."] = "Beitrag nicht verfügbar.";
$a->strings["Item was not found."] = "Beitrag konnte nicht gefunden werden.";
$a->strings["Group created."] = "Gruppe erstellt.";
@ -364,11 +422,12 @@ $a->strings["Members"] = "Mitglieder";
$a->strings["All Contacts"] = "Alle Kontakte";
$a->strings["Invalid profile identifier."] = "Ungültiger Profil-Bezeichner";
$a->strings["Profile Visibility Editor"] = "Editor für die Profil-Sichtbarkeit";
$a->strings["Profile"] = "Profil";
$a->strings["Visible To"] = "Sichtbar für";
$a->strings["All Contacts (with secure profile access)"] = "Alle Kontakte (mit gesichertem Profil zugriff)";
$a->strings["View Contacts"] = "Kontakte anzeigen";
$a->strings["No contacts."] = "Keine Kontakte.";
$a->strings["An invitation is required."] = "Du benötigst eine Einladung.";
$a->strings["Invitation could not be verified."] = "Die Einladung konnte nicht überprüft werden.";
$a->strings["Invalid OpenID url"] = "Ungültige OpenID URL";
$a->strings["Please enter the required information."] = "Bitte trage die erforderlichen Informationen ein.";
$a->strings["Please use a shorter name."] = "Bitte verwende einen kürzeren Namen.";
@ -392,6 +451,8 @@ $a->strings["You may (optionally) fill in this form via OpenID by supplying your
$a->strings["If you are not familiar with OpenID, please leave that field blank and fill in the rest of the items."] = "Wenn du nicht mit OpenID vertraut bist, lass dieses Feld bitte leer und fülle die restlichen Felder aus.";
$a->strings["Your OpenID (optional): "] = "Deine OpenID (optional): ";
$a->strings["Include your profile in member directory?"] = "Soll dein Profil im Nutzerverzeichnis angezeigt werden?";
$a->strings["Membership on this site is by invitation only."] = "Mitgliedschaft auf dieser Seite ist nur nach vorheriger Einladung möglich.";
$a->strings["Your invitation ID: "] = "ID deiner Einladung: ";
$a->strings["Registration"] = "Registration";
$a->strings["Your Full Name (e.g. Joe Smith): "] = "Vollständiger Name (z.B. Joe Smith): ";
$a->strings["Your Email Address: "] = "Deine EMail Adresse: ";
@ -409,10 +470,9 @@ $a->strings["Bug reports and issues: please visit"] = "Probleme oder Fehler gefu
$a->strings["Suggestions, praise, donations, etc. - please email \"Info\" at Friendika - dot com"] = "Vorschläge, Lobeshymnen, Spenden usw. - bitte eine Email an \"Info\" at Friendika - dot com (englisch bevorzugt)";
$a->strings["Installed plugins/addons/apps"] = "Installierte Plugins/Erweiterungen/Apps";
$a->strings["No installed plugins/addons/apps"] = "Keine Plugins/Erweiterungen/Apps installiert";
$a->strings["Please login."] = "Bitte melde dich an.";
$a->strings["Registration revoked for %s"] = "Registration für %s wurde zurück gezogen";
$a->strings["Account approved."] = "Account freigegeben.";
$a->strings["[Embedded content - reload page to view]"] = "[Eingebetteter Inhalt - Seite neu laden zum Betrachten]";
$a->strings["Registration revoked for %s"] = "Registration für %s wurde zurück gezogen";
$a->strings["Please login."] = "Bitte melde dich an.";
$a->strings["Unable to locate original post."] = "Konnte das original Posting nicht finden.";
$a->strings["Empty post discarded."] = "Leere Nachricht wurde verworfen.";
$a->strings["Wall Photos"] = "Pinnwand Bilder";
@ -425,7 +485,6 @@ $a->strings["This message was sent to you by %s, a member of the Friendika socia
$a->strings["You may visit them online at %s"] = "Du kannst sie online unter %s besuchen";
$a->strings["Please contact the sender by replying to this post if you do not wish to receive these messages."] = "Please contact the sender by replying to this post if you do not wish to receive these messages.";
$a->strings["%s posted an update."] = "%s hat ein Update gepostet.";
$a->strings["Item not found."] = "Beitrag nicht gefunden.";
$a->strings["Image uploaded but image cropping failed."] = "Bilder hochgeladen aber das Zuschneiden ist fehlgeschlagen.";
$a->strings["Image size reduction [%s] failed."] = "Verkleinern der Bildgröße von [%s] ist gescheitert.";
$a->strings["Unable to process image"] = "Bild konnte nicht verarbeitet werden";
@ -464,26 +523,113 @@ $a->strings["D, d M Y - g:i A"] = "D, d. M Y - g:i A";
$a->strings["Message not available."] = "Nachricht nicht verfügbar.";
$a->strings["Delete message"] = "Nachricht löschen";
$a->strings["Send Reply"] = "Antwort senden";
$a->strings["Site"] = "Seite";
$a->strings["Users"] = "Nutzer";
$a->strings["Plugins"] = "Plugins";
$a->strings["Update"] = "Aktualisierungen";
$a->strings["Logs"] = "Protokolle";
$a->strings["User registrations waiting for confirmation"] = "Nutzeranmeldungen die auf Bestätigung warten";
$a->strings["Item not found."] = "Beitrag nicht gefunden.";
$a->strings["Administration"] = "Administration";
$a->strings["Summary"] = "Zusammenfassung";
$a->strings["Registered users"] = "Registrierte Nutzer";
$a->strings["Pending registrations"] = "Anstehende Anmeldungen";
$a->strings["Version"] = "Version";
$a->strings["Active plugins"] = "Aktive Plugins";
$a->strings["Site settings updated."] = "Seiteneinstellungen aktualisiert.";
$a->strings["Closed"] = "Geschlossen";
$a->strings["Requires approval"] = "Bedarf Zustimmung";
$a->strings["Open"] = "Offen";
$a->strings["File upload"] = "Datei hochladen";
$a->strings["Policies"] = "Regeln";
$a->strings["Advanced"] = "Erweitert";
$a->strings["Site name"] = "Seiten Name";
$a->strings["Banner/Logo"] = "Banner/Logo";
$a->strings["System language"] = "System Sprache";
$a->strings["System theme"] = "Systemweites Thema";
$a->strings["Maximum image size"] = "Maximale Größe von Bildern";
$a->strings["Register policy"] = "Registrationsmethode";
$a->strings["Register text"] = "Registrationstext";
$a->strings["Allowed friend domains"] = "Erlaubte Domains für Kontakte";
$a->strings["Allowed email domains"] = "Erlaubte Domains für Emails";
$a->strings["Block public"] = "Öffentlichen Zugriff blockieren";
$a->strings["Force publish"] = "Erzwinge Veröffentlichung";
$a->strings["Global directory update URL"] = "URL für Updates beim weltweiten Verzeichnis";
$a->strings["Block multiple registrations"] = "Unterbinde mehrfach Registration";
$a->strings["OpenID support"] = "OpenID Unterstützung";
$a->strings["Gravatar support"] = "Gravatar Unterstützung";
$a->strings["Fullname check"] = "Name auf Vollständigkeit überprüfen";
$a->strings["UTF-8 Regular expressions"] = "UTF-8 Reguläre Ausdrücke";
$a->strings["Show Community Page"] = "Gemeinschaftsseite anzeigen";
$a->strings["Enable OStatus support"] = "OStatus Unterstützung aktivieren";
$a->strings["Only allow Friendika contacts"] = "Erlaube ausschlließlich Friendika Kontakte";
$a->strings["Verify SSL"] = "SSL Überprüfen";
$a->strings["Proxy user"] = "Proxy Nutzer";
$a->strings["Proxy URL"] = "Proxy URL";
$a->strings["Network timeout"] = "Netzwerk Wartezeit";
$a->strings["%s user blocked"] = array(
0 => "%s Nutzer gesperrt",
1 => "%s Nutzer gesperrt/entsperrt",
);
$a->strings["%s user deleted"] = array(
0 => "%s Nutzer gelöscht",
1 => "%s Nutzer gelöscht",
);
$a->strings["User '%s' deleted"] = "Nutzer '%s' gelöscht";
$a->strings["User '%s' unblocked"] = "Nutzer '%s' entsperrt";
$a->strings["User '%s' blocked"] = "Nutzer '%s' gesperrt";
$a->strings["select all"] = "Alle auswählen";
$a->strings["User registrations waiting for confirm"] = "Neuanmeldungen die auf deine Bestätigung warten";
$a->strings["Request date"] = "Anfrage Datum";
$a->strings["Email"] = "Email";
$a->strings["No registrations."] = "Keine Neuanmeldungen.";
$a->strings["Deny"] = "Verwehren";
$a->strings["Block"] = "Sperren";
$a->strings["Unblock"] = "Entsperren";
$a->strings["Register date"] = "Anmeldedatum";
$a->strings["Last login"] = "Letzte Anmeldung";
$a->strings["Last item"] = "Letzter Beitrag";
$a->strings["Account"] = "Nutzerkonto";
$a->strings["Selected users will be deleted!\\n\\nEverything these users had posted on this site will be permanently deleted!\\n\\nAre you sure?"] = "Die markierten Nutzer werden gelöscht!\\n\\nAlle Beiträge die diese Nutzer auf dieser Seite veröffentlicht haben werden permanent gelöscht!\\n\\nBist du dir sicher?";
$a->strings["The user {0} will be deleted!\\n\\nEverything this user has posted on this site will be permanently deleted!\\n\\nAre you sure?"] = "Der Nutzer {0} wird gelöscht!\\n\\nAlles was dieser Nutzer auf dieser Seite veröffentlicht hat wird permanent gelöscht!\\n\\nBist du dir sicher?";
$a->strings["Plugin %s disabled."] = "Plugin %s deaktiviert.";
$a->strings["Plugin %s enabled."] = "Plugin %s aktiviert.";
$a->strings["Disable"] = "Ausschalten";
$a->strings["Enable"] = "Einschalten";
$a->strings["Toggle"] = "Umschalten";
$a->strings["Settings"] = "Einstellungen";
$a->strings["Log settings updated."] = "Protokolleinstellungen aktualisiert.";
$a->strings["Clear"] = "löschen";
$a->strings["Debugging"] = "Protokoll führen";
$a->strings["Log file"] = "Protokolldatei";
$a->strings["Must be writable by web server. Relative to your Friendika index.php."] = "Muss schreibbar durch den Webserver sein. Angabe relativ zu Friendikas indes.php.";
$a->strings["Log level"] = "Protokollevel";
$a->strings["Close"] = "Schließen";
$a->strings["FTP Host"] = "FTP Host";
$a->strings["FTP Path"] = "FTP Pfad";
$a->strings["FTP User"] = "FTP Nutzername";
$a->strings["FTP Password"] = "FTP Passwort";
$a->strings["No profile"] = "Kein Profil";
$a->strings["Access to this profile has been restricted."] = "Der Zugriff zu diesem Profil wurde eingeschrängt.";
$a->strings["Status"] = "Status";
$a->strings["Photos"] = "Bilder";
$a->strings["Access to this profile has been restricted."] = "Der Zugriff zu diesem Profil wurde eingeschränkt.";
$a->strings["Tips for New Members"] = "Tipps für neue Nutzer";
$a->strings["Login failed."] = "Annmeldung fehlgeschlagen.";
$a->strings["Welcome "] = "Willkommen ";
$a->strings["Please upload a profile photo."] = "Bitte lade ein Profilbild hoch.";
$a->strings["Welcome back "] = "Willkommen zurück ";
$a->strings["The profile address specified does not provide adequate information."] = "Die angegebene Profiladresse liefert unzureichende Informationen.";
$a->strings["This site is not configured to allow communications with other networks."] = "Diese Seite ist so konfiguriert, dass keine Kommunikation mit anderen Netzwerken erfolgen kann.";
$a->strings["No compatible communication protocols or feeds were discovered."] = "Es wurden keine kompatiblen Kommunikationsprotokolle oder Feeds gefunden.";
$a->strings["The profile address specified does not provide adequate information."] = "Die angegebene Profiladresse liefert unzureichende Informationen.";
$a->strings["An author or name was not found."] = "Es wurde kein Autor oder Name gefunden.";
$a->strings["No browser URL could be matched to this address."] = "Zu dieser Adresse konnte keine passende Browser URL gefunden werden.";
$a->strings["Communication options with this network have been restricted."] = "Kommunikations-Optionen mit diesem Netzwerk wurden eingeschränkt.";
$a->strings["Limited profile. This person will be unable to receive direct/personal notifications from you."] = "Eingeschränktes Profil. Diese Person wird keine direkten/privaten Nachrichten von dir erhalten können.";
$a->strings["Unable to retrieve contact information."] = "Konnte die Kontaktinformationen nicht empfangen.";
$a->strings["following"] = "folgen";
$a->strings["Item has been removed."] = "Eintrag wurde entfernt.";
$a->strings["New mail received at "] = "New mail received at ";
$a->strings["Applications"] = "Anwendungen";
$a->strings["No installed applications."] = "Keine Applikationen installiert.";
$a->strings["Search"] = "Suche";
$a->strings["No results."] = "Keine Ergebnisse.";
$a->strings["Profile not found."] = "Profil nicht gefunden.";
$a->strings["Profile Name is required."] = "Profilname ist erforderlich.";
$a->strings["Profile updated."] = "Profil aktualisiert.";
@ -492,7 +638,6 @@ $a->strings["Profile-"] = "Profil-";
$a->strings["New profile created."] = "Neues Profil angelegt.";
$a->strings["Profile unavailable to clone."] = "Profil nicht zum Duplizieren verfügbar.";
$a->strings["Hide your contact/friend list from viewers of this profile?"] = "Liste der Kontakte/Freunde vor Betrachtern dieses Profils verbergen?";
$a->strings["Hide profile details and all your messages from unknown viewers?"] = "Profildetails und all deine Beiträge vor unbekannten Besuchern verbergen?";
$a->strings["Edit Profile Details"] = "Profil bearbeiten";
$a->strings["View this profile"] = "Dieses Profil anzeigen";
$a->strings["Create a new profile using these settings"] = "Neues Profil anlegen und diese Einstellungen verwenden";
@ -502,7 +647,7 @@ $a->strings["Profile Name:"] = "Profilname:";
$a->strings["Your Full Name:"] = "Dein kompletter Name:";
$a->strings["Title/Description:"] = "Titel/Beschreibung:";
$a->strings["Your Gender:"] = "Dein Geschlecht:";
$a->strings["Birthday (y/m/d):"] = "Geburtstag (y/m/d):";
$a->strings["Birthday (%s):"] = "Geburtstag (%s):";
$a->strings["Street Address:"] = "Adresse:";
$a->strings["Locality/City:"] = "Wohnort/Stadt:";
$a->strings["Postal/Zip Code:"] = "Postleitzahl:";
@ -536,7 +681,7 @@ $a->strings["Profiles"] = "Profile";
$a->strings["Change profile photo"] = "Profilbild ändern";
$a->strings["Create New Profile"] = "Neues Profil anlegen";
$a->strings["Profile Image"] = "Profilbild";
$a->strings["Visible to everybody"] = "Für jeden sichtbar";
$a->strings["visible to everybody"] = "sichtbar für jeden";
$a->strings["Edit visibility"] = "Sichtbarkeit bearbeiten";
$a->strings["Global Directory"] = "Weltweites Verzeichnis";
$a->strings["Normal site view"] = "Normale Seitenansicht";
@ -551,10 +696,12 @@ $a->strings["%d message sent."] = array(
0 => "%d Nachricht gesendet.",
1 => "%d Nachrichten gesendet.",
);
$a->strings["You have no more invitations available"] = "Du hast keine weiteren Einladungen";
$a->strings["Send invitations"] = "Einladungen senden";
$a->strings["Enter email addresses, one per line:"] = "Email Adressen eingeben, eine pro Zeile:";
$a->strings["Please join my social network on %s"] = "Bitte trete meinem Sozialen Netzwerk auf %s bei";
$a->strings["To accept this invitation, please visit:"] = "Um diese Einladung anzunehmen beuche bitte:";
$a->strings["You will need to supply this invitation code: \$invite_code"] = "Du benötigst den folgenden Einladungs Code: \$invite_code";
$a->strings["Once you have registered, please connect with me via my profile page at:"] = "Sobald du registriert bist kontaktiere mich bitte auf meiner Profilseite:";
$a->strings["Response from remote site was not understood."] = "Antwort der entfernten Gegenstelle unverständlich.";
$a->strings["Unexpected response from remote site: "] = "Unerwartete Antwort der Gegenstelle: ";
@ -579,14 +726,19 @@ $a->strings["Facebook Connect"] = "Mit Facebook verbinden";
$a->strings["Install Facebook connector for this account."] = "Facebook Connector für diesen Account installieren.";
$a->strings["Remove Facebook connector"] = "Facebook Connector entfernen";
$a->strings["Post to Facebook by default"] = "Sende standardmäßig nach Facebook";
$a->strings["Link all your Facebook friends and conversations"] = "Verknüpfe all deine Facebook-Freunde und Unterhaltungen";
$a->strings["Warning: Your Facebook privacy settings can not be imported."] = "Warnung: Deine Privatsphären Einstellungen können nicht von Facebook importiert werden.";
$a->strings["Linked Facebook items <strong>may</strong> be publicly visible, depending on your privacy settings for this website/account."] = "Eingebundene Beiträge von Facebook <strong>könnten</strong> öffentlich sichtbar sein, abhängig von deinen Privatsphären-Einstellungen für dieses Nutzerkonto.";
$a->strings["Facebook"] = "Facebook";
$a->strings["Facebook Connector Settings"] = "Facebook Verbindungseinstellungen";
$a->strings["Post to Facebook"] = "Zu Facebook posten";
$a->strings["Post to Facebook cancelled because of multi-network access permission conflict."] = "Das Senden nach Facebook wurde zurückgezogen da Konflikte bei den Multi-Netzwerks-Rechten vorliegen.";
$a->strings["Image: "] = "Bild";
$a->strings["View on Friendika"] = "Auf Friendika ansehen";
$a->strings["Widgets key: "] = "Widgets Schlüssel: ";
$a->strings["Facebook post failed. Queued for retry."] = "Senden an Facebook gescheitert. Wir versuchen es später erneut.";
$a->strings["Generate new key"] = "Neuen Schlüssel erstellen";
$a->strings["Widgets key"] = "Widgets Schlüssel";
$a->strings["Widgets available"] = "Verfügbare Widgets";
$a->strings["Connect on Friendika!"] = "Auf Friendika Verbinden!";
$a->strings["Three Dimensional Tic-Tac-Toe"] = "Dreidimensionales Tic-Tac-Toe";
$a->strings["3D Tic-Tac-Toe"] = "3D Tic-Tac-Toe";
@ -602,8 +754,6 @@ $a->strings["\"Cat\" game!"] = "Unentschieden!";
$a->strings["I won!"] = "Ich gewinne!";
$a->strings["Randplace Settings"] = "Randplace Einstellungen";
$a->strings["Enable Randplace Plugin"] = "Randplace Erweiterung aktivieren";
$a->strings["Select files to upload: "] = "Wähle Dateien zum Upload aus: ";
$a->strings["Use the following controls only if the Java uploader [above] fails to launch."] = "Verwende die folgenden Kontrollen nur, wenn der Java Uploader [oben] nicht funktioniert.";
$a->strings["Upload a file"] = "Datei hochladen";
$a->strings["Drop files here to upload"] = "Ziehe die Dateien hier her die du hochladen willst";
$a->strings["Failed"] = "Fehlgeschlagen";
@ -612,8 +762,15 @@ $a->strings["Uploaded file is empty"] = "Hochgeladene Datei ist leer";
$a->strings["Uploaded file is too large"] = "Hochgeladene Datei ist zu groß";
$a->strings["File has an invalid extension, it should be one of "] = "Die Dateiextension ist nicht erlaubt, sie muss eine der folgenden sein ";
$a->strings["Upload was cancelled, or server error encountered"] = "Upload abgebrochen oder Serverfehler aufgetreten";
$a->strings["Impressum"] = "Impressum";
$a->strings["Site Owner"] = "Betreiber der Seite";
$a->strings["Email Address"] = "Email Adresse";
$a->strings["Postal Address"] = "Postalische Anschrift";
$a->strings["The impressum addon needs to be configured!<br />Please add at least the <tt>owner</tt> variable to your config file. For other variables please refer to the README file of the addon."] = "Das Impressums Plugin muss noch konfiguriert werden.<br />Bitte gebe mindestens den <tt>Betreiber</tt> in der Konfiguration an. Alle weiteren Parameter werden in der README Datei des Addons erleutert.";
$a->strings["Site Owners Profile"] = "Profil des Seitenbetreibers";
$a->strings["Notes"] = "Hinweise";
$a->strings["OEmbed settings updated"] = "OEmbed Einstellungen aktualisiert.";
$a->strings["Use OEmbed for YouTube videos: "] = "OEmbed für YouTube videos verwenden: ";
$a->strings["Use OEmbed for YouTube videos"] = "OEmbed für Youtube Videos verwenden";
$a->strings["URL to embed:"] = "URL zum Einbetten:";
$a->strings["Post to StatusNet"] = "Nach StatusNet senden";
$a->strings["Please contact your site administrator.<br />The provided API URL is not valid."] = "Bitte kontaktiere den Administrator der Seite.<br />Die gegebene API URL ist nicht gültig.";
@ -634,18 +791,25 @@ $a->strings["Cancel Connection Process"] = "Verbindungsprozess abbrechen";
$a->strings["Current StatusNet API is"] = "Derzeitige StatusNet API URL lautet";
$a->strings["Cancel StatusNet Connection"] = "Verbindung zum StatusNet Server abbrechen";
$a->strings["Currently connected to: "] = "Momentan verbunden mit: ";
$a->strings["If enabled all your <strong>public</strong> postings will be posted to the associated StatusNet account."] = "Wenn aktiv, werden alle deine <strong>öffentlichen</strong> Beiträge auch auf dem verbundenen StatusNet Account veröffentlicht.";
$a->strings["If enabled all your <strong>public</strong> postings can be posted to the associated StatusNet account. You can choose to do so by default (here) or for every posting separately in the posting options when writing the entry."] = "Wenn aktiviert können all deine <strong>öffentlichen</strong> Einträge auf dem verbundenen StatusNet Konto veröffentlicht werden. Du kannst dies (hier) als Standartverhalten einstellen oder für jeden Eintrag separat in den Beitragsoptionen beim Schreiben des Eintrags festlegen.";
$a->strings["Allow posting to StatusNet"] = "Nach StatusNet senden erlauben";
$a->strings["Send public postings to StatusNet by default"] = "Veröffentliche alle öffentlichen Beiträge auch bei StatusNet";
$a->strings["Clear OAuth configuration"] = "OAuth Konfiguration löschen";
$a->strings["Piwik Base URL"] = "Piwik Basis URL";
$a->strings["Site ID"] = "Seiten ID";
$a->strings["Show opt-out cookie link?"] = "Link zum Setzen des Opt-Out Cookies anzeigen?";
$a->strings["Post to Twitter"] = "Nach Twitter senden";
$a->strings["Twitter settings updated."] = "Twitter Einstellungen aktualisiert.";
$a->strings["Twitter Posting Settings"] = "Twitter Posting Einstellungen";
$a->strings["No consumer key pair for Twitter found. Please contact your site administrator."] = "Kein Consumer Schlüsselpaar für Twitter gefunden. Bitte wende dich an den Administrator der Seite.";
$a->strings["At this Friendika instance the Twitter plugin was enabled but you have not yet connected your account to your Twitter account. To do so click the button below to get a PIN from Twitter which you have to copy into the input box below and submit the form. Only your <strong>public</strong> posts will be posted to Twitter."] = "Auf dieser Friendika Instanz wurde das Twitter Plugin aktiviert dein Account ist allerdings noch nicht mit einem Twitter Account verbunden. Um deinen Account mit Twitter zu verbinden, klick auf den Button weiter unten und gib die PIN die du auf Twitter erhälst hier ein. Es werden ausschließlich deine <strong>öffentlichen</strong> Nachrichten auf Twitter veröffentlicht.";
$a->strings["Log in with Twitter"] = "bei Twitter anmelden";
$a->strings["Copy the PIN from Twitter here"] = "Kopiere die Twitter PIN hier her";
$a->strings["If enabled all your <strong>public</strong> postings will be posted to the associated Twitter account as well."] = "Wenn dies aktiviert ist, werden alle deine <strong>öffentlichen</strong> Nachricten auch auf dem verbundenen Twitter Account veröffentlicht.";
$a->strings["Send public postings to Twitter"] = "Veröffentliche öffentliche Nachrichten auf Twitter";
$a->strings["If enabled all your <strong>public</strong> postings can be posted to the associated Twitter account. You can choose to do so by default (here) or for every posting separately in the posting options when writing the entry."] = "Wenn aktiviert können all deine <strong>öffentlichen</strong> Einträge auf dem verbundenen Twitter Konto veröffentlicht werden. Du kannst dies (hier) als Standartverhalten einstellen oder für jeden Eintrag separat in den Beitragsoptionen beim Schreiben des Eintrags festlegen.";
$a->strings["Allow posting to Twitter"] = "Nach Twitter senden erlauben";
$a->strings["Send public postings to Twitter by default"] = "Veröffentliche alle öffentlichen Beiträge auch bei Twitter";
$a->strings["Consumer key"] = "Anwender Schlüssel";
$a->strings["Consumer secret"] = "Anwender Geheimnis";
$a->strings["Gender:"] = "Geschlecht:";
$a->strings["Birthday:"] = "Geburtstag:";
$a->strings["j F, Y"] = "j F, Y";
@ -729,28 +893,80 @@ $a->strings["Uncertain"] = "Unsicher";
$a->strings["Complicated"] = "Kompliziert";
$a->strings["Don't care"] = "Ist mir nicht wichtig";
$a->strings["Ask me"] = "Frag mich";
$a->strings["l F d, Y \\@ g:i A"] = "l F d, Y \\@ g:i A";
$a->strings["Starts:"] = "Beginnt:";
$a->strings["Finishes:"] = "Endet:";
$a->strings["prev"] = "vorige";
$a->strings["first"] = "erste";
$a->strings["last"] = "letzte";
$a->strings["next"] = "nächste";
$a->strings["No contacts"] = "Keine Kontakte";
$a->strings["%d Contact"] = array(
0 => "%d Kontakt",
1 => "%d Kontakte",
);
$a->strings["Monday"] = "Montag";
$a->strings["Tuesday"] = "Dienstag";
$a->strings["Wednesday"] = "Mittwoch";
$a->strings["Thursday"] = "Donnerstag";
$a->strings["Friday"] = "Freitag";
$a->strings["Saturday"] = "Samstag";
$a->strings["Sunday"] = "Sonntag";
$a->strings["January"] = "Januar";
$a->strings["February"] = "Februar";
$a->strings["March"] = "März";
$a->strings["April"] = "April";
$a->strings["May"] = "Mai";
$a->strings["June"] = "Juni";
$a->strings["July"] = "Juli";
$a->strings["August"] = "August";
$a->strings["September"] = "September";
$a->strings["October"] = "Oktober";
$a->strings["November"] = "November";
$a->strings["December"] = "Dezember";
$a->strings["bytes"] = "Byte";
$a->strings["Select an alternate language"] = "Alternative Sprache auswählen";
$a->strings["Embedding disabled"] = "Einbettungen deaktiviert";
$a->strings["Create a new group"] = "Neue Gruppe erstellen";
$a->strings["Everybody"] = "Alle Kontakte";
$a->strings["Logout"] = "Abmelden";
$a->strings["End this session"] = "Diese Sitzung beenden";
$a->strings["Login"] = "Anmeldung";
$a->strings["Sign in"] = "Anmelden";
$a->strings["Home"] = "Persönlich";
$a->strings["Home Page"] = "Home Page";
$a->strings["Create an account"] = "Account erstellen";
$a->strings["Help and documentation"] = "Hilfe und Dokumentation";
$a->strings["Apps"] = "Apps";
$a->strings["Addon applications, utilities, games"] = "Addon Anwendungen, Dienstprogramme, Spiele";
$a->strings["Search site content"] = "Inhalt der Seite durchsuchen";
$a->strings["Conversations on this site"] = "Unterhaltungen auf dieser Seite";
$a->strings["Directory"] = "Verzeichnis";
$a->strings["People directory"] = "Nutzerverzeichnis";
$a->strings["Network"] = "Netzwerk";
$a->strings["Conversations from your friends"] = "Unterhaltungen deiner Kontakte";
$a->strings["Your posts and conversations"] = "Deine Einträge und Unterhaltungen";
$a->strings["Notifications"] = "Benachrichtigungen";
$a->strings["Friend requests"] = "Kontaktanfragen";
$a->strings["Private mail"] = "Private Email";
$a->strings["Manage"] = "Verwalten";
$a->strings["Settings"] = "Einstellungen";
$a->strings["Manage other pages"] = "Andere Seiten verwalten";
$a->strings["Manage/edit profiles"] = "Profile verwalten/editieren";
$a->strings["Manage/edit friends and contacts"] = "Freunde und Kontakte verwalten/editieren";
$a->strings["Admin"] = "Administration";
$a->strings["Site setup and configuration"] = "Einstellungen der Seite und Konfiguration";
$a->strings["Logged out."] = "Abgemeldet.";
$a->strings["Miscellaneous"] = "Verschiedenes";
$a->strings["less than a second ago"] = "vor weniger als einer Sekunde";
$a->strings["year"] = "Jahr";
$a->strings["years"] = "Jahre";
$a->strings["month"] = "Monat";
$a->strings["day"] = "Tag";
$a->strings["never"] = "nie";
$a->strings["less than a second ago"] = "vor weniger als einer Sekunde";
$a->strings["years"] = "Jahre";
$a->strings["months"] = "Monate";
$a->strings["week"] = "Woche";
$a->strings["weeks"] = "Wochen";
$a->strings["day"] = "Tag";
$a->strings["days"] = "Tage";
$a->strings["hour"] = "Stunde";
$a->strings["hours"] = "Stunden";
$a->strings["minute"] = "Minute";
@ -761,19 +977,23 @@ $a->strings[" ago"] = " her";
$a->strings["From: "] = "Von: ";
$a->strings["Image/photo"] = "Bild/Foto";
$a->strings["Cannot locate DNS info for database server '%s'"] = "Kann die DNS Informationen für den Datenbanken Server '%s' nicht ermitteln.";
$a->strings["Visible To:"] = "Sichtbar für:";
$a->strings["everybody"] = "jeder";
$a->strings["Groups"] = "Gruppen";
$a->strings["Except For:"] = "Abgesehen von:";
$a->strings["Visible to everybody"] = "Für jeden sichtbar";
$a->strings["show"] = "anzeigen";
$a->strings["don't show"] = "nicht anzeigen";
$a->strings["(no subject)"] = "(kein Betreff)";
$a->strings["You have a new follower at "] = "Du hast einen neuen Kontakt auf ";
$a->strings["event"] = "Veranstaltung";
$a->strings["View %s's profile"] = "Betrachte %s's Profil";
$a->strings["%s from %s"] = "%s von %s";
$a->strings["View in context"] = "Im Zusammenhang betrachten";
$a->strings["See more posts like this"] = "Mehr Beiträge wie diesen anzeigen";
$a->strings["See all %d comments"] = "Alle %d Kommentare anzeigen";
$a->strings["Select"] = "Auswählen";
$a->strings["toggle star status"] = "Stern Status umschalten";
$a->strings["to"] = "to";
$a->strings["Wall-to-Wall"] = "Wall-to-Wall";
$a->strings["via Wall-To-Wall:"] = "via Wall-To-Wall:";
$a->strings["Delete Selected Items"] = "Lösche die markierten Beiträge";
$a->strings["View status"] = "Status anzeigen";
$a->strings["View profile"] = "Profil anzeigen";
$a->strings["View photos"] = "Fotos ansehen";
@ -801,44 +1021,13 @@ $a->strings["Password: "] = "Passwort: ";
$a->strings["Nickname/Email/OpenID: "] = "Spitzname/Email/OpenID: ";
$a->strings["Password (if not OpenID): "] = "Passwort (falls nicht OpenID): ";
$a->strings["Forgot your password?"] = "Passwort vergessen?";
$a->strings["prev"] = "vorige";
$a->strings["first"] = "erste";
$a->strings["last"] = "letzte";
$a->strings["next"] = "nächste";
$a->strings["No contacts"] = "Keine Kontakte";
$a->strings["%d Contact"] = array(
0 => "%d Kontakt",
1 => "%d Kontakte",
);
$a->strings["Connect"] = "Verbinden";
$a->strings["Location:"] = "Ort:";
$a->strings[", "] = ", ";
$a->strings["Status:"] = "Status:";
$a->strings["Monday"] = "Montag";
$a->strings["Tuesday"] = "Dienstag";
$a->strings["Wednesday"] = "Mittwoch";
$a->strings["Thursday"] = "Donnerstag";
$a->strings["Friday"] = "Freitag";
$a->strings["Saturday"] = "Samstag";
$a->strings["Sunday"] = "Sonntag";
$a->strings["January"] = "Januar";
$a->strings["February"] = "Februar";
$a->strings["March"] = "März";
$a->strings["April"] = "April";
$a->strings["May"] = "Mai";
$a->strings["June"] = "Juni";
$a->strings["July"] = "Juli";
$a->strings["August"] = "August";
$a->strings["September"] = "September";
$a->strings["October"] = "Oktober";
$a->strings["November"] = "November";
$a->strings["December"] = "Dezember";
$a->strings["g A l F d"] = "g A l F d";
$a->strings["Birthday Reminders"] = "Geburtstagserinnerungen";
$a->strings["Birthdays this week:"] = "Geburtstage diese Woche:";
$a->strings["(Adjusted for local time)"] = "(an die lokale Zeit angepasst)";
$a->strings["[today]"] = "[heute]";
$a->strings["bytes"] = "Byte";
$a->strings["link to source"] = "Link zum original Posting";
$a->strings["Not Found"] = "Nicht gefunden";
$a->strings["Page not found."] = "Seite nicht gefunden.";

11
view/diaspora_comment.tpl Normal file
View File

@ -0,0 +1,11 @@
<XML>
<post>
<comment>
<guid>$guid</guid>
<parent_guid>$parent_guid</parent_guid>
<author_signature>$authorsig</author_signature>
<text>$body</text>
<diaspora_handle>$handle</diaspora_handle>
</comment>
</post>
</XML>

View File

@ -0,0 +1,12 @@
<XML>
<post>
<comment>
<guid>$guid</guid>
<parent_guid>$parent_guid</parent_guid>
<parent_author_signature>$parentsig</parent_author_signature>
<author_signature>$authorsig</author_signature>
<text>$body</text>
<diaspora_handle>$handle</diaspora_handle>
</comment>
</post>
</XML>

12
view/diaspora_like.tpl Normal file
View File

@ -0,0 +1,12 @@
<XML>
<post>
<like>
<target_type>$type</target_type>
<guid>$guid</guid>
<parent_guid>$parent_guid</parent_guid>
<author_signature>$authorsig</author_signature>
<positive>$positive</positive>
<diaspora_handle>$handle</diaspora_handle>
</like>
</post>
</XML>

View File

@ -0,0 +1,13 @@
<XML>
<post>
<like>
<guid>$guid</guid>
<target_type>$type</target_type>
<parent_guid>$parent_guid</parent_guid>
<parent_author_signature>$parentsig</parent_author_signature>
<author_signature>$authrosig</author_signature>
<positive>$positive</positive>
<diaspora_handle>$handle</diaspora_handle>
</like>
</post>
</XML>

11
view/diaspora_post.tpl Normal file
View File

@ -0,0 +1,11 @@
<XML>
<post>
<status_message>
<raw_message>$body</raw_message>
<guid>$guid</guid>
<diaspora_handle>$handle</diaspora_handle>
<public>$public</public>
<created_at>$created</created_at>
</status_message>
</post>
</XML>

View File

@ -0,0 +1,9 @@
<XML>
<post>
<retraction>
<post_guid>$guid</post_guid>
<type>$type</type>
<diaspora_handle>$handle</diaspora_handle>
</retraction>
</post>
</XML>

8
view/diaspora_share.tpl Normal file
View File

@ -0,0 +1,8 @@
<XML>
<post>
<request>
<sender_handle>$sender</sender_handle>
<recipient_handle>$recipient</recipient_handle>
</request>
</post>
</XML>

View File

@ -11,6 +11,7 @@ function initEditor(cb){
theme : "advanced",
mode : "specific_textareas",
editor_selector: /(profile-jot-text|prvmail-text)/,
auto_focus: "profile-jot-text",
plugins : "bbcode,paste,autoresize",
theme_advanced_buttons1 : "bold,italic,underline,undo,redo,link,unlink,image,forecolor,formatselect,code",
theme_advanced_buttons2 : "",

View File

@ -5,5 +5,5 @@ $data
</me:data>
<me:encoding>$encoding</me:encoding>
<me:alg>$algorithm</me:alg>
<me:sig keyhash="$keyhash">$signature</me:sig>
<me:sig key_id="$keyhash">$signature</me:sig>
</me:env>

View File

@ -1,3 +1,5 @@
$default
<h1>$banner</h1>
<div id="profile-edit-links">
@ -12,7 +14,6 @@
<div id="profile-edit-links-end"></div>
$default
<div id="profile-edit-wrapper" >
<form id="profile-edit-form" name="form1" action="profiles/$profile_id" method="post" >

View File

@ -24,3 +24,5 @@ $marital
$homepage
$diaspora

View File

@ -3416,7 +3416,7 @@ msgstr "segundos"
#: ../../include/datetime.php:164
msgid " ago"
msgstr "atrás"
msgstr " atrás"
#: ../../include/poller.php:380
msgid "From: "

View File

@ -757,7 +757,7 @@ $a->strings["minute"] = "minuto";
$a->strings["minutes"] = "minutos";
$a->strings["second"] = "segundo";
$a->strings["seconds"] = "segundos";
$a->strings[" ago"] = "atrás";
$a->strings[" ago"] = " atrás";
$a->strings["From: "] = "De: ";
$a->strings["Image/photo"] = "Imagem/foto";
$a->strings["Cannot locate DNS info for database server '%s'"] = "Não foi possível localizar a informação de DNS para o servidor de banco de dados '%s'";

View File

@ -57,5 +57,6 @@
<div id="register-submit-end" ></div>
</form>
<div class="cc-license">$license</div>
$license

View File

@ -45,7 +45,7 @@ code {
border: 1px solid #444;
background: #EEE;
color: #444;
padding: 0px 10px 10px 10px;
padding: 10px;
margin-top: 20px;
}
/*blockquote:before {
@ -539,13 +539,12 @@ input#dfrn-url {
width: 300px;
}
#profile-edit-drop-link-wrapper {
float: left;
}
#profile-edit-links-end {
clear: both;
margin-bottom: 15px;
}
.profile-listing-photo {
border: none;
}
@ -1487,6 +1486,7 @@ input#dfrn-url {
height: 20px;
color:#cccccc;
border: 1px solid #cccccc;
padding: 3px 0px 0px 5px;
}

View File

@ -2,7 +2,7 @@
<XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'
xmlns:hm='http://host-meta.net/xrd/1.0'>
<hm:Host>$domain</hm:Host>
<hm:Host>$zroot</hm:Host>
<Link rel='lrdd' template='$domain/xrd/?uri={uri}' />
<Link rel='acct-mgmt' href='$domain/amcd' />

View File

@ -15,7 +15,7 @@
href="$profile_url" />
<Link rel="http://microformats.org/profile/hcard"
type="text/html"
href="$profile_url" />
href="$hcard_url" />
<Link rel="http://webfinger.net/rel/avatar"
type="image/jpeg"
href="$photo" />