Merge develop into 20171122_-_port_tagcloud

Conflicts:
	include/features.php
This commit is contained in:
rabuzarus 2017-11-25 23:41:20 +01:00
commit 4224209497
65 changed files with 1336 additions and 969 deletions

View file

@ -69,30 +69,28 @@ If you can successfully access your Friendica instance through https, there are
This is the simplest way to enforce site-wide secure access. This is the simplest way to enforce site-wide secure access.
Every time a user tries to access any Friendica page by any mean (manual address bar entry or link), the web server issues a Permanent Redirect response with the secure protocol prepended to the requested URL. Every time a user tries to access any Friendica page by any mean (manual address bar entry or link), the web server issues a Permanent Redirect response with the secure protocol prepended to the requested URL.
With Apache, simply add the following lines to the [code].htaccess[/code] file in the root folder of your Friendica instance (thanks to [url=https://github.com/AlfredSK]AlfredSK[/url]): With Apache, enable the modules rewrite and ssl (with a shared hosting provider, this should be enabled already):
[code] sudo a2enmod rewrite ssl
#Force SSL connections
RewriteEngine On Add the following lines to the .htaccess file in the root folder of your Friendica instance (thanks to [url=https://github.com/AlfredSK]AlfredSK[/url]):
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://your.friendica.domain/$1 [R=301,L]
[/code]
With nginx, configure your [code]server[/code] directive this way (thanks to [url=https://bjornjohansen.no/redirect-to-https-with-nginx/]Bjørn Johansen[/url]): RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://your.friendica.domain/$1 [R=301,L]
[code] With nginx, configure your server directive this way ([documentation](https://www.nginx.com/blog/creating-nginx-rewrite-rules/)):
server {
server {
listen 80; listen 80;
listen [::]:80;
server_name your.friendica.domain; server_name your.friendica.domain;
return 301 https://$server_name$request_uri; return 301 https://$server_name$request_uri;
} }
[/code]
### SSL Settings ### SSL Settings
In the Admin Settings, there are three SSL-related settings: In the Admin Settings, there are three SSL-related settings:
- **SSL link policy**: this affects how Friendica generates internal links. If your SSL installation was successful, we recommend "Force all links to SSL" just in case your web server configuration can't be altered like described above.
- **Force SSL**: This forces all external links to HTTPS, which may solve Mixed-Content issues, but not all websites support HTTPS yet. Use at your own risk. 1. **SSL link policy**: this affects how Friendica generates internal links. If your SSL installation was successful, we recommend "Force all links to SSL" just in case your web server configuration can't be altered like described above.
- **Verify SSL**: Enabling this will prevent Friendica to interact with self-signed SSL sites. We recommend you leave it on as a self-signed SSL certificate can be a vectorfor a man-in-the-middle attack. 2. **Force SSL**: This forces all external links to HTTPS, which may solve Mixed-Content issues, but not all websites support HTTPS yet. Use at your own risk.
3. **Verify SSL**: Enabling this will prevent Friendica to interact with self-signed SSL sites. We recommend you leave it on as a self-signed SSL certificate can be a vectorfor a man-in-the-middle attack.

View file

@ -23,6 +23,7 @@ Example: To set the directory value please add this line to your .htconfig.php:
## system ## ## system ##
* **allowed_link_protocols** (Array) - Allowed protocols in links URLs, add at your own risk. http is always allowed. * **allowed_link_protocols** (Array) - Allowed protocols in links URLs, add at your own risk. http is always allowed.
* **always_show_preview** (Boolean) - Only show small preview picures. Default value is false.
* **birthday_input_format** - Default value is "ymd". * **birthday_input_format** - Default value is "ymd".
* **block_local_dir** (Boolean) - Blocks the access to the directory of the local users. * **block_local_dir** (Boolean) - Blocks the access to the directory of the local users.
* **auth_cookie_lifetime** (Integer) - Number of days that should pass without any activity before a user who chose "Remember me" when logging in is considered logged out. Defaults to 7. * **auth_cookie_lifetime** (Integer) - Number of days that should pass without any activity before a user who chose "Remember me" when logging in is considered logged out. Defaults to 7.

View file

@ -1,105 +0,0 @@
<?php
/**
* Throwable exceptions to return HTTP status code
*
* This list of Exception has be extracted from
* here http://racksburg.com/choosing-an-http-status-code/
*/
class HTTPException extends Exception {
var $httpcode = 200;
var $httpdesc = "";
public function __construct($message="", $code = 0, Exception $previous = null) {
if ($this->httpdesc=="") {
$this->httpdesc = preg_replace("|([a-z])([A-Z])|",'$1 $2', str_replace("Exception","",get_class($this)));
}
parent::__construct($message, $code, $previous);
}
}
// 4xx
class TooManyRequestsException extends HTTPException {
var $httpcode = 429;
}
class UnauthorizedException extends HTTPException {
var $httpcode = 401;
}
class ForbiddenException extends HTTPException {
var $httpcode = 403;
}
class NotFoundException extends HTTPException {
var $httpcode = 404;
}
class GoneException extends HTTPException {
var $httpcode = 410;
}
class MethodNotAllowedException extends HTTPException {
var $httpcode = 405;
}
class NonAcceptableException extends HTTPException {
var $httpcode = 406;
}
class LenghtRequiredException extends HTTPException {
var $httpcode = 411;
}
class PreconditionFailedException extends HTTPException {
var $httpcode = 412;
}
class UnsupportedMediaTypeException extends HTTPException {
var $httpcode = 415;
}
class ExpetationFailesException extends HTTPException {
var $httpcode = 417;
}
class ConflictException extends HTTPException {
var $httpcode = 409;
}
class UnprocessableEntityException extends HTTPException {
var $httpcode = 422;
}
class ImATeapotException extends HTTPException {
var $httpcode = 418;
var $httpdesc = "I'm A Teapot";
}
class BadRequestException extends HTTPException {
var $httpcode = 400;
}
// 5xx
class ServiceUnavaiableException extends HTTPException {
var $httpcode = 503;
}
class BadGatewayException extends HTTPException {
var $httpcode = 502;
}
class GatewayTimeoutException extends HTTPException {
var $httpcode = 504;
}
class NotImplementedException extends HTTPException {
var $httpcode = 501;
}
class InternalServerErrorException extends HTTPException {
var $httpcode = 500;
}

View file

@ -12,11 +12,19 @@ use Friendica\Core\Config;
use Friendica\Core\NotificationsManager; use Friendica\Core\NotificationsManager;
use Friendica\Core\Worker; use Friendica\Core\Worker;
use Friendica\Database\DBM; use Friendica\Database\DBM;
use Friendica\Network\HTTPException;
use Friendica\Network\HTTPException\BadRequestException;
use Friendica\Network\HTTPException\ForbiddenException;
use Friendica\Network\HTTPException\InternalServerErrorException;
use Friendica\Network\HTTPException\MethodNotAllowedException;
use Friendica\Network\HTTPException\NotFoundException;
use Friendica\Network\HTTPException\NotImplementedException;
use Friendica\Network\HTTPException\UnauthorizedException;
use Friendica\Network\HTTPException\TooManyRequestsException;
use Friendica\Object\Contact; use Friendica\Object\Contact;
use Friendica\Protocol\Diaspora; use Friendica\Protocol\Diaspora;
use Friendica\Util\XML; use Friendica\Util\XML;
require_once 'include/HTTPExceptions.php';
require_once 'include/bbcode.php'; require_once 'include/bbcode.php';
require_once 'include/datetime.php'; require_once 'include/datetime.php';
require_once 'include/conversation.php'; require_once 'include/conversation.php';
@ -3435,11 +3443,7 @@ function api_fr_photoalbum_delete($type)
} }
// now let's delete all photos from the album // now let's delete all photos from the album
$result = q( $result = dba::delete('photo', array('uid' => api_user(), 'album' => $album));
"DELETE FROM `photo` WHERE `uid` = %d AND `album` = '%s'",
intval(api_user()),
dbesc($album)
);
// return success of deletion or error message // return success of deletion or error message
if ($result) { if ($result) {
@ -3722,11 +3726,7 @@ function api_fr_photo_delete($type)
throw new BadRequestException("photo not available"); throw new BadRequestException("photo not available");
} }
// now we can perform on the deletion of the photo // now we can perform on the deletion of the photo
$result = q( $result = dba::delete('photo', array('uid' => api_user(), 'resource-id' => $photo_id));
"DELETE FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s'",
intval(api_user()),
dbesc($photo_id)
);
// return success of deletion or error message // return success of deletion or error message
if ($result) { if ($result) {
@ -4299,7 +4299,7 @@ function api_share_as_retweet(&$item)
{ {
$body = trim($item["body"]); $body = trim($item["body"]);
if (Diaspora::is_reshare($body, false)===false) { if (Diaspora::isReshare($body, false)===false) {
return false; return false;
} }
@ -4307,7 +4307,7 @@ function api_share_as_retweet(&$item)
$attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism", "$1", $body); $attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism", "$1", $body);
/* /*
* Skip if there is no shared message in there * Skip if there is no shared message in there
* we already checked this in diaspora::is_reshare() * we already checked this in diaspora::isReshare()
* but better one more than one less... * but better one more than one less...
*/ */
if ($body == $attributes) { if ($body == $attributes) {

View file

@ -52,7 +52,10 @@ function bb_attachment($Text, $simplehtml = false, $tryoembed = true) {
$data["title"] = str_replace(array("http://", "https://"), "", $data["title"]); $data["title"] = str_replace(array("http://", "https://"), "", $data["title"]);
} }
if (((strpos($data["text"], "[img=") !== false) || (strpos($data["text"], "[img]") !== false)) && ($data["image"] != "")) { if (((strpos($data["text"], "[img=") !== false)
|| (strpos($data["text"], "[img]") !== false)
|| Config::get('system', 'always_show_preview'))
&& ($data["image"] != "")) {
$data["preview"] = $data["image"]; $data["preview"] = $data["image"];
$data["image"] = ""; $data["image"] = "";
} }

View file

@ -1536,8 +1536,8 @@ function conv_sort(array $item_list, $order)
*/ */
foreach ($parents as $i => $parent) { foreach ($parents as $i => $parent) {
$parents[$i]['children'] = $parents[$i]['children'] =
get_item_children($item_array, $parent, $thread_allowed) array_merge(get_item_children($item_array, $parent, $thread_allowed),
+ get_item_children($item_array, $parent, false); get_item_children($item_array, $parent, false));
} }
foreach ($parents as $i => $parent) { foreach ($parents as $i => $parent) {

View file

@ -713,6 +713,12 @@ class dba {
* @return boolean was the insert successfull? * @return boolean was the insert successfull?
*/ */
public static function insert($table, $param, $on_duplicate_update = false) { public static function insert($table, $param, $on_duplicate_update = false) {
if (empty($table) || empty($param)) {
logger('Table and fields have to be set');
return false;
}
$sql = "INSERT INTO `".self::escape($table)."` (`".implode("`, `", array_keys($param))."`) VALUES (". $sql = "INSERT INTO `".self::escape($table)."` (`".implode("`, `", array_keys($param))."`) VALUES (".
substr(str_repeat("?, ", count($param)), 0, -2).")"; substr(str_repeat("?, ", count($param)), 0, -2).")";
@ -852,6 +858,12 @@ class dba {
* @return boolean|array was the delete successfull? When $in_process is set: deletion data * @return boolean|array was the delete successfull? When $in_process is set: deletion data
*/ */
public static function delete($table, $param, $in_process = false, &$callstack = array()) { public static function delete($table, $param, $in_process = false, &$callstack = array()) {
if (empty($table) || empty($param)) {
logger('Table and condition have to be set');
return false;
}
$commands = array(); $commands = array();
// Create a key for the loop prevention // Create a key for the loop prevention
@ -1014,9 +1026,14 @@ class dba {
* @return boolean was the update successfull? * @return boolean was the update successfull?
*/ */
public static function update($table, $fields, $condition, $old_fields = array()) { public static function update($table, $fields, $condition, $old_fields = array()) {
if (empty($table) || empty($fields) || empty($condition)) {
logger('Table, fields and condition have to be set');
return false;
}
$table = self::escape($table); $table = self::escape($table);
if (count($condition) > 0) {
$array_element = each($condition); $array_element = each($condition);
$array_key = $array_element['key']; $array_key = $array_element['key'];
if (is_int($array_key)) { if (is_int($array_key)) {
@ -1024,9 +1041,6 @@ class dba {
} else { } else {
$condition_string = " WHERE `".implode("` = ? AND `", array_keys($condition))."` = ?"; $condition_string = " WHERE `".implode("` = ? AND `", array_keys($condition))."` = ?";
} }
} else {
$condition_string = "";
}
if (is_bool($old_fields)) { if (is_bool($old_fields)) {
$do_insert = $old_fields; $do_insert = $old_fields;

View file

@ -216,7 +216,7 @@ function event_delete($event_id) {
return; return;
} }
q("DELETE FROM `event` WHERE `id` = %d", intval($event_id)); dba::delete('event', array('id' => $event_id));
logger("Deleted event ".$event_id, LOGGER_DEBUG); logger("Deleted event ".$event_id, LOGGER_DEBUG);
} }

View file

@ -14,13 +14,13 @@ use Friendica\Core\PConfig;
* @return boolean * @return boolean
*/ */
function feature_enabled($uid, $feature) { function feature_enabled($uid, $feature) {
$x = Config::get('feature_lock', $feature); $x = Config::get('feature_lock', $feature, false);
if (is_null($x)) { if (!$x) {
$x = PConfig::get($uid, 'feature', $feature); $x = PConfig::get($uid, 'feature', $feature, false);
if (is_null($x)) { if (!$x) {
$x = Config::get('feature', $feature); $x = Config::get('feature', $feature, false);
if (is_null($x)) { if (!$x) {
$x = get_feature_default($feature); $x = get_feature_default($feature);
} }
} }
@ -67,53 +67,53 @@ function get_features($filtered = true) {
'general' => array( 'general' => array(
t('General Features'), t('General Features'),
//array('expire', t('Content Expiration'), t('Remove old posts/comments after a period of time')), //array('expire', t('Content Expiration'), t('Remove old posts/comments after a period of time')),
array('multi_profiles', t('Multiple Profiles'), t('Ability to create multiple profiles'), false, Config::get('feature_lock','multi_profiles')), array('multi_profiles', t('Multiple Profiles'), t('Ability to create multiple profiles'), false, Config::get('feature_lock','multi_profiles', false)),
array('photo_location', t('Photo Location'), t('Photo metadata is normally stripped. This extracts the location (if present) prior to stripping metadata and links it to a map.'), false, Config::get('feature_lock','photo_location')), array('photo_location', t('Photo Location'), t('Photo metadata is normally stripped. This extracts the location (if present) prior to stripping metadata and links it to a map.'), false, Config::get('feature_lock','photo_location', false)),
array('export_calendar', t('Export Public Calendar'), t('Ability for visitors to download the public calendar'), false, Config::get('feature_lock','export_calendar')), array('export_calendar', t('Export Public Calendar'), t('Ability for visitors to download the public calendar'), false, Config::get('feature_lock','export_calendar', false)),
), ),
// Post composition // Post composition
'composition' => array( 'composition' => array(
t('Post Composition Features'), t('Post Composition Features'),
array('preview', t('Post Preview'), t('Allow previewing posts and comments before publishing them'), false, Config::get('feature_lock','preview')), array('preview', t('Post Preview'), t('Allow previewing posts and comments before publishing them'), false, Config::get('feature_lock','preview', false)),
array('aclautomention', t('Auto-mention Forums'), t('Add/remove mention when a forum page is selected/deselected in ACL window.'), false, Config::get('feature_lock','aclautomention')), array('aclautomention', t('Auto-mention Forums'), t('Add/remove mention when a forum page is selected/deselected in ACL window.'), false, Config::get('feature_lock','aclautomention', false)),
), ),
// Network sidebar widgets // Network sidebar widgets
'widgets' => array( 'widgets' => array(
t('Network Sidebar Widgets'), t('Network Sidebar Widgets'),
array('archives', t('Search by Date'), t('Ability to select posts by date ranges'), false, Config::get('feature_lock','archives')), array('archives', t('Search by Date'), t('Ability to select posts by date ranges'), false, Config::get('feature_lock','archives', false)),
array('forumlist_widget', t('List Forums'), t('Enable widget to display the forums your are connected with'), true, Config::get('feature_lock','forumlist_widget')), array('forumlist_widget', t('List Forums'), t('Enable widget to display the forums your are connected with'), true, Config::get('feature_lock','forumlist_widget', false)),
array('groups', t('Group Filter'), t('Enable widget to display Network posts only from selected group'), false, Config::get('feature_lock','groups')), array('groups', t('Group Filter'), t('Enable widget to display Network posts only from selected group'), false, Config::get('feature_lock','groups', false)),
array('networks', t('Network Filter'), t('Enable widget to display Network posts only from selected network'), false, Config::get('feature_lock','networks')), array('networks', t('Network Filter'), t('Enable widget to display Network posts only from selected network'), false, Config::get('feature_lock','networks', false)),
array('savedsearch', t('Saved Searches'), t('Save search terms for re-use'), false, Config::get('feature_lock','savedsearch')), array('savedsearch', t('Saved Searches'), t('Save search terms for re-use'), false, Config::get('feature_lock','savedsearch', false)),
), ),
// Network tabs // Network tabs
'net_tabs' => array( 'net_tabs' => array(
t('Network Tabs'), t('Network Tabs'),
array('personal_tab', t('Network Personal Tab'), t('Enable tab to display only Network posts that you\'ve interacted on'), false, Config::get('feature_lock','personal_tab')), array('personal_tab', t('Network Personal Tab'), t('Enable tab to display only Network posts that you\'ve interacted on'), false, Config::get('feature_lock','personal_tab', false)),
array('new_tab', t('Network New Tab'), t('Enable tab to display only new Network posts (from the last 12 hours)'), false, Config::get('feature_lock','new_tab')), array('new_tab', t('Network New Tab'), t('Enable tab to display only new Network posts (from the last 12 hours)'), false, Config::get('feature_lock','new_tab', false)),
array('link_tab', t('Network Shared Links Tab'), t('Enable tab to display only Network posts with links in them'), false, Config::get('feature_lock','link_tab')), array('link_tab', t('Network Shared Links Tab'), t('Enable tab to display only Network posts with links in them'), false, Config::get('feature_lock','link_tab', false)),
), ),
// Item tools // Item tools
'tools' => array( 'tools' => array(
t('Post/Comment Tools'), t('Post/Comment Tools'),
array('multi_delete', t('Multiple Deletion'), t('Select and delete multiple posts/comments at once'), false, Config::get('feature_lock','multi_delete')), array('multi_delete', t('Multiple Deletion'), t('Select and delete multiple posts/comments at once'), false, Config::get('feature_lock','multi_delete', false)),
array('edit_posts', t('Edit Sent Posts'), t('Edit and correct posts and comments after sending'), false, Config::get('feature_lock','edit_posts')), array('edit_posts', t('Edit Sent Posts'), t('Edit and correct posts and comments after sending'), false, Config::get('feature_lock','edit_posts', false)),
array('commtag', t('Tagging'), t('Ability to tag existing posts'), false, Config::get('feature_lock','commtag')), array('commtag', t('Tagging'), t('Ability to tag existing posts'), false, Config::get('feature_lock','commtag', false)),
array('categories', t('Post Categories'), t('Add categories to your posts'), false, Config::get('feature_lock','categories')), array('categories', t('Post Categories'), t('Add categories to your posts'), false, Config::get('feature_lock','categories', false)),
array('filing', t('Saved Folders'), t('Ability to file posts under folders'), false, Config::get('feature_lock','filing')), array('filing', t('Saved Folders'), t('Ability to file posts under folders'), false, Config::get('feature_lock','filing', false)),
array('dislike', t('Dislike Posts'), t('Ability to dislike posts/comments'), false, Config::get('feature_lock','dislike')), array('dislike', t('Dislike Posts'), t('Ability to dislike posts/comments'), false, Config::get('feature_lock','dislike', false)),
array('star_posts', t('Star Posts'), t('Ability to mark special posts with a star indicator'), false, Config::get('feature_lock','star_posts')), array('star_posts', t('Star Posts'), t('Ability to mark special posts with a star indicator'), false, Config::get('feature_lock','star_posts', false)),
array('ignore_posts', t('Mute Post Notifications'), t('Ability to mute notifications for a thread'), false, Config::get('feature_lock','ignore_posts')), array('ignore_posts', t('Mute Post Notifications'), t('Ability to mute notifications for a thread'), false, Config::get('feature_lock','ignore_posts', false)),
), ),
// Advanced Profile Settings // Advanced Profile Settings
'advanced_profile' => array( 'advanced_profile' => array(
t('Advanced Profile Settings'), t('Advanced Profile Settings'),
array('forumlist_profile', t('List Forums'), t('Show visitors public community forums at the Advanced Profile Page'), false, Config::get('feature_lock','forumlist_profile')), array('forumlist_profile', t('List Forums'), t('Show visitors public community forums at the Advanced Profile Page'), false, Config::get('feature_lock','forumlist_profile', false)),
array('tagadelic', t('Tag Cloud'), t('Provide a personal tag cloud on your profile page'), false, Config::get('feature_lock', 'tagadelic')), array('tagadelic', t('Tag Cloud'), t('Provide a personal tag cloud on your profile page'), false, Config::get('feature_lock', 'tagadelic')),
), ),
); );
@ -126,7 +126,7 @@ function get_features($filtered = true) {
$kquantity = count($arr[$k]); $kquantity = count($arr[$k]);
for ($y = 0; $y < $kquantity; $y ++) { for ($y = 0; $y < $kquantity; $y ++) {
if (is_array($arr[$k][$y])) { if (is_array($arr[$k][$y])) {
if (is_null($arr[$k][$y][4])) { if (!$arr[$k][$y][4]) {
$has_items = true; $has_items = true;
} }
else { else {

View file

@ -344,7 +344,7 @@ function feed_import($xml,$importer,&$contact, &$hub, $simulate = false) {
$item["title"] = ''; $item["title"] = '';
} }
if ($contact["fetch_further_information"]) { if (!empty($contact["fetch_further_information"]) && ($contact["fetch_further_information"] < 3)) {
$preview = ""; $preview = "";
// Handle enclosures and treat them as preview picture // Handle enclosures and treat them as preview picture
@ -384,6 +384,9 @@ function feed_import($xml,$importer,&$contact, &$hub, $simulate = false) {
if (!strstr($item["body"], '[url') && ($item['plink'] != '')) { if (!strstr($item["body"], '[url') && ($item['plink'] != '')) {
$item["body"] .= "[hr][url]".$item['plink']."[/url]"; $item["body"] .= "[hr][url]".$item['plink']."[/url]";
} }
if ($contact["fetch_further_information"] == 3) {
$item["tag"] = add_page_keywords($item["plink"], false, $preview, true, $contact["ffi_keyword_blacklist"]);
}
} }
if (!$simulate) { if (!$simulate) {

View file

@ -272,7 +272,7 @@ function new_contact($uid, $url, $interactive = false, $network = '') {
} }
if ($contact['network'] == NETWORK_DIASPORA) { if ($contact['network'] == NETWORK_DIASPORA) {
$ret = Diaspora::send_share($a->user,$contact); $ret = Diaspora::sendShare($a->user, $contact);
logger('share returns: '.$ret); logger('share returns: '.$ret);
} }
} }

View file

@ -79,10 +79,7 @@ function group_rmv($uid,$name) {
} }
// remove all members // remove all members
$r = q("DELETE FROM `group_member` WHERE `uid` = %d AND `gid` = %d ", dba::delete('group_member', array('uid' => $uid, 'pid' => $group_id));
intval($uid),
intval($group_id)
);
// remove group // remove group
$r = q("UPDATE `group` SET `deleted` = 1 WHERE `uid` = %d AND `name` = '%s'", $r = q("UPDATE `group` SET `deleted` = 1 WHERE `uid` = %d AND `name` = '%s'",
@ -109,20 +106,19 @@ function group_byname($uid,$name) {
return false; return false;
} }
function group_rmv_member($uid,$name,$member) { function group_rmv_member($uid, $name, $member) {
$gid = group_byname($uid,$name); $gid = group_byname($uid, $name);
if (! $gid)
if (!$gid) {
return false; return false;
if (! ( $uid && $gid && $member)) }
if (!($uid && $gid && $member)) {
return false; return false;
$r = q("DELETE FROM `group_member` WHERE `uid` = %d AND `gid` = %d AND `contact-id` = %d", }
intval($uid),
intval($gid), $r = dba::delete('group_member', array('uid' => $uid, 'gid' => $gid, 'contact-id' => $member));
intval($member)
);
return $r; return $r;
} }

View file

@ -207,7 +207,8 @@ function add_page_info_data($data) {
$preview = str_replace(array("[", "]"), array("&#91;", "&#93;"), htmlentities($data["images"][0]["src"], ENT_QUOTES, 'UTF-8', false)); $preview = str_replace(array("[", "]"), array("&#91;", "&#93;"), htmlentities($data["images"][0]["src"], ENT_QUOTES, 'UTF-8', false));
// if the preview picture is larger than 500 pixels then show it in a larger mode // if the preview picture is larger than 500 pixels then show it in a larger mode
// But only, if the picture isn't higher than large (To prevent huge posts) // But only, if the picture isn't higher than large (To prevent huge posts)
if (($data["images"][0]["width"] >= 500) && ($data["images"][0]["width"] >= $data["images"][0]["height"])) { if (!Config::get('system', 'always_show_preview') && ($data["images"][0]["width"] >= 500)
&& ($data["images"][0]["width"] >= $data["images"][0]["height"])) {
$text .= " image='".$preview."'"; $text .= " image='".$preview."'";
} else { } else {
$text .= " preview='".$preview."'"; $text .= " preview='".$preview."'";
@ -426,7 +427,7 @@ function uri_to_guid($uri, $host = "") {
* @return array Item array with removed conversation data * @return array Item array with removed conversation data
*/ */
function store_conversation($arr) { function store_conversation($arr) {
if (in_array($arr['network'], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS))) { if (in_array($arr['network'], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS)) && !empty($arr['uri'])) {
$conversation = array('item-uri' => $arr['uri'], 'received' => DBM::date()); $conversation = array('item-uri' => $arr['uri'], 'received' => DBM::date());
if (isset($arr['parent-uri']) && ($arr['parent-uri'] != $arr['uri'])) { if (isset($arr['parent-uri']) && ($arr['parent-uri'] != $arr['uri'])) {
@ -2122,7 +2123,7 @@ function drop_item($id, $interactive = true) {
} }
if ((local_user() == $item['uid']) || ($contact_id) || (! $interactive)) { if ((local_user() == $item['uid']) || $contact_id || !$interactive) {
// Check if we should do HTML-based delete confirmation // Check if we should do HTML-based delete confirmation
if ($_REQUEST['confirm']) { if ($_REQUEST['confirm']) {
@ -2189,30 +2190,18 @@ function drop_item($id, $interactive = true) {
* generate a resource-id and therefore aren't intimately linked to the item. * generate a resource-id and therefore aren't intimately linked to the item.
*/ */
if (strlen($item['resource-id'])) { if (strlen($item['resource-id'])) {
q("DELETE FROM `photo` WHERE `resource-id` = '%s' AND `uid` = %d ", dba::delete('photo', array('resource-id' => $item['resource-id'], 'uid' => $item['uid']));
dbesc($item['resource-id']),
intval($item['uid'])
);
// ignore the result
} }
// If item is a link to an event, nuke the event record. // If item is a link to an event, nuke the event record.
if (intval($item['event-id'])) { if (intval($item['event-id'])) {
q("DELETE FROM `event` WHERE `id` = %d AND `uid` = %d", dba::delete('event', array('id' => $item['event-id'], 'uid' => $item['uid']));
intval($item['event-id']),
intval($item['uid'])
);
// ignore the result
} }
// If item has attachments, drop them // If item has attachments, drop them
foreach (explode(", ", $item['attach']) as $attach) { foreach (explode(", ", $item['attach']) as $attach) {
preg_match("|attach/(\d+)|", $attach, $matches); preg_match("|attach/(\d+)|", $attach, $matches);
q("DELETE FROM `attach` WHERE `id` = %d AND `uid` = %d", dba::delete('attach', array('id' => $matches[1], 'uid' => $item['uid']));
intval($matches[1]),
local_user()
);
// ignore the result
} }
// The new code splits the queries since the mysql optimizer really has bad problems with subqueries // The new code splits the queries since the mysql optimizer really has bad problems with subqueries

View file

@ -163,9 +163,7 @@ function do_like($item_id, $verb) {
// Clean up the Diaspora signatures for this like // Clean up the Diaspora signatures for this like
// Go ahead and do it even if Diaspora support is disabled. We still want to clean up // Go ahead and do it even if Diaspora support is disabled. We still want to clean up
// if it had been enabled in the past // if it had been enabled in the past
q("DELETE FROM `sign` WHERE `iid` = %d", dba::delete('sign', array('iid' => $like_item['id']));
intval($like_item['id'])
);
$like_item_id = $like_item['id']; $like_item_id = $like_item['id'];
Worker::add(PRIORITY_HIGH, "Notifier", "like", $like_item_id); Worker::add(PRIORITY_HIGH, "Notifier", "like", $like_item_id);
@ -249,7 +247,7 @@ EOT;
} }
// Save the author information for the like in case we need to relay to Diaspora // Save the author information for the like in case we need to relay to Diaspora
Diaspora::store_like_signature($item_contact, $new_item_id); Diaspora::storeLikeSignature($item_contact, $new_item_id);
$new_item['id'] = $new_item_id; $new_item['id'] = $new_item_id;

View file

@ -113,7 +113,7 @@ class FKOAuthDataStore extends OAuthDataStore {
} }
q("DELETE FROM tokens WHERE id='%s'", $token->key); dba::delete('tokens', array('id' => $token->key));
if (!is_null($ret) && $uverifier!==false){ if (!is_null($ret) && $uverifier!==false){

View file

@ -28,17 +28,17 @@ function oembed_replacecb($matches){
* @return bool|object Returns object with embed content or false if no embedable * @return bool|object Returns object with embed content or false if no embedable
* content exists * content exists
*/ */
function oembed_fetch_url($embedurl, $no_rich_type = false){ function oembed_fetch_url($embedurl, $no_rich_type = false) {
$embedurl = trim($embedurl, "'"); $embedurl = trim($embedurl, "'");
$embedurl = trim($embedurl, '"'); $embedurl = trim($embedurl, '"');
$a = get_app(); $a = get_app();
$r = q("SELECT * FROM `oembed` WHERE `url` = '%s'", $condition = array('url' => normalise_link($embedurl));
dbesc(normalise_link($embedurl))); $r = dba::select('oembed', array('content'), $condition, array('limit' => 1));
if (DBM::is_result($r)) { if (DBM::is_result($r)) {
$txt = $r[0]["content"]; $txt = $r["content"];
} else { } else {
$txt = Cache::get($a->videowidth . $embedurl); $txt = Cache::get($a->videowidth . $embedurl);
} }

View file

@ -16,19 +16,16 @@ use Friendica\Database\DBM;
* @param string $plugin name of the addon * @param string $plugin name of the addon
* @return boolean * @return boolean
*/ */
if (! function_exists('uninstall_plugin')){ function uninstall_plugin($plugin) {
function uninstall_plugin($plugin){
logger("Addons: uninstalling " . $plugin); logger("Addons: uninstalling " . $plugin);
q("DELETE FROM `addon` WHERE `name` = '%s' ", dba::delete('addon', array('name' => $plugin));
dbesc($plugin)
);
@include_once('addon/' . $plugin . '/' . $plugin . '.php'); @include_once('addon/' . $plugin . '/' . $plugin . '.php');
if (function_exists($plugin . '_uninstall')) { if (function_exists($plugin . '_uninstall')) {
$func = $plugin . '_uninstall'; $func = $plugin . '_uninstall';
$func(); $func();
} }
}} }
/** /**
* @brief installs an addon. * @brief installs an addon.
@ -36,12 +33,12 @@ function uninstall_plugin($plugin){
* @param string $plugin name of the addon * @param string $plugin name of the addon
* @return bool * @return bool
*/ */
if (! function_exists('install_plugin')){
function install_plugin($plugin) { function install_plugin($plugin) {
// silently fail if plugin was removed // silently fail if plugin was removed
if (! file_exists('addon/' . $plugin . '/' . $plugin . '.php')) if (!file_exists('addon/' . $plugin . '/' . $plugin . '.php')) {
return false; return false;
}
logger("Addons: installing " . $plugin); logger("Addons: installing " . $plugin);
$t = @filemtime('addon/' . $plugin . '/' . $plugin . '.php'); $t = @filemtime('addon/' . $plugin . '/' . $plugin . '.php');
@include_once('addon/' . $plugin . '/' . $plugin . '.php'); @include_once('addon/' . $plugin . '/' . $plugin . '.php');
@ -62,26 +59,24 @@ function install_plugin($plugin) {
dba::update('addon', array('hidden' => true), array('name' => $plugin)); dba::update('addon', array('hidden' => true), array('name' => $plugin));
} }
return true; return true;
} } else {
else {
logger("Addons: FAILED installing " . $plugin); logger("Addons: FAILED installing " . $plugin);
return false; return false;
} }
}
}}
// reload all updated plugins // reload all updated plugins
if (! function_exists('reload_plugins')) {
function reload_plugins() { function reload_plugins() {
$plugins = Config::get('system','addon'); $plugins = Config::get('system', 'addon');
if (strlen($plugins)) { if (strlen($plugins)) {
$r = q("SELECT * FROM `addon` WHERE `installed` = 1"); $r = q("SELECT * FROM `addon` WHERE `installed` = 1");
if (DBM::is_result($r)) if (DBM::is_result($r)) {
$installed = $r; $installed = $r;
else } else {
$installed = array(); $installed = array();
}
$parr = explode(',',$plugins); $parr = explode(',',$plugins);
@ -115,7 +110,7 @@ function reload_plugins() {
} }
} }
}} }
/** /**
* @brief check if addon is enabled * @brief check if addon is enabled
@ -137,21 +132,17 @@ function plugin_enabled($plugin) {
* @param int $priority A priority (defaults to 0) * @param int $priority A priority (defaults to 0)
* @return mixed|bool * @return mixed|bool
*/ */
if (! function_exists('register_hook')) { function register_hook($hook, $file, $function, $priority=0) {
function register_hook($hook,$file,$function,$priority=0) { $condition = array('hook' => $hook, 'file' => $file, 'function' => $function);
$exists = dba::exists('hook', $condition);
$r = q("SELECT * FROM `hook` WHERE `hook` = '%s' AND `file` = '%s' AND `function` = '%s' LIMIT 1", if ($exists) {
dbesc($hook),
dbesc($file),
dbesc($function)
);
if (DBM::is_result($r))
return true; return true;
}
$r = dba::insert('hook', array('hook' => $hook, 'file' => $file, 'function' => $function, 'priority' => $priority)); $r = dba::insert('hook', array('hook' => $hook, 'file' => $file, 'function' => $function, 'priority' => $priority));
return $r; return $r;
}} }
/** /**
* @brief unregisters a hook. * @brief unregisters a hook.
@ -161,16 +152,11 @@ function register_hook($hook,$file,$function,$priority=0) {
* @param string $function the name of the function that the hook called * @param string $function the name of the function that the hook called
* @return array * @return array
*/ */
if (! function_exists('unregister_hook')) { function unregister_hook($hook, $file, $function) {
function unregister_hook($hook,$file,$function) { $condition = array('hook' => $hook, 'file' => $file, 'function' => $function);
$r = dba::delete('hook', $condition);
$r = q("DELETE FROM `hook` WHERE `hook` = '%s' AND `file` = '%s' AND `function` = '%s'",
dbesc($hook),
dbesc($file),
dbesc($function)
);
return $r; return $r;
}} }
function load_hooks() { function load_hooks() {
@ -224,17 +210,13 @@ function call_single_hook($a, $name, $hook, &$data = null) {
$func($a, $data); $func($a, $data);
} else { } else {
// remove orphan hooks // remove orphan hooks
q("DELETE FROM `hook` WHERE `hook` = '%s' AND `file` = '%s' AND `function` = '%s'", $condition = array('hook' => $name, 'file' => $hook[0], 'function' => $hook[1]);
dbesc($name), dba::delete('hook', $condition);
dbesc($hook[0]),
dbesc($hook[1])
);
} }
} }
//check if an app_menu hook exist for plugin $name. //check if an app_menu hook exist for plugin $name.
//Return true if the plugin is an app //Return true if the plugin is an app
if (! function_exists('plugin_is_app')) {
function plugin_is_app($name) { function plugin_is_app($name) {
$a = get_app(); $a = get_app();
@ -246,7 +228,7 @@ function plugin_is_app($name) {
} }
return false; return false;
}} }
/** /**
* @brief Parse plugin comment in search of plugin infos. * @brief Parse plugin comment in search of plugin infos.
@ -264,8 +246,7 @@ function plugin_is_app($name) {
* @return array with the plugin information * @return array with the plugin information
*/ */
if (! function_exists('get_plugin_info')){ function get_plugin_info($plugin) {
function get_plugin_info($plugin){
$a = get_app(); $a = get_app();
@ -285,14 +266,14 @@ function get_plugin_info($plugin){
$r = preg_match("|/\*.*\*/|msU", $f, $m); $r = preg_match("|/\*.*\*/|msU", $f, $m);
if ($r){ if ($r) {
$ll = explode("\n", $m[0]); $ll = explode("\n", $m[0]);
foreach ( $ll as $l ) { foreach ( $ll as $l ) {
$l = trim($l,"\t\n\r */"); $l = trim($l,"\t\n\r */");
if ($l!=""){ if ($l != "") {
list($k,$v) = array_map("trim", explode(":",$l,2)); list($k,$v) = array_map("trim", explode(":",$l,2));
$k= strtolower($k); $k= strtolower($k);
if ($k=="author"){ if ($k == "author") {
$r=preg_match("|([^<]+)<([^>]+)>|", $v, $m); $r=preg_match("|([^<]+)<([^>]+)>|", $v, $m);
if ($r) { if ($r) {
$info['author'][] = array('name'=>$m[1], 'link'=>$m[2]); $info['author'][] = array('name'=>$m[1], 'link'=>$m[2]);
@ -300,7 +281,7 @@ function get_plugin_info($plugin){
$info['author'][] = array('name'=>$v); $info['author'][] = array('name'=>$v);
} }
} else { } else {
if (array_key_exists($k,$info)){ if (array_key_exists($k,$info)) {
$info[$k]=$v; $info[$k]=$v;
} }
} }
@ -310,7 +291,7 @@ function get_plugin_info($plugin){
} }
return $info; return $info;
}} }
/** /**
@ -329,8 +310,7 @@ function get_plugin_info($plugin){
* @return array * @return array
*/ */
if (! function_exists('get_theme_info')){ function get_theme_info($theme) {
function get_theme_info($theme){
$info=Array( $info=Array(
'name' => $theme, 'name' => $theme,
'description' => "", 'description' => "",
@ -356,14 +336,14 @@ function get_theme_info($theme){
$r = preg_match("|/\*.*\*/|msU", $f, $m); $r = preg_match("|/\*.*\*/|msU", $f, $m);
if ($r){ if ($r) {
$ll = explode("\n", $m[0]); $ll = explode("\n", $m[0]);
foreach ( $ll as $l ) { foreach ( $ll as $l ) {
$l = trim($l,"\t\n\r */"); $l = trim($l,"\t\n\r */");
if ($l!=""){ if ($l != "") {
list($k,$v) = array_map("trim", explode(":",$l,2)); list($k,$v) = array_map("trim", explode(":",$l,2));
$k= strtolower($k); $k= strtolower($k);
if ($k=="author"){ if ($k == "author") {
$r=preg_match("|([^<]+)<([^>]+)>|", $v, $m); $r=preg_match("|([^<]+)<([^>]+)>|", $v, $m);
if ($r) { if ($r) {
@ -371,8 +351,7 @@ function get_theme_info($theme){
} else { } else {
$info['author'][] = array('name'=>$v); $info['author'][] = array('name'=>$v);
} }
} } elseif ($k == "maintainer") {
elseif ($k=="maintainer"){
$r=preg_match("|([^<]+)<([^>]+)>|", $v, $m); $r=preg_match("|([^<]+)<([^>]+)>|", $v, $m);
if ($r) { if ($r) {
$info['maintainer'][] = array('name'=>$m[1], 'link'=>$m[2]); $info['maintainer'][] = array('name'=>$m[1], 'link'=>$m[2]);
@ -380,7 +359,7 @@ function get_theme_info($theme){
$info['maintainer'][] = array('name'=>$v); $info['maintainer'][] = array('name'=>$v);
} }
} else { } else {
if (array_key_exists($k,$info)){ if (array_key_exists($k,$info)) {
$info[$k]=$v; $info[$k]=$v;
} }
} }
@ -390,7 +369,7 @@ function get_theme_info($theme){
} }
return $info; return $info;
}} }
/** /**
* @brief Returns the theme's screenshot. * @brief Returns the theme's screenshot.
@ -411,8 +390,7 @@ function get_theme_screenshot($theme) {
} }
// install and uninstall theme // install and uninstall theme
if (! function_exists('uninstall_theme')){ function uninstall_theme($theme) {
function uninstall_theme($theme){
logger("Addons: uninstalling theme " . $theme); logger("Addons: uninstalling theme " . $theme);
include_once("view/theme/$theme/theme.php"); include_once("view/theme/$theme/theme.php");
@ -420,9 +398,8 @@ function uninstall_theme($theme){
$func = "{$theme}_uninstall"; $func = "{$theme}_uninstall";
$func(); $func();
} }
}} }
if (! function_exists('install_theme')){
function install_theme($theme) { function install_theme($theme) {
// silently fail if theme was removed // silently fail if theme was removed
@ -443,7 +420,7 @@ function install_theme($theme) {
return false; return false;
} }
}} }
/** /**
* @brief Get the full path to relevant theme files by filename * @brief Get the full path to relevant theme files by filename

View file

@ -13,9 +13,7 @@ function update_queue_time($id) {
function remove_queue_item($id) { function remove_queue_item($id) {
logger('queue: remove queue item ' . $id); logger('queue: remove queue item ' . $id);
q("DELETE FROM `queue` WHERE `id` = %d", dba::delete('queue', array('id' => $id));
intval($id)
);
} }
/** /**

View file

@ -251,7 +251,7 @@ function delete_thread($itemid, $itemuri = "") {
} }
// Using dba::delete at this time could delete the associated item entries // Using dba::delete at this time could delete the associated item entries
$result = q("DELETE FROM `thread` WHERE `iid` = %d", intval($itemid)); $result = dba::e("DELETE FROM `thread` WHERE `iid` = ?", $itemid);
logger("delete_thread: Deleted thread for item ".$itemid." - ".print_r($result, true), LOGGER_DEBUG); logger("delete_thread: Deleted thread for item ".$itemid." - ".print_r($result, true), LOGGER_DEBUG);

View file

@ -576,8 +576,14 @@ function contacts_content(App $a) {
$lost_contact = (($contact['archive'] && $contact['term-date'] > NULL_DATE && $contact['term-date'] < datetime_convert('','','now')) ? t('Communications lost with this contact!') : ''); $lost_contact = (($contact['archive'] && $contact['term-date'] > NULL_DATE && $contact['term-date'] < datetime_convert('','','now')) ? t('Communications lost with this contact!') : '');
if ($contact['network'] == NETWORK_FEED) { if ($contact['network'] == NETWORK_FEED) {
$fetch_further_information = array('fetch_further_information', t('Fetch further information for feeds'), $contact['fetch_further_information'], t('Fetch further information for feeds'), $fetch_further_information = array('fetch_further_information',
array('0'=>t('Disabled'), '1'=>t('Fetch information'), '2'=>t('Fetch information and keywords'))); t('Fetch further information for feeds'),
$contact['fetch_further_information'],
t("Fetch information like preview pictures, title and teaser from the feed item. You can activate this if the feed doesn't contain much text. Keywords are taken from the meta header in the feed item and are posted as hash tags."),
array('0' => t('Disabled'),
'1' => t('Fetch information'),
'3' => t('Fetch keywords'),
'2' => t('Fetch information and keywords')));
} }
if (in_array($contact['network'], array(NETWORK_FEED, NETWORK_MAIL, NETWORK_MAIL2))) if (in_array($contact['network'], array(NETWORK_FEED, NETWORK_MAIL, NETWORK_MAIL2)))
$poll_interval = contact_poll_interval($contact['priority'],(! $poll_enabled)); $poll_interval = contact_poll_interval($contact['priority'],(! $poll_enabled));

View file

@ -440,7 +440,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) {
if ((isset($new_relation) && $new_relation == CONTACT_IS_FRIEND)) { if ((isset($new_relation) && $new_relation == CONTACT_IS_FRIEND)) {
if (($contact) && ($contact['network'] === NETWORK_DIASPORA)) { if (($contact) && ($contact['network'] === NETWORK_DIASPORA)) {
$ret = Diaspora::send_share($user[0],$r[0]); $ret = Diaspora::sendShare($user[0],$r[0]);
logger('share returns: ' . $ret); logger('share returns: ' . $ret);
} }

View file

@ -175,7 +175,7 @@ function dfrn_notify_post(App $a) {
*we got a key. old code send only the key, without RINO version. *we got a key. old code send only the key, without RINO version.
* we assume RINO 1 if key and no RINO version * we assume RINO 1 if key and no RINO version
*/ */
$data = DFRN::aes_decrypt(hex2bin($data), $final_key); $data = DFRN::aesDecrypt(hex2bin($data), $final_key);
break; break;
case 2: case 2:
try { try {

View file

@ -68,12 +68,12 @@ function fetch_init(App $a)
} }
$user = $r[0]; $user = $r[0];
$status = Diaspora::build_status($item[0], $user); $status = Diaspora::buildStatus($item[0], $user);
$xml = Diaspora::build_post_xml($status["type"], $status["message"]); $xml = Diaspora::buildPostXml($status["type"], $status["message"]);
// Send the envelope // Send the envelope
header("Content-Type: application/magic-envelope+xml; charset=utf-8"); header("Content-Type: application/magic-envelope+xml; charset=utf-8");
echo Diaspora::build_magic_envelope($xml, $user); echo Diaspora::buildMagicEnvelope($xml, $user);
killme(); killme();
} }

View file

@ -985,7 +985,7 @@ function item_post(App $a) {
// Store the comment signature information in case we need to relay to Diaspora // Store the comment signature information in case we need to relay to Diaspora
Diaspora::store_comment_signature($datarray, $author, ($self ? $user['prvkey'] : false), $post_id); Diaspora::storeCommentSignature($datarray, $author, ($self ? $user['prvkey'] : false), $post_id);
} else { } else {
$parent = $post_id; $parent = $post_id;

View file

@ -58,8 +58,8 @@ function p_init($a){
} }
$user = $r[0]; $user = $r[0];
$status = Diaspora::build_status($item[0], $user); $status = Diaspora::buildStatus($item[0], $user);
$xml = Diaspora::build_post_xml($status["type"], $status["message"]); $xml = Diaspora::buildPostXml($status["type"], $status["message"]);
header("Content-Type: application/xml; charset=utf-8"); header("Content-Type: application/xml; charset=utf-8");
echo $xml; echo $xml;

View file

@ -49,14 +49,14 @@ function receive_post(App $a) {
} }
logger('mod-diaspora: message is in the new format', LOGGER_DEBUG); logger('mod-diaspora: message is in the new format', LOGGER_DEBUG);
$msg = Diaspora::decode_raw($importer, $postdata); $msg = Diaspora::decodeRaw($importer, $postdata);
} else { } else {
logger('mod-diaspora: decode message in the old format', LOGGER_DEBUG); logger('mod-diaspora: decode message in the old format', LOGGER_DEBUG);
$msg = Diaspora::decode($importer, $xml); $msg = Diaspora::decode($importer, $xml);
if ($public && !$msg) { if ($public && !$msg) {
logger('mod-diaspora: decode message in the new format', LOGGER_DEBUG); logger('mod-diaspora: decode message in the new format', LOGGER_DEBUG);
$msg = Diaspora::decode_raw($importer, $xml); $msg = Diaspora::decodeRaw($importer, $xml);
} }
} }
@ -72,7 +72,7 @@ function receive_post(App $a) {
$ret = true; $ret = true;
if ($public) { if ($public) {
Diaspora::dispatch_public($msg); Diaspora::dispatchPublic($msg);
} else { } else {
$ret = Diaspora::dispatch($importer, $msg); $ret = Diaspora::dispatch($importer, $msg);
} }

View file

@ -1,4 +1,4 @@
#!/usr/bin/php #!/usr/bin/env php
<?php <?php
/* /*
* ejabberd extauth script for the integration with friendica * ejabberd extauth script for the integration with friendica
@ -33,18 +33,19 @@
*/ */
use Friendica\App; use Friendica\App;
use Friendica\Core\Config; use Friendica\Util\ExAuth;
use Friendica\Database\DBM;
if (sizeof($_SERVER["argv"]) == 0) if (sizeof($_SERVER["argv"]) == 0) {
die(); die();
}
$directory = dirname($_SERVER["argv"][0]); $directory = dirname($_SERVER["argv"][0]);
if (substr($directory, 0, 1) != "/") if (substr($directory, 0, 1) != DIRECTORY_SEPARATOR) {
$directory = $_SERVER["PWD"]."/".$directory; $directory = $_SERVER["PWD"] . DIRECTORY_SEPARATOR . $directory;
}
$directory = realpath($directory."/.."); $directory = realpath($directory . DIRECTORY_SEPARATOR . "..");
chdir($directory); chdir($directory);
@ -53,259 +54,10 @@ require_once "include/dba.php";
$a = new App(dirname(__DIR__)); $a = new App(dirname(__DIR__));
@include(".htconfig.php"); @include ".htconfig.php";
dba::connect($db_host, $db_user, $db_pass, $db_data); dba::connect($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data); unset($db_host, $db_user, $db_pass, $db_data);
$oAuth = new exAuth(); $oAuth = new ExAuth();
class exAuth { $oAuth->readStdin();
private $bDebug;
/**
* @brief Create the class and do the authentification studd
*
* @param boolean $bDebug Debug mode
*/
public function __construct() {
// setter
$this->bDebug = (int)Config::get('jabber', 'debug');
openlog('auth_ejabberd', LOG_PID, LOG_USER);
$this->writeLog(LOG_NOTICE, "start");
// We are connected to the SQL server.
while (!feof(STDIN)) {
// Quit if the database connection went down
if (!dba::connected()) {
$this->writeLog(LOG_ERR, "the database connection went down");
return;
}
$iHeader = fgets(STDIN, 3);
$aLength = unpack("n", $iHeader);
$iLength = $aLength["1"];
// No data? Then quit
if ($iLength == 0) {
$this->writeLog(LOG_ERR, "we got no data, quitting");
return;
}
// Fetching the data
$sData = fgets(STDIN, $iLength + 1);
$this->writeLog(LOG_DEBUG, "received data: ". $sData);
$aCommand = explode(":", $sData);
if (is_array($aCommand)) {
switch ($aCommand[0]) {
case "isuser":
// Check the existance of a given username
$this->isuser($aCommand);
break;
case "auth":
// Check if the givven password is correct
$this->auth($aCommand);
break;
case "setpass":
// We don't accept the setting of passwords here
$this->writeLog(LOG_NOTICE, "setpass command disabled");
fwrite(STDOUT, pack("nn", 2, 0));
break;
default:
// We don't know the given command
$this->writeLog(LOG_NOTICE, "unknown command ". $aCommand[0]);
fwrite(STDOUT, pack("nn", 2, 0));
break;
}
} else {
$this->writeLog(LOG_NOTICE, "invalid command string ".$sData);
fwrite(STDOUT, pack("nn", 2, 0));
}
}
}
/**
* @brief Check if the given username exists
*
* @param array $aCommand The command array
*/
private function isuser($aCommand) {
$a = get_app();
// Check if there is a username
if (!isset($aCommand[1])) {
$this->writeLog(LOG_NOTICE, "invalid isuser command, no username given");
fwrite(STDOUT, pack("nn", 2, 0));
return;
}
// Now we check if the given user is valid
$sUser = str_replace(array("%20", "(a)"), array(" ", "@"), $aCommand[1]);
// Does the hostname match? So we try directly
if ($a->get_hostname() == $aCommand[2]) {
$this->writeLog(LOG_INFO, "internal user check for ". $sUser."@".$aCommand[2]);
$sQuery = "SELECT `uid` FROM `user` WHERE `nickname`='".dbesc($sUser)."'";
$this->writeLog(LOG_DEBUG, "using query ". $sQuery);
$r = q($sQuery);
$found = DBM::is_result($r);
} else {
$found = false;
}
// If the hostnames doesn't match or there is some failure, we try to check remotely
if (!$found) {
$found = $this->check_user($aCommand[2], $aCommand[1], true);
}
if ($found) {
// The user is okay
$this->writeLog(LOG_NOTICE, "valid user: ". $sUser);
fwrite(STDOUT, pack("nn", 2, 1));
} else {
// The user isn't okay
$this->writeLog(LOG_WARNING, "invalid user: ". $sUser);
fwrite(STDOUT, pack("nn", 2, 0));
}
}
/**
* @brief Check remote user existance via HTTP(S)
*
* @param string $host The hostname
* @param string $user Username
* @param boolean $ssl Should the check be done via SSL?
*
* @return boolean Was the user found?
*/
private function check_user($host, $user, $ssl) {
$this->writeLog(LOG_INFO, "external user check for ".$user."@".$host);
$url = ($ssl ? "https":"http")."://".$host."/noscrape/".$user;
$data = z_fetch_url($url);
if (!is_array($data))
return(false);
if ($data["return_code"] != "200")
return(false);
$json = @json_decode($data["body"]);
if (!is_object($json))
return(false);
return($json->nick == $user);
}
/**
* @brief Authenticate the givven user and password
*
* @param array $aCommand The command array
*/
private function auth($aCommand) {
$a = get_app();
// check user authentication
if (sizeof($aCommand) != 4) {
$this->writeLog(LOG_NOTICE, "invalid auth command, data missing");
fwrite(STDOUT, pack("nn", 2, 0));
return;
}
// We now check if the password match
$sUser = str_replace(array("%20", "(a)"), array(" ", "@"), $aCommand[1]);
// Does the hostname match? So we try directly
if ($a->get_hostname() == $aCommand[2]) {
$this->writeLog(LOG_INFO, "internal auth for ".$sUser."@".$aCommand[2]);
$sQuery = "SELECT `uid`, `password` FROM `user` WHERE `nickname`='".dbesc($sUser)."'";
$this->writeLog(LOG_DEBUG, "using query ". $sQuery);
if ($oResult = q($sQuery)) {
$uid = $oResult[0]["uid"];
$Error = ($oResult[0]["password"] != hash('whirlpool',$aCommand[3]));
} else {
$this->writeLog(LOG_WARNING, "invalid query: ". $sQuery);
$Error = true;
$uid = -1;
}
if ($Error) {
$oConfig = q("SELECT `v` FROM `pconfig` WHERE `uid` = %d AND `cat` = 'xmpp' AND `k`='password' LIMIT 1;", intval($uid));
$this->writeLog(LOG_INFO, "check against alternate password for ".$sUser."@".$aCommand[2]);
$Error = ($aCommand[3] != $oConfig[0]["v"]);
}
} else {
$Error = true;
}
// If the hostnames doesn't match or there is some failure, we try to check remotely
if ($Error) {
$Error = !$this->check_credentials($aCommand[2], $aCommand[1], $aCommand[3], true);
}
if ($Error) {
$this->writeLog(LOG_WARNING, "authentification failed for user ".$sUser."@". $aCommand[2]);
fwrite(STDOUT, pack("nn", 2, 0));
} else {
$this->writeLog(LOG_NOTICE, "authentificated user ".$sUser."@".$aCommand[2]);
fwrite(STDOUT, pack("nn", 2, 1));
}
}
/**
* @brief Check remote credentials via HTTP(S)
*
* @param string $host The hostname
* @param string $user Username
* @param string $password Password
* @param boolean $ssl Should the check be done via SSL?
*
* @return boolean Are the credentials okay?
*/
private function check_credentials($host, $user, $password, $ssl) {
$url = ($ssl ? "https":"http")."://".$host."/api/account/verify_credentials.json";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $user.':'.$password);
$header = curl_exec($ch);
$curl_info = @curl_getinfo($ch);
$http_code = $curl_info["http_code"];
curl_close($ch);
$this->writeLog(LOG_INFO, "external auth for ".$user."@".$host." returned ".$http_code);
return ($http_code == 200);
}
/**
* @brief write data to the syslog
*
* @param integer $loglevel The syslog loglevel
* @param string $sMessage The syslog message
*/
private function writeLog($loglevel, $sMessage) {
if (!$this->bDebug && ($loglevel >= LOG_DEBUG)) {
return;
}
syslog($loglevel, $sMessage);
}
/**
* @brief destroy the class, close the syslog connection.
*/
public function __destruct() {
$this->writeLog(LOG_NOTICE, "stop");
closelog();
}
}

View file

@ -722,7 +722,7 @@ class App {
if (DBM::is_result($r)) { if (DBM::is_result($r)) {
foreach ($r AS $process) { foreach ($r AS $process) {
if (!posix_kill($process['pid'], 0)) { if (!posix_kill($process['pid'], 0)) {
q('DELETE FROM `process` WHERE `pid` = %d', intval($process['pid'])); dba::delete('process', array('pid' => $process['pid']));
} }
} }
} }
@ -733,7 +733,7 @@ class App {
* @brief Remove the active process from the "process" table * @brief Remove the active process from the "process" table
*/ */
function end_process() { function end_process() {
q('DELETE FROM `process` WHERE `pid` = %d', intval(getmypid())); dba::delete('process', array('pid' => getmypid()));
} }
function get_useragent() { function get_useragent() {

View file

@ -0,0 +1,27 @@
<?php
/**
* Throwable exceptions to return HTTP status code
*
* This list of Exception has be extracted from
* here http://racksburg.com/choosing-an-http-status-code/
*/
namespace Friendica\Network;
use Exception;
class HTTPException extends Exception
{
var $httpcode = 200;
var $httpdesc = "";
public function __construct($message = '', $code = 0, Exception $previous = null)
{
if ($this->httpdesc == '') {
$classname = str_replace('Exception', '', str_replace('Friendica\Network\HTTPException\\', '', get_class($this)));
$this->httpdesc = preg_replace("|([a-z])([A-Z])|",'$1 $2', $classname);
}
parent::__construct($message, $code, $previous);
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace Friendica\Network\HTTPException;
use Friendica\Network\HTTPException;
class BadGatewayException extends HTTPException
{
var $httpcode = 502;
}

View file

@ -0,0 +1,10 @@
<?php
namespace Friendica\Network\HTTPException;
use Friendica\Network\HTTPException;
class BadRequestException extends HTTPException
{
var $httpcode = 400;
}

View file

@ -0,0 +1,10 @@
<?php
namespace Friendica\Network\HTTPException;
use Friendica\Network\HTTPException;
class ConflictException extends HTTPException
{
var $httpcode = 409;
}

View file

@ -0,0 +1,10 @@
<?php
namespace Friendica\Network\HTTPException;
use Friendica\Network\HTTPException;
class ExpectationFailedException extends HTTPException
{
var $httpcode = 417;
}

View file

@ -0,0 +1,10 @@
<?php
namespace Friendica\Network\HTTPException;
use Friendica\Network\HTTPException;
class ForbiddenException extends HTTPException
{
var $httpcode = 403;
}

View file

@ -0,0 +1,10 @@
<?php
namespace Friendica\Network\HTTPException;
use Friendica\Network\HTTPException;
class GatewayTimeoutException extends HTTPException
{
var $httpcode = 504;
}

View file

@ -0,0 +1,10 @@
<?php
namespace Friendica\Network\HTTPException;
use Friendica\Network\HTTPException;
class GoneException extends HTTPException
{
var $httpcode = 410;
}

View file

@ -0,0 +1,11 @@
<?php
namespace Friendica\Network\HTTPException;
use Friendica\Network\HTTPException;
class ImATeapotException extends HTTPException
{
var $httpcode = 418;
var $httpdesc = "I'm A Teapot";
}

View file

@ -0,0 +1,10 @@
<?php
namespace Friendica\Network\HTTPException;
use Friendica\Network\HTTPException;
class InternalServerErrorException extends HTTPException
{
var $httpcode = 500;
}

View file

@ -0,0 +1,10 @@
<?php
namespace Friendica\Network\HTTPException;
use Friendica\Network\HTTPException;
class LenghtRequiredException extends HTTPException
{
var $httpcode = 411;
}

View file

@ -0,0 +1,10 @@
<?php
namespace Friendica\Network\HTTPException;
use Friendica\Network\HTTPException;
class MethodNotAllowedException extends HTTPException
{
var $httpcode = 405;
}

View file

@ -0,0 +1,10 @@
<?php
namespace Friendica\Network\HTTPException;
use Friendica\Network\HTTPException;
class NonAcceptableException extends HTTPException
{
var $httpcode = 406;
}

View file

@ -0,0 +1,9 @@
<?php
namespace Friendica\Network\HTTPException;
use Friendica\Network\HTTPException;
class NotFoundException extends HTTPException {
var $httpcode = 404;
}

View file

@ -0,0 +1,10 @@
<?php
namespace Friendica\Network\HTTPException;
use Friendica\Network\HTTPException;
class NotImplementedException extends HTTPException
{
var $httpcode = 501;
}

View file

@ -0,0 +1,10 @@
<?php
namespace Friendica\Network\HTTPException;
use Friendica\Network\HTTPException;
class PreconditionFailedException extends HTTPException
{
var $httpcode = 412;
}

View file

@ -0,0 +1,10 @@
<?php
namespace Friendica\Network\HTTPException;
use Friendica\Network\HTTPException;
class ServiceUnavaiableException extends HTTPException
{
var $httpcode = 503;
}

View file

@ -0,0 +1,10 @@
<?php
namespace Friendica\Network\HTTPException;
use Friendica\Network\HTTPException;
class TooManyRequestsException extends HTTPException
{
var $httpcode = 429;
}

View file

@ -0,0 +1,10 @@
<?php
namespace Friendica\Network\HTTPException;
use Friendica\Network\HTTPException;
class UnauthorizedException extends HTTPException
{
var $httpcode = 401;
}

View file

@ -0,0 +1,10 @@
<?php
namespace Friendica\Network\HTTPException;
use Friendica\Network\HTTPException;
class UnprocessableEntityException extends HTTPException
{
var $httpcode = 422;
}

View file

@ -0,0 +1,10 @@
<?php
namespace Friendica\Network\HTTPException;
use Friendica\Network\HTTPException;
class UnsupportedMediaTypeException extends HTTPException
{
var $httpcode = 415;
}

View file

@ -21,29 +21,29 @@ use dba;
require_once 'boot.php'; require_once 'boot.php';
require_once 'include/text.php'; require_once 'include/text.php';
/**
* @brief functions for interacting with a contact
*/
class Contact extends BaseObject class Contact extends BaseObject
{ {
/** /**
* @brief Marks a contact for removal * @brief Marks a contact for removal
* *
* @param int $id * @param int $id contact id
* @return null * @return null
*/ */
public static function remove($id) public static function remove($id)
{ {
// We want just to make sure that we don't delete our "self" contact // We want just to make sure that we don't delete our "self" contact
$r = q( $r = dba::select('contact', array('uid'), array('id' => $id, 'self' => false), array('limit' => 1));
"SELECT `uid` FROM `contact` WHERE `id` = %d AND NOT `self` LIMIT 1", intval($id)
); if (!DBM::is_result($r) || !intval($r['uid'])) {
if (!DBM::is_result($r) || !intval($r[0]['uid'])) {
return; return;
} }
$archive = PConfig::get($r[0]['uid'], 'system', 'archive_removed_contacts'); $archive = PConfig::get($r['uid'], 'system', 'archive_removed_contacts');
if ($archive) { if ($archive) {
q( dba::update('contact', array('archive' => true, 'network' => 'none', 'writable' => false), array('id' => $id));
"UPDATE `contact` SET `archive` = 1, `network` = 'none', `writable` = 0 WHERE id = %d", intval($id)
);
return; return;
} }
@ -58,6 +58,7 @@ class Contact extends BaseObject
* *
* @param array $user User unfriending * @param array $user User unfriending
* @param array $contact Contact unfriended * @param array $contact Contact unfriended
* @return void
*/ */
public static function terminateFriendship(array $user, array $contact) public static function terminateFriendship(array $user, array $contact)
{ {
@ -88,7 +89,7 @@ class Contact extends BaseObject
* This provides for the possibility that their database is temporarily messed * This provides for the possibility that their database is temporarily messed
* up or some other transient event and that there's a possibility we could recover from it. * up or some other transient event and that there's a possibility we could recover from it.
* *
* @param array $contact * @param array $contact contact to mark for archival
* @return type * @return type
*/ */
public static function markForArchival(array $contact) public static function markForArchival(array $contact)
@ -99,18 +100,12 @@ class Contact extends BaseObject
} }
if ($contact['term-date'] <= NULL_DATE) { if ($contact['term-date'] <= NULL_DATE) {
q( dba::update('contact', array('term-date' => datetime_convert()), array('id' => $contact['id']));
"UPDATE `contact` SET `term-date` = '%s' WHERE `id` = %d", dbesc(datetime_convert()), intval($contact['id'])
);
if ($contact['url'] != '') { if ($contact['url'] != '') {
q( dba::update('contact', array('term-date' => datetime_convert()), array('`nurl` = ? AND `term-date` <= ?', normalise_link($contact['url']), NULL_DATE));
"UPDATE `contact` SET `term-date` = '%s'
WHERE `nurl` = '%s' AND `term-date` <= '1000-00-00'", dbesc(datetime_convert()), dbesc(normalise_link($contact['url']))
);
} }
} else { } else {
/* @todo /* @todo
* We really should send a notification to the owner after 2-3 weeks * We really should send a notification to the owner after 2-3 weeks
* so they won't be surprised when the contact vanishes and can take * so they won't be surprised when the contact vanishes and can take
@ -120,19 +115,14 @@ class Contact extends BaseObject
/// @todo Check for contact vitality via probing /// @todo Check for contact vitality via probing
$expiry = $contact['term-date'] . ' + 32 days '; $expiry = $contact['term-date'] . ' + 32 days ';
if (datetime_convert() > datetime_convert('UTC', 'UTC', $expiry)) { if (datetime_convert() > datetime_convert('UTC', 'UTC', $expiry)) {
/* Relationship is really truly dead. archive them rather than /* Relationship is really truly dead. archive them rather than
* delete, though if the owner tries to unarchive them we'll start * delete, though if the owner tries to unarchive them we'll start
* the whole process over again. * the whole process over again.
*/ */
q( dba::update('contact', array('archive' => 1), array('id' => $contact['id']));
"UPDATE `contact` SET `archive` = 1 WHERE `id` = %d", intval($contact['id'])
);
if ($contact['url'] != '') { if ($contact['url'] != '') {
q( dba::update('contact', array('archive' => 1), array('nurl' => normalise_link($contact['url'])));
"UPDATE `contact` SET `archive` = 1 WHERE `nurl` = '%s'", dbesc(normalise_link($contact['url']))
);
} }
} }
} }
@ -143,17 +133,16 @@ class Contact extends BaseObject
* *
* @see Contact::markForArchival() * @see Contact::markForArchival()
* *
* @param array $contact * @param array $contact contact to be unmarked for archival
* @return null * @return null
*/ */
public static function unmarkForArchival(array $contact) public static function unmarkForArchival(array $contact)
{ {
$r = q( $condition = array('`id` = ? AND (`term-date` > ? OR `archive`)', $contact[`id`], NULL_DATE);
"SELECT `term-date` FROM `contact` WHERE `id` = %d AND (`term-date` > '%s' OR `archive`)", intval($contact['id']), dbesc('1000-00-00 00:00:00') $exists = dba::exists('contact', $condition);
);
// We don't need to update, we never marked this contact for archival // We don't need to update, we never marked this contact for archival
if (!DBM::is_result($r)) { if (!$exists) {
return; return;
} }
@ -237,7 +226,7 @@ class Contact extends BaseObject
if (DBM::is_result($r)) { if (DBM::is_result($r)) {
// If there is more than one entry we filter out the connector networks // If there is more than one entry we filter out the connector networks
if (count($r) > 1) { if (count($r) > 1) {
foreach ($r AS $id => $result) { foreach ($r as $id => $result) {
if ($result["network"] == NETWORK_STATUSNET) { if ($result["network"] == NETWORK_STATUSNET) {
unset($r[$id]); unset($r[$id]);
} }
@ -291,8 +280,9 @@ class Contact extends BaseObject
$profile["micro"] = $profile["thumb"]; $profile["micro"] = $profile["thumb"];
} }
if ((($profile["addr"] == "") || ($profile["name"] == "")) && ($profile["gid"] != 0) && if ((($profile["addr"] == "") || ($profile["name"] == "")) && ($profile["gid"] != 0)
in_array($profile["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS))) { && in_array($profile["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS))
) {
Worker::add(PRIORITY_LOW, "UpdateGContact", $profile["gid"]); Worker::add(PRIORITY_LOW, "UpdateGContact", $profile["gid"]);
} }
@ -362,8 +352,8 @@ class Contact extends BaseObject
/** /**
* @brief Returns the data array for the photo menu of a given contact * @brief Returns the data array for the photo menu of a given contact
* *
* @param array $contact * @param array $contact contact
* @param int $uid * @param int $uid optional, default 0
* @return array * @return array
*/ */
public static function photoMenu(array $contact, $uid = 0) public static function photoMenu(array $contact, $uid = 0)
@ -386,14 +376,14 @@ class Contact extends BaseObject
if ($contact['uid'] != $uid) { if ($contact['uid'] != $uid) {
if ($uid == 0) { if ($uid == 0) {
$profile_link = zrl($contact['url']); $profile_link = zrl($contact['url']);
$menu = Array('profile' => array(t('View Profile'), $profile_link, true)); $menu = array('profile' => array(t('View Profile'), $profile_link, true));
return $menu; return $menu;
} }
$r = q("SELECT * FROM `contact` WHERE `nurl` = '%s' AND `network` = '%s' AND `uid` = %d", dbesc($contact['nurl']), dbesc($contact['network']), intval($uid)); $r = dba::select('contact', array(), array('nurl' => $contact['nurl'], 'network' => $contact['network'], 'uid' => $uid), array('limit' => 1));
if ($r) { if ($r) {
return self::photoMenu($r[0], $uid); return self::photoMenu($r, $uid);
} else { } else {
$profile_link = zrl($contact['url']); $profile_link = zrl($contact['url']);
$connlnk = 'follow/?url=' . $contact['url']; $connlnk = 'follow/?url=' . $contact['url'];
@ -438,7 +428,7 @@ class Contact extends BaseObject
$contact_drop_link = System::baseUrl() . '/contacts/' . $contact['id'] . '/drop?confirm=1'; $contact_drop_link = System::baseUrl() . '/contacts/' . $contact['id'] . '/drop?confirm=1';
/** /**
* menu array: * Menu array:
* "name" => [ "Label", "link", (bool)Should the link opened in a new tab? ] * "name" => [ "Label", "link", (bool)Should the link opened in a new tab? ]
*/ */
$menu = array( $menu = array(
@ -459,7 +449,7 @@ class Contact extends BaseObject
$menucondensed = array(); $menucondensed = array();
foreach ($menu AS $menuname => $menuitem) { foreach ($menu as $menuname => $menuitem) {
if ($menuitem[1] != '') { if ($menuitem[1] != '') {
$menucondensed[$menuname] = $menuitem; $menucondensed[$menuname] = $menuitem;
} }
@ -469,14 +459,15 @@ class Contact extends BaseObject
} }
/** /**
* @brief Returns ungrouped contact count or list for user
*
* Returns either the total number of ungrouped contacts for the given user * Returns either the total number of ungrouped contacts for the given user
* id or a paginated list of ungrouped contacts. * id or a paginated list of ungrouped contacts.
* *
* @brief Returns ungrouped contact count or list for user * @param int $uid uid
* @param int $start optional, default 0
* @param int $count optional, default 0
* *
* @param int $uid
* @param int $start
* @param int $count
* @return array * @return array
*/ */
public static function getUngroupedList($uid, $start = 0, $count = 0) public static function getUngroupedList($uid, $start = 0, $count = 0)
@ -510,7 +501,6 @@ class Contact extends BaseObject
AND `pending` = 0 AND `pending` = 0
LIMIT %d, %d", intval($uid), intval($uid), intval($start), intval($count) LIMIT %d, %d", intval($uid), intval($uid), intval($start), intval($count)
); );
return $r; return $r;
} }
@ -561,7 +551,7 @@ class Contact extends BaseObject
if (!DBM::is_result($contact)) { if (!DBM::is_result($contact)) {
// The link could be provided as http although we stored it as https // The link could be provided as http although we stored it as https
$ssl_url = str_replace('http://', 'https://', $url); $ssl_url = str_replace('http://', 'https://', $url);
$r = dba::p("SELECT `id`, `avatar-date` FROM `contact` WHERE `alias` IN (?, ?, ?) AND `uid` = ? LIMIT 1", $url, normalise_link($url), $ssl_url, $uid); $r = dba::select('contact', array('id', 'avatar-date'), array('`alias` IN (?, ?, ?) AND `uid` = ?', $url, normalise_link($url), $ssl_url, $uid), array('limit' => 1));
$contact = dba::fetch($r); $contact = dba::fetch($r);
dba::close($r); dba::close($r);
} }
@ -608,7 +598,8 @@ class Contact extends BaseObject
$url = $data["url"]; $url = $data["url"];
if (!$contact_id) { if (!$contact_id) {
dba::insert('contact', array('uid' => $uid, 'created' => datetime_convert(), 'url' => $data["url"], dba::insert(
'contact', array('uid' => $uid, 'created' => datetime_convert(), 'url' => $data["url"],
'nurl' => normalise_link($data["url"]), 'addr' => $data["addr"], 'nurl' => normalise_link($data["url"]), 'addr' => $data["addr"],
'alias' => $data["alias"], 'notify' => $data["notify"], 'poll' => $data["poll"], 'alias' => $data["alias"], 'notify' => $data["notify"], 'poll' => $data["poll"],
'name' => $data["name"], 'nick' => $data["nick"], 'photo' => $data["photo"], 'name' => $data["name"], 'nick' => $data["nick"], 'photo' => $data["photo"],
@ -619,9 +610,11 @@ class Contact extends BaseObject
'confirm' => $data["confirm"], 'poco' => $data["poco"], 'confirm' => $data["confirm"], 'poco' => $data["poco"],
'name-date' => datetime_convert(), 'uri-date' => datetime_convert(), 'name-date' => datetime_convert(), 'uri-date' => datetime_convert(),
'avatar-date' => datetime_convert(), 'writable' => 1, 'blocked' => 0, 'avatar-date' => datetime_convert(), 'writable' => 1, 'blocked' => 0,
'readonly' => 0, 'pending' => 0)); 'readonly' => 0, 'pending' => 0)
);
$contacts = q("SELECT `id` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d ORDER BY `id` LIMIT 2", dbesc(normalise_link($data["url"])), intval($uid)); $s = dba::select('contact', array('id'), array('nurl' => normalise_link($data["url"]), 'uid' => $uid), array('order' => array('id'), 'limit' => 2));
$contacts = dba::inArray($s);
if (!DBM::is_result($contacts)) { if (!DBM::is_result($contacts)) {
return 0; return 0;
} }
@ -735,13 +728,14 @@ class Contact extends BaseObject
/** /**
* @brief Returns posts from a given contact url * @brief Returns posts from a given contact url
* *
* @param App $a argv application class
* @param string $contact_url Contact URL * @param string $contact_url Contact URL
* *
* @return string posts in HTML * @return string posts in HTML
*/ */
public static function getPostsFromUrl($contact_url) public static function getPostsFromUrl($contact_url)
{ {
$a = self::getApp();
require_once 'include/conversation.php'; require_once 'include/conversation.php';
// There are no posts with "uid = 0" with connector networks // There are no posts with "uid = 0" with connector networks
@ -767,7 +761,6 @@ class Contact extends BaseObject
" ORDER BY `item`.`created` DESC LIMIT %d, %d", intval($author_id), intval(local_user()), intval($a->pager['start']), intval($a->pager['itemspage']) " ORDER BY `item`.`created` DESC LIMIT %d, %d", intval($author_id), intval(local_user()), intval($a->pager['start']), intval($a->pager['itemspage'])
); );
$a = self::getApp();
$o = conversation($a, $r, 'community', false); $o = conversation($a, $r, 'community', false);
@ -790,8 +783,7 @@ class Contact extends BaseObject
// "page-flags" is a field in the user table, // "page-flags" is a field in the user table,
// "forum" and "prv" are used in the contact table. They stand for PAGE_COMMUNITY and PAGE_PRVGROUP. // "forum" and "prv" are used in the contact table. They stand for PAGE_COMMUNITY and PAGE_PRVGROUP.
// "community" is used in the gcontact table and is true if the contact is PAGE_COMMUNITY or PAGE_PRVGROUP. // "community" is used in the gcontact table and is true if the contact is PAGE_COMMUNITY or PAGE_PRVGROUP.
if ( if ((isset($contact['page-flags']) && (intval($contact['page-flags']) == PAGE_COMMUNITY))
(isset($contact['page-flags']) && (intval($contact['page-flags']) == PAGE_COMMUNITY))
|| (isset($contact['page-flags']) && (intval($contact['page-flags']) == PAGE_PRVGROUP)) || (isset($contact['page-flags']) && (intval($contact['page-flags']) == PAGE_PRVGROUP))
|| (isset($contact['forum']) && intval($contact['forum'])) || (isset($contact['forum']) && intval($contact['forum']))
|| (isset($contact['prv']) && intval($contact['prv'])) || (isset($contact['prv']) && intval($contact['prv']))

View file

@ -60,7 +60,7 @@ class DFRN
$doc = new DOMDocument('1.0', 'utf-8'); $doc = new DOMDocument('1.0', 'utf-8');
$doc->formatOutput = true; $doc->formatOutput = true;
$root = self::add_header($doc, $owner, "dfrn:owner", "", false); $root = self::addHeader($doc, $owner, "dfrn:owner", "", false);
if (! count($items)) { if (! count($items)) {
return trim($doc->saveXML()); return trim($doc->saveXML());
@ -258,7 +258,7 @@ class DFRN
$author = "author"; $author = "author";
} }
$root = self::add_header($doc, $owner, $author, $alternatelink, true); $root = self::addHeader($doc, $owner, $author, $alternatelink, true);
/// @TODO This hook can't work anymore /// @TODO This hook can't work anymore
// call_hooks('atom_feed', $atom); // call_hooks('atom_feed', $atom);
@ -370,7 +370,7 @@ class DFRN
$root->setAttribute("xmlns:ostatus", NAMESPACE_OSTATUS); $root->setAttribute("xmlns:ostatus", NAMESPACE_OSTATUS);
$root->setAttribute("xmlns:statusnet", NAMESPACE_STATUSNET); $root->setAttribute("xmlns:statusnet", NAMESPACE_STATUSNET);
//$root = self::add_header($doc, $owner, "dfrn:owner", "", false); //$root = self::addHeader($doc, $owner, "dfrn:owner", "", false);
foreach ($items as $item) { foreach ($items as $item) {
$entry = self::entry($doc, $type, $item, $owner, true, 0); $entry = self::entry($doc, $type, $item, $owner, true, 0);
@ -398,7 +398,7 @@ class DFRN
$doc = new DOMDocument('1.0', 'utf-8'); $doc = new DOMDocument('1.0', 'utf-8');
$doc->formatOutput = true; $doc->formatOutput = true;
$root = self::add_header($doc, $owner, "dfrn:owner", "", false); $root = self::addHeader($doc, $owner, "dfrn:owner", "", false);
$mail = $doc->createElement("dfrn:mail"); $mail = $doc->createElement("dfrn:mail");
$sender = $doc->createElement("dfrn:sender"); $sender = $doc->createElement("dfrn:sender");
@ -411,7 +411,7 @@ class DFRN
XML::addElement($doc, $mail, "dfrn:id", $item['uri']); XML::addElement($doc, $mail, "dfrn:id", $item['uri']);
XML::addElement($doc, $mail, "dfrn:in-reply-to", $item['parent-uri']); XML::addElement($doc, $mail, "dfrn:in-reply-to", $item['parent-uri']);
XML::addElement($doc, $mail, "dfrn:sentdate", datetime_convert('UTC', 'UTC', $item['created'] . '+00:00' , ATOM_TIME)); XML::addElement($doc, $mail, "dfrn:sentdate", datetime_convert('UTC', 'UTC', $item['created'] . '+00:00', ATOM_TIME));
XML::addElement($doc, $mail, "dfrn:subject", $item['title']); XML::addElement($doc, $mail, "dfrn:subject", $item['title']);
XML::addElement($doc, $mail, "dfrn:content", $item['body']); XML::addElement($doc, $mail, "dfrn:content", $item['body']);
@ -434,7 +434,7 @@ class DFRN
$doc = new DOMDocument('1.0', 'utf-8'); $doc = new DOMDocument('1.0', 'utf-8');
$doc->formatOutput = true; $doc->formatOutput = true;
$root = self::add_header($doc, $owner, "dfrn:owner", "", false); $root = self::addHeader($doc, $owner, "dfrn:owner", "", false);
$suggest = $doc->createElement("dfrn:suggest"); $suggest = $doc->createElement("dfrn:suggest");
@ -486,7 +486,7 @@ class DFRN
$doc = new DOMDocument('1.0', 'utf-8'); $doc = new DOMDocument('1.0', 'utf-8');
$doc->formatOutput = true; $doc->formatOutput = true;
$root = self::add_header($doc, $owner, "dfrn:owner", "", false); $root = self::addHeader($doc, $owner, "dfrn:owner", "", false);
$relocate = $doc->createElement("dfrn:relocate"); $relocate = $doc->createElement("dfrn:relocate");
@ -501,7 +501,7 @@ class DFRN
XML::addElement($doc, $relocate, "dfrn:confirm", $owner['confirm']); XML::addElement($doc, $relocate, "dfrn:confirm", $owner['confirm']);
XML::addElement($doc, $relocate, "dfrn:notify", $owner['notify']); XML::addElement($doc, $relocate, "dfrn:notify", $owner['notify']);
XML::addElement($doc, $relocate, "dfrn:poll", $owner['poll']); XML::addElement($doc, $relocate, "dfrn:poll", $owner['poll']);
XML::addElement($doc, $relocate, "dfrn:sitepubkey", Config::get('system','site_pubkey')); XML::addElement($doc, $relocate, "dfrn:sitepubkey", Config::get('system', 'site_pubkey'));
$root->appendChild($relocate); $root->appendChild($relocate);
@ -520,7 +520,7 @@ class DFRN
* @return object XML root object * @return object XML root object
* @todo Add type-hints * @todo Add type-hints
*/ */
private static function add_header($doc, $owner, $authorelement, $alternatelink = "", $public = false) private static function addHeader($doc, $owner, $authorelement, $alternatelink = "", $public = false)
{ {
if ($alternatelink == "") { if ($alternatelink == "") {
@ -579,7 +579,7 @@ class DFRN
XML::addElement($doc, $root, "updated", datetime_convert("UTC", "UTC", "now", ATOM_TIME)); XML::addElement($doc, $root, "updated", datetime_convert("UTC", "UTC", "now", ATOM_TIME));
$author = self::add_author($doc, $owner, $authorelement, $public); $author = self::addAuthor($doc, $owner, $authorelement, $public);
$root->appendChild($author); $root->appendChild($author);
return $root; return $root;
@ -591,11 +591,12 @@ class DFRN
* @param object $doc XML document * @param object $doc XML document
* @param array $owner Owner record * @param array $owner Owner record
* @param string $authorelement Element name for the author * @param string $authorelement Element name for the author
* @param boolean $public boolean
* *
* @return object XML author object * @return object XML author object
* @todo Add type-hints * @todo Add type-hints
*/ */
private static function add_author($doc, $owner, $authorelement, $public) private static function addAuthor($doc, $owner, $authorelement, $public)
{ {
// Is the profile hidden or shouldn't be published in the net? Then add the "hide" element // Is the profile hidden or shouldn't be published in the net? Then add the "hide" element
$r = q( $r = q(
@ -739,7 +740,7 @@ class DFRN
* @return object XML author object * @return object XML author object
* @todo Add type-hints * @todo Add type-hints
*/ */
private static function add_entry_author($doc, $element, $contact_url, $item) private static function addEntryAuthor($doc, $element, $contact_url, $item)
{ {
$contact = Contact::getDetailsByURL($contact_url, $item["uid"]); $contact = Contact::getDetailsByURL($contact_url, $item["uid"]);
@ -780,7 +781,7 @@ class DFRN
* @return object XML activity object * @return object XML activity object
* @todo Add type-hints * @todo Add type-hints
*/ */
private static function create_activity($doc, $element, $activity) private static function createActivity($doc, $element, $activity)
{ {
if ($activity) { if ($activity) {
$entry = $doc->createElement($element); $entry = $doc->createElement($element);
@ -810,7 +811,7 @@ class DFRN
// XML does need a single element as root element so we add a dummy element here // XML does need a single element as root element so we add a dummy element here
$data = parse_xml_string("<dummy>" . $r->link . "</dummy>", false); $data = parse_xml_string("<dummy>" . $r->link . "</dummy>", false);
if (is_object($data)) { if (is_object($data)) {
foreach ($data->link AS $link) { foreach ($data->link as $link) {
$attributes = array(); $attributes = array();
foreach ($link->attributes() as $parameter => $value) { foreach ($link->attributes() as $parameter => $value) {
$attributes[$parameter] = $value; $attributes[$parameter] = $value;
@ -843,7 +844,7 @@ class DFRN
* @return object XML attachment object * @return object XML attachment object
* @todo Add type-hints * @todo Add type-hints
*/ */
private static function get_attachment($doc, $root, $item) private static function getAttachment($doc, $root, $item)
{ {
$arr = explode('[/attach],', $item['attach']); $arr = explode('[/attach],', $item['attach']);
if (count($arr)) { if (count($arr)) {
@ -932,10 +933,10 @@ class DFRN
$htmlbody = bbcode($htmlbody, false, false, 7); $htmlbody = bbcode($htmlbody, false, false, 7);
} }
$author = self::add_entry_author($doc, "author", $item["author-link"], $item); $author = self::addEntryAuthor($doc, "author", $item["author-link"], $item);
$entry->appendChild($author); $entry->appendChild($author);
$dfrnowner = self::add_entry_author($doc, "dfrn:owner", $item["owner-link"], $item); $dfrnowner = self::addEntryAuthor($doc, "dfrn:owner", $item["owner-link"], $item);
$entry->appendChild($dfrnowner); $entry->appendChild($dfrnowner);
if (($item['parent'] != $item['id']) || ($item['parent-uri'] !== $item['uri']) || (($item['thr-parent'] !== '') && ($item['thr-parent'] !== $item['uri']))) { if (($item['parent'] != $item['id']) || ($item['parent-uri'] !== $item['uri']) || (($item['thr-parent'] !== '') && ($item['thr-parent'] !== $item['uri']))) {
@ -1041,12 +1042,12 @@ class DFRN
XML::addElement($doc, $entry, "activity:object-type", ACTIVITY_OBJ_COMMENT); XML::addElement($doc, $entry, "activity:object-type", ACTIVITY_OBJ_COMMENT);
} }
$actobj = self::create_activity($doc, "activity:object", $item['object']); $actobj = self::createActivity($doc, "activity:object", $item['object']);
if ($actobj) { if ($actobj) {
$entry->appendChild($actobj); $entry->appendChild($actobj);
} }
$actarg = self::create_activity($doc, "activity:target", $item['target']); $actarg = self::createActivity($doc, "activity:target", $item['target']);
if ($actarg) { if ($actarg) {
$entry->appendChild($actarg); $entry->appendChild($actarg);
} }
@ -1099,7 +1100,7 @@ class DFRN
} }
} }
self::get_attachment($doc, $entry, $item); self::getAttachment($doc, $entry, $item);
return $entry; return $entry;
} }
@ -1112,7 +1113,7 @@ class DFRN
* *
* @return string encrypted data * @return string encrypted data
*/ */
private static function aes_encrypt($data, $key) private static function aesEncrypt($data, $key)
{ {
return openssl_encrypt($data, 'aes-128-ecb', $key, OPENSSL_RAW_DATA); return openssl_encrypt($data, 'aes-128-ecb', $key, OPENSSL_RAW_DATA);
} }
@ -1125,7 +1126,7 @@ class DFRN
* *
* @return string decrypted data * @return string decrypted data
*/ */
public static function aes_decrypt($encrypted, $key) public static function aesDecrypt($encrypted, $key)
{ {
return openssl_decrypt($encrypted, 'aes-128-ecb', $key, OPENSSL_RAW_DATA); return openssl_decrypt($encrypted, 'aes-128-ecb', $key, OPENSSL_RAW_DATA);
} }
@ -1291,7 +1292,7 @@ class DFRN
case 1: case 1:
// Deprecated rino version! // Deprecated rino version!
$key = openssl_random_pseudo_bytes(16); $key = openssl_random_pseudo_bytes(16);
$data = self::aes_encrypt($postvars['data'], $key); $data = self::aesEncrypt($postvars['data'], $key);
break; break;
case 2: case 2:
// RINO 2 based on php-encryption // RINO 2 based on php-encryption
@ -1392,9 +1393,10 @@ class DFRN
* *
* @param array $contact Contact record * @param array $contact Contact record
* @param string $birthday Birthday of the contact * @param string $birthday Birthday of the contact
* @return void
* @todo Add array type-hint for $contact * @todo Add array type-hint for $contact
*/ */
private static function birthday_event($contact, $birthday) private static function birthdayEvent($contact, $birthday)
{ {
// Check for duplicates // Check for duplicates
$r = q( $r = q(
@ -1412,7 +1414,7 @@ class DFRN
logger("updating birthday: ".$birthday." for contact ".$contact["id"]); logger("updating birthday: ".$birthday." for contact ".$contact["id"]);
$bdtext = sprintf(t("%s\'s birthday"), $contact["name"]); $bdtext = sprintf(t("%s\'s birthday"), $contact["name"]);
$bdtext2 = sprintf(t("Happy Birthday %s"), " [url=".$contact["url"]."]".$contact["name"]."[/url]") ; $bdtext2 = sprintf(t("Happy Birthday %s"), " [url=".$contact["url"]."]".$contact["name"]."[/url]");
$r = q( $r = q(
"INSERT INTO `event` (`uid`,`cid`,`created`,`edited`,`start`,`finish`,`summary`,`desc`,`type`) "INSERT INTO `event` (`uid`,`cid`,`created`,`edited`,`start`,`finish`,`summary`,`desc`,`type`)
@ -1437,6 +1439,7 @@ class DFRN
* @param array $importer Record of the importer user mixed with contact of the content * @param array $importer Record of the importer user mixed with contact of the content
* @param string $element Element name from which the data is fetched * @param string $element Element name from which the data is fetched
* @param bool $onlyfetch Should the data only be fetched or should it update the contact record as well * @param bool $onlyfetch Should the data only be fetched or should it update the contact record as well
* @param string $xml optional, default empty
* *
* @return Returns an array with relevant data of the author * @return Returns an array with relevant data of the author
* @todo Find good type-hints for all parameter * @todo Find good type-hints for all parameter
@ -1474,10 +1477,10 @@ class DFRN
$avatarlist = array(); $avatarlist = array();
/// @todo check if "avatar" or "photo" would be the best field in the specification /// @todo check if "avatar" or "photo" would be the best field in the specification
$avatars = $xpath->query($element."/atom:link[@rel='avatar']", $context); $avatars = $xpath->query($element."/atom:link[@rel='avatar']", $context);
foreach ($avatars AS $avatar) { foreach ($avatars as $avatar) {
$href = ""; $href = "";
$width = 0; $width = 0;
foreach ($avatar->attributes AS $attributes) { foreach ($avatar->attributes as $attributes) {
/// @TODO Rewrite these similar if () to one switch /// @TODO Rewrite these similar if () to one switch
if ($attributes->name == "href") { if ($attributes->name == "href") {
$href = $attributes->textContent; $href = $attributes->textContent;
@ -1505,14 +1508,14 @@ class DFRN
// When was the last change to name or uri? // When was the last change to name or uri?
$name_element = $xpath->query($element . "/atom:name", $context)->item(0); $name_element = $xpath->query($element . "/atom:name", $context)->item(0);
foreach ($name_element->attributes AS $attributes) { foreach ($name_element->attributes as $attributes) {
if ($attributes->name == "updated") { if ($attributes->name == "updated") {
$poco["name-date"] = $attributes->textContent; $poco["name-date"] = $attributes->textContent;
} }
} }
$link_element = $xpath->query($element . "/atom:link", $context)->item(0); $link_element = $xpath->query($element . "/atom:link", $context)->item(0);
foreach ($link_element->attributes AS $attributes) { foreach ($link_element->attributes as $attributes) {
if ($attributes->name == "updated") { if ($attributes->name == "updated") {
$poco["uri-date"] = $attributes->textContent; $poco["uri-date"] = $attributes->textContent;
} }
@ -1571,7 +1574,7 @@ class DFRN
// Save the keywords into the contact table // Save the keywords into the contact table
$tags = array(); $tags = array();
$tagelements = $xpath->evaluate($element . "/poco:tags/text()", $context); $tagelements = $xpath->evaluate($element . "/poco:tags/text()", $context);
foreach ($tagelements AS $tag) { foreach ($tagelements as $tag) {
$tags[$tag->nodeValue] = $tag->nodeValue; $tags[$tag->nodeValue] = $tag->nodeValue;
} }
@ -1608,12 +1611,12 @@ class DFRN
$contact = array_merge($contact, $poco); $contact = array_merge($contact, $poco);
if ($old_bdyear != $contact["bdyear"]) { if ($old_bdyear != $contact["bdyear"]) {
self::birthday_event($contact, $birthday); self::birthdayEvent($contact, $birthday);
} }
// Get all field names // Get all field names
$fields = array(); $fields = array();
foreach ($r[0] AS $field => $data) { foreach ($r[0] as $field => $data) {
$fields[$field] = $data; $fields[$field] = $data;
} }
@ -1626,14 +1629,14 @@ class DFRN
// Update check for this field has to be done differently // Update check for this field has to be done differently
$datefields = array("name-date", "uri-date"); $datefields = array("name-date", "uri-date");
foreach ($datefields AS $field) { foreach ($datefields as $field) {
if (strtotime($contact[$field]) > strtotime($r[0][$field])) { if (strtotime($contact[$field]) > strtotime($r[0][$field])) {
logger("Difference for contact " . $contact["id"] . " in field '" . $field . "'. New value: '" . $contact[$field] . "', old value '" . $r[0][$field] . "'", LOGGER_DEBUG); logger("Difference for contact " . $contact["id"] . " in field '" . $field . "'. New value: '" . $contact[$field] . "', old value '" . $r[0][$field] . "'", LOGGER_DEBUG);
$update = true; $update = true;
} }
} }
foreach ($fields AS $field => $data) { foreach ($fields as $field => $data) {
if ($contact[$field] != $r[0][$field]) { if ($contact[$field] != $r[0][$field]) {
logger("Difference for contact " . $contact["id"] . " in field '" . $field . "'. New value: '" . $contact[$field] . "', old value '" . $r[0][$field] . "'", LOGGER_DEBUG); logger("Difference for contact " . $contact["id"] . " in field '" . $field . "'. New value: '" . $contact[$field] . "', old value '" . $r[0][$field] . "'", LOGGER_DEBUG);
$update = true; $update = true;
@ -1692,7 +1695,7 @@ class DFRN
* @return string XML string * @return string XML string
* @todo Find good type-hints for all parameter * @todo Find good type-hints for all parameter
*/ */
private static function transform_activity($xpath, $activity, $element) private static function transformActivity($xpath, $activity, $element)
{ {
if (!is_object($activity)) { if (!is_object($activity)) {
return ""; return "";
@ -1743,9 +1746,10 @@ class DFRN
* @param object $xpath XPath object * @param object $xpath XPath object
* @param object $mail mail elements * @param object $mail mail elements
* @param array $importer Record of the importer user mixed with contact of the content * @param array $importer Record of the importer user mixed with contact of the content
* @return void
* @todo Find good type-hints for all parameter * @todo Find good type-hints for all parameter
*/ */
private static function process_mail($xpath, $mail, $importer) private static function processMail($xpath, $mail, $importer)
{ {
logger("Processing mails"); logger("Processing mails");
@ -1794,9 +1798,10 @@ class DFRN
* @param object $xpath XPath object * @param object $xpath XPath object
* @param object $suggestion suggestion elements * @param object $suggestion suggestion elements
* @param array $importer Record of the importer user mixed with contact of the content * @param array $importer Record of the importer user mixed with contact of the content
* @return boolean
* @todo Find good type-hints for all parameter * @todo Find good type-hints for all parameter
*/ */
private static function process_suggestion($xpath, $suggestion, $importer) private static function processSuggestion($xpath, $suggestion, $importer)
{ {
$a = get_app(); $a = get_app();
@ -1903,7 +1908,8 @@ class DFRN
intval(0) intval(0)
); );
notification(array( notification(
array(
"type" => NOTIFY_SUGGEST, "type" => NOTIFY_SUGGEST,
"notify_flags" => $importer["notify-flags"], "notify_flags" => $importer["notify-flags"],
"language" => $importer["language"], "language" => $importer["language"],
@ -1928,9 +1934,10 @@ class DFRN
* @param object $xpath XPath object * @param object $xpath XPath object
* @param object $relocation relocation elements * @param object $relocation relocation elements
* @param array $importer Record of the importer user mixed with contact of the content * @param array $importer Record of the importer user mixed with contact of the content
* @return boolean
* @todo Find good type-hints for all parameter * @todo Find good type-hints for all parameter
*/ */
private static function process_relocation($xpath, $relocation, $importer) private static function processRelocation($xpath, $relocation, $importer)
{ {
logger("Processing relocations"); logger("Processing relocations");
@ -2080,9 +2087,10 @@ class DFRN
* @param array $item the new item record * @param array $item the new item record
* @param array $importer Record of the importer user mixed with contact of the content * @param array $importer Record of the importer user mixed with contact of the content
* @param int $entrytype Is it a toplevel entry, a comment or a relayed comment? * @param int $entrytype Is it a toplevel entry, a comment or a relayed comment?
* @return mixed
* @todo set proper type-hints (array?) * @todo set proper type-hints (array?)
*/ */
private static function update_content($current, $item, $importer, $entrytype) private static function updateContent($current, $item, $importer, $entrytype)
{ {
$changed = false; $changed = false;
@ -2137,7 +2145,7 @@ class DFRN
* @return int Is it a toplevel entry, a comment or a relayed comment? * @return int Is it a toplevel entry, a comment or a relayed comment?
* @todo set proper type-hints (array?) * @todo set proper type-hints (array?)
*/ */
private static function get_entry_type($importer, $item) private static function getEntryType($importer, $item)
{ {
if ($item["parent-uri"] != $item["uri"]) { if ($item["parent-uri"] != $item["uri"]) {
$community = false; $community = false;
@ -2208,9 +2216,10 @@ class DFRN
* @param array $item the new item record * @param array $item the new item record
* @param array $importer Record of the importer user mixed with contact of the content * @param array $importer Record of the importer user mixed with contact of the content
* @param int $posted_id The record number of item record that was just posted * @param int $posted_id The record number of item record that was just posted
* @return void
* @todo set proper type-hints (array?) * @todo set proper type-hints (array?)
*/ */
private static function do_poke($item, $importer, $posted_id) private static function doPoke($item, $importer, $posted_id)
{ {
$verb = urldecode(substr($item["verb"], strpos($item["verb"], "#")+1)); $verb = urldecode(substr($item["verb"], strpos($item["verb"], "#")+1));
if (!$verb) { if (!$verb) {
@ -2245,7 +2254,7 @@ class DFRN
"link" => System::baseUrl()."/display/".urlencode(get_item_guid($posted_id)), "link" => System::baseUrl()."/display/".urlencode(get_item_guid($posted_id)),
"source_name" => stripslashes($item["author-name"]), "source_name" => stripslashes($item["author-name"]),
"source_link" => $item["author-link"], "source_link" => $item["author-link"],
"source_photo" => ((link_compare($item["author-link"],$importer["url"])) "source_photo" => ((link_compare($item["author-link"], $importer["url"]))
? $importer["thumb"] : $item["author-avatar"]), ? $importer["thumb"] : $item["author-avatar"]),
"verb" => $item["verb"], "verb" => $item["verb"],
"otype" => "person", "otype" => "person",
@ -2267,7 +2276,7 @@ class DFRN
* @return bool Should the processing of the entries be continued? * @return bool Should the processing of the entries be continued?
* @todo set proper type-hints (array?) * @todo set proper type-hints (array?)
*/ */
private static function process_verbs($entrytype, $importer, &$item, &$is_like) private static function processVerbs($entrytype, $importer, &$item, &$is_like)
{ {
logger("Process verb ".$item["verb"]." and object-type ".$item["object-type"]." for entrytype ".$entrytype, LOGGER_DEBUG); logger("Process verb ".$item["verb"]." and object-type ".$item["object-type"]." for entrytype ".$entrytype, LOGGER_DEBUG);
@ -2338,7 +2347,6 @@ class DFRN
} }
if (($item["verb"] == ACTIVITY_TAG) && ($item["object-type"] == ACTIVITY_OBJ_TAGTERM)) { if (($item["verb"] == ACTIVITY_TAG) && ($item["object-type"] == ACTIVITY_OBJ_TAGTERM)) {
$xo = parse_xml_string($item["object"], false); $xo = parse_xml_string($item["object"], false);
$xt = parse_xml_string($item["target"], false); $xt = parse_xml_string($item["target"], false);
@ -2356,8 +2364,9 @@ class DFRN
// extract tag, if not duplicate, add to parent item // extract tag, if not duplicate, add to parent item
if ($xo->content) { if ($xo->content) {
if (!(stristr($r[0]["tag"],trim($xo->content)))) { if (!(stristr($r[0]["tag"], trim($xo->content)))) {
q("UPDATE `item` SET `tag` = '%s' WHERE `id` = %d", q(
"UPDATE `item` SET `tag` = '%s' WHERE `id` = %d",
dbesc($r[0]["tag"] . (strlen($r[0]["tag"]) ? ',' : '') . '#[url=' . $xo->id . ']'. $xo->content . '[/url]'), dbesc($r[0]["tag"] . (strlen($r[0]["tag"]) ? ',' : '') . '#[url=' . $xo->id . ']'. $xo->content . '[/url]'),
intval($r[0]["id"]) intval($r[0]["id"])
); );
@ -2375,17 +2384,18 @@ class DFRN
* *
* @param object $links link elements * @param object $links link elements
* @param array $item the item record * @param array $item the item record
* @return void
* @todo set proper type-hints * @todo set proper type-hints
*/ */
private static function parse_links($links, &$item) private static function parseLinks($links, &$item)
{ {
$rel = ""; $rel = "";
$href = ""; $href = "";
$type = ""; $type = "";
$length = "0"; $length = "0";
$title = ""; $title = "";
foreach ($links AS $link) { foreach ($links as $link) {
foreach ($link->attributes AS $attributes) { foreach ($link->attributes as $attributes) {
/// @TODO Rewrite these repeated (same) if () statements to a switch() /// @TODO Rewrite these repeated (same) if () statements to a switch()
if ($attributes->name == "href") { if ($attributes->name == "href") {
$href = $attributes->textContent; $href = $attributes->textContent;
@ -2428,9 +2438,11 @@ class DFRN
* @param object $xpath XPath object * @param object $xpath XPath object
* @param object $entry entry elements * @param object $entry entry elements
* @param array $importer Record of the importer user mixed with contact of the content * @param array $importer Record of the importer user mixed with contact of the content
* @param object $xml xml
* @return void
* @todo Add type-hints * @todo Add type-hints
*/ */
private static function process_entry($header, $xpath, $entry, $importer, $xml) private static function processEntry($header, $xpath, $entry, $importer, $xml)
{ {
logger("Processing entries"); logger("Processing entries");
@ -2527,7 +2539,7 @@ class DFRN
$notice_info = $xpath->query("statusnet:notice_info", $entry); $notice_info = $xpath->query("statusnet:notice_info", $entry);
if ($notice_info && ($notice_info->length > 0)) { if ($notice_info && ($notice_info->length > 0)) {
foreach ($notice_info->item(0)->attributes AS $attributes) { foreach ($notice_info->item(0)->attributes as $attributes) {
if ($attributes->name == "source") { if ($attributes->name == "source") {
$item["app"] = strip_tags($attributes->textContent); $item["app"] = strip_tags($attributes->textContent);
} }
@ -2549,7 +2561,7 @@ class DFRN
} }
$object = $xpath->query("activity:object", $entry)->item(0); $object = $xpath->query("activity:object", $entry)->item(0);
$item["object"] = self::transform_activity($xpath, $object, "object"); $item["object"] = self::transformActivity($xpath, $object, "object");
if (trim($item["object"]) != "") { if (trim($item["object"]) != "") {
$r = parse_xml_string($item["object"], false); $r = parse_xml_string($item["object"], false);
@ -2559,14 +2571,14 @@ class DFRN
} }
$target = $xpath->query("activity:target", $entry)->item(0); $target = $xpath->query("activity:target", $entry)->item(0);
$item["target"] = self::transform_activity($xpath, $target, "target"); $item["target"] = self::transformActivity($xpath, $target, "target");
$categories = $xpath->query("atom:category", $entry); $categories = $xpath->query("atom:category", $entry);
if ($categories) { if ($categories) {
foreach ($categories AS $category) { foreach ($categories as $category) {
$term = ""; $term = "";
$scheme = ""; $scheme = "";
foreach ($category->attributes AS $attributes) { foreach ($category->attributes as $attributes) {
if ($attributes->name == "term") { if ($attributes->name == "term") {
$term = $attributes->textContent; $term = $attributes->textContent;
} }
@ -2596,14 +2608,14 @@ class DFRN
$links = $xpath->query("atom:link", $entry); $links = $xpath->query("atom:link", $entry);
if ($links) { if ($links) {
self::parse_links($links, $item); self::parseLinks($links, $item);
} }
$item['conversation-uri'] = $xpath->query('ostatus:conversation/text()', $entry)->item(0)->nodeValue; $item['conversation-uri'] = $xpath->query('ostatus:conversation/text()', $entry)->item(0)->nodeValue;
$conv = $xpath->query('ostatus:conversation', $entry); $conv = $xpath->query('ostatus:conversation', $entry);
if (is_object($conv->item(0))) { if (is_object($conv->item(0))) {
foreach ($conv->item(0)->attributes AS $attributes) { foreach ($conv->item(0)->attributes as $attributes) {
if ($attributes->name == "ref") { if ($attributes->name == "ref") {
$item['conversation-uri'] = $attributes->textContent; $item['conversation-uri'] = $attributes->textContent;
} }
@ -2618,7 +2630,7 @@ class DFRN
$inreplyto = $xpath->query("thr:in-reply-to", $entry); $inreplyto = $xpath->query("thr:in-reply-to", $entry);
if (is_object($inreplyto->item(0))) { if (is_object($inreplyto->item(0))) {
foreach ($inreplyto->item(0)->attributes AS $attributes) { foreach ($inreplyto->item(0)->attributes as $attributes) {
if ($attributes->name == "ref") { if ($attributes->name == "ref") {
$item["parent-uri"] = $attributes->textContent; $item["parent-uri"] = $attributes->textContent;
} }
@ -2626,7 +2638,7 @@ class DFRN
} }
// Get the type of the item (Top level post, reply or remote reply) // Get the type of the item (Top level post, reply or remote reply)
$entrytype = self::get_entry_type($importer, $item); $entrytype = self::getEntryType($importer, $item);
// Now assign the rest of the values that depend on the type of the message // Now assign the rest of the values that depend on the type of the message
if (in_array($entrytype, array(DFRN_REPLY, DFRN_REPLY_RC))) { if (in_array($entrytype, array(DFRN_REPLY, DFRN_REPLY_RC))) {
@ -2699,14 +2711,14 @@ class DFRN
} }
} }
if (!self::process_verbs($entrytype, $importer, $item, $is_like)) { if (!self::processVerbs($entrytype, $importer, $item, $is_like)) {
logger("Exiting because 'process_verbs' told us so", LOGGER_DEBUG); logger("Exiting because 'processVerbs' told us so", LOGGER_DEBUG);
return; return;
} }
// Update content if 'updated' changes // Update content if 'updated' changes
if (DBM::is_result($current)) { if (DBM::is_result($current)) {
if (self::update_content($r[0], $item, $importer, $entrytype)) { if (self::updateContent($r[0], $item, $importer, $entrytype)) {
logger("Item ".$item["uri"]." was updated.", LOGGER_DEBUG); logger("Item ".$item["uri"]." was updated.", LOGGER_DEBUG);
} else { } else {
logger("Item ".$item["uri"]." already existed.", LOGGER_DEBUG); logger("Item ".$item["uri"]." already existed.", LOGGER_DEBUG);
@ -2783,8 +2795,9 @@ class DFRN
logger("Item was stored with id ".$posted_id, LOGGER_DEBUG); logger("Item was stored with id ".$posted_id, LOGGER_DEBUG);
if (stristr($item["verb"],ACTIVITY_POKE)) if (stristr($item["verb"], ACTIVITY_POKE)) {
self::do_poke($item, $importer, $posted_id); self::doPoke($item, $importer, $posted_id);
}
} }
} }
@ -2794,13 +2807,14 @@ class DFRN
* @param object $xpath XPath object * @param object $xpath XPath object
* @param object $deletion deletion elements * @param object $deletion deletion elements
* @param array $importer Record of the importer user mixed with contact of the content * @param array $importer Record of the importer user mixed with contact of the content
* @return void
* @todo set proper type-hints * @todo set proper type-hints
*/ */
private static function process_deletion($xpath, $deletion, $importer) private static function processDeletion($xpath, $deletion, $importer)
{ {
logger("Processing deletions"); logger("Processing deletions");
foreach ($deletion->attributes AS $attributes) { foreach ($deletion->attributes as $attributes) {
if ($attributes->name == "ref") { if ($attributes->name == "ref") {
$uri = $attributes->textContent; $uri = $attributes->textContent;
} }
@ -2832,7 +2846,7 @@ class DFRN
} else { } else {
$item = $r[0]; $item = $r[0];
$entrytype = self::get_entry_type($importer, $item); $entrytype = self::getEntryType($importer, $item);
if (!$item["deleted"]) { if (!$item["deleted"]) {
logger('deleting item '.$item["id"].' uri='.$uri, LOGGER_DEBUG); logger('deleting item '.$item["id"].' uri='.$uri, LOGGER_DEBUG);
@ -2846,7 +2860,6 @@ class DFRN
} }
if (($item["verb"] == ACTIVITY_TAG) && ($item["object-type"] == ACTIVITY_OBJ_TAGTERM)) { if (($item["verb"] == ACTIVITY_TAG) && ($item["object-type"] == ACTIVITY_OBJ_TAGTERM)) {
$xo = parse_xml_string($item["object"], false); $xo = parse_xml_string($item["object"], false);
$xt = parse_xml_string($item["target"], false); $xt = parse_xml_string($item["target"], false);
@ -3017,8 +3030,8 @@ class DFRN
// We are processing relocations even if we are ignoring a contact // We are processing relocations even if we are ignoring a contact
$relocations = $xpath->query("/atom:feed/dfrn:relocate"); $relocations = $xpath->query("/atom:feed/dfrn:relocate");
foreach ($relocations AS $relocation) { foreach ($relocations as $relocation) {
self::process_relocation($xpath, $relocation, $importer); self::processRelocation($xpath, $relocation, $importer);
} }
if ($importer["readonly"]) { if ($importer["readonly"]) {
@ -3029,29 +3042,29 @@ class DFRN
} }
$mails = $xpath->query("/atom:feed/dfrn:mail"); $mails = $xpath->query("/atom:feed/dfrn:mail");
foreach ($mails AS $mail) { foreach ($mails as $mail) {
self::process_mail($xpath, $mail, $importer); self::processMail($xpath, $mail, $importer);
} }
$suggestions = $xpath->query("/atom:feed/dfrn:suggest"); $suggestions = $xpath->query("/atom:feed/dfrn:suggest");
foreach ($suggestions AS $suggestion) { foreach ($suggestions as $suggestion) {
self::process_suggestion($xpath, $suggestion, $importer); self::processSuggestion($xpath, $suggestion, $importer);
} }
$deletions = $xpath->query("/atom:feed/at:deleted-entry"); $deletions = $xpath->query("/atom:feed/at:deleted-entry");
foreach ($deletions AS $deletion) { foreach ($deletions as $deletion) {
self::process_deletion($xpath, $deletion, $importer); self::processDeletion($xpath, $deletion, $importer);
} }
if (!$sort_by_date) { if (!$sort_by_date) {
$entries = $xpath->query("/atom:feed/atom:entry"); $entries = $xpath->query("/atom:feed/atom:entry");
foreach ($entries AS $entry) { foreach ($entries as $entry) {
self::process_entry($header, $xpath, $entry, $importer, $xml); self::processEntry($header, $xpath, $entry, $importer, $xml);
} }
} else { } else {
$newentries = array(); $newentries = array();
$entries = $xpath->query("/atom:feed/atom:entry"); $entries = $xpath->query("/atom:feed/atom:entry");
foreach ($entries AS $entry) { foreach ($entries as $entry) {
$created = $xpath->query("atom:published/text()", $entry)->item(0)->nodeValue; $created = $xpath->query("atom:published/text()", $entry)->item(0)->nodeValue;
$newentries[strtotime($created)] = $entry; $newentries[strtotime($created)] = $entry;
} }
@ -3059,8 +3072,8 @@ class DFRN
// Now sort after the publishing date // Now sort after the publishing date
ksort($newentries); ksort($newentries);
foreach ($newentries AS $entry) { foreach ($newentries as $entry) {
self::process_entry($header, $xpath, $entry, $importer, $xml); self::processEntry($header, $xpath, $entry, $importer, $xml);
} }
} }
logger("Import done for user " . $importer["uid"] . " from contact " . $importer["id"], LOGGER_DEBUG); logger("Import done for user " . $importer["uid"] . " from contact " . $importer["id"], LOGGER_DEBUG);

File diff suppressed because it is too large Load diff

View file

@ -298,6 +298,7 @@ class OStatus
* @param array $importer user record of the importing user * @param array $importer user record of the importing user
* @param array $contact contact * @param array $contact contact
* @param string $hub Called by reference, returns the fetched hub data * @param string $hub Called by reference, returns the fetched hub data
* @return void
*/ */
public static function import($xml, $importer, &$contact, &$hub) public static function import($xml, $importer, &$contact, &$hub)
{ {
@ -309,7 +310,7 @@ class OStatus
* *
* @param string $xml The XML * @param string $xml The XML
* @param array $importer user record of the importing user * @param array $importer user record of the importing user
* @param array $contact * @param array $contact contact
* @param string $hub Called by reference, returns the fetched hub data * @param string $hub Called by reference, returns the fetched hub data
* @param boolean $stored Is the post fresh imported or from the database? * @param boolean $stored Is the post fresh imported or from the database?
* @param boolean $initialize Is it the leading post so that data has to be initialized? * @param boolean $initialize Is it the leading post so that data has to be initialized?
@ -537,6 +538,10 @@ class OStatus
return true; return true;
} }
/**
* @param object $item item
* @return void
*/
private static function deleteNotice($item) private static function deleteNotice($item)
{ {
$condition = array('uid' => $item['uid'], 'author-link' => $item['author-link'], 'uri' => $item['uri']); $condition = array('uid' => $item['uid'], 'author-link' => $item['author-link'], 'uri' => $item['uri']);
@ -567,6 +572,7 @@ class OStatus
* @param object $entry The xml entry that is processed * @param object $entry The xml entry that is processed
* @param array $item The item array * @param array $item The item array
* @param array $importer user record of the importing user * @param array $importer user record of the importing user
* @return void
*/ */
private static function processPost($xpath, $entry, &$item, $importer) private static function processPost($xpath, $entry, &$item, $importer)
{ {
@ -708,6 +714,7 @@ class OStatus
* *
* @param string $conversation The link to the conversation * @param string $conversation The link to the conversation
* @param string $conversation_uri The conversation in "uri" format * @param string $conversation_uri The conversation in "uri" format
* @return void
*/ */
private static function fetchConversation($conversation, $conversation_uri) private static function fetchConversation($conversation, $conversation_uri)
{ {
@ -768,6 +775,7 @@ class OStatus
* @param string $xml The feed * @param string $xml The feed
* @param string $conversation conversation * @param string $conversation conversation
* @param string $conversation_uri conversation uri * @param string $conversation_uri conversation uri
* @return void
*/ */
private static function storeConversation($xml, $conversation = '', $conversation_uri = '') private static function storeConversation($xml, $conversation = '', $conversation_uri = '')
{ {
@ -844,13 +852,14 @@ class OStatus
/** /**
* @brief Fetch the own post so that it can be stored later * @brief Fetch the own post so that it can be stored later
* @param array $item The item array
* *
* We want to store the original data for later processing. * We want to store the original data for later processing.
* This function is meant for cases where we process a feed with multiple entries. * This function is meant for cases where we process a feed with multiple entries.
* In that case we need to fetch the single posts here. * In that case we need to fetch the single posts here.
* *
* @param string $self The link to the self item * @param string $self The link to the self item
* @param array $item The item array
* @return void
*/ */
private static function fetchSelf($self, &$item) private static function fetchSelf($self, &$item)
{ {
@ -885,6 +894,7 @@ class OStatus
* @param string $related The link to the related item * @param string $related The link to the related item
* @param string $related_uri The related item in "uri" format * @param string $related_uri The related item in "uri" format
* @param array $importer user record of the importing user * @param array $importer user record of the importing user
* @return void
*/ */
private static function fetchRelated($related, $related_uri, $importer) private static function fetchRelated($related, $related_uri, $importer)
{ {
@ -1293,6 +1303,7 @@ class OStatus
* @param object $doc XML document * @param object $doc XML document
* @param object $root XML root element where the hub links are added * @param object $root XML root element where the hub links are added
* @param object $nick nick * @param object $nick nick
* @return void
*/ */
public static function hublinks($doc, $root, $nick) public static function hublinks($doc, $root, $nick)
{ {
@ -1306,6 +1317,7 @@ class OStatus
* @param object $doc XML document * @param object $doc XML document
* @param object $root XML root element where the hub links are added * @param object $root XML root element where the hub links are added
* @param array $item Data of the item that is to be posted * @param array $item Data of the item that is to be posted
* @return void
*/ */
private static function getAttachment($doc, $root, $item) private static function getAttachment($doc, $root, $item)
{ {
@ -1582,7 +1594,7 @@ class OStatus
* @param object $doc XML document * @param object $doc XML document
* @param array $item Data of the item that is to be posted * @param array $item Data of the item that is to be posted
* @param array $owner Contact data of the poster * @param array $owner Contact data of the poster
* @param $repeated_guid * @param string $repeated_guid guid
* @param bool $toplevel Is it for en entry element (false) or a feed entry (true)? * @param bool $toplevel Is it for en entry element (false) or a feed entry (true)?
* *
* @return object Entry element * @return object Entry element
@ -1872,6 +1884,7 @@ class OStatus
* @param string $title Title for the post * @param string $title Title for the post
* @param string $verb The activity verb * @param string $verb The activity verb
* @param bool $complete Add the "status_net" element? * @param bool $complete Add the "status_net" element?
* @return void
*/ */
private static function entryContent($doc, $entry, $item, $owner, $title, $verb = "", $complete = true) private static function entryContent($doc, $entry, $item, $owner, $title, $verb = "", $complete = true)
{ {
@ -1914,6 +1927,7 @@ class OStatus
* @param array $item Data of the item that is to be posted * @param array $item Data of the item that is to be posted
* @param array $owner Contact data of the poster * @param array $owner Contact data of the poster
* @param bool $complete default true * @param bool $complete default true
* @return void
*/ */
private static function entryFooter($doc, $entry, $item, $owner, $complete = true) private static function entryFooter($doc, $entry, $item, $owner, $complete = true)
{ {

305
src/Util/ExAuth.php Normal file
View file

@ -0,0 +1,305 @@
<?php
/*
* ejabberd extauth script for the integration with friendica
*
* Originally written for joomla by Dalibor Karlovic <dado@krizevci.info>
* modified for Friendica by Michael Vogel <icarus@dabo.de>
* published under GPL
*
* Latest version of the original script for joomla is available at:
* http://87.230.15.86/~dado/ejabberd/joomla-login
*
* Installation:
*
* - Change it's owner to whichever user is running the server, ie. ejabberd
* $ chown ejabberd:ejabberd /path/to/friendica/scripts/auth_ejabberd.php
*
* - Change the access mode so it is readable only to the user ejabberd and has exec
* $ chmod 700 /path/to/friendica/scripts/auth_ejabberd.php
*
* - Edit your ejabberd.cfg file, comment out your auth_method and add:
* {auth_method, external}.
* {extauth_program, "/path/to/friendica/script/auth_ejabberd.php"}.
*
* - Restart your ejabberd service, you should be able to login with your friendica auth info
*
* Other hints:
* - if your users have a space or a @ in their nickname, they'll run into trouble
* registering with any client so they should be instructed to replace these chars
* " " (space) is replaced with "%20"
* "@" is replaced with "(a)"
*
*/
namespace Friendica\Util;
use Friendica\Core\Config;
use Friendica\Core\PConfig;
use Friendica\Database\DBM;
use dba;
require_once 'include/dba.php';
class ExAuth
{
private $bDebug;
/**
* @brief Create the class
*
* @param boolean $bDebug Debug mode
*/
public function __construct()
{
$this->bDebug = (int) Config::get('jabber', 'debug');
openlog('auth_ejabberd', LOG_PID, LOG_USER);
$this->writeLog(LOG_NOTICE, 'start');
}
/**
* @brief Standard input reading function, executes the auth with the provided
* parameters
*
* @return null
*/
public function readStdin()
{
while (!feof(STDIN)) {
// Quit if the database connection went down
if (!dba::connected()) {
$this->writeLog(LOG_ERR, 'the database connection went down');
return;
}
$iHeader = fgets(STDIN, 3);
$aLength = unpack('n', $iHeader);
$iLength = $aLength['1'];
// No data? Then quit
if ($iLength == 0) {
$this->writeLog(LOG_ERR, 'we got no data, quitting');
return;
}
// Fetching the data
$sData = fgets(STDIN, $iLength + 1);
$this->writeLog(LOG_DEBUG, 'received data: ' . $sData);
$aCommand = explode(':', $sData);
if (is_array($aCommand)) {
switch ($aCommand[0]) {
case 'isuser':
// Check the existance of a given username
$this->isUser($aCommand);
break;
case 'auth':
// Check if the givven password is correct
$this->auth($aCommand);
break;
case 'setpass':
// We don't accept the setting of passwords here
$this->writeLog(LOG_NOTICE, 'setpass command disabled');
fwrite(STDOUT, pack('nn', 2, 0));
break;
default:
// We don't know the given command
$this->writeLog(LOG_NOTICE, 'unknown command ' . $aCommand[0]);
fwrite(STDOUT, pack('nn', 2, 0));
break;
}
} else {
$this->writeLog(LOG_NOTICE, 'invalid command string ' . $sData);
fwrite(STDOUT, pack('nn', 2, 0));
}
}
}
/**
* @brief Check if the given username exists
*
* @param array $aCommand The command array
*/
private function isUser(array $aCommand)
{
$a = get_app();
// Check if there is a username
if (!isset($aCommand[1])) {
$this->writeLog(LOG_NOTICE, 'invalid isuser command, no username given');
fwrite(STDOUT, pack('nn', 2, 0));
return;
}
// Now we check if the given user is valid
$sUser = str_replace(array('%20', '(a)'), array(' ', '@'), $aCommand[1]);
// Does the hostname match? So we try directly
if ($a->get_hostname() == $aCommand[2]) {
$this->writeLog(LOG_INFO, 'internal user check for ' . $sUser . '@' . $aCommand[2]);
$found = dba::exists('user', ['nickname' => $sUser]);
} else {
$found = false;
}
// If the hostnames doesn't match or there is some failure, we try to check remotely
if (!$found) {
$found = $this->checkUser($aCommand[2], $aCommand[1], true);
}
if ($found) {
// The user is okay
$this->writeLog(LOG_NOTICE, 'valid user: ' . $sUser);
fwrite(STDOUT, pack('nn', 2, 1));
} else {
// The user isn't okay
$this->writeLog(LOG_WARNING, 'invalid user: ' . $sUser);
fwrite(STDOUT, pack('nn', 2, 0));
}
}
/**
* @brief Check remote user existance via HTTP(S)
*
* @param string $host The hostname
* @param string $user Username
* @param boolean $ssl Should the check be done via SSL?
*
* @return boolean Was the user found?
*/
private function checkUser($host, $user, $ssl)
{
$this->writeLog(LOG_INFO, 'external user check for ' . $user . '@' . $host);
$url = ($ssl ? 'https' : 'http') . '://' . $host . '/noscrape/' . $user;
$data = z_fetch_url($url);
if (!is_array($data)) {
return false;
}
if ($data['return_code'] != '200') {
return false;
}
$json = @json_decode($data['body']);
if (!is_object($json)) {
return false;
}
return $json->nick == $user;
}
/**
* @brief Authenticate the given user and password
*
* @param array $aCommand The command array
*/
private function auth(array $aCommand)
{
$a = get_app();
// check user authentication
if (sizeof($aCommand) != 4) {
$this->writeLog(LOG_NOTICE, 'invalid auth command, data missing');
fwrite(STDOUT, pack('nn', 2, 0));
return;
}
// We now check if the password match
$sUser = str_replace(array('%20', '(a)'), array(' ', '@'), $aCommand[1]);
// Does the hostname match? So we try directly
if ($a->get_hostname() == $aCommand[2]) {
$this->writeLog(LOG_INFO, 'internal auth for ' . $sUser . '@' . $aCommand[2]);
$aUser = dba::select('user', ['uid', 'password'], ['nickname' => $sUser], ['limit' => 1]);
if (DBM::is_result($aUser)) {
$uid = $aUser['uid'];
$Error = $aUser['password'] != hash('whirlpool', $aCommand[3]);
} else {
$this->writeLog(LOG_WARNING, 'user not found: ' . $sUser);
$Error = true;
$uid = -1;
}
if ($Error) {
$this->writeLog(LOG_INFO, 'check against alternate password for ' . $sUser . '@' . $aCommand[2]);
$sPassword = PConfig::get($uid, 'xmpp', 'password', null, true);
$Error = ($aCommand[3] != $sPassword);
}
} else {
$Error = true;
}
// If the hostnames doesn't match or there is some failure, we try to check remotely
if ($Error) {
$Error = !$this->checkCredentials($aCommand[2], $aCommand[1], $aCommand[3], true);
}
if ($Error) {
$this->writeLog(LOG_WARNING, 'authentification failed for user ' . $sUser . '@' . $aCommand[2]);
fwrite(STDOUT, pack('nn', 2, 0));
} else {
$this->writeLog(LOG_NOTICE, 'authentificated user ' . $sUser . '@' . $aCommand[2]);
fwrite(STDOUT, pack('nn', 2, 1));
}
}
/**
* @brief Check remote credentials via HTTP(S)
*
* @param string $host The hostname
* @param string $user Username
* @param string $password Password
* @param boolean $ssl Should the check be done via SSL?
*
* @return boolean Are the credentials okay?
*/
private function checkCredentials($host, $user, $password, $ssl)
{
$url = ($ssl ? 'https' : 'http') . '://' . $host . '/api/account/verify_credentials.json';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $user . ':' . $password);
curl_exec($ch);
$curl_info = @curl_getinfo($ch);
$http_code = $curl_info['http_code'];
curl_close($ch);
$this->writeLog(LOG_INFO, 'external auth for ' . $user . '@' . $host . ' returned ' . $http_code);
return $http_code == 200;
}
/**
* @brief write data to the syslog
*
* @param integer $loglevel The syslog loglevel
* @param string $sMessage The syslog message
*/
private function writeLog($loglevel, $sMessage)
{
if (!$this->bDebug && ($loglevel >= LOG_DEBUG)) {
return;
}
syslog($loglevel, $sMessage);
}
/**
* @brief destroy the class, close the syslog connection.
*/
public function __destruct()
{
$this->writeLog(LOG_NOTICE, 'stop');
closelog();
}
}

View file

@ -155,14 +155,15 @@ class CronJobs {
if (!$cachetime) { if (!$cachetime) {
$cachetime = PROXY_DEFAULT_TIME; $cachetime = PROXY_DEFAULT_TIME;
} }
q('DELETE FROM `photo` WHERE `uid` = 0 AND `resource-id` LIKE "pic:%%" AND `created` < NOW() - INTERVAL %d SECOND', $cachetime); $condition = array('`uid` = 0 AND `resource-id` LIKE "pic:%" AND `created` < NOW() - INTERVAL ? SECOND', $cachetime);
dba::delete('photo', $condition);
} }
// Delete the cached OEmbed entries that are older than one year // Delete the cached OEmbed entries that are older than three month
q("DELETE FROM `oembed` WHERE `created` < NOW() - INTERVAL 3 MONTH"); dba::delete('oembed', array("`created` < NOW() - INTERVAL 3 MONTH"));
// Delete the cached "parse_url" entries that are older than one year // Delete the cached "parse_url" entries that are older than three month
q("DELETE FROM `parsed_url` WHERE `created` < NOW() - INTERVAL 3 MONTH"); dba::delete('parsed_url', array("`created` < NOW() - INTERVAL 3 MONTH"));
// Maximum table size in megabyte // Maximum table size in megabyte
$max_tablesize = intval(Config::get('system','optimize_max_tablesize')) * 1000000; $max_tablesize = intval(Config::get('system','optimize_max_tablesize')) * 1000000;

View file

@ -485,7 +485,7 @@ class Delivery {
break; break;
if ($mail) { if ($mail) {
Diaspora::send_mail($item,$owner,$contact); Diaspora::sendMail($item,$owner,$contact);
break; break;
} }
@ -498,7 +498,7 @@ class Delivery {
if (($target_item['deleted']) && (($target_item['uri'] === $target_item['parent-uri']) || $followup)) { if (($target_item['deleted']) && (($target_item['uri'] === $target_item['parent-uri']) || $followup)) {
// top-level retraction // top-level retraction
logger('diaspora retract: '.$loc); logger('diaspora retract: '.$loc);
Diaspora::send_retraction($target_item,$owner,$contact,$public_message); Diaspora::sendRetraction($target_item,$owner,$contact,$public_message);
break; break;
} elseif ($relocate) { } elseif ($relocate) {
Diaspora::sendAccountMigration($owner, $contact, $uid); Diaspora::sendAccountMigration($owner, $contact, $uid);
@ -506,17 +506,17 @@ class Delivery {
} elseif ($followup) { } elseif ($followup) {
// send comments and likes to owner to relay // send comments and likes to owner to relay
logger('diaspora followup: '.$loc); logger('diaspora followup: '.$loc);
Diaspora::send_followup($target_item,$owner,$contact,$public_message); Diaspora::sendFollowup($target_item,$owner,$contact,$public_message);
break; break;
} elseif ($target_item['uri'] !== $target_item['parent-uri']) { } elseif ($target_item['uri'] !== $target_item['parent-uri']) {
// we are the relay - send comments, likes and relayable_retractions to our conversants // we are the relay - send comments, likes and relayable_retractions to our conversants
logger('diaspora relay: '.$loc); logger('diaspora relay: '.$loc);
Diaspora::send_relay($target_item,$owner,$contact,$public_message); Diaspora::sendRelay($target_item,$owner,$contact,$public_message);
break; break;
} elseif ($top_level && !$walltowall) { } elseif ($top_level && !$walltowall) {
// currently no workable solution for sending walltowall // currently no workable solution for sending walltowall
logger('diaspora status: '.$loc); logger('diaspora status: '.$loc);
Diaspora::send_status($target_item,$owner,$contact,$public_message); Diaspora::sendStatus($target_item,$owner,$contact,$public_message);
break; break;
} }

View file

@ -525,7 +525,7 @@ class Notifier {
if ($diaspora_delivery) { if ($diaspora_delivery) {
if (!$followup) { if (!$followup) {
$r0 = Diaspora::relay_list(); $r0 = Diaspora::relayList();
} }
$r1 = q("SELECT `batch`, ANY_VALUE(`id`) AS `id`, ANY_VALUE(`name`) AS `name`, ANY_VALUE(`network`) AS `network` $r1 = q("SELECT `batch`, ANY_VALUE(`id`) AS `id`, ANY_VALUE(`name`) AS `name`, ANY_VALUE(`network`) AS `network`

View file

@ -14,6 +14,6 @@ class ProfileUpdate {
return; return;
} }
Diaspora::send_profile($uid); Diaspora::sendProfile($uid);
} }
} }

View file

@ -0,0 +1,47 @@
# Bookmarklet-share2friendica
Javascript bookmarklet to share websites with your friendica account
## Getting Started
### Installing
Open the file bookmarklet-share2friendica.js and change 'YourFriendicaDoomain.tld" with your friendica domain
If you friendica is at https://myfriend.myfami.ly/ , the original ...
```javascript
javascript:(function(){f='https://YourFriendicaDomain.tld/bookmarklet/?url='+encodeURIC....
```
... has to be changed to ...
```javascript
javascript:(function(){f='https://myfriend.myfami.ly/bookmarklet/?url='+encodeURIC....
```
*Please copy the whole script, not only the part mentioned here!*
Then create a new bookmark, give it a name like "share2Friendica" and paste the script in the address field. Save it. Now you can click on that bookmarklet every time you want to share a website, you are currently reading. A new small window will open where title is prefilled and the website you want to share is put as attachement in the body of the new post.
## Additional notes if it doesn't work
* Make sure the site you want to share is allowed to run javascript. (enable it in your script blocker)
* Check the apostrophes that are used. Sometimes it is changed by the copy and paste process depending on the editor you are using, or if you copy it from a website. Correct it and it will work again.
## Authors
* **diaspora** - *Initial work* - [Share all teh internetz!](https://share.diasporafoundation.org/about.html)
* **hoergen** - *Adaptation to Friendica (2017)* - [hoergen.org](https://hoergen.org)
## License
This project is licensed under the same license like friendica
## Acknowledgments
* Hat tip to anyone who's code was used
* Hat tip to everyone who does everyday a little something ot make this world better
* Had tip but spent it

View file

@ -0,0 +1 @@
javascript:(function(){f='https://YourFriendicaDomain.tld/bookmarklet/?url='+encodeURIComponent(window.location.href)+'&title='+encodeURIComponent(document.title);a=function(){if(!window.open(f+'&jump=doclose','friendica','location=yes,links=no,scrollbars=no,toolbar=no,width=620,height=250'))location.href=f+'jump=yes'};if(/Firefox/.test(navigator.userAgent)){setTimeout(a,0)}else{a()}})()

65
util/global_community_block.php Executable file
View file

@ -0,0 +1,65 @@
#!/usr/bin/env php
<?php
/**
* @brief tool to block an account from the node
*
* With this tool, you can block an account in such a way, that no postings
* or comments this account writes are accepted to the node.
*
* Usage: pass the URL of the to be blocked account as only parameter
* at the command line when running this tool. E.g.
*
* $> util/global_community_block.php http://example.com/profile/bob
*
* will block bob@example.com.
*
* Author: Tobias Diekershoff
*
* License: AGPLv3 or later, same as Friendica
**/
if ($argc != 2 || $argv[1] == "-h" || $argv[1] == "--help" || $argv[1] == "-?") {
echo "Usage: ".$argv[0]." [-h|profile_url]\r\n";
echo " -h, -?, --help ... show this help\r\n";
echo " profile_url ...... The URL of the profile you want to silence\r\n";
echo "\r\n";
echo "Example: block bob@example.com\r\n";
echo "$> ".$argv[0]." https://example.com/profiles/bob\r\n";
echo "\r\n";
exit(0);
}
use Friendica\Database\DBM;
use Friendica\Network\Probe;
require_once 'boot.php';
require_once 'include/dba.php';
require_once 'include/text.php';
$a = get_app();
require_once '.htconfig.php';
dba::connect($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
/**
* 1. make nurl from last parameter
* 2. check DB (contact) if there is a contact with uid=0 and that nurl, get the ID
* 3. set the flag hidden=1 for the contact entry with the found ID
**/
$net = Probe::uri($argv[1]);
if (in_array($net['network'], array(NETWORK_PHANTOM, NETWORK_MAIL))) {
echo 'This account seems not to exist.';
echo "\r\n";
exit(1);
}
$nurl = normalise_link($net['url']);
$r = dba::select('contact', array('id'), array('nurl' => $nurl, 'uid' => 0), array('limit' => 1));
if (DBM::is_result($r)) {
dba::update('contact', array('blocked' => true), array('id' => $r['id']));
echo "NOTICE: The account should be blocked from the node now\r\n";
} else {
echo "NOTICE: Could not find any entry for this URL (".$nurl.")\r\n";
}
?>

View file

@ -0,0 +1,68 @@
#!/usr/bin/env php
<?php
/**
* @brief tool to silence accounts on the global community page
*
* With this tool, you can silence an account on the global community page.
* Postings from silenced accounts will not be displayed on the community
* page. This silencing does only affect the display on the community page,
* accounts following the silenced accounts will still get their postings.
*
* Usage: pass the URL of the profile to be silenced account as only parameter
* at the command line when running this tool. E.g.
*
* $> util/global_community_silence.php http://example.com/profile/bob
*
* will silence bob@example.com so that his postings won't appear at
* the global community page.
*
* Author: Tobias Diekershoff
*
* License: AGPLv3 or later, same as Friendica
**/
if ($argc != 2 || $argv[1] == "-h" || $argv[1] == "--help" || $argv[1] == "-?") {
echo "Usage: ".$argv[0]." [-h|profile_url]\r\n";
echo " -h, -?, --help ... show this help\r\n";
echo " profile_url ...... The URL of the profile you want to silence\r\n";
echo "\r\n";
echo "Example: Silence bob@example.com\r\n";
echo "$> ".$argv[0]." https://example.com/profiles/bob\r\n";
echo "\r\n";
exit(0);
}
use Friendica\Database\DBM;
use Friendica\Network\Probe;
require_once 'boot.php';
require_once 'include/dba.php';
require_once 'include/text.php';
$a = get_app();
require_once '.htconfig.php';
dba::connect($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
/**
* 1. make nurl from last parameter
* 2. check DB (contact) if there is a contact with uid=0 and that nurl, get the ID
* 3. set the flag hidden=1 for the contact entry with the found ID
**/
$net = Probe::uri($argv[1]);
if (in_array($net['network'], array(NETWORK_PHANTOM, NETWORK_MAIL))) {
echo "This account seems not to exist.";
echo "\r\n";
exit(1);
}
$nurl = normalise_link($net['url']);
$r = dba::select("contact", array("id"), array("nurl" => $nurl, "uid" => 0), array("limit" => 1));
if (DBM::is_result($r)) {
dba::update("contact", array("hidden" => true), array("id" => $r["id"]));
echo "NOTICE: The account should be silenced from the global community page\r\n";
} else {
echo "NOTICE: Could not find any entry for this URL (".$nurl.")\r\n";
}
?>

View file

@ -1,4 +1,3 @@
<div id="contact-edit-wrapper" > <div id="contact-edit-wrapper" >
{{* Insert Tab-Nav *}} {{* Insert Tab-Nav *}}
@ -71,7 +70,7 @@
{{include file="field_checkbox.tpl" field=$notify}} {{include file="field_checkbox.tpl" field=$notify}}
{{if $fetch_further_information}} {{if $fetch_further_information}}
{{include file="field_select.tpl" field=$fetch_further_information}} {{include file="field_select.tpl" field=$fetch_further_information}}
{{if $fetch_further_information.2 == 2 }} {{include file="field_textarea.tpl" field=$ffi_keyword_blacklist}} {{/if}} {{if $fetch_further_information.2 == 2 || $fetch_further_information.2 == 3}} {{include file="field_textarea.tpl" field=$ffi_keyword_blacklist}} {{/if}}
{{/if}} {{/if}}
{{include file="field_checkbox.tpl" field=$hidden}} {{include file="field_checkbox.tpl" field=$hidden}}

View file

@ -134,7 +134,7 @@
{{include file="field_checkbox.tpl" field=$notify}} {{include file="field_checkbox.tpl" field=$notify}}
{{if $fetch_further_information}} {{if $fetch_further_information}}
{{include file="field_select.tpl" field=$fetch_further_information}} {{include file="field_select.tpl" field=$fetch_further_information}}
{{if $fetch_further_information.2 == 2 }} {{include file="field_textarea.tpl" field=$ffi_keyword_blacklist}} {{/if}} {{if $fetch_further_information.2 == 2 || $fetch_further_information.2 == 3}} {{include file="field_textarea.tpl" field=$ffi_keyword_blacklist}} {{/if}}
{{/if}} {{/if}}
{{include file="field_checkbox.tpl" field=$hidden}} {{include file="field_checkbox.tpl" field=$hidden}}

View file

@ -71,7 +71,7 @@
{{include file="field_checkbox.tpl" field=$notify}} {{include file="field_checkbox.tpl" field=$notify}}
{{if $fetch_further_information}} {{if $fetch_further_information}}
{{include file="field_select.tpl" field=$fetch_further_information}} {{include file="field_select.tpl" field=$fetch_further_information}}
{{if $fetch_further_information.2 == 2 }} {{include file="field_textarea.tpl" field=$ffi_keyword_blacklist}} {{/if}} {{if $fetch_further_information.2 == 2 || $fetch_further_information.2 == 3}} {{include file="field_textarea.tpl" field=$ffi_keyword_blacklist}} {{/if}}
{{/if}} {{/if}}
{{include file="field_checkbox.tpl" field=$hidden}} {{include file="field_checkbox.tpl" field=$hidden}}