Merge remote-tracking branch 'upstream/master'
Conflicts: boot.php include/dba/dba_driver.php include/diaspora.php include/follow.php include/session.php include/zot.php mod/photos.php mod/ping.php
This commit is contained in:
94
include/Import/Importer.php
Normal file
94
include/Import/Importer.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php /** @file */
|
||||
|
||||
namespace Redmatrix\Import;
|
||||
|
||||
|
||||
class Import {
|
||||
|
||||
$credentials = null;
|
||||
$itemlist = null;
|
||||
$src_items = null;
|
||||
|
||||
$items = null;
|
||||
|
||||
function get_credentials() {
|
||||
|
||||
}
|
||||
|
||||
function get_itemlist() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
function get_item_ident($item) {
|
||||
|
||||
}
|
||||
|
||||
function get_item($item_ident) {
|
||||
|
||||
}
|
||||
|
||||
function get_taxonomy($item_ident) {
|
||||
|
||||
}
|
||||
|
||||
function get_children($item_ident) {
|
||||
|
||||
}
|
||||
|
||||
function convert_item($item_ident) {
|
||||
|
||||
}
|
||||
|
||||
function convert_taxonomy($item_ident) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
function convert_child($child) {
|
||||
|
||||
}
|
||||
|
||||
function store($item,$update = false) {
|
||||
|
||||
}
|
||||
|
||||
function run() {
|
||||
|
||||
$this->credentials = $this->get_credentials();
|
||||
$this->itemlist = $this->get_itemlist();
|
||||
if($this->itemlist) {
|
||||
$this->src_items = array();
|
||||
$this->items = array();
|
||||
$cnt = 0;
|
||||
foreach($this->itemlist as $item) {
|
||||
$ident = $item->get_item_ident($item);
|
||||
$this->src_items[$ident]['item'] = $this->get_item($ident);
|
||||
$this->src_items[$ident]['taxonomy'] = $this->get_taxonomy($ident);
|
||||
$this->src_items[$ident]['children'] = $this->get_children($ident);
|
||||
$this->items[$cnt]['item'] = $this->convert_item($ident);
|
||||
$this->items[$cnt]['item']['term'] = $this->convert_taxonomy($ident);
|
||||
if($this->src_items[$ident]['children']) {
|
||||
$this->items[$cnt]['children'] = array();
|
||||
foreach($this->src_items[$ident]['children'] as $child) {
|
||||
$this[$cnt]['children'][] = $this->convert_child($child);
|
||||
}
|
||||
}
|
||||
$cnt ++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
282
include/Import/refimport.php
Normal file
282
include/Import/refimport.php
Normal file
@@ -0,0 +1,282 @@
|
||||
<?php
|
||||
|
||||
require_once('include/html2bbcode.php');
|
||||
require_once('include/hubloc.php');
|
||||
|
||||
// Sample module for importing conversation data from Reflection CMS. Some preparation was used to
|
||||
// dump relevant posts, categories and comments into individual JSON files, and also JSON dump of
|
||||
// the user table to search for avatars. Importation was also batched in sets of 20 posts per page
|
||||
// visit so as to survive shared hosting process limits. This provides some clues as how to handle
|
||||
// WordPress imports, which use a somewhat similar DB structure. The batching and individual files
|
||||
// might not be needed in VPS environments. As such this could be considered an extreme test case, but
|
||||
// the importation was successful in all regards using this code. The module URL was visited repeatedly
|
||||
// with a browser until all the posts had been imported.
|
||||
|
||||
|
||||
|
||||
|
||||
define('REDMATRIX_IMPORTCHANNEL','mike');
|
||||
define('REFLECT_EXPORTUSERNAME','mike');
|
||||
define('REFLECT_BLOGNAME','Diary and Other Rantings');
|
||||
define('REFLECT_BASEURL','http://example.com/');
|
||||
define('REFLECT_USERFILE','user.json');
|
||||
|
||||
// set to true if you need to process everything again
|
||||
define('REFLECT_OVERWRITE',false);
|
||||
|
||||
// we'll only process a small number of posts at a time on a shared host.
|
||||
|
||||
define('REFLECT_MAXPERRUN',30);
|
||||
|
||||
function reflect_get_channel() {
|
||||
|
||||
// this will be the channel_address or nickname of the red channel
|
||||
|
||||
$c = q("select * from channel left join xchan on channel_hash = xchan_hash
|
||||
where channel_address = '%s' limit 1",
|
||||
dbesc(REDMATRIX_IMPORTCHANNEL)
|
||||
);
|
||||
return $c[0];
|
||||
}
|
||||
|
||||
|
||||
function refimport_content(&$a) {
|
||||
|
||||
$channel = reflect_get_channel();
|
||||
|
||||
// load the user file. We need that to find the commenter's avatars
|
||||
|
||||
$u = file_get_contents(REFLECT_USERFILE);
|
||||
if($u) {
|
||||
$users = json_decode($u,true);
|
||||
}
|
||||
|
||||
$ignored = 0;
|
||||
$processed = 0;
|
||||
|
||||
$files = glob('article/*');
|
||||
if(! $files)
|
||||
return;
|
||||
|
||||
foreach($files as $f) {
|
||||
$s = file_get_contents($f);
|
||||
$j = json_decode($s,true);
|
||||
|
||||
if(! $j)
|
||||
continue;
|
||||
|
||||
$arr = array();
|
||||
|
||||
// see if this article was already processed
|
||||
$r = q("select * from item where mid = '%s' and uid = %d limit 1",
|
||||
dbesc($j['guid']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if($r) {
|
||||
if(REFLECT_OVERWRITE)
|
||||
$arr['id'] = $r[0]['id'];
|
||||
else {
|
||||
$ignored ++;
|
||||
rename($f,str_replace('article','done',$f));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$arr['uid'] = $channel['channel_account_id'];
|
||||
$arr['aid'] = $channel['channel_id'];
|
||||
$arr['mid'] = $arr['parent_mid'] = $j['guid'];
|
||||
$arr['created'] = $j['created'];
|
||||
$arr['edited'] = $j['edited'];
|
||||
$arr['author_xchan'] = $channel['channel_hash'];
|
||||
$arr['owner_xchan'] = $channel['channel_hash'];
|
||||
$arr['app'] = REFLECT_BLOGNAME;
|
||||
$arr['item_flags'] = ITEM_ORIGIN|ITEM_WALL|ITEM_THREAD_TOP;
|
||||
$arr['verb'] = ACTIVITY_POST;
|
||||
|
||||
// this is an assumption
|
||||
$arr['comment_policy'] = 'contacts';
|
||||
|
||||
|
||||
// import content. In this case the content is XHTML.
|
||||
|
||||
$arr['title'] = html2bbcode($j['title']);
|
||||
$arr['title'] = htmlspecialchars($arr['title'],ENT_COMPAT,'UTF-8',false);
|
||||
|
||||
|
||||
$arr['body'] = html2bbcode($j['body']);
|
||||
$arr['body'] = htmlspecialchars($arr['body'],ENT_COMPAT,'UTF-8',false);
|
||||
|
||||
|
||||
// convert relative urls to other posts on that service to absolute url on our service.
|
||||
$arr['body'] = preg_replace_callback("/\[url\=\/+article\/(.*?)\](.*?)\[url\]/",'reflect_article_callback',$arr['body']);
|
||||
|
||||
// also import any photos
|
||||
$arr['body'] = preg_replace_callback("/\[img(.*?)\](.*?)\[\/img\]/",'reflect_photo_callback',$arr['body']);
|
||||
|
||||
|
||||
// add categories
|
||||
|
||||
if($j['taxonomy'] && is_array($j['taxonomy']) && count($j['taxonomy'])) {
|
||||
$arr['term'] = array();
|
||||
foreach($j['taxonomy'] as $tax) {
|
||||
$arr['term'][] = array(
|
||||
'uid' => $channel['channel_id'],
|
||||
'type' => TERM_CATEGORY,
|
||||
'otype' => TERM_OBJ_POST,
|
||||
'term' => trim($tax['name']),
|
||||
'url' => $channel['xchan_url'] . '?f=&cat=' . urlencode(trim($tax['name']))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// store the item
|
||||
|
||||
if($arr['id'])
|
||||
item_store_update($arr);
|
||||
else
|
||||
item_store($arr);
|
||||
|
||||
// if there are any comments, process them
|
||||
// $comment['registered'] is somebody with an account on the system. Others are mostly anonymous
|
||||
|
||||
if($j['comments']) {
|
||||
foreach($j['comments'] as $comment) {
|
||||
$user = (($comment['registered']) ? reflect_find_user($users,$comment['author']) : null);
|
||||
reflect_comment_store($channel,$arr,$comment,$user);
|
||||
}
|
||||
}
|
||||
$processed ++;
|
||||
|
||||
if(REFLECT_MAXPERRUN && $processed > REFLECT_MAXPERRUN)
|
||||
break;
|
||||
}
|
||||
return 'processed: ' . $processed . EOL . 'completed: ' . $ignored . EOL;
|
||||
|
||||
}
|
||||
|
||||
function reflect_article_callback($matches) {
|
||||
return '[zrl=' . z_root() . '/display/'. $matches[1] . ']' . $matches[2] . '[/zrl]';
|
||||
}
|
||||
|
||||
function reflect_photo_callback($matches) {
|
||||
|
||||
if(strpos($matches[2],'http') !== false)
|
||||
return $matches[0];
|
||||
|
||||
$prefix = REFLECT_BASEURL;
|
||||
$x = z_fetch_url($prefix.$matches[2],true);
|
||||
|
||||
$hash = basename($matches[2]);
|
||||
|
||||
if($x['success']) {
|
||||
$channel = reflect_get_channel();
|
||||
require_once('include/photos.php');
|
||||
$p = photo_upload($channel,$channel,
|
||||
array('data' => $x['body'],
|
||||
'resource_id' => str_replace('-','',$hash),
|
||||
'filename' => $hash . '.jpg',
|
||||
'type' => 'image/jpeg',
|
||||
'not_visible' => true
|
||||
)
|
||||
);
|
||||
|
||||
if($p['success'])
|
||||
$newlink = $p['resource_id'] . '-0.jpg';
|
||||
|
||||
|
||||
// import photo and locate the link for it.
|
||||
return '[zmg]' . z_root() . '/photo/' . $newlink . '[/zmg]';
|
||||
|
||||
}
|
||||
// no replacement. Leave it alone.
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
function reflect_find_user($users,$name) {
|
||||
if($users) {
|
||||
foreach($users as $x) {
|
||||
if($x['name'] === $name) {
|
||||
return $x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
function reflect_comment_store($channel,$post,$comment,$user) {
|
||||
|
||||
// if the commenter was the channel owner, use their redmatrix xchan
|
||||
|
||||
if($comment['author'] === REFLECT_EXPORTUSERNAME && $comment['registered'])
|
||||
$hash = $channel['xchan_hash'];
|
||||
else {
|
||||
// we need a unique hash for the commenter. We don't know how many may have supplied
|
||||
// http://yahoo.com as their URL, so we'll use their avatar guid if they have one.
|
||||
// anonymous folks may get more than one xchan_hash if they commented more than once.
|
||||
|
||||
$hash = (($comment['registered'] && $user) ? $user['avatar'] : '');
|
||||
if(! $hash)
|
||||
$hash = random_string() . '.unknown';
|
||||
|
||||
// create an xchan for them which will also import their profile photo
|
||||
// they will have a network type 'unknown'.
|
||||
|
||||
$x = array(
|
||||
'hash' => $hash,
|
||||
'guid' => $hash,
|
||||
'url' => (($comment['url']) ? $comment['url'] : z_root()),
|
||||
'photo' => (($user) ? REFLECT_BASEURL . $user['avatar'] : z_root() . '/' . get_default_profile_photo()),
|
||||
'name' => $comment['author']
|
||||
);
|
||||
xchan_store($x);
|
||||
|
||||
}
|
||||
|
||||
$arr = array();
|
||||
|
||||
$r = q("select * from item where mid = '%s' and uid = %d limit 1",
|
||||
dbesc($comment['guid']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if($r) {
|
||||
if(REFLECT_OVERWRITE)
|
||||
$arr['id'] = $r[0]['id'];
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
// this is a lot like storing the post except for subtle differences, like parent_mid, flags, author_xchan,
|
||||
// and we don't have a comment edited field so use creation date
|
||||
|
||||
$arr['uid'] = $channel['channel_account_id'];
|
||||
$arr['aid'] = $channel['channel_id'];
|
||||
$arr['mid'] = $comment['guid'];
|
||||
$arr['parent_mid'] = $post['mid'];
|
||||
$arr['created'] = $comment['created'];
|
||||
$arr['edited'] = $comment['created'];
|
||||
$arr['author_xchan'] = $hash;
|
||||
$arr['owner_xchan'] = $channel['channel_hash'];
|
||||
$arr['item_flags'] = ITEM_ORIGIN|ITEM_WALL;
|
||||
$arr['verb'] = ACTIVITY_POST;
|
||||
$arr['comment_policy'] = 'contacts';
|
||||
|
||||
|
||||
$arr['title'] = html2bbcode($comment['title']);
|
||||
$arr['title'] = htmlspecialchars($arr['title'],ENT_COMPAT,'UTF-8',false);
|
||||
|
||||
|
||||
$arr['body'] = html2bbcode($comment['body']);
|
||||
$arr['body'] = htmlspecialchars($arr['body'],ENT_COMPAT,'UTF-8',false);
|
||||
$arr['body'] = preg_replace_callback("/\[url\=\/+article\/(.*?)\](.*?)\[url\]/",'reflect_article_callback',$arr['body']);
|
||||
$arr['body'] = preg_replace_callback("/\[img(.*?)\](.*?)\[\/img\]/",'reflect_photo_callback',$arr['body']);
|
||||
|
||||
// logger('comment: ' . print_r($arr,true));
|
||||
|
||||
if($arr['id'])
|
||||
item_store_update($arr);
|
||||
else
|
||||
item_store($arr);
|
||||
|
||||
}
|
||||
@@ -277,7 +277,7 @@ function bb2diaspora_itemwallwall(&$item) {
|
||||
}
|
||||
|
||||
if(($item['mid'] == $item['parent_mid']) && ($item['author_xchan'] != $item['owner_xchan']) && (is_array($item['author']))) {
|
||||
logger('bb2diaspora_itemwallwall: author: ' . print_r($item['author'],true), LOGGER_DEBUG);
|
||||
logger('bb2diaspora_itemwallwall: author: ' . print_r($item['author'],true), LOGGER_DATA);
|
||||
}
|
||||
|
||||
if(($item['mid'] == $item['parent_mid']) && ($item['author_xchan'] != $item['owner_xchan']) && (is_array($item['author'])) && $item['author']['xchan_url'] && $item['author']['xchan_name'] && $item['author']['xchan_photo_m']) {
|
||||
@@ -388,7 +388,7 @@ function bb2diaspora_itembody($item,$force_update = false) {
|
||||
}
|
||||
}
|
||||
|
||||
logger('bb2diaspora_itembody : ' . $body);
|
||||
// logger('bb2diaspora_itembody : ' . $body, LOGGER_DATA);
|
||||
|
||||
return html_entity_decode($body);
|
||||
|
||||
@@ -462,7 +462,7 @@ function format_event_diaspora($ev) {
|
||||
|
||||
$bd_format = t('l F d, Y \@ g:i A') ; // Friday January 18, 2011 @ 8 AM
|
||||
|
||||
$o = 'Friendica event notification:' . "\n";
|
||||
$o = t('Redmatrix event notification:') . "\n";
|
||||
|
||||
$o .= '**' . (($ev['summary']) ? bb2diaspora($ev['summary']) : bb2diaspora($ev['desc'])) . '**' . "\n";
|
||||
|
||||
|
||||
@@ -29,8 +29,7 @@ function findpeople_widget() {
|
||||
'$random' => t('Random Profile'),
|
||||
'$inv' => t('Invite Friends'),
|
||||
'$advanced_search' => $advanced_search,
|
||||
'$advanced_hint' => t('Exammple: name=fred and country=iceland'),
|
||||
'$find_advanced' => t('Advanced Find'),
|
||||
'$advanced_hint' => "\r\n" . t('Advanced example: name=fred and country=iceland'),
|
||||
'$loggedin' => local_user()
|
||||
));
|
||||
|
||||
|
||||
@@ -1493,8 +1493,12 @@ function network_tabs() {
|
||||
|
||||
|
||||
function profile_tabs($a, $is_owner=False, $nickname=Null){
|
||||
//echo "<pre>"; var_dump($a->user); killme();
|
||||
|
||||
|
||||
// Don't provide any profile tabs if we're running as the sys channel
|
||||
|
||||
if($a->is_sys)
|
||||
return;
|
||||
|
||||
$channel = $a->get_channel();
|
||||
|
||||
if (is_null($nickname))
|
||||
|
||||
@@ -134,10 +134,17 @@ function dob($dob) {
|
||||
if(! $f)
|
||||
$f = 'ymd';
|
||||
|
||||
if ($dob && $dob != '0000-00-00')
|
||||
$o = datesel($f,mktime(0,0,0,0,0,1900),mktime(),mktime(0,0,0,$month,$day,$year),'dob');
|
||||
if($dob === '0000-00-00')
|
||||
$value = '';
|
||||
else
|
||||
$o = datesel($f,mktime(0,0,0,0,0,1900),mktime(),false,'dob');
|
||||
$value = (($year) ? datetime_convert('UTC','UTC',$dob,'Y-m-d') : datetime_convert('UTC','UTC',$dob,'m-d'));
|
||||
|
||||
$o = '<input type="text" name="dob" value="' . $value . '" placeholder="' . t('YYYY-MM-DD or MM-DD') . '" />';
|
||||
|
||||
// if ($dob && $dob != '0000-00-00')
|
||||
// $o = datesel($f,mktime(0,0,0,0,0,1900),mktime(),mktime(0,0,0,$month,$day,$year),'dob');
|
||||
// else
|
||||
// $o = datesel($f,mktime(0,0,0,0,0,1900),mktime(),false,'dob');
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
<?php /** @file */
|
||||
<?php
|
||||
/**
|
||||
* @file dba_driver.php
|
||||
* @brief some database related functions and abstract driver class.
|
||||
*
|
||||
* This file contains the abstract database driver class dba_driver and some
|
||||
* functions for working with databases.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Returns the database driver object.
|
||||
*
|
||||
* If available it will use PHP's mysqli otherwise mysql driver.
|
||||
*
|
||||
* @param string $server DB server name
|
||||
* @param string $port DB port
|
||||
* @param string $user DB username
|
||||
* @param string $pass DB password
|
||||
* @param string $db database name
|
||||
* @param string $dbtype 0 for mysql, 1 for postgres
|
||||
* @param bool $install Defaults to false
|
||||
* @return null|dba_driver A database driver object (dba_mysql|dba_mysqli) or null if no driver found.
|
||||
*/
|
||||
function dba_factory($server, $port,$user,$pass,$db,$dbtype,$install = false) {
|
||||
$dba = null;
|
||||
|
||||
@@ -23,7 +44,12 @@ function dba_factory($server, $port,$user,$pass,$db,$dbtype,$install = false) {
|
||||
return $dba;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief abstract database driver class.
|
||||
*
|
||||
* This class gets extended by the real database driver classes, e.g. dba_mysql,
|
||||
* dba_mysqli.
|
||||
*/
|
||||
abstract class dba_driver {
|
||||
// legacy behavior
|
||||
const INSTALL_SCRIPT='install/schema_mysql.sql';
|
||||
@@ -35,16 +61,51 @@ abstract class dba_driver {
|
||||
public $connected = false;
|
||||
public $error = false;
|
||||
|
||||
abstract function connect($server, $port, $user,$pass,$db);
|
||||
/**
|
||||
* @brief Connect to the database.
|
||||
*
|
||||
* This abstract function needs to be implemented in the real driver.
|
||||
*
|
||||
* @param string $server DB server name
|
||||
* @param string $port DB port
|
||||
* @param string $user DB username
|
||||
* @param string $pass DB password
|
||||
* @param string $db database name
|
||||
* @return bool
|
||||
*/
|
||||
abstract function connect($server, $port, $user, $pass, $db);
|
||||
|
||||
/**
|
||||
* @brief Perform a DB query with the SQL statement $sql.
|
||||
*
|
||||
* This abstract function needs to be implemented in the real driver.
|
||||
*
|
||||
* @param string $sql The SQL query to execute
|
||||
*/
|
||||
abstract function q($sql);
|
||||
|
||||
/**
|
||||
* @brief Escape a string before being passed to a DB query.
|
||||
*
|
||||
* This abstract function needs to be implemented in the real driver.
|
||||
*
|
||||
* @param string $str The string to escape.
|
||||
*/
|
||||
abstract function escape($str);
|
||||
|
||||
/**
|
||||
* @brief Close the database connection.
|
||||
*
|
||||
* This abstract function needs to be implemented in the real driver.
|
||||
*/
|
||||
abstract function close();
|
||||
|
||||
|
||||
function __construct($server, $port, $user,$pass,$db,$install = false) {
|
||||
if(($install) && (! $this->install($server, $port, $user,$pass,$db))) {
|
||||
if(($install) && (! $this->install($server, $port, $user, $pass, $db))) {
|
||||
return;
|
||||
}
|
||||
$this->connect($server, $port, $user,$pass,$db);
|
||||
$this->connect($server, $port, $user, $pass, $db);
|
||||
}
|
||||
|
||||
function get_null_date() {
|
||||
@@ -77,7 +138,11 @@ abstract class dba_driver {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets the database driver's debugging state.
|
||||
*
|
||||
* @param int $dbg 0 to disable debugging
|
||||
*/
|
||||
function dbg($dbg) {
|
||||
$this->debug = $dbg;
|
||||
}
|
||||
@@ -107,11 +172,12 @@ abstract class dba_driver {
|
||||
function unescapebin($str) {
|
||||
return $str;
|
||||
}
|
||||
|
||||
}
|
||||
} // end abstract dba_driver class
|
||||
|
||||
|
||||
|
||||
// Procedural functions
|
||||
|
||||
function printable($s) {
|
||||
$s = preg_replace("~([\x01-\x08\x0E-\x0F\x10-\x1F\x7F-\xFF])~",".", $s);
|
||||
$s = str_replace("\x00",'.',$s);
|
||||
@@ -120,21 +186,35 @@ function printable($s) {
|
||||
return $s;
|
||||
}
|
||||
|
||||
// Procedural functions
|
||||
|
||||
/**
|
||||
* @brief set database driver debugging state.
|
||||
*
|
||||
* @param int $state 0 to disable debugging
|
||||
*/
|
||||
function dbg($state) {
|
||||
global $db;
|
||||
|
||||
if($db)
|
||||
$db->dbg($state);
|
||||
$db->dbg($state);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Escape strings being passed to DB queries.
|
||||
*
|
||||
* Always escape strings being used in DB queries. This function returns the
|
||||
* escaped string. Integer DB parameters should all be proven integers by
|
||||
* wrapping with intval().
|
||||
*
|
||||
* @param string $str A string to pass to a DB query
|
||||
* @return Return an escaped string of the value to pass to a DB query.
|
||||
*/
|
||||
function dbesc($str) {
|
||||
global $db;
|
||||
|
||||
if($db && $db->connected)
|
||||
return($db->escape($str));
|
||||
else
|
||||
return(str_replace("'","\\'",$str));
|
||||
return(str_replace("'", "\\'", $str));
|
||||
}
|
||||
function dbescbin($str) {
|
||||
global $db;
|
||||
@@ -186,59 +266,73 @@ function db_concat($fld, $sep) {
|
||||
// 'user', 1);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Execute a SQL query with printf style args.
|
||||
*
|
||||
* printf style arguments %s and %d are replaced with variable arguments, which
|
||||
* should each be appropriately dbesc() or intval().
|
||||
* SELECT queries return an array of results or false if SQL or DB error. Other
|
||||
* queries return true if the command was successful or false if it wasn't.
|
||||
*
|
||||
* Example:
|
||||
* $r = q("SELECT * FROM `%s` WHERE `uid` = %d",
|
||||
* 'user', 1);
|
||||
*
|
||||
* @param string $sql The SQL query to execute
|
||||
* @return bool|array
|
||||
*/
|
||||
function q($sql) {
|
||||
|
||||
global $db;
|
||||
|
||||
$args = func_get_args();
|
||||
unset($args[0]);
|
||||
|
||||
if($db && $db->connected) {
|
||||
$stmt = vsprintf($sql,$args);
|
||||
$stmt = vsprintf($sql, $args);
|
||||
if($stmt === false) {
|
||||
if(version_compare(PHP_VERSION,'5.4.0') >= 0)
|
||||
logger('dba: vsprintf error: ' . print_r(debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT,1),true));
|
||||
if(version_compare(PHP_VERSION, '5.4.0') >= 0)
|
||||
logger('dba: vsprintf error: ' .
|
||||
print_r(debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 1), true));
|
||||
else
|
||||
logger('dba: vsprintf error: ' . print_r(debug_backtrace(),true));
|
||||
logger('dba: vsprintf error: ' . print_r(debug_backtrace(), true));
|
||||
}
|
||||
return $db->q($stmt);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
/*
|
||||
* This will happen occasionally trying to store the
|
||||
* session data after abnormal program termination
|
||||
*
|
||||
*/
|
||||
logger('dba: no database: ' . print_r($args,true));
|
||||
return false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Raw DB query, no arguments.
|
||||
*
|
||||
* Raw db query, no arguments
|
||||
* This function executes a raw DB query without any arguments.
|
||||
*
|
||||
* @param string $sql The SQL query to execute
|
||||
*/
|
||||
|
||||
|
||||
function dbq($sql) {
|
||||
|
||||
global $db;
|
||||
|
||||
if($db && $db->connected)
|
||||
$ret = $db->q($sql);
|
||||
else
|
||||
$ret = false;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
// Caller is responsible for ensuring that any integer arguments to
|
||||
|
||||
// Caller is responsible for ensuring that any integer arguments to
|
||||
// dbesc_array are actually integers and not malformed strings containing
|
||||
// SQL injection vectors. All integer array elements should be specifically
|
||||
// cast to int to avoid trouble.
|
||||
|
||||
|
||||
|
||||
function dbesc_array_cb(&$item, $key) {
|
||||
if(is_string($item)) {
|
||||
if($item == '0000-00-00 00:00:00' && ACTIVE_DBTYPE == DBTYPE_POSTGRES)
|
||||
@@ -248,7 +342,6 @@ function dbesc_array_cb(&$item, $key) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
function dbesc_array(&$arr) {
|
||||
if(is_array($arr) && count($arr)) {
|
||||
array_walk($arr,'dbesc_array_cb');
|
||||
|
||||
@@ -40,6 +40,10 @@ function deliver_run($argv, $argc) {
|
||||
|
||||
$notify = json_decode($r[0]['outq_notify'],true);
|
||||
|
||||
// Check if this is a conversation request packet. It won't have outq_msg
|
||||
// but will be an encrypted packet - so will need to be handed off to
|
||||
// web delivery rather than processed inline.
|
||||
|
||||
$sendtoweb = false;
|
||||
if(array_key_exists('iv',$notify) && (! $r[0]['outq_msg']))
|
||||
$sendtoweb = true;
|
||||
@@ -48,8 +52,7 @@ function deliver_run($argv, $argc) {
|
||||
logger('deliver: local delivery', LOGGER_DEBUG);
|
||||
// local delivery
|
||||
// we should probably batch these and save a few delivery processes
|
||||
// If there is no outq_msg, this is a refresh_all message which does not require local handling
|
||||
// also send 'request' packets to the webservice so it can decode the packet
|
||||
|
||||
if($r[0]['outq_msg']) {
|
||||
$m = json_decode($r[0]['outq_msg'],true);
|
||||
if(array_key_exists('message_list',$m)) {
|
||||
|
||||
@@ -58,7 +58,7 @@ function diaspora_dispatch($importer,$msg,$attempt=1) {
|
||||
|
||||
$xmlbase = $parsed_xml->post;
|
||||
|
||||
logger('diaspora_dispatch: ' . print_r($xmlbase,true), LOGGER_DATA);
|
||||
// logger('diaspora_dispatch: ' . print_r($xmlbase,true), LOGGER_DATA);
|
||||
|
||||
|
||||
if($xmlbase->request) {
|
||||
@@ -673,16 +673,15 @@ function diaspora_request($importer,$xml) {
|
||||
return;
|
||||
}
|
||||
|
||||
$default_perms = 0;
|
||||
// look for default permissions to apply in return - e.g. auto-friend
|
||||
$z = q("select * from abook where abook_channel = %d and (abook_flags & %d)>0 limit 1",
|
||||
intval($importer['channel_id']),
|
||||
intval(ABOOK_FLAG_SELF)
|
||||
);
|
||||
|
||||
if($z)
|
||||
$default_perms = intval($z[0]['abook_my_perms']);
|
||||
|
||||
$role = get_pconfig($channel['channel_id'],'system','permissions_role');
|
||||
if($role) {
|
||||
$x = get_role_perms($role);
|
||||
if($x['perms_auto'])
|
||||
$default_perms = $x['perms_accept'];
|
||||
}
|
||||
if(! $default_perms)
|
||||
$default_perms = intval(get_pconfig($channel['channel_id'],'system','autoperms'));
|
||||
|
||||
$their_perms = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK|PERMS_W_STREAM|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT|PERMS_R_STORAGE|PERMS_R_PAGES;
|
||||
|
||||
$r = q("insert into abook ( abook_account, abook_channel, abook_xchan, abook_my_perms, abook_their_perms, abook_closeness, abook_rating, abook_created, abook_updated, abook_connected, abook_dob, abook_flags) values ( %d, %d, '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', %d )",
|
||||
|
||||
@@ -64,14 +64,10 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
|
||||
$j = json_decode($ret['body'],true);
|
||||
}
|
||||
|
||||
$my_perms = get_channel_default_perms($uid);
|
||||
|
||||
if($is_red && $j) {
|
||||
|
||||
|
||||
// fixme - we need to be able to define these somewhere for the custom role
|
||||
$my_perms = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK
|
||||
|PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
|
||||
|PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE;
|
||||
|
||||
$role = get_pconfig($uid,'system','permissions_role');
|
||||
if($role) {
|
||||
$x = get_role_perms($role);
|
||||
@@ -141,7 +137,6 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
|
||||
}
|
||||
}
|
||||
|
||||
$my_perms = 0;
|
||||
$their_perms = 0;
|
||||
$xchan_hash = '';
|
||||
|
||||
@@ -168,7 +163,6 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
|
||||
if($r) {
|
||||
$xchan_hash = $r[0]['xchan_hash'];
|
||||
$their_perms = 0;
|
||||
$my_perms = PERMS_W_STREAM|PERMS_W_MAIL;
|
||||
$role = get_pconfig($uid,'system','permissions_role');
|
||||
if($role) {
|
||||
$x = get_role_perms($role);
|
||||
|
||||
@@ -348,10 +348,13 @@ function create_identity($arr) {
|
||||
dbesc($a->get_baseurl() . "/photo/profile/m/{$newuid}")
|
||||
);
|
||||
|
||||
$myperms = 0;
|
||||
if($role_permissions) {
|
||||
$myperms = ((array_key_exists('perms_auto',$role_permissions) && $role_permissions['perms_auto']) ? intval($role_permissions['perms_accept']) : 0);
|
||||
}
|
||||
else
|
||||
$myperms = PERMS_R_STREAM|PERMS_R_PROFILE|PERMS_R_PHOTOS|PERMS_R_ABOOK
|
||||
|PERMS_W_STREAM|PERMS_W_WALL|PERMS_W_COMMENT|PERMS_W_MAIL|PERMS_W_CHAT
|
||||
|PERMS_R_STORAGE|PERMS_R_PAGES|PERMS_W_LIKE;
|
||||
|
||||
$r = q("insert into abook ( abook_account, abook_channel, abook_xchan, abook_closeness, abook_created, abook_updated, abook_flags, abook_my_perms )
|
||||
values ( %d, %d, '%s', %d, '%s', '%s', %d, %d ) ",
|
||||
@@ -373,6 +376,8 @@ function create_identity($arr) {
|
||||
set_pconfig($newuid,'system','permissions_role',$arr['permissions_role']);
|
||||
if(array_key_exists('online',$role_permissions))
|
||||
set_pconfig($newuid,'system','hide_presence',1-intval($role_permissions['online']));
|
||||
if(array_key_exists('perms_auto',$role_permissions))
|
||||
set_pconfig($newuid,'system','autoperms',(($role_permissions['perms_auto']) ? $role_permissions['perms_accept'] : 0));
|
||||
}
|
||||
|
||||
// Create a group with yourself as a member. This allows somebody to use it
|
||||
@@ -885,6 +890,8 @@ function profile_sidebar($profile, $block = 0, $show_connect = true) {
|
||||
|| (x($profile,'country_name') == 1))
|
||||
$location = t('Location:');
|
||||
|
||||
$profile['homepage'] = linkify($profile['homepage']);
|
||||
|
||||
$gender = ((x($profile,'gender') == 1) ? t('Gender:') : False);
|
||||
$marital = ((x($profile,'marital') == 1) ? t('Status:') : False);
|
||||
$homepage = ((x($profile,'homepage') == 1) ? t('Homepage:') : False);
|
||||
@@ -1561,4 +1568,16 @@ function notifications_on($channel_id,$value) {
|
||||
intval($channel_id)
|
||||
);
|
||||
return $x;
|
||||
}
|
||||
|
||||
|
||||
function get_channel_default_perms($uid) {
|
||||
|
||||
$r = q("select abook_my_perms from abook where abook_channel = %d and abook_flags & %d limit 1",
|
||||
intval($uid),
|
||||
intval(ABOOK_FLAG_SELF)
|
||||
);
|
||||
if($r)
|
||||
return $r[0]['abook_my_perms'];
|
||||
return 0;
|
||||
}
|
||||
@@ -2974,7 +2974,15 @@ function tgroup_check($uid,$item) {
|
||||
// At this point we've determined that the person receiving this post was mentioned in it.
|
||||
// Now let's check if this mention was inside a reshare so we don't spam a forum
|
||||
|
||||
$body = preg_replace('/\[share(.*?)\[\/share\]/','',$item['body']);
|
||||
|
||||
$body = $item['body'];
|
||||
|
||||
if(array_key_exists('item_flags',$item) && ($item['item_flags'] & ITEM_OBSCURED) && $body) {
|
||||
$key = get_config('system','prvkey');
|
||||
$body = crypto_unencapsulate(json_decode($body,true),$key);
|
||||
}
|
||||
|
||||
$body = preg_replace('/\[share(.*?)\[\/share\]/','',$body);
|
||||
|
||||
$pattern = '/@\!?\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($term['term'] . '+','/') . '\[\/zrl\]/';
|
||||
|
||||
@@ -4128,10 +4136,13 @@ function first_post_date($uid,$wall = false) {
|
||||
* current flat list of all representative dates.
|
||||
*/
|
||||
|
||||
function list_post_dates($uid,$wall) {
|
||||
function list_post_dates($uid,$wall,$mindate) {
|
||||
$dnow = datetime_convert('',date_default_timezone_get(),'now','Y-m-d');
|
||||
|
||||
$dthen = first_post_date($uid,$wall);
|
||||
if($mindate)
|
||||
$dthen = datetime_convert('',date_default_timezone_get(),$mindate);
|
||||
else
|
||||
$dthen = first_post_date($uid,$wall);
|
||||
if(! $dthen)
|
||||
return array();
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ EOT;
|
||||
$nav['search'] = array('search', t('Search'), "", t('Search site content'));
|
||||
|
||||
|
||||
$nav['directory'] = array('directory', t('Directory'), "", t('Channel Locator'));
|
||||
$nav['directory'] = array('directory', t('Directory'), "", t('Channel Directory'));
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -549,7 +549,7 @@ function get_role_perms($role) {
|
||||
$ret['channel_r_profile'] = PERMS_PUBLIC;
|
||||
$ret['channel_r_photos'] = PERMS_PUBLIC;
|
||||
$ret['channel_r_abook'] = PERMS_PUBLIC;
|
||||
$ret['channel_w_stream'] = PERMS_CONTACTS;
|
||||
$ret['channel_w_stream'] = 0;
|
||||
$ret['channel_w_wall'] = PERMS_CONTACTS;
|
||||
$ret['channel_w_tagwall'] = PERMS_CONTACTS;
|
||||
$ret['channel_w_comment'] = PERMS_CONTACTS;
|
||||
@@ -581,7 +581,7 @@ function get_role_perms($role) {
|
||||
$ret['channel_r_profile'] = PERMS_PUBLIC;
|
||||
$ret['channel_r_photos'] = PERMS_PUBLIC;
|
||||
$ret['channel_r_abook'] = PERMS_PUBLIC;
|
||||
$ret['channel_w_stream'] = PERMS_CONTACTS;
|
||||
$ret['channel_w_stream'] = 0;
|
||||
$ret['channel_w_wall'] = PERMS_CONTACTS;
|
||||
$ret['channel_w_tagwall'] = PERMS_SPECIFIC;
|
||||
$ret['channel_w_comment'] = PERMS_CONTACTS;
|
||||
@@ -614,7 +614,7 @@ function get_role_perms($role) {
|
||||
$ret['channel_r_profile'] = PERMS_CONTACTS;
|
||||
$ret['channel_r_photos'] = PERMS_CONTACTS;
|
||||
$ret['channel_r_abook'] = PERMS_CONTACTS;
|
||||
$ret['channel_w_stream'] = PERMS_CONTACTS;
|
||||
$ret['channel_w_stream'] = 0;
|
||||
$ret['channel_w_wall'] = PERMS_CONTACTS;
|
||||
$ret['channel_w_tagwall'] = 0;
|
||||
$ret['channel_w_comment'] = PERMS_CONTACTS;
|
||||
|
||||
@@ -179,7 +179,7 @@ function photo_upload($channel, $observer, $args) {
|
||||
if($args['title'])
|
||||
$p['title'] = $args['title'];
|
||||
if($args['description'])
|
||||
$p['desciprion'] = $args['description'];
|
||||
$p['description'] = $args['description'];
|
||||
|
||||
|
||||
$r1 = $ph->save($p);
|
||||
@@ -432,7 +432,7 @@ function photos_create_item($channel, $creator_hash, $photo, $visible = false) {
|
||||
// Create item container
|
||||
|
||||
$item_flags = ITEM_WALL|ITEM_ORIGIN|ITEM_THREAD_TOP;
|
||||
$item_restrict = (($visible) ? ITEM_HIDDEN : ITEM_VISIBLE);
|
||||
$item_restrict = (($visible) ? ITEM_VISIBLE : ITEM_HIDDEN);
|
||||
|
||||
$title = '';
|
||||
$mid = item_message_id();
|
||||
|
||||
@@ -128,8 +128,8 @@ function poller_run($argv, $argc){
|
||||
|
||||
if(($d2 != $d1) && ($h1 == $h2)) {
|
||||
|
||||
require_once('include/dir_fns.php');
|
||||
check_upstream_directory();
|
||||
require_once('include/dir_fns.php');
|
||||
check_upstream_directory();
|
||||
|
||||
call_hooks('cron_daily',datetime_convert());
|
||||
|
||||
@@ -315,6 +315,7 @@ function poller_run($argv, $argc){
|
||||
$update = true;
|
||||
}
|
||||
else {
|
||||
|
||||
// if we've never connected with them, start the mark for death countdown from now
|
||||
|
||||
if($c == NULL_DATE) {
|
||||
@@ -361,7 +362,6 @@ function poller_run($argv, $argc){
|
||||
$update = true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if((! $update) && (! $force))
|
||||
|
||||
@@ -84,8 +84,9 @@ function ref_session_destroy ($id) {
|
||||
|
||||
function ref_session_gc($expire) {
|
||||
q("DELETE FROM session WHERE expire < %d", dbesc(time()));
|
||||
db_optimizetable('session');
|
||||
return true;
|
||||
if (! get_config('system','innodb'))
|
||||
db_optimizetable('session');
|
||||
return true;
|
||||
}
|
||||
|
||||
$gc_probability = 50;
|
||||
|
||||
@@ -209,13 +209,35 @@ function tagblock($link,$uid,$count = 0,$authors = '',$flags = 0,$restrict = 0,$
|
||||
if($r) {
|
||||
$o = '<div class="tagblock widget"><h3>' . t('Tags') . '</h3><div class="tags" align="center">';
|
||||
foreach($r as $rr) {
|
||||
$o .= '<a href="'.$link .'/' . '?f=&tag=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n";
|
||||
$o .= '<span class="tag'.$rr[2].'">#</span><a href="'.$link .'/' . '?f=&tag=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n";
|
||||
}
|
||||
$o .= '</div></div>';
|
||||
}
|
||||
return $o;
|
||||
}
|
||||
|
||||
function catblock($uid,$count = 0,$authors = '',$flags = 0,$restrict = 0,$type = TERM_CATEGORY) {
|
||||
$o = '';
|
||||
$tab = 0;
|
||||
|
||||
$r = tagadelic($uid,$count,$authors,$flags,$restrict,$type);
|
||||
|
||||
if($r) {
|
||||
$c = q("select channel_address from channel where channel_id = %d limit 1",
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
$o = '<div class="tagblock widget"><h3>' . t('Categories') . '</h3><div class="tags" align="center">';
|
||||
foreach($r as $rr) {
|
||||
$o .= '<a href="channel/' . $c[0]['channel_address']. '?f=&cat=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n";
|
||||
}
|
||||
$o .= '</div></div>';
|
||||
}
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function dir_tagblock($link,$r) {
|
||||
$o = '';
|
||||
$tab = 0;
|
||||
|
||||
@@ -2025,12 +2025,22 @@ function json_decode_plus($s) {
|
||||
|
||||
|
||||
function design_tools() {
|
||||
|
||||
$channel = get_app()->get_channel();
|
||||
$sys = false;
|
||||
|
||||
if(get_app()->is_sys && is_site_admin()) {
|
||||
require_once('include/identity.php');
|
||||
$channel = get_sys_channel();
|
||||
$sys = true;
|
||||
}
|
||||
|
||||
$who = $channel['channel_address'];
|
||||
|
||||
return replace_macros(get_markup_template('design_tools.tpl'), array(
|
||||
'$title' => t('Design'),
|
||||
'$who' => $who,
|
||||
'$sys' => $sys,
|
||||
'$blocks' => t('Blocks'),
|
||||
'$menus' => t('Menus'),
|
||||
'$layout' => t('Layouts'),
|
||||
@@ -2050,7 +2060,7 @@ function normalise_openid($s) {
|
||||
|
||||
// used in ajax endless scroll request to find out all the args that the master page was viewing.
|
||||
// This was using $_REQUEST, but $_REQUEST also contains all your cookies. So we're restricting it
|
||||
// to $_GET. If this is used in a post handler, that decision may need to be considered.
|
||||
// to $_GET and $_POST.
|
||||
|
||||
function extra_query_args() {
|
||||
$s = '';
|
||||
@@ -2058,7 +2068,15 @@ function extra_query_args() {
|
||||
foreach($_GET as $k => $v) {
|
||||
// these are request vars we don't want to duplicate
|
||||
if(! in_array($k, array('q','f','zid','page','PHPSESSID'))) {
|
||||
$s .= '&' . $k . '=' . $v;
|
||||
$s .= '&' . $k . '=' . urlencode($v);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(count($_POST)) {
|
||||
foreach($_POST as $k => $v) {
|
||||
// these are request vars we don't want to duplicate
|
||||
if(! in_array($k, array('q','f','zid','page','PHPSESSID'))) {
|
||||
$s .= '&' . $k . '=' . urlencode($v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,19 +330,32 @@ function widget_archive($arr) {
|
||||
|
||||
$wall = ((array_key_exists('wall', $arr)) ? intval($arr['wall']) : 0);
|
||||
$style = ((array_key_exists('style', $arr)) ? $arr['style'] : 'select');
|
||||
$showend = ((get_pconfig($uid,'system','archive_show_end_date')) ? true : false);
|
||||
$mindate = get_pconfig($uid,'system','archive_mindate');
|
||||
$visible_years = get_pconfig($uid,'system','archive_visible_years');
|
||||
if(! $visible_years)
|
||||
$visible_years = 5;
|
||||
|
||||
|
||||
$url = z_root() . '/' . $a->cmd;
|
||||
|
||||
|
||||
$ret = list_post_dates($uid,$wall);
|
||||
$ret = list_post_dates($uid,$wall,$mindate);
|
||||
|
||||
if(! count($ret))
|
||||
return '';
|
||||
|
||||
$cutoff_year = intval(datetime_convert('',date_default_timezone_get(),'now','Y')) - $visible_years;
|
||||
$cutoff = ((array_key_exists($cutoff_year,$ret))? true : false);
|
||||
|
||||
$o = replace_macros(get_markup_template('posted_date_widget.tpl'),array(
|
||||
'$title' => t('Archives'),
|
||||
'$size' => ((count($ret) > 6) ? 6 : count($ret)),
|
||||
'$size' => $visible_years,
|
||||
'$cutoff_year' => $cutoff_year,
|
||||
'$cutoff' => $cutoff,
|
||||
'$url' => $url,
|
||||
'$style' => $style,
|
||||
'$showend' => $showend,
|
||||
'$dates' => $ret
|
||||
));
|
||||
return $o;
|
||||
@@ -387,6 +400,17 @@ function widget_tagcloud_wall($arr) {
|
||||
return tagblock('search',$a->profile['profile_uid'],$limit,$a->profile['channel_hash'],ITEM_WALL);
|
||||
return '';
|
||||
}
|
||||
function widget_catcloud_wall($arr) {
|
||||
$a = get_app();
|
||||
if((! $a->profile['profile_uid']) || (! $a->profile['channel_hash']))
|
||||
return '';
|
||||
if(! perm_is_allowed($a->profile['profile_uid'],get_observer_hash(),'view_stream'))
|
||||
return '';
|
||||
|
||||
$limit = ((array_key_exists('limit',$arr)) ? intval($arr['limit']) : 50);
|
||||
return catblock($a->profile['profile_uid'],$limit,$a->profile['channel_hash'],ITEM_WALL);
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
function widget_affinity($arr) {
|
||||
@@ -493,7 +517,7 @@ function widget_settings_menu($arr) {
|
||||
|
||||
if($role === false || $role === 'custom') {
|
||||
$tabs[] = array(
|
||||
'label' => t('Automatic Permissions (Advanced)'),
|
||||
'label' => t('Connection Default Permissions'),
|
||||
'url' => $a->get_baseurl(true) . '/connedit/' . $abook_self_id,
|
||||
'selected' => ''
|
||||
);
|
||||
@@ -561,7 +585,7 @@ function widget_design_tools($arr) {
|
||||
// otherwise local_user() is sufficient for permissions.
|
||||
|
||||
if($a->profile['profile_uid'])
|
||||
if($a->profile['profile_uid'] != local_user())
|
||||
if(($a->profile['profile_uid'] != local_user()) && (! $a->is_sys))
|
||||
return '';
|
||||
|
||||
if(! local_user())
|
||||
|
||||
141
include/zot.php
141
include/zot.php
@@ -5,7 +5,7 @@ require_once('include/items.php');
|
||||
require_once('include/hubloc.php');
|
||||
|
||||
/**
|
||||
* Red implementation of zot protocol.
|
||||
* Red implementation of zot protocol.
|
||||
*
|
||||
* https://github.com/friendica/red/wiki/zot
|
||||
* https://github.com/friendica/red/wiki/Zot---A-High-Level-Overview
|
||||
@@ -20,8 +20,8 @@ require_once('include/hubloc.php');
|
||||
* Generates a unique string for use as a zot guid using our DNS-based url, the channel nickname and some entropy.
|
||||
* The entropy ensures uniqueness against re-installs where the same URL and nickname are chosen.
|
||||
* NOTE: zot doesn't require this to be unique. Internally we use a whirlpool hash of this guid and the signature
|
||||
* of this guid signed with the channel private key. This can be verified and should make the probability of
|
||||
* collision of the verified result negligible within the constraints of our immediate universe.
|
||||
* of this guid signed with the channel private key. This can be verified and should make the probability of
|
||||
* collision of the verified result negligible within the constraints of our immediate universe.
|
||||
*
|
||||
* @param string channel_nickname = unique nickname of controlling entity
|
||||
*
|
||||
@@ -51,7 +51,7 @@ function make_xchan_hash($guid,$guid_sig) {
|
||||
|
||||
/**
|
||||
* @function zot_get_hublocs($hash)
|
||||
* Given a zot hash, return all distinct hubs.
|
||||
* Given a zot hash, return all distinct hubs.
|
||||
* This function is used in building the zot discovery packet
|
||||
* and therefore should only be used by channels which are defined
|
||||
* on this hub
|
||||
@@ -71,7 +71,7 @@ function make_xchan_hash($guid,$guid_sig) {
|
||||
* hubloc_connect char(255)
|
||||
* hubloc_sitekey text
|
||||
* hubloc_updated datetime
|
||||
* hubloc_connected datetime
|
||||
* hubloc_connected datetime
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -85,21 +85,21 @@ function zot_get_hublocs($hash) {
|
||||
);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @function zot_build_packet($channel,$type = 'notify',$recipients = null, $remote_key = null, $secret = null)
|
||||
* builds a zot notification packet that you can either
|
||||
* store in the queue with a message array or call zot_zot to immediately
|
||||
* store in the queue with a message array or call zot_zot to immediately
|
||||
* zot it to the other side
|
||||
*
|
||||
* @param array $channel => sender channel structure
|
||||
* @param string $type => packet type: one of 'ping', 'pickup', 'purge', 'refresh', 'force_refresh', 'notify', 'auth_check'
|
||||
* @param array $recipients => envelope information, array ( 'guid' => string, 'guid_sig' => string ); empty for public posts
|
||||
* @param string $remote_key => optional public site key of target hub used to encrypt entire packet
|
||||
* NOTE: remote_key and encrypted packets are required for 'auth_check' packets, optional for all others
|
||||
* NOTE: remote_key and encrypted packets are required for 'auth_check' packets, optional for all others
|
||||
* @param string $secret => random string, required for packets which require verification/callback
|
||||
* e.g. 'pickup', 'purge', 'notify', 'auth_check'. Packet types 'ping', 'force_refresh', and 'refresh' do not require verification
|
||||
* e.g. 'pickup', 'purge', 'notify', 'auth_check'. Packet types 'ping', 'force_refresh', and 'refresh' do not require verification
|
||||
*
|
||||
* @returns string json encoded zot packet
|
||||
*/
|
||||
@@ -441,15 +441,15 @@ function zot_refresh($them,$channel = null, $force = false) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
$default_perms = 0;
|
||||
// look for default permissions to apply in return - e.g. auto-friend
|
||||
$z = q("select * from abook where abook_channel = %d and (abook_flags & %d)>0 limit 1",
|
||||
intval($channel['channel_id']),
|
||||
intval(ABOOK_FLAG_SELF)
|
||||
);
|
||||
|
||||
if($z)
|
||||
$default_perms = intval($z[0]['abook_my_perms']);
|
||||
$role = get_pconfig($channel['channel_id'],'system','permissions_role');
|
||||
if($role) {
|
||||
$xx = get_role_perms($role);
|
||||
if($xx['perms_auto'])
|
||||
$default_perms = $xx['perms_accept'];
|
||||
}
|
||||
if(! $default_perms)
|
||||
$default_perms = intval(get_pconfig($channel['channel_id'],'system','autoperms'));
|
||||
|
||||
|
||||
// Keep original perms to check if we need to notify them
|
||||
$previous_perms = get_all_perms($channel['channel_id'],$x['hash']);
|
||||
@@ -701,10 +701,10 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
|
||||
|
||||
$dirmode = get_config('system','directory_mode');
|
||||
|
||||
if((($arr['site']['directory_mode'] === 'standalone') || ($dirmode & DIRECTORY_MODE_STANDALONE))
|
||||
&& ($arr['site']['url'] != z_root()))
|
||||
if((($arr['site']['directory_mode'] === 'standalone') || ($dirmode & DIRECTORY_MODE_STANDALONE)) && ($arr['site']['url'] != z_root()))
|
||||
$arr['searchable'] = false;
|
||||
|
||||
|
||||
$hidden = (1 - intval($arr['searchable']));
|
||||
|
||||
// Be careful - XCHAN_FLAGS_HIDDEN should evaluate to 1
|
||||
@@ -723,6 +723,11 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
|
||||
if($deleted_changed)
|
||||
$new_flags = $new_flags ^ XCHAN_FLAGS_DELETED;
|
||||
|
||||
$public_forum = (($r[0]['xchan_flags'] & XCHAN_FLAGS_PUBFORUM) ? true : false);
|
||||
$pubforum_changed = ((intval($public_forum) != intval($arr['public_forum'])) ? true : false);
|
||||
if($pubforum_changed)
|
||||
$new_flags = $r[0]['xchan_flags'] ^ XCHAN_FLAGS_PUBFORUM;
|
||||
|
||||
if(($r[0]['xchan_name_date'] != $arr['name_updated'])
|
||||
|| ($r[0]['xchan_connurl'] != $arr['connections_url'])
|
||||
|| ($r[0]['xchan_flags'] != $new_flags)
|
||||
@@ -1073,7 +1078,7 @@ function zot_import($arr, $sender_url) {
|
||||
|
||||
if(array_key_exists('iv',$i['notify'])) {
|
||||
$i['notify'] = json_decode(crypto_unencapsulate($i['notify'],get_config('system','prvkey')),true);
|
||||
}
|
||||
}
|
||||
|
||||
logger('zot_import: notify: ' . print_r($i['notify'],true), LOGGER_DATA);
|
||||
|
||||
@@ -1084,6 +1089,8 @@ function zot_import($arr, $sender_url) {
|
||||
}
|
||||
|
||||
$message_request = ((array_key_exists('message_id',$i['notify'])) ? true : false);
|
||||
if($message_request)
|
||||
logger('processing message request');
|
||||
|
||||
$i['notify']['sender']['hash'] = make_xchan_hash($i['notify']['sender']['guid'],$i['notify']['sender']['guid_sig']);
|
||||
$deliveries = null;
|
||||
@@ -1107,7 +1114,7 @@ function zot_import($arr, $sender_url) {
|
||||
// It's a specifically targetted post. If we were sent a public_scope hint (likely),
|
||||
// get rid of it so that it doesn't get stored and cause trouble.
|
||||
|
||||
if(array_key_exists('message',$i) && array_key_exists('public_scope',$i['message']))
|
||||
if(($i) && is_array($i) && array_key_exists('message',$i) && is_array($i['message']) && array_key_exists('public_scope',$i['message']))
|
||||
unset($i['message']['public_scope']);
|
||||
|
||||
$deliveries = $r;
|
||||
@@ -1446,15 +1453,24 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false,$reque
|
||||
if(! $r) {
|
||||
$result[] = array($d['hash'],'comment parent not found',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']);
|
||||
|
||||
// We don't seem to have a copy of this conversation or at least the parent - so request a copy of the entire conversation to date.
|
||||
// Don't do this if it's a relay post as we're the ones who are supposed to have the copy and we don't want the request to loop.
|
||||
// Also don't do this if this comment came from a conversation request packet. It's possible that comments are allowed but posting
|
||||
// isn't and that could cause a conversation fetch loop. We can detect these packets since they are delivered via a 'notify' packet type
|
||||
// that has a message_id element in the initial zot packet (just like the corresponding 'request' packet type which makes the request).
|
||||
// We don't seem to have a copy of this conversation or at least the parent
|
||||
// - so request a copy of the entire conversation to date.
|
||||
// Don't do this if it's a relay post as we're the ones who are supposed to
|
||||
// have the copy and we don't want the request to loop.
|
||||
// Also don't do this if this comment came from a conversation request packet.
|
||||
// It's possible that comments are allowed but posting isn't and that could
|
||||
// cause a conversation fetch loop. We can detect these packets since they are
|
||||
// delivered via a 'notify' packet type that has a message_id element in the
|
||||
// initial zot packet (just like the corresponding 'request' packet type which
|
||||
// makes the request).
|
||||
// We'll also check the send_stream permission - because if it isn't allowed,
|
||||
// the top level post is unlikely to be imported and
|
||||
// this is just an exercise in futility.
|
||||
|
||||
if((! $relay) && (! $request))
|
||||
if((! $relay) && (! $request) && (! $public)
|
||||
&& perm_is_allowed($channel['channel_id'],$sender['hash'],'send_stream')) {
|
||||
proc_run('php', 'include/notifier.php', 'request', $channel['channel_id'], $sender['hash'], $arr['parent_mid']);
|
||||
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if($relay) {
|
||||
@@ -2451,8 +2467,8 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) {
|
||||
|
||||
$channel = $r[0];
|
||||
|
||||
$max_friends = service_class_fetch($channel['channel_id'],'total_channels');
|
||||
$max_feeds = account_service_class_fetch($channel['channel_account_id'],'total_feeds');
|
||||
$max_friends = service_class_fetch($channel['channel_id'],'total_channels');
|
||||
$max_feeds = account_service_class_fetch($channel['channel_account_id'],'total_feeds');
|
||||
|
||||
|
||||
if($channel['channel_hash'] != $sender['hash']) {
|
||||
@@ -2538,7 +2554,7 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) {
|
||||
continue;
|
||||
}
|
||||
$j = json_decode($f['body'],true);
|
||||
if(! ($j['success'] && $j['guid'])) {
|
||||
if(! ($j['success'] && $j['guid'])) {
|
||||
logger('process_channel_sync_delivery: probe failed.');
|
||||
continue;
|
||||
}
|
||||
@@ -2636,8 +2652,8 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) {
|
||||
intval($channel['channel_id']),
|
||||
intval($cl['visible']),
|
||||
intval($cl['deleted']),
|
||||
dbesc($cl['name'])
|
||||
);
|
||||
dbesc($cl['name'])
|
||||
);
|
||||
}
|
||||
|
||||
// now look for any collections locally which weren't in the list we just received.
|
||||
@@ -2810,12 +2826,25 @@ function import_author_zot($x) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function zot_process_message_request($data)
|
||||
* If a site receives a comment to a post but finds they have no parent to attach it with, they
|
||||
* may send a 'request' packet containing the message_id of the missing parent. This is the handler
|
||||
* for that packet. We will create a message_list array of the entire conversation starting with
|
||||
* the missing parent and invoke delivery to the sender of the packet.
|
||||
*
|
||||
* include/deliver.php (for local delivery) and mod/post.php (for web delivery) detect the existence of
|
||||
* this 'message_list' at the destination and split it into individual messages which are
|
||||
* processed/delivered in order.
|
||||
*
|
||||
* Called from mod/post.php
|
||||
*/
|
||||
|
||||
|
||||
function zot_process_message_request($data) {
|
||||
$ret = array('success' => false);
|
||||
|
||||
// note: disabled until the loops stop.
|
||||
return $ret;
|
||||
|
||||
if(! $data['message_id']) {
|
||||
$ret['message'] = 'no message_id';
|
||||
logger('no message_id');
|
||||
@@ -2825,6 +2854,10 @@ function zot_process_message_request($data) {
|
||||
$sender = $data['sender'];
|
||||
$sender_hash = make_xchan_hash($sender['guid'],$sender['guid_sig']);
|
||||
|
||||
/*
|
||||
* Find the local channel in charge of this post (the first and only recipient of the request packet)
|
||||
*/
|
||||
|
||||
$arr = $data['recipients'][0];
|
||||
$recip_hash = make_xchan_hash($arr['guid'],$arr['guid_sig']);
|
||||
$c = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_hash = '%s' limit 1",
|
||||
@@ -2835,20 +2868,27 @@ function zot_process_message_request($data) {
|
||||
$ret['message'] .= 'recipient not found.' . EOL;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* fetch the requested conversation
|
||||
*/
|
||||
|
||||
$messages = zot_feed($c[0]['channel_id'],$sender_hash,array('message_id' => $data['message_id']));
|
||||
|
||||
if($messages) {
|
||||
$env_recips = null;
|
||||
|
||||
$r = q("select hubloc_guid, hubloc_url, hubloc_sitekey, hubloc_network, hubloc_flags, hubloc_callback, hubloc_host
|
||||
from hubloc where hubloc_hash = '" . dbesc($sender_hash) . "' and not (hubloc_flags & %d)>0
|
||||
from hubloc where hubloc_hash = '%s' and not (hubloc_flags & %d)>0
|
||||
and not (hubloc_status & %d)>0 group by hubloc_sitekey",
|
||||
intval(HUBLOC_FLAGS_DELETED),
|
||||
intval(HUBLOC_OFFLINE)
|
||||
);
|
||||
if(! $r) {
|
||||
logger('no hubs');
|
||||
return $ret;
|
||||
}
|
||||
dbesc($sender_hash),
|
||||
intval(HUBLOC_FLAGS_DELETED),
|
||||
intval(HUBLOC_OFFLINE)
|
||||
);
|
||||
if(! $r) {
|
||||
logger('no hubs');
|
||||
return $ret;
|
||||
}
|
||||
$hubs = $r;
|
||||
$hublist = array();
|
||||
$keys = array();
|
||||
@@ -2856,10 +2896,16 @@ function zot_process_message_request($data) {
|
||||
$private = ((array_key_exists('flags',$messages[0]) && in_array('private',$messages[0]['flags'])) ? true : false);
|
||||
if($private)
|
||||
$env_recips = array('guid' => $sender['guid'],'guid_sig' => $sender['guid_sig'],'hash' => $sender_hash);
|
||||
|
||||
$data_packet = json_encode(array('message_list' => $messages));
|
||||
|
||||
foreach($hubs as $hub) {
|
||||
$hash = random_string();
|
||||
|
||||
/*
|
||||
* create a notify packet and drop the actual message packet in the queue for pickup
|
||||
*/
|
||||
|
||||
$n = zot_build_packet($c[0],'notify',$env_recips,(($private) ? $hub['hubloc_sitekey'] : null),$hash,array('message_id' => $data['message_id']));
|
||||
q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async,
|
||||
outq_created, outq_updated, outq_notify, outq_msg )
|
||||
@@ -2875,6 +2921,11 @@ function zot_process_message_request($data) {
|
||||
dbesc($n),
|
||||
dbesc($data_packet)
|
||||
);
|
||||
|
||||
/*
|
||||
* invoke delivery to send out the notify packet
|
||||
*/
|
||||
|
||||
proc_run('php','include/deliver.php',$hash);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user