Merge remote branch 'upstream/master'

This commit is contained in:
Michael Vogel 2012-05-09 14:57:46 +02:00
commit 51432d9b31
45 changed files with 756 additions and 206 deletions

View file

@ -12,13 +12,13 @@ for a in $SUBDIRS; do
if [[ ! -f $TGZ ]]; then if [[ ! -f $TGZ ]]; then
echo "Building: " $TGZ echo "Building: " $TGZ
# git log $a > $a/$a.log # git log $a > $a/$a.log
tar zcvf $TGZ $a tar zcvf $TGZ --exclude=.[a-z]* $a
else else
TOUCHED=`find $a -cnewer $TGZ` TOUCHED=`find $a -cnewer $TGZ`
if [[ -n $TOUCHED ]]; then if [[ -n $TOUCHED ]]; then
echo "Building: " $TGZ echo "Building: " $TGZ
# git log $a > $a/$a.log # git log $a > $a/$a.log
tar zcvf $TGZ $a tar zcvf $TGZ --exclude=.[a-z]* $a
fi fi
fi fi
done done

Binary file not shown.

View file

@ -1,7 +1,7 @@
Installing the Friendica/Facebook connector Installing the Friendica/Facebook connector
Detailed instructions how to use this plugin can be found at Detailed instructions how to use this plugin can be found at
https://github.com/friendica/friendica/wiki/How-to:-Friendica%E2%80%99s-Facebook-connector the [How to: Friendica's Facebook Connector](https://github.com/friendica/friendica/wiki/How-to:-Friendica%E2%80%99s-Facebook-connector) page.
Vidoes and embeds will not be posted if there is no other content. Links Vidoes and embeds will not be posted if there is no other content. Links
and images will be converted to a format suitable for the Facebook API and and images will be converted to a format suitable for the Facebook API and
@ -12,5 +12,4 @@ authenticate to your site to establish identity. We will address this
in a future release. in a future release.
Info: please make sure that you understand all aspects due to Friendica's Info: please make sure that you understand all aspects due to Friendica's
default licence which is: MIT License (further info: default licence which is: [MIT License](https://github.com/friendica/friendica/blob/master/LICENSE)
https://github.com/friendica/friendica/blob/master/LICENSE)

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Name: Facebook Connector * Name: Facebook Connector
* Version: 1.2 * Version: 1.3
* Author: Mike Macgirvin <http://macgirvin.com/profile/mike> * Author: Mike Macgirvin <http://macgirvin.com/profile/mike>
* Tobias Hößl <https://github.com/CatoTH/> * Tobias Hößl <https://github.com/CatoTH/>
*/ */
@ -33,6 +33,7 @@ define('FACEBOOK_MAXPOSTLEN', 63206);
define('FACEBOOK_SESSION_ERR_NOTIFICATION_INTERVAL', 259200); // 3 days define('FACEBOOK_SESSION_ERR_NOTIFICATION_INTERVAL', 259200); // 3 days
define('FACEBOOK_DEFAULT_POLL_INTERVAL', 60); // given in minutes define('FACEBOOK_DEFAULT_POLL_INTERVAL', 60); // given in minutes
define('FACEBOOK_MIN_POLL_INTERVAL', 5); define('FACEBOOK_MIN_POLL_INTERVAL', 5);
define('FACEBOOK_RTU_ERR_MAIL_AFTER_MINUTES', 180); // 3 hours
require_once('include/security.php'); require_once('include/security.php');
@ -429,6 +430,10 @@ function facebook_post(&$a) {
$uid = local_user(); $uid = local_user();
if($uid){ if($uid){
$fb_limited = get_config('facebook','restrict');
$value = ((x($_POST,'post_by_default')) ? intval($_POST['post_by_default']) : 0); $value = ((x($_POST,'post_by_default')) ? intval($_POST['post_by_default']) : 0);
set_pconfig($uid,'facebook','post_by_default', $value); set_pconfig($uid,'facebook','post_by_default', $value);
@ -444,7 +449,13 @@ function facebook_post(&$a) {
set_pconfig($uid,'facebook','blocked_apps',escape_tags(trim($_POST['blocked_apps']))); set_pconfig($uid,'facebook','blocked_apps',escape_tags(trim($_POST['blocked_apps'])));
$linkvalue = ((x($_POST,'facebook_linking')) ? intval($_POST['facebook_linking']) : 0); $linkvalue = ((x($_POST,'facebook_linking')) ? intval($_POST['facebook_linking']) : 0);
set_pconfig($uid,'facebook','no_linking', (($linkvalue) ? 0 : 1));
if($fb_limited) {
if($linkvalue == 0)
set_pconfig($uid,'facebook','no_linking', 1);
}
else
set_pconfig($uid,'facebook','no_linking', (($linkvalue) ? 0 : 1));
// FB linkage was allowed but has just been turned off - remove all FB contacts and posts // FB linkage was allowed but has just been turned off - remove all FB contacts and posts
@ -495,6 +506,9 @@ function facebook_content(&$a) {
info( t('Updating contacts') . EOL); info( t('Updating contacts') . EOL);
} }
$fb_limited = get_config('facebook','restrict');
$o = ''; $o = '';
$fb_installed = false; $fb_installed = false;
@ -516,7 +530,7 @@ function facebook_content(&$a) {
return ''; return '';
} }
$a->page['htmlhead'] .= '<link rel="stylesheet" type="text/css" href="' $a->page['htmlhead'] .= '<link rel="stylesheet" type="text/css" href="'
. $a->get_baseurl() . '/addon/facebook/facebook.css' . '" media="all" />' . "\r\n"; . $a->get_baseurl() . '/addon/facebook/facebook.css' . '" media="all" />' . "\r\n";
$o .= '<h3>' . t('Facebook Connect') . '</h3>'; $o .= '<h3>' . t('Facebook Connect') . '</h3>';
@ -548,6 +562,15 @@ function facebook_content(&$a) {
$no_linking = get_pconfig(local_user(),'facebook','no_linking'); $no_linking = get_pconfig(local_user(),'facebook','no_linking');
$checked = (($no_linking) ? '' : ' checked="checked" '); $checked = (($no_linking) ? '' : ' checked="checked" ');
if($fb_limited) {
if($no_linking) {
$o .= EOL . '<strong>' . t('Facebook friend linking has been disabled on this site. The following settings will have no effect.') . '</strong>' . EOL;
$checked .= " disabled ";
}
else {
$o .= EOL . '<strong>' . t('Facebook friend linking has been disabled on this site. If you disable it, you will be unable to re-enable it.') . '</strong>' . EOL;
}
}
$o .= '<input type="checkbox" name="facebook_linking" value="1"' . $checked . '/>' . ' ' . t('Link all your Facebook friends and conversations on this website') . EOL ; $o .= '<input type="checkbox" name="facebook_linking" value="1"' . $checked . '/>' . ' ' . t('Link all your Facebook friends and conversations on this website') . EOL ;
$o .= '<p>' . t('Facebook conversations consist of your <em>profile wall</em> and your friend <em>stream</em>.'); $o .= '<p>' . t('Facebook conversations consist of your <em>profile wall</em> and your friend <em>stream</em>.');
@ -592,7 +615,7 @@ function facebook_cron($a,$b) {
$poll_interval = FACEBOOK_DEFAULT_POLL_INTERVAL; $poll_interval = FACEBOOK_DEFAULT_POLL_INTERVAL;
if($last) { if($last) {
$next = $last + $poll_interval; $next = $last + ($poll_interval * 60);
if($next > time()) if($next > time())
return; return;
} }
@ -643,8 +666,15 @@ function facebook_cron($a,$b) {
logger('facebook_cron: Successful', LOGGER_NORMAL); logger('facebook_cron: Successful', LOGGER_NORMAL);
else { else {
logger('facebook_cron: Failed', LOGGER_NORMAL); logger('facebook_cron: Failed', LOGGER_NORMAL);
if(strlen($a->config['admin_email']) && !get_config('facebook', 'realtime_err_mailsent')) { $first_err = get_config('facebook', 'realtime_first_err');
if (!$first_err) {
$first_err = time();
set_config('facebook', 'realtime_first_err', $first_err);
}
$first_err_ago = (time() - $first_err);
if(strlen($a->config['admin_email']) && !get_config('facebook', 'realtime_err_mailsent') && $first_err_ago > (FACEBOOK_RTU_ERR_MAIL_AFTER_MINUTES * 60)) {
mail($a->config['admin_email'], t('Problems with Facebook Real-Time Updates'), mail($a->config['admin_email'], t('Problems with Facebook Real-Time Updates'),
"Hi!\n\nThere's a problem with the Facebook Real-Time Updates that cannot be solved automatically. Maybe a permission issue?\n\nPlease try to re-activate it on " . $a->config["system"]["url"] . "/admin/plugins/facebook\n\nThis e-mail will only be sent once.", "Hi!\n\nThere's a problem with the Facebook Real-Time Updates that cannot be solved automatically. Maybe a permission issue?\n\nPlease try to re-activate it on " . $a->config["system"]["url"] . "/admin/plugins/facebook\n\nThis e-mail will only be sent once.",
'From: ' . t('Administrator') . '@' . $_SERVER['SERVER_NAME'] . "\n" 'From: ' . t('Administrator') . '@' . $_SERVER['SERVER_NAME'] . "\n"
@ -657,6 +687,7 @@ function facebook_cron($a,$b) {
} }
} else { // !facebook_check_realtime_active() } else { // !facebook_check_realtime_active()
del_config('facebook', 'realtime_err_mailsent'); del_config('facebook', 'realtime_err_mailsent');
del_config('facebook', 'realtime_first_err');
} }
} }
@ -693,6 +724,7 @@ function facebook_plugin_admin(&$a, &$o){
$appid = get_config('facebook', 'appid' ); $appid = get_config('facebook', 'appid' );
$appsecret = get_config('facebook', 'appsecret' ); $appsecret = get_config('facebook', 'appsecret' );
$poll_interval = get_config('facebook', 'poll_interval' ); $poll_interval = get_config('facebook', 'poll_interval' );
$sync_comments = get_config('facebook', 'sync_comments' );
if (!$poll_interval) $poll_interval = FACEBOOK_DEFAULT_POLL_INTERVAL; if (!$poll_interval) $poll_interval = FACEBOOK_DEFAULT_POLL_INTERVAL;
$ret1 = q("SELECT `v` FROM `config` WHERE `cat` = 'facebook' AND `k` = 'appid' LIMIT 1"); $ret1 = q("SELECT `v` FROM `config` WHERE `cat` = 'facebook' AND `k` = 'appid' LIMIT 1");
@ -709,9 +741,10 @@ function facebook_plugin_admin(&$a, &$o){
} else $o .= t('The correctness of the API Key could not be detected. Somthing strange\'s going on.') . '<br>'; } else $o .= t('The correctness of the API Key could not be detected. Somthing strange\'s going on.') . '<br>';
} }
$o .= '<label for="fb_appid">' . t('App-ID / API-Key') . '</label><input name="appid" type="text" value="' . escape_tags($appid ? $appid : "") . '"><br style="clear: both;">'; $o .= '<label for="fb_appid">' . t('App-ID / API-Key') . '</label><input id="fb_appid" name="appid" type="text" value="' . escape_tags($appid ? $appid : "") . '"><br style="clear: both;">';
$o .= '<label for="fb_appsecret">' . t('Application secret') . '</label><input name="appsecret" type="text" value="' . escape_tags($appsecret ? $appsecret : "") . '"><br style="clear: both;">'; $o .= '<label for="fb_appsecret">' . t('Application secret') . '</label><input id="fb_appsecret" name="appsecret" type="text" value="' . escape_tags($appsecret ? $appsecret : "") . '"><br style="clear: both;">';
$o .= '<label for="fb_poll_interval">' . sprintf(t('Polling Interval (min. %1$s minutes)'), FACEBOOK_MIN_POLL_INTERVAL) . '</label><input name="poll_interval" type="number" min="' . FACEBOOK_MIN_POLL_INTERVAL . '" value="' . $poll_interval . '"><br style="clear: both;">'; $o .= '<label for="fb_poll_interval">' . sprintf(t('Polling Interval in minutes (minimum %1$s minutes)'), FACEBOOK_MIN_POLL_INTERVAL) . '</label><input name="poll_interval" id="fb_poll_interval" type="number" min="' . FACEBOOK_MIN_POLL_INTERVAL . '" value="' . $poll_interval . '"><br style="clear: both;">';
$o .= '<label for="fb_sync_comments">' . t('Synchronize comments (no comments on Facebook are missed, at the cost of increased system load)') . '</label><input name="sync_comments" id="fb_sync_comments" type="checkbox" ' . ($sync_comments ? 'checked' : '') . '><br style="clear: both;">';
$o .= '<input type="submit" name="fb_save_keys" value="' . t('Save') . '">'; $o .= '<input type="submit" name="fb_save_keys" value="' . t('Save') . '">';
if ($working_connection) { if ($working_connection) {
@ -729,9 +762,9 @@ function facebook_plugin_admin(&$a, &$o){
/** /**
* @param App $a * @param App $a
* @param null|object $o
*/ */
function facebook_plugin_admin_post(&$a, &$o){
function facebook_plugin_admin_post(&$a){
check_form_security_token_redirectOnErr('/admin/plugins/facebook', 'fbsave'); check_form_security_token_redirectOnErr('/admin/plugins/facebook', 'fbsave');
if (x($_REQUEST,'fb_save_keys')) { if (x($_REQUEST,'fb_save_keys')) {
@ -739,6 +772,7 @@ function facebook_plugin_admin_post(&$a, &$o){
set_config('facebook', 'appsecret', $_REQUEST['appsecret']); set_config('facebook', 'appsecret', $_REQUEST['appsecret']);
$poll_interval = IntVal($_REQUEST['poll_interval']); $poll_interval = IntVal($_REQUEST['poll_interval']);
if ($poll_interval >= FACEBOOK_MIN_POLL_INTERVAL) set_config('facebook', 'poll_interval', $poll_interval); if ($poll_interval >= FACEBOOK_MIN_POLL_INTERVAL) set_config('facebook', 'poll_interval', $poll_interval);
set_config('facebook', 'sync_comments', (x($_REQUEST, 'sync_comments') ? 1 : 0));
del_config('facebook', 'app_access_token'); del_config('facebook', 'app_access_token');
info(t('The new values have been saved.')); info(t('The new values have been saved.'));
} }
@ -1361,6 +1395,219 @@ function fb_get_photo($uid,$link) {
return ""; return "";
} }
/**
* @param App $a
* @param array $user
* @param array $self
* @param string $fb_id
* @param bool $wall
* @param array $orig_post
* @param object $cmnt
*/
function fb_consume_comment(&$a, &$user, &$self, $fb_id, $wall, &$orig_post, &$cmnt) {
if(! $orig_post)
return;
$top_item = $orig_post['id'];
$uid = IntVal($user[0]['uid']);
$r = q("SELECT * FROM `item` WHERE `uid` = %d AND ( `uri` = '%s' OR `extid` = '%s' ) LIMIT 1",
intval($uid),
dbesc('fb::' . $cmnt->id),
dbesc('fb::' . $cmnt->id)
);
if(count($r))
return;
$cmntdata = array();
$cmntdata['parent'] = $top_item;
$cmntdata['verb'] = ACTIVITY_POST;
$cmntdata['gravity'] = 6;
$cmntdata['uid'] = $uid;
$cmntdata['wall'] = (($wall) ? 1 : 0);
$cmntdata['uri'] = 'fb::' . $cmnt->id;
$cmntdata['parent-uri'] = $orig_post['uri'];
if($cmnt->from->id == $fb_id) {
$cmntdata['contact-id'] = $self[0]['id'];
}
else {
$r = q("SELECT * FROM `contact` WHERE `notify` = '%s' AND `uid` = %d LIMIT 1",
dbesc($cmnt->from->id),
intval($uid)
);
if(count($r)) {
$cmntdata['contact-id'] = $r[0]['id'];
if($r[0]['blocked'] || $r[0]['readonly'])
return;
}
}
if(! x($cmntdata,'contact-id'))
$cmntdata['contact-id'] = $orig_post['contact-id'];
$cmntdata['app'] = 'facebook';
$cmntdata['created'] = datetime_convert('UTC','UTC',$cmnt->created_time);
$cmntdata['edited'] = datetime_convert('UTC','UTC',$cmnt->created_time);
$cmntdata['verb'] = ACTIVITY_POST;
$cmntdata['author-name'] = $cmnt->from->name;
$cmntdata['author-link'] = 'http://facebook.com/profile.php?id=' . $cmnt->from->id;
$cmntdata['author-avatar'] = 'https://graph.facebook.com/' . $cmnt->from->id . '/picture';
$cmntdata['body'] = $cmnt->message;
$item = item_store($cmntdata);
$myconv = q("SELECT `author-link`, `author-avatar`, `parent` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `parent` != 0 AND `deleted` = 0",
dbesc($orig_post['uri']),
intval($uid)
);
if(count($myconv)) {
$importer_url = $a->get_baseurl() . '/profile/' . $user[0]['nickname'];
foreach($myconv as $conv) {
// now if we find a match, it means we're in this conversation
if(! link_compare($conv['author-link'],$importer_url))
continue;
require_once('include/enotify.php');
$conv_parent = $conv['parent'];
notification(array(
'type' => NOTIFY_COMMENT,
'notify_flags' => $user[0]['notify-flags'],
'language' => $user[0]['language'],
'to_name' => $user[0]['username'],
'to_email' => $user[0]['email'],
'uid' => $user[0]['uid'],
'item' => $cmntdata,
'link' => $a->get_baseurl() . '/display/' . $user[0]['nickname'] . '/' . $item,
'source_name' => $cmntdata['author-name'],
'source_link' => $cmntdata['author-link'],
'source_photo' => $cmntdata['author-avatar'],
'verb' => ACTIVITY_POST,
'otype' => 'item',
'parent' => $conv_parent,
));
// only send one notification
break;
}
}
}
/**
* @param App $a
* @param array $user
* @param array $self
* @param string $fb_id
* @param bool $wall
* @param array $orig_post
* @param object $likes
*/
function fb_consume_like(&$a, &$user, &$self, $fb_id, $wall, &$orig_post, &$likes) {
$top_item = $orig_post['id'];
$uid = IntVal($user[0]['uid']);
if(! $orig_post)
return;
// If we posted the like locally, it will be found with our url, not the FB url.
$second_url = (($likes->id == $fb_id) ? $self[0]['url'] : 'http://facebook.com/profile.php?id=' . $likes->id);
$r = q("SELECT * FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `verb` = '%s'
AND ( `author-link` = '%s' OR `author-link` = '%s' ) LIMIT 1",
dbesc($orig_post['uri']),
intval($uid),
dbesc(ACTIVITY_LIKE),
dbesc('http://facebook.com/profile.php?id=' . $likes->id),
dbesc($second_url)
);
if(count($r))
return;
$likedata = array();
$likedata['parent'] = $top_item;
$likedata['verb'] = ACTIVITY_LIKE;
$likedata['gravity'] = 3;
$likedata['uid'] = $uid;
$likedata['wall'] = (($wall) ? 1 : 0);
$likedata['uri'] = item_new_uri($a->get_baseurl(), $uid);
$likedata['parent-uri'] = $orig_post['uri'];
if($likes->id == $fb_id)
$likedata['contact-id'] = $self[0]['id'];
else {
$r = q("SELECT * FROM `contact` WHERE `notify` = '%s' AND `uid` = %d AND `blocked` = 0 AND `readonly` = 0 LIMIT 1",
dbesc($likes->id),
intval($uid)
);
if(count($r))
$likedata['contact-id'] = $r[0]['id'];
}
if(! x($likedata,'contact-id'))
$likedata['contact-id'] = $orig_post['contact-id'];
$likedata['app'] = 'facebook';
$likedata['verb'] = ACTIVITY_LIKE;
$likedata['author-name'] = $likes->name;
$likedata['author-link'] = 'http://facebook.com/profile.php?id=' . $likes->id;
$likedata['author-avatar'] = 'https://graph.facebook.com/' . $likes->id . '/picture';
$author = '[url=' . $likedata['author-link'] . ']' . $likedata['author-name'] . '[/url]';
$objauthor = '[url=' . $orig_post['author-link'] . ']' . $orig_post['author-name'] . '[/url]';
$post_type = t('status');
$plink = '[url=' . $orig_post['plink'] . ']' . $post_type . '[/url]';
$likedata['object-type'] = ACTIVITY_OBJ_NOTE;
$likedata['body'] = sprintf( t('%1$s likes %2$s\'s %3$s'), $author, $objauthor, $plink);
$likedata['object'] = '<object><type>' . ACTIVITY_OBJ_NOTE . '</type><local>1</local>' .
'<id>' . $orig_post['uri'] . '</id><link>' . xmlify('<link rel="alternate" type="text/html" href="' . xmlify($orig_post['plink']) . '" />') . '</link><title>' . $orig_post['title'] . '</title><content>' . $orig_post['body'] . '</content></object>';
item_store($likedata);
}
/**
* @param App $a
* @param array $user
* @param object $entry
* @param array $self
* @param string $fb_id
* @param bool $wall
* @param array $orig_post
*/
function fb_consume_status(&$a, &$user, &$entry, &$self, $fb_id, $wall, &$orig_post) {
$uid = IntVal($user[0]['uid']);
$access_token = get_pconfig($uid, 'facebook', 'access_token');
$s = fetch_url('https://graph.facebook.com/' . $entry->id . '?access_token=' . $access_token);
if($s) {
$j = json_decode($s);
if (isset($j->comments) && isset($j->comments->data))
foreach ($j->comments->data as $cmnt)
fb_consume_comment($a, $user, $self, $fb_id, $wall, $orig_post, $cmnt);
if (isset($j->likes) && isset($j->likes->data) && isset($j->likes->count)) {
if (count($j->likes->data) == $j->likes->count) {
foreach ($j->likes->data as $likers) fb_consume_like($a, $user, $self, $fb_id, $wall, $orig_post, $likers);
} else {
$t = fetch_url('https://graph.facebook.com/' . $entry->id . '/likes?access_token=' . $access_token);
if ($t) {
$k = json_decode($t);
if (isset($k->data))
foreach ($k->data as $likers)
fb_consume_like($a, $user, $self, $fb_id, $wall, $orig_post, $likers);
}
}
}
}
}
/** /**
* @param int $uid * @param int $uid
* @param object $j * @param object $j
@ -1370,7 +1617,6 @@ function fb_consume_stream($uid,$j,$wall = false) {
$a = get_app(); $a = get_app();
$user = q("SELECT * FROM `user` WHERE `uid` = %d AND `account_expired` = 0 LIMIT 1", $user = q("SELECT * FROM `user` WHERE `uid` = %d AND `account_expired` = 0 LIMIT 1",
intval($uid) intval($uid)
); );
@ -1390,6 +1636,9 @@ function fb_consume_stream($uid,$j,$wall = false) {
$blocked_apps = get_pconfig($uid,'facebook','blocked_apps'); $blocked_apps = get_pconfig($uid,'facebook','blocked_apps');
$blocked_apps_arr = explode(',',$blocked_apps); $blocked_apps_arr = explode(',',$blocked_apps);
$sync_comments = get_config('facebook', 'sync_comments');
/** @var string $self_id */
$self_id = get_pconfig($uid,'facebook','self_id'); $self_id = get_pconfig($uid,'facebook','self_id');
if(! count($j->data) || (! strlen($self_id))) if(! count($j->data) || (! strlen($self_id)))
return; return;
@ -1591,169 +1840,53 @@ function fb_consume_stream($uid,$j,$wall = false) {
} }
} }
/** @var array $orig_post */
$likers_num = (isset($entry->likes) && isset($entry->likes->count) ? IntVal($entry->likes->count) : 0 );
if(isset($entry->likes) && isset($entry->likes->data)) if(isset($entry->likes) && isset($entry->likes->data))
$likers = $entry->likes->data; $likers = $entry->likes->data;
else else
$likers = null; $likers = null;
$comments_num = (isset($entry->comments) && isset($entry->comments->count) ? IntVal($entry->comments->count) : 0 );
if(isset($entry->comments) && isset($entry->comments->data)) if(isset($entry->comments) && isset($entry->comments->data))
$comments = $entry->comments->data; $comments = $entry->comments->data;
else else
$comments = null; $comments = null;
if(is_array($likers)) { $needs_sync = false;
foreach($likers as $likes) {
if(! $orig_post) if(is_array($likers)) {
continue; foreach($likers as $likes) fb_consume_like($a, $user, $self, $self_id, $wall, $orig_post, $likes);
if ($sync_comments) {
// If we posted the like locally, it will be found with our url, not the FB url. $r = q("SELECT COUNT(*) likes FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `verb` = '%s' AND `parent-uri` != `uri`",
dbesc($orig_post['uri']),
$second_url = (($likes->id == $self_id) ? $self[0]['url'] : 'http://facebook.com/profile.php?id=' . $likes->id); intval($uid),
dbesc(ACTIVITY_LIKE)
$r = q("SELECT * FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `verb` = '%s' );
AND ( `author-link` = '%s' OR `author-link` = '%s' ) LIMIT 1", if ($r[0]['likes'] < $likers_num) {
dbesc($orig_post['uri']), logger('fb_consume_stream: missing likes found for ' . $orig_post['uri'] . ' (we have ' . $r[0]['likes'] . ' of ' . $likers_num . '). Synchronizing...', LOGGER_DEBUG);
intval($uid), $needs_sync = true;
dbesc(ACTIVITY_LIKE), }
dbesc('http://facebook.com/profile.php?id=' . $likes->id), }
dbesc($second_url)
);
if(count($r))
continue;
$likedata = array();
$likedata['parent'] = $top_item;
$likedata['verb'] = ACTIVITY_LIKE;
$likedata['gravity'] = 3;
$likedata['uid'] = $uid;
$likedata['wall'] = (($wall) ? 1 : 0);
$likedata['uri'] = item_new_uri($a->get_baseurl(), $uid);
$likedata['parent-uri'] = $orig_post['uri'];
if($likes->id == $self_id)
$likedata['contact-id'] = $self[0]['id'];
else {
$r = q("SELECT * FROM `contact` WHERE `notify` = '%s' AND `uid` = %d AND `blocked` = 0 AND `readonly` = 0 LIMIT 1",
dbesc($likes->id),
intval($uid)
);
if(count($r))
$likedata['contact-id'] = $r[0]['id'];
}
if(! x($likedata,'contact-id'))
$likedata['contact-id'] = $orig_post['contact-id'];
$likedata['app'] = 'facebook';
$likedata['verb'] = ACTIVITY_LIKE;
$likedata['author-name'] = $likes->name;
$likedata['author-link'] = 'http://facebook.com/profile.php?id=' . $likes->id;
$likedata['author-avatar'] = 'https://graph.facebook.com/' . $likes->id . '/picture';
$author = '[url=' . $likedata['author-link'] . ']' . $likedata['author-name'] . '[/url]';
$objauthor = '[url=' . $orig_post['author-link'] . ']' . $orig_post['author-name'] . '[/url]';
$post_type = t('status');
$plink = '[url=' . $orig_post['plink'] . ']' . $post_type . '[/url]';
$likedata['object-type'] = ACTIVITY_OBJ_NOTE;
$likedata['body'] = sprintf( t('%1$s likes %2$s\'s %3$s'), $author, $objauthor, $plink);
$likedata['object'] = '<object><type>' . ACTIVITY_OBJ_NOTE . '</type><local>1</local>' .
'<id>' . $orig_post['uri'] . '</id><link>' . xmlify('<link rel="alternate" type="text/html" href="' . xmlify($orig_post['plink']) . '" />') . '</link><title>' . $orig_post['title'] . '</title><content>' . $orig_post['body'] . '</content></object>';
item_store($likedata);
}
} }
if(is_array($comments)) { if(is_array($comments)) {
foreach($comments as $cmnt) { foreach($comments as $cmnt) fb_consume_comment($a, $user, $self, $self_id, $wall, $orig_post, $cmnt);
if ($sync_comments) {
if(! $orig_post) $r = q("SELECT COUNT(*) comments FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `verb` = '%s' AND `parent-uri` != `uri`",
continue; dbesc($orig_post['uri']),
intval($uid),
$r = q("SELECT * FROM `item` WHERE `uid` = %d AND ( `uri` = '%s' OR `extid` = '%s' ) LIMIT 1", ACTIVITY_POST
intval($uid), );
dbesc('fb::' . $cmnt->id), if ($r[0]['comments'] < $comments_num) {
dbesc('fb::' . $cmnt->id) logger('fb_consume_stream: missing comments found for ' . $orig_post['uri'] . ' (we have ' . $r[0]['comments'] . ' of ' . $comments_num . '). Synchronizing...', LOGGER_DEBUG);
); $needs_sync = true;
if(count($r)) }
continue;
$cmntdata = array();
$cmntdata['parent'] = $top_item;
$cmntdata['verb'] = ACTIVITY_POST;
$cmntdata['gravity'] = 6;
$cmntdata['uid'] = $uid;
$cmntdata['wall'] = (($wall) ? 1 : 0);
$cmntdata['uri'] = 'fb::' . $cmnt->id;
$cmntdata['parent-uri'] = $orig_post['uri'];
if($cmnt->from->id == $self_id) {
$cmntdata['contact-id'] = $self[0]['id'];
}
else {
$r = q("SELECT * FROM `contact` WHERE `notify` = '%s' AND `uid` = %d LIMIT 1",
dbesc($cmnt->from->id),
intval($uid)
);
if(count($r)) {
$cmntdata['contact-id'] = $r[0]['id'];
if($r[0]['blocked'] || $r[0]['readonly'])
continue;
}
}
if(! x($cmntdata,'contact-id'))
$cmntdata['contact-id'] = $orig_post['contact-id'];
$cmntdata['app'] = 'facebook';
$cmntdata['created'] = datetime_convert('UTC','UTC',$cmnt->created_time);
$cmntdata['edited'] = datetime_convert('UTC','UTC',$cmnt->created_time);
$cmntdata['verb'] = ACTIVITY_POST;
$cmntdata['author-name'] = $cmnt->from->name;
$cmntdata['author-link'] = 'http://facebook.com/profile.php?id=' . $cmnt->from->id;
$cmntdata['author-avatar'] = 'https://graph.facebook.com/' . $cmnt->from->id . '/picture';
$cmntdata['body'] = $cmnt->message;
$item = item_store($cmntdata);
$myconv = q("SELECT `author-link`, `author-avatar`, `parent` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `parent` != 0 ",
dbesc($orig_post['uri']),
intval($uid)
);
if(count($myconv)) {
$importer_url = $a->get_baseurl() . '/profile/' . $user[0]['nickname'];
foreach($myconv as $conv) {
// now if we find a match, it means we're in this conversation
if(! link_compare($conv['author-link'],$importer_url))
continue;
require_once('include/enotify.php');
$conv_parent = $conv['parent'];
notification(array(
'type' => NOTIFY_COMMENT,
'notify_flags' => $user[0]['notify-flags'],
'language' => $user[0]['language'],
'to_name' => $user[0]['username'],
'to_email' => $user[0]['email'],
'uid' => $user[0]['uid'],
'item' => $cmntdata,
'link' => $a->get_baseurl() . '/display/' . $user[0]['nickname'] . '/' . $item,
'source_name' => $cmntdata['author-name'],
'source_link' => $cmntdata['author-link'],
'source_photo' => $cmntdata['author-avatar'],
'verb' => ACTIVITY_POST,
'otype' => 'item',
'parent' => $conv_parent,
));
// only send one notification
break;
}
}
} }
} }
if ($needs_sync) fb_consume_status($a, $user, $entry, $self, $self_id, $wall, $orig_post);
} }
} }

BIN
facebook_restrict.tgz Normal file

Binary file not shown.

View file

@ -0,0 +1,18 @@
<?php
/**
* Name: Facebook Restrict
* Description: Install this addon and Facebook users will not be able to link friends. Existing users that are linking friends will not be affected.
* Version: 1.0
* Author: Mike Macgirvin <http://macgirvin.com/profile/mike>
*/
function facebook_restrict_install() {
set_config('facebook','restrict',1);
}
function facebook_restrict_uninstall() {
set_config('facebook','restrict',0);
}

BIN
hangman.tar.gz Normal file

Binary file not shown.

4
hangman/hang.css Normal file
View file

@ -0,0 +1,4 @@
.hanga {font:bold 14pt Courier, "Courier New", monospace;text-align:center;}
.hangt {font:normal 16pt Courier, "Courier New", monospace;text-align:center;color:#efefef;}
.hangb {width:800px;height:430px;overflow:hidden;background:#777;border:#000000 1px solid;}

BIN
hangman/hang0.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

BIN
hangman/hang1.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 B

BIN
hangman/hang10.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 B

BIN
hangman/hang2.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

BIN
hangman/hang3.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

BIN
hangman/hang4.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 B

BIN
hangman/hang5.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 B

BIN
hangman/hang6.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 B

BIN
hangman/hang7.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 481 B

BIN
hangman/hang8.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

BIN
hangman/hang9.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 495 B

51
hangman/hangans.js Normal file
View file

@ -0,0 +1,51 @@
var img = ''
var opts = new Array(); var r = 0;
opts[r++] = '^!33#`4!<^#`/9~1$4>-';
opts[r++] = '#:#0# 9 66@28?>0?/@+';
opts[r++] = '@!45::!@9/5/1>*5_2>7';
opts[r++] = '1`-52:#<<9_`2:2#8/9!';
opts[r++] = '4! $:5 $9_=^+59-9:25';
opts[r++] = '1+`2-52+-<917:0*!1#3';
opts[r++] = '65<@#::! /9<6649 *6>';
opts[r++] = '6+4#`!25+ 9_7^2?~:+<';
opts[r++] = '1-`250#:/933:5!>679 ';
opts[r++] = '^!88# <2! @#99/*_^`>';
opts[r++] = '!68:52-4#9_53*24:$>4';
opts[r++] = '$!`$! 2-! 9+$$~+71?$';
opts[r++] = '#:#8^! 2525<9--4>~-+';
opts[r++] = '2#<25@-:!`9:335^~+9/';
opts[r++] = '8+45!2`5<294 57#52#6';
opts[r++] = '@!`45+:+$/9_@4` -42`';
opts[r++] = '2#68#<2-+-<933$=4@`~';
opts[r++] = '5 @+ <+:!3:#9-~$8+-+';
opts[r++] = '- @+ <@5+ !3:#957?=1';
opts[r++] = '<5 5<2#`9`58$$462$!9';
opts[r++] = '8+`2# 25+-<99<^4<14*';
opts[r++] = '^!33#`4!<^#`/9$5-<$3';
opts[r++] = '6+`25@5! 9<:**6 *!`<';
opts[r++] = '1!::+85! 9181+!>$8- ';
opts[r++] = '>+`@#<2#`<^5`#91>!=?';
opts[r++] = '6!$ 515@# 29+:21<!6!';
opts[r++] = '- @+ <+:!3:#9^35 6=*';
opts[r++] = '8#<<565<25@9`6@2^6$*';
opts[r++] = '@!852!:92^-@#/@018+7';
opts[r++] = '4#<8#`!2#9-?!/-__110';
opts[r++] = '!8!2^#25@9?=3=_$#95^';
opts[r++] = '1+`<!~# 90:6//>?750+';
opts[r++] = '45<@+ <+:!2#9//_*35$';
opts[r++] = '^+``515@92/>@5:?5_@4';
opts[r++] = '<+:52-4#9+#8>?6_4#*7';
opts[r++] = '568#`@#8253:#96+?0!@';
opts[r++] = '8525!3:#917_~ 2^16!*';
opts[r++] = '@/ 5@!:9!32`20#?6^@3';
opts[r++] = '@+ 4#6 #494`0`-`2-~=';
opts[r++] = '4#<+:!2#96@@<*^:!/~=';
opts[r++] = ':-$-3`5+-<9_*3=*?842';
opts[r++] = '4#<8+ 4# 2902+83>#8^';
opts[r++] = ' #@`+25@95?3<_+`*+3^';
opts[r++] = '1- #3`5+-<90*@>3?-->';
opts[r++] = ':!6# 2!3:#9>6/9@_6>3';
opts[r++] = '+352-!`/9 #9~--1<<1<';
opts[r++] = '@`565 !:95^@3701#$~$';
opts[r++] = '6#:! @^+:/9>:<4_$/>@';

22
hangman/hangman.js Normal file
View file

@ -0,0 +1,22 @@
// Hangman Javascript
// copyright 10th June 2005, 8th December 2005 by Stephen Chapman
// permission to use this Javascript on your web page is granted
// provided that all of the code in this script (including these
// comments) is used without any alteration
var page = self.location.toString(); page = page.substr(0,page.indexOf('?'));
var qsParm = new Array();function qs() {var query = window.location.search.substring(1);var parms = query.split('&');for (var i=0; i<parms.length; i++) {var pos = parms[i].indexOf('=');if (pos > 0) {var key = parms[i].substring(0,pos);var val = parms[i].substring(pos+1);qsParm[key] = val;}}}
qsParm['opt'] = null;qsParm['al'] = null;qsParm['w'] = null;qs();
var win = 0;if (qsParm['win']) win = parseInt(qsParm['win']);
var opt = -1;if (qsParm['opt']) opt = qsParm['opt']%71; else opt = Math.floor(Math.random()*opts.length);
var al = '--------------------------';if (qsParm['al']) al = qsParm['al'];
var wr = 'xhwdarqpnez';var dc = '7!3@4#1$^5*~:6 +8=`<2-0>_/?9';
var wx = 0; if (qsParm['w']) wx = wr.indexOf(qsParm['w']);
var answer = trans2(opts[opt]);
function trans2(op) {var opn = '';for (var i = 0; i < op.length; i++) {var ch = op.substr(i,1);if (ch == dc.substr(27,1)) break; if (ch == dc.substr(0,1)) opn += ' '; else opn += String.fromCharCode(dc.indexOf(ch)+64);} return opn;}
function selectLetter(s) {s = parseInt(s); var ch = String.fromCharCode(s+65); if (answer.indexOf(ch) == -1) wx++; al = al.substring(0,s) + ch + al.substring(s+1,al.length); var opty = Math.floor(Math.random()*165)*71 + opt; top.location = page + '?opt='+opty+'&al='+al+'&w=' +wr.charAt(wx); return false;}
function availLetter() {document.write('<div class="hangt">'); for (var i = 0; i < al.length; i++) {
var ltr = String.fromCharCode(i+65); if (al.charAt(i) == ltr) document.write(' '); else document.write('<a href="#" onclick="selectLetter(\''+i+'\')">'+ ltr+'<\/a> '); if (i == 12) document.write('<br \/>');} document.write('<\/div>');}
function displayAnswer() {var correct = ''; document.write('<div class="hanga"> <br \/>'); for (var i = 0; i < answer.length; i++) {if (answer.substr(i,1) == ' ') {document.write(' '); correct += ' ';} else {var ltr = ''; if (win == 0) ltr = al.charAt(answer.charCodeAt(i)-65); else ltr = answer.substr(i,1); document.write(ltr + ' '); correct += ltr;}} document.write('<\/div>'); if (win == 0) {var opty = Math.floor(Math.random()*165)*71 + opt; if (wr.charAt(wx) == 'z') top.location = page + '?win=1&opt='+opty+'&w='+wr.charAt(wx); if (correct == answer.toUpperCase()) top.location = page + '?win=4&opt='+ opty+'&w='+wr.charAt(wx);}}
document.write('<div class="hangb">'); if (win == 0) availLetter(); else if (win == 4) document.write('<div class="hangt">YOU WIN<br \/><a href="'+page+'">Try Again<\/a><\/div>'); else document.write('<div class="hangt">YOU LOSE<br \/><a href="'+page+'">Try Again<\/a><\/div>'); document.write('<div align="center"> <br \/><img src="'+img+'hang'+wx+'.gif" width="100" height="100" alt="hangman image '+wx+'" \/><br \/> <\/div>'); displayAnswer(); document.write('<\/div>');

49
hangman/hangman.php Normal file
View file

@ -0,0 +1,49 @@
<?php
/**
* Name: Hangman Plugin
* Description: spell words, hang dudes
* Version: 1.0
* Author: tony baldwin <https://free-haven.org/profile/tony>
*/
function hangman_install() {
register_hook('app_menu', 'addon/hangman/hangman.php', 'hangman_app_menu');
}
function hangman_uninstall() {
unregister_hook('hangman_menu', 'addon/hangman/hangman.php', 'hangman_app_menu');
}
function hangman_app_menu($a,&$b) {
$b['app_menu'][] = '<div class="app-title"><a href="hangman">' . t('Hangman') . '</a></div>';
}
function hangman_module() {
return;
}
function hangman_content(&$a) {
$baseurl = $a->get_baseurl() . '/addon/hangman';
$a->page['htmlhead'] .= '<link rel="stylesheet" href="' .$a->get_baseurl() . '/addon/hangman/hang.css' . '" type="text/css" />' . "\r\n";
$a->page['htmlhead'] .= '<script src="' .$a->get_baseurl() . '/addon/hangman/hangans.js' .'" type="text/javascript"> </script>' . "\r\n";
$o = '';
$o .= <<< EOT
<script src="$baseurl/hangman.js" type="text/javascript">
</script><noscript><div align="center"><b>The Hangman
game requires Javascript</b><br />You either have
Javascript disabled<br />or the browser you are using does
not<br />support Javascript. Please use a Javascript
<br />enabled browser to access this game.</div></noscript>
EOT;
return $o;
}

Binary file not shown.

View file

@ -1,7 +1,7 @@
{{ inc field_input.tpl with $field=$owner }}{{ endinc }} {{ inc field_input.tpl with $field=$owner }}{{ endinc }}
{{ inc field_input.tpl with $field=$ownerprofile }}{{ endinc }} {{ inc field_input.tpl with $field=$ownerprofile }}{{ endinc }}
{{ inc field_input.tpl with $field=$postal }}{{ endinc }} {{ inc field_textarea.tpl with $field=$postal }}{{ endinc }}
{{ inc field_input.tpl with $field=$notes }}{{ endinc }} {{ inc field_textarea.tpl with $field=$notes }}{{ endinc }}
{{ inc field_input.tpl with $field=$email }}{{ endinc }} {{ inc field_input.tpl with $field=$email }}{{ endinc }}
{{ inc field_input.tpl with $field=$footer_text }}{{ endinc }} {{ inc field_textarea.tpl with $field=$footer_text }}{{ endinc }}
<div class="submit"><input type="submit" name="page_site" value="$submit" /></div> <div class="submit"><input type="submit" name="page_site" value="$submit" /></div>

View file

@ -2,11 +2,13 @@
/** /**
* Name: Impressum * Name: Impressum
* Description: Plugin to add contact information to the about page (/friendica) * Description: Plugin to add contact information to the about page (/friendica)
* Version: 1.1 * Version: 1.2
* Author: Tobias Diekershoff <http://diekershoff.homeunix.net/friendika/profile/tobias> * Author: Tobias Diekershoff <http://diekershoff.homeunix.net/friendika/profile/tobias>
* License: 3-clause BSD license * License: 3-clause BSD license
*/ */
require_once('include/bbcode.php');
function impressum_install() { function impressum_install() {
register_hook('about_hook', 'addon/impressum/impressum.php', 'impressum_show'); register_hook('about_hook', 'addon/impressum/impressum.php', 'impressum_show');
register_hook('page_end', 'addon/impressum/impressum.php', 'impressum_footer'); register_hook('page_end', 'addon/impressum/impressum.php', 'impressum_footer');
@ -24,7 +26,7 @@ function obfuscate_email ($s) {
return $s; return $s;
} }
function impressum_footer($a, &$b) { function impressum_footer($a, &$b) {
$text = get_config('impressum','footer_text'); $text = bbcode(get_config('impressum','footer_text'), true);
if (! $text == '') { if (! $text == '') {
$a->page['htmlhead'] .= '<link rel="stylesheet" type="text/css" href="'.$a->get_baseurl().'/addon/impressum/impressum.css" media="all" />'; $a->page['htmlhead'] .= '<link rel="stylesheet" type="text/css" href="'.$a->get_baseurl().'/addon/impressum/impressum.css" media="all" />';
$b .= '<div id="impressum_footer">'.$text.'</div>'; $b .= '<div id="impressum_footer">'.$text.'</div>';
@ -34,8 +36,8 @@ function impressum_show($a,&$b) {
$b .= '<h3>'.t('Impressum').'</h3>'; $b .= '<h3>'.t('Impressum').'</h3>';
$owner = get_config('impressum', 'owner'); $owner = get_config('impressum', 'owner');
$owner_profile = get_config('impressum','ownerprofile'); $owner_profile = get_config('impressum','ownerprofile');
$postal = get_config('impressum', 'postal'); $postal = bbcode(get_config('impressum', 'postal'), true);
$notes = get_config('impressum', 'notes'); $notes = bbcode(get_config('impressum', 'notes'), true);
$email = obfuscate_email( get_config('impressum','email') ); $email = obfuscate_email( get_config('impressum','email') );
if (strlen($owner)) { if (strlen($owner)) {
if (strlen($owner_profile)) { if (strlen($owner_profile)) {
@ -66,12 +68,12 @@ function impressum_plugin_admin_post (&$a) {
$notes = ((x($_POST, 'notes')) ? (trim($_POST['notes'])) : ''); $notes = ((x($_POST, 'notes')) ? (trim($_POST['notes'])) : '');
$email = ((x($_POST, 'email')) ? notags(trim($_POST['email'])) : ''); $email = ((x($_POST, 'email')) ? notags(trim($_POST['email'])) : '');
$footer_text = ((x($_POST, 'footer_text')) ? (trim($_POST['footer_text'])) : ''); $footer_text = ((x($_POST, 'footer_text')) ? (trim($_POST['footer_text'])) : '');
set_config('impressum','owner',$owner); set_config('impressum','owner',strip_tags($owner));
set_config('impressum','ownerprofile',$ownerprofile); set_config('impressum','ownerprofile',strip_tags($ownerprofile));
set_config('impressum','postal',$postal); set_config('impressum','postal',strip_tags($postal));
set_config('impressum','email',$email); set_config('impressum','email',strip_tags($email));
set_config('impressum','notes',$notes); set_config('impressum','notes',strip_tags($notes));
set_config('impressum','footer_text',$footer_text); set_config('impressum','footer_text',strip_tags($footer_text));
info( t('Settings updated.'). EOL ); info( t('Settings updated.'). EOL );
} }
function impressum_plugin_admin (&$a, &$o) { function impressum_plugin_admin (&$a, &$o) {
@ -80,9 +82,9 @@ function impressum_plugin_admin (&$a, &$o) {
'$submit' => t('Submit'), '$submit' => t('Submit'),
'$owner' => array('owner', t('Site Owner'), get_config('impressum','owner'), t('The page operators name.')), '$owner' => array('owner', t('Site Owner'), get_config('impressum','owner'), t('The page operators name.')),
'$ownerprofile' => array('ownerprofile', t('Site Owners Profile'), get_config('impressum','ownerprofile'), t('Profile address of the operator.')), '$ownerprofile' => array('ownerprofile', t('Site Owners Profile'), get_config('impressum','ownerprofile'), t('Profile address of the operator.')),
'$postal' => array('postal', t('Postal Address'), get_config('impressum','postal'), t('How to contact the operator via snail mail.')), '$postal' => array('postal', t('Postal Address'), get_config('impressum','postal'), t('How to contact the operator via snail mail. You can use BBCode here.')),
'$notes' => array('notes', t('Notes'), get_config('impressum','notes'), t('Additional notes that are displayed beneath the contact information.')), '$notes' => array('notes', t('Notes'), get_config('impressum','notes'), t('Additional notes that are displayed beneath the contact information. You can use BBCode here.')),
'$email' => array('email', t('Email Address'), get_config('impressum','email'), t('How to contact the operator via email. (will be displayed obfuscated)')), '$email' => array('email', t('Email Address'), get_config('impressum','email'), t('How to contact the operator via email. (will be displayed obfuscated)')),
'$footer_text' => array('footer_text', t('Footer note'), get_config('impressum','footer_text'), t('Text for the footer.')), '$footer_text' => array('footer_text', t('Footer note'), get_config('impressum','footer_text'), t('Text for the footer. You can use BBCode here.')),
)); ));
} }

Binary file not shown.

BIN
page.tgz

Binary file not shown.

View file

@ -24,7 +24,8 @@ function page_getpage($uid) {
$pagelist = array(); $pagelist = array();
$contacts = q("SELECT `id`, `url`, `name`, `micro`FROM `contact` $contacts = q("SELECT `id`, `url`, `name`, `micro`FROM `contact`
WHERE `network`= 'dfrn' AND `forum` = 1 AND `uid` = %d", WHERE `network`= 'dfrn' AND `forum` = 1 AND `uid` = %d
order by name asc ",
intval($uid) intval($uid)
); );
@ -47,14 +48,28 @@ function page_page_end($a,&$b) {
<h3>'.t("Forums").'</h3></div> <h3>'.t("Forums").'</h3></div>
<div id="sidebar-page-list"><ul>'; <div id="sidebar-page-list"><ul>';
$contacts = page_getpage($a->user['uid']); $contacts = page_getpage($a->user['uid']);
$total_shown = 0;
$more = false;
foreach($contacts as $contact) { foreach($contacts as $contact) {
$page .= '<li style="list-style-type: none;" class="tool"><img height="20" width="20" src="' . $contact['micro'] .'" alt="' . $contact['url'] . '" /> <a href="'.$a->get_baseurl().'/redir/'.$contact["id"].'" title="' . $contact['url'] . '" class="label" target="external-link">'. $page .= '<li style="list-style-type: none;" class="tool"><img height="20" width="20" src="' . $contact['micro'] .'" alt="' . $contact['url'] . '" /> <a href="'.$a->get_baseurl().'/redir/'.$contact["id"].'" title="' . $contact['url'] . '" class="label" target="external-link">'.
$contact["name"]."</a></li>"; $contact["name"]."</a></li>";
$total_shown ++;
if($total_shown == 6) {
$more = true;
$page .= '</ul><div id="hide-comments-page-widget" class="fakelink" onclick="showHideComments(\'page-widget\');" >' . t('show more')
. '</div><div id="collapsed-comments-page-widget" style="display: none;" ><ul>';
}
} }
if($more)
$page .= '</div>';
$page .= "</ul></div></div>"; $page .= "</ul></div></div>";
if (sizeof($contacts) > 0) if (sizeof($contacts) > 0)
$a->page['aside'] = $page . $a->page['aside']; $a->page['aside'] = $page . $a->page['aside'];
} }
?>

BIN
pages.tgz

Binary file not shown.

Binary file not shown.

View file

@ -5,6 +5,7 @@
* Description: Post to Posterous accounts * Description: Post to Posterous accounts
* Version: 1.0 * Version: 1.0
* Author: Mike Macgirvin <http://macgirvin.com/profile/mike> * Author: Mike Macgirvin <http://macgirvin.com/profile/mike>
* Author: Tony Baldwin <https://free-haven.org/u/tony>
*/ */
function posterous_install() { function posterous_install() {
@ -59,6 +60,8 @@ function posterous_settings(&$a,&$s) {
$pstr_username = get_pconfig(local_user(), 'posterous', 'posterous_username'); $pstr_username = get_pconfig(local_user(), 'posterous', 'posterous_username');
$pstr_password = get_pconfig(local_user(), 'posterous', 'posterous_password'); $pstr_password = get_pconfig(local_user(), 'posterous', 'posterous_password');
$pstr_site_id = get_pconfig(local_user(), 'posterous', 'posterous_site_id');
$pstr_api_token = get_pconfig(local_user(), 'posterous', 'posterous_api_token');
/* Add some HTML to the existing form */ /* Add some HTML to the existing form */
@ -80,6 +83,16 @@ function posterous_settings(&$a,&$s) {
$s .= '<input id="posterous-password" type="password" name="posterous_password" value="' . $pstr_password . '" />'; $s .= '<input id="posterous-password" type="password" name="posterous_password" value="' . $pstr_password . '" />';
$s .= '</div><div class="clear"></div>'; $s .= '</div><div class="clear"></div>';
$s .= '<div id="posterous-site_id-wrapper">';
$s .= '<label id="posterous-site_id-label" for="posterous-site_id">' . t('Posterous site ID') . '</label>';
$s .= '<input id="posterous-site_id" type="text" name="posterous_site_id" value="' . $pstr_site_id . '" />';
$s .= '</div><div class="clear"></div>';
$s .= '<div id="posterous-api_token-wrapper">';
$s .= '<label id="posterous-api_token-label" for="posterous-api_token">' . t('Posterous API token') . '</label>';
$s .= '<input id="posterous-api_token" type="text" name="posterous_api_token" value="' . $pstr_api_token . '" />';
$s .= '</div><div class="clear"></div>';
$s .= '<div id="posterous-bydefault-wrapper">'; $s .= '<div id="posterous-bydefault-wrapper">';
$s .= '<label id="posterous-bydefault-label" for="posterous-bydefault">' . t('Post to Posterous by default') . '</label>'; $s .= '<label id="posterous-bydefault-label" for="posterous-bydefault">' . t('Post to Posterous by default') . '</label>';
$s .= '<input id="posterous-bydefault" type="checkbox" name="posterous_bydefault" value="1" ' . $def_checked . '/>'; $s .= '<input id="posterous-bydefault" type="checkbox" name="posterous_bydefault" value="1" ' . $def_checked . '/>';
@ -100,6 +113,8 @@ function posterous_settings_post(&$a,&$b) {
set_pconfig(local_user(),'posterous','post_by_default',intval($_POST['posterous_bydefault'])); set_pconfig(local_user(),'posterous','post_by_default',intval($_POST['posterous_bydefault']));
set_pconfig(local_user(),'posterous','posterous_username',trim($_POST['posterous_username'])); set_pconfig(local_user(),'posterous','posterous_username',trim($_POST['posterous_username']));
set_pconfig(local_user(),'posterous','posterous_password',trim($_POST['posterous_password'])); set_pconfig(local_user(),'posterous','posterous_password',trim($_POST['posterous_password']));
set_pconfig(local_user(),'posterous','posterous_site_id',trim($_POST['posterous_site_id']));
set_pconfig(local_user(),'posterous','posterous_api_token',trim($_POST['posterous_api_token']));
} }
@ -138,6 +153,9 @@ function posterous_post_local(&$a,&$b) {
function posterous_send(&$a,&$b) { function posterous_send(&$a,&$b) {
logger('posterous_send: invoked');
return;
if($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited'])) if($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited']))
return; return;
@ -150,12 +168,13 @@ function posterous_send(&$a,&$b) {
$pstr_username = get_pconfig($b['uid'],'posterous','posterous_username'); $pstr_username = get_pconfig($b['uid'],'posterous','posterous_username');
$pstr_password = get_pconfig($b['uid'],'posterous','posterous_password'); $pstr_password = get_pconfig($b['uid'],'posterous','posterous_password');
$pstr_blog = 'http://www.posterous.com/api/write'; $pstr_site_id = get_pconfig($b['uid'],'posterous','posterous_site_id');
$pstr_blog = "http://posterous.com/api/2/sites/$pstr_site_id/posts";
$pstr_api_token = get_pconfig($b['uid'],'posterous','posterous_api_token');
if($pstr_username && $pstr_password && $pstr_blog) { if($pstr_username && $pstr_password && $pstr_blog) {
require_once('include/bbcode.php'); require_once('include/bbcode.php');
require_once('posterous-api.php');
$tag_arr = array(); $tag_arr = array();
$tags = ''; $tags = '';
$x = preg_match_all('/\#\[(.*?)\](.*?)\[/',$b['tag'],$matches,PREG_SET_ORDER); $x = preg_match_all('/\#\[(.*?)\](.*?)\[/',$b['tag'],$matches,PREG_SET_ORDER);
@ -170,18 +189,28 @@ function posterous_send(&$a,&$b) {
$params = array( $params = array(
'title' => (($b['title']) ? $b['title'] : t('Post from Friendica')), 'post[title]' => (($b['title']) ? $b['title'] : t('Post from Friendica')),
'type' => 'regular', 'post[source]' => 'Friendica',
'autopost' => 1, 'post[tags]' => $tags,
'source' => 'Friendica', 'post[body]' => bbcode($b['body']),
'is_private' => false, 'api_token' => $pstr_api_token,
'tags' => $tags, 'site_id' => $pstr_site_id
'body' => bbcode($b['body'])
); );
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $pstr_blog);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $pstr_username . ':' . $pstr_password);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$api = new PosterousAPI($pstr_username,$pstr_password); $data = curl_exec($ch);
$result = curl_multi_getcontent($ch);
curl_close($ch);
$result = $api->newpost($params);
logger('posterous_send: ' . $result); logger('posterous_send: ' . $result);
} }
} }

View file

@ -0,0 +1,4 @@
Once activated, this addon acs as a proxy between the user and external image resources.
If external images are to be shown, like avatars or embedded images, the server retrieves the image and the local link is sent to the user.
By using this proxy, the server hosting the original image cannot retrieve personal information of the user like the IP address, User Agent or Cookies.
However, the remote server will be able to track the IP address of the server hosting the friendica installation.

View file

@ -0,0 +1,175 @@
<?php
/**
* Name: Privacy Image Cache
* Version: 0.1
* Author: Tobias Hößl <https://github.com/CatoTH/>
*/
define("PRIVACY_IMAGE_CACHE_DEFAULT_TIME", 86400); // 1 Day
require_once('include/security.php');
function privacy_image_cache_install() {
register_hook('bbcode', 'addon/privacy_image_cache/privacy_image_cache.php', 'privacy_image_cache_bbcode_hook');
register_hook('display_item', 'addon/privacy_image_cache/privacy_image_cache.php', 'privacy_image_cache_display_item_hook');
register_hook('ping_xmlize', 'addon/privacy_image_cache/privacy_image_cache.php', 'privacy_image_cache_ping_xmlize_hook');
register_hook('cron', 'addon/privacy_image_cache/privacy_image_cache.php', 'privacy_image_cache_cron');
}
function privacy_image_cache_uninstall() {
unregister_hook('bbcode', 'addon/privacy_image_cache/privacy_image_cache.php', 'privacy_image_cache_bbcode_hook');
unregister_hook('display_item', 'addon/privacy_image_cache/privacy_image_cache.php', 'privacy_image_cache_display_item_hook');
unregister_hook('ping_xmlize', 'addon/privacy_image_cache/privacy_image_cache.php', 'privacy_image_cache_ping_xmlize_hook');
unregister_hook('cron', 'addon/privacy_image_cache/privacy_image_cache.php', 'privacy_image_cache_cron');
}
function privacy_image_cache_module() {}
function privacy_image_cache_init() {
$urlhash = 'pic:' . sha1($_REQUEST['url']);
$r = q("SELECT * FROM `photo` WHERE `resource-id` = '%s' LIMIT 1", $urlhash );
if (count($r)) {
$img_str = $r[0]['data'];
}
else {
require_once("Photo.php");
$img_str = fetch_url($_REQUEST['url'],true);
$img = new Photo($img_str);
if($img->is_valid()) {
$img->store(0, 0, $urlhash, $_REQUEST['url'], '', 100);
$img_str = $img->imageString();
}
}
header("Content-type: image/jpeg");
header("Expires: " . gmdate("D, d M Y H:i:s", time() + (3600*24)) . " GMT");
header("Cache-Control: max-age=" . (3600*24));
echo $img_str;
killme();
}
/**
* @param $url string
* @return boolean
*/
function privacy_image_cache_is_local_image($url) {
if ($url[0] == '/') return true;
$baseurl = get_app()->get_baseurl();
return (substr($url, 0, strlen($baseurl)) == $baseurl);
}
/**
* @param array $matches
* @return string
*/
function privacy_image_cache_img_cb($matches) {
if (privacy_image_cache_is_local_image($matches[2])) return $matches[2];
return $matches[1] . "/privacy_image_cache/?url=" . escape_tags(addslashes($matches[2])) . $matches[3];
}
/**
* @param App $a
* @param string $o
*/
function privacy_image_cache_bbcode_hook(&$a, &$o) {
$o = preg_replace_callback("/(<img [^>]*src *= *[\"'])([^\"']+)([\"'][^>]*>)/siU", "privacy_image_cache_img_cb", $o);
}
/**
* @param App $a
* @param string $o
*/
function privacy_image_cache_display_item_hook(&$a, &$o) {
if (isset($o["output"])) {
if (isset($o["output"]["thumb"]) && !privacy_image_cache_is_local_image($o["output"]["thumb"]))
$o["output"]["thumb"] = "/privacy_image_cache/?url=" . escape_tags(addslashes($o["output"]["thumb"]));
if (isset($o["output"]["author-avatar"]) && !privacy_image_cache_is_local_image($o["output"]["author-avatar"]))
$o["output"]["author-avatar"] = "/privacy_image_cache/?url=" . escape_tags(addslashes($o["output"]["author-avatar"]));
}
}
/**
* @param App $a
* @param string $o
*/
function privacy_image_cache_ping_xmlize_hook(&$a, &$o) {
if ($o["photo"] != "" && !privacy_image_cache_is_local_image($o["photo"]))
$o["photo"] = "/privacy_image_cache/?url=" . escape_tags(addslashes($o["photo"]));
}
/**
* @param App $a
* @param null|object $b
*/
function privacy_image_cache_cron(&$a, &$b) {
$cachetime = get_config('privacy_image_cache','cache_time');
if (!$cachetime) $cachetime = PRIVACY_IMAGE_CACHE_DEFAULT_TIME;
$last = get_config('pi_cache','last_delete');
$time = time();
if ($time < ($last + 3600)) return;
logger("Purging old Cache of the Privacy Image Cache", LOGGER_DEBUG);
q('DELETE FROM `photo` WHERE `uid` = 0 AND `resource-id` LIKE "pic:%%" AND `created` < NOW() - INTERVAL %d SECOND', $cachetime);
set_config('pi_cache', 'last_delete', $time);
}
/**
* @param App $a
* @param null|object $o
*/
function privacy_image_cache_plugin_admin(&$a, &$o){
$o = '<input type="hidden" name="form_security_token" value="' . get_form_security_token("picsave") . '">';
$cachetime = get_config('privacy_image_cache','cache_time');
if (!$cachetime) $cachetime = PRIVACY_IMAGE_CACHE_DEFAULT_TIME;
$cachetime_h = Ceil($cachetime / 3600);
$o .= '<label for="pic_cachetime">' . t('Lifetime of the cache (in hours)') . '</label>
<input id="pic_cachetime" name="cachetime" type="text" value="' . escape_tags($cachetime_h) . '"><br style="clear: both;">';
$o .= '<input type="submit" name="save" value="' . t('Save') . '">';
$o .= '<h4>' . t('Cache Statistics') . '</h4>';
$num = q('SELECT COUNT(*) num, SUM(LENGTH(data)) size FROM `photo` WHERE `uid`=0 AND `contact-id`=0 AND `resource-id` LIKE "pic:%%"');
$o .= '<label for="statictics_num">' . t('Number of items') . '</label><input style="color: gray;" id="statistics_num" disabled value="' . escape_tags($num[0]['num']) . '"><br style="clear: both;">';
$size = Ceil($num[0]['size'] / (1024 * 1024));
$o .= '<label for="statictics_size">' . t('Size of the cache') . '</label><input style="color: gray;" id="statistics_size" disabled value="' . $size . ' MB"><br style="clear: both;">';
$o .= '<input type="submit" name="delete_all" value="' . t('Delete the whole cache') . '">';
}
/**
* @param App $a
* @param null|object $o
*/
function privacy_image_cache_plugin_admin_post(&$a, &$o){
check_form_security_token_redirectOnErr('/admin/plugins/privacy_image_cache', 'picsave');
if (isset($_REQUEST['save'])) {
$cachetime_h = IntVal($_REQUEST['cachetime']);
if ($cachetime_h < 1) $cachetime_h = 1;
set_config('privacy_image_cache','cache_time', $cachetime_h * 3600);
}
if (isset($_REQUEST['delete_all'])) {
q('DELETE FROM `photo` WHERE `uid` = 0 AND `resource-id` LIKE "pic:%%"');
}
}

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 864 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -214,8 +214,8 @@ function smiley_pack_smilies(&$a,&$b) {
$b['texts'][] = ':basketball'; $b['texts'][] = ':basketball';
$b['icons'][] = '<img src="' . $a->get_baseurl() . '/addon/smiley_pack/icons/sport/basketball.gif' . '" alt="' . ':basketball' . '" />'; $b['icons'][] = '<img src="' . $a->get_baseurl() . '/addon/smiley_pack/icons/sport/basketball.gif' . '" alt="' . ':basketball' . '" />';
$b['texts'][] = ':bowling'; $b['texts'][] = '~bowling';
$b['icons'][] = '<img src="' . $a->get_baseurl() . '/addon/smiley_pack/icons/sport/bowling.gif' . '" alt="' . ':bowling' . '" />'; $b['icons'][] = '<img src="' . $a->get_baseurl() . '/addon/smiley_pack/icons/sport/bowling.gif' . '" alt="' . '~bowling' . '" />';
$b['texts'][] = ':cycling'; $b['texts'][] = ':cycling';
$b['icons'][] = '<img src="' . $a->get_baseurl() . '/addon/smiley_pack/icons/sport/cycling.gif' . '" alt="' . ':cycling' . '" />'; $b['icons'][] = '<img src="' . $a->get_baseurl() . '/addon/smiley_pack/icons/sport/cycling.gif' . '" alt="' . ':cycling' . '" />';
@ -284,6 +284,9 @@ function smiley_pack_smilies(&$a,&$b) {
$b['texts'][] = ':pillow'; $b['texts'][] = ':pillow';
$b['icons'][] = '<img src="' . $a->get_baseurl() . '/addon/smiley_pack/icons/tired/pillow.gif' . '" alt="' . ':pillow' . '" />'; $b['icons'][] = '<img src="' . $a->get_baseurl() . '/addon/smiley_pack/icons/tired/pillow.gif' . '" alt="' . ':pillow' . '" />';
$b['texts'][] = ':yawn';
$b['icons'][] = '<img src="' . $a->get_baseurl() . '/addon/smiley_pack/icons/tired/yawn.gif' . '" alt="' . ':yawn' . '" />';
#Fight/Flame/Violent smileys #Fight/Flame/Violent smileys
$b['texts'][] = ':2guns'; $b['texts'][] = ':2guns';

Binary file not shown.

Binary file not shown.

View file

@ -2,7 +2,7 @@
/** /**
* Name: StatusNet Connector * Name: StatusNet Connector
* Description: Relay public postings to a connected StatusNet account * Description: Relay public postings to a connected StatusNet account
* Version: 1.0.4 * Version: 1.0.5
* Author: Tobias Diekershoff <http://diekershoff.homeunix.net/friendika/profile/tobias> * Author: Tobias Diekershoff <http://diekershoff.homeunix.net/friendika/profile/tobias>
*/ */
@ -435,9 +435,9 @@ function statusnet_post_hook(&$a,&$b) {
// shorten all the links in a 200000 character long essay. // shorten all the links in a 200000 character long essay.
if (! $b['title']=='') { if (! $b['title']=='') {
$tmp = $b['title'] . ' : '. $b['body']; $tmp = $b['title'] . ' : '. $b['body'];
$tmp = substr($tmp, 0, 4*$max_char); // $tmp = substr($tmp, 0, 4*$max_char);
} else { } else {
$tmp = substr($b['body'], 0, 3*$max_char); $tmp = $b['body']; // substr($b['body'], 0, 3*$max_char);
} }
// if [url=bla][img]blub.png[/img][/url] get blub.png // if [url=bla][img]blub.png[/img][/url] get blub.png
$tmp = preg_replace( '/\[url\=(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)\]\[img\](\\w+.*?)\\[\\/img\]\\[\\/url\]/i', '$2', $tmp); $tmp = preg_replace( '/\[url\=(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)\]\[img\](\\w+.*?)\\[\\/img\]\\[\\/url\]/i', '$2', $tmp);

Binary file not shown.

View file

@ -21,10 +21,13 @@ Online version of this document: http://ur1.ca/35mml
___ Requirements ___ ___ Requirements ___
To use this plugin you have to register your Friendica instance as an To use this plugin you have to register an application for your friendica
_client application_ for Twitter with _read and write_ access, we do not intend instance on Twitter with
to use Twitter for login. The registration can be done at twitter.com/apps * read and write access
and you need to have a Twitter account to do so. * don't set a callback URL
* we do not intend to use Twitter for login
The registration can be done at twitter.com/apps and you need a Twitter
account for doing so.
After you registered the application you get an OAuth consumer key / secret After you registered the application you get an OAuth consumer key / secret
pair that identifies your app, you will need them for configuration. pair that identifies your app, you will need them for configuration.

View file

@ -2,7 +2,7 @@
/** /**
* Name: Twitter Connector * Name: Twitter Connector
* Description: Relay public postings to a connected Twitter account * Description: Relay public postings to a connected Twitter account
* Version: 1.0.3 * Version: 1.0.4
* Author: Tobias Diekershoff <http://diekershoff.homeunix.net/friendika/profile/tobias> * Author: Tobias Diekershoff <http://diekershoff.homeunix.net/friendika/profile/tobias>
*/ */
@ -301,9 +301,9 @@ function twitter_post_hook(&$a,&$b) {
// shorten all the links in a 200000 character long essay. // shorten all the links in a 200000 character long essay.
if (! $b['title']=='') { if (! $b['title']=='') {
$tmp = $b['title'] . ' : '. $b['body']; $tmp = $b['title'] . ' : '. $b['body'];
$tmp = substr($tmp, 0, 4*$max_char); // $tmp = substr($tmp, 0, 4*$max_char);
} else { } else {
$tmp = substr($b['body'], 0, 3*$max_char); $tmp = $b['body']; // substr($b['body'], 0, 3*$max_char);
} }
// if [url=bla][img]blub.png[/img][/url] get blub.png // if [url=bla][img]blub.png[/img][/url] get blub.png
$tmp = preg_replace( '/\[url\=(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)\]\[img\](\\w+.*?)\\[\\/img\]\\[\\/url\]/i', '$2', $tmp); $tmp = preg_replace( '/\[url\=(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)\]\[img\](\\w+.*?)\\[\\/img\]\\[\\/url\]/i', '$2', $tmp);

Binary file not shown.

View file

@ -0,0 +1,43 @@
<?php
function friendheader_widget_name() {
return "Shows friends as a bar";
}
function friendheader_widget_help() {
return "";
}
function friendheader_widget_args(){
return Array();
}
function friendheader_widget_size(){
return Array('780px','140px');
}
function friendheader_widget_content(&$a, $conf){
$r = q("SELECT `profile`.`uid` AS `profile_uid`, `profile`.* , `user`.* FROM `profile`
LEFT JOIN `user` ON `profile`.`uid` = `user`.`uid`
WHERE `user`.`uid` = %s AND `profile`.`is-default` = 1 LIMIT 1",
intval($conf['uid'])
);
if(!count($r)) return;
$a->profile = $r[0];
$o = "";
$o .= "<style>
body {font-size: 0.8em; margin: 0px; padding: 0px;}
#contact-block { overflow: hidden; height: auto; }
.contact-block-h4 { float: left; margin: 0px; }
.allcontact-link { float: right; margin: 0px; }
.contact-block-content { clear:both; }
.contact-block-div { display: block !important; float: left!important; width: 50px!important; height: 50px!important; margin: 2px!important;}
</style>";
$o .= _abs_url(contact_block());
$o .= "<a href='".$a->get_baseurl().'/profile/'.$a->profile['nickname']."' target=new>". t('Get added to this list!') ."</a>";
return $o;
}