Resolved merge conflicts

This commit is contained in:
Manuel Jiménez Friaza 2018-11-24 13:01:01 +01:00
commit f865d6e5da
54 changed files with 1776 additions and 1066 deletions

View File

@ -5,8 +5,8 @@ Run hubzilla-setup.sh for an unattended installation of hubzilla.
The script is known to work without adjustments with
+ Hardware
- Mini-PC with Debian-9.2-amd64, or
- Rapberry 3 with Raspbian, Debian-9.3
- Mini-PC with Debian-9.5-amd64, or
- Rapberry 3 with Raspbian, Debian-9.5
+ DynDNS
- selfHOST.de
- freedns.afraid.org
@ -38,7 +38,7 @@ Software
- apt-get install git
- mkdir -p /var/www
- cd /var/www
- git clone https://github.com/redmatrix/hubzilla.git html
- git clone https://framagit.org/hubzilla/core.git html
- cd html/.homeinstall
- cp hubzilla-config.txt.template hubzilla-config.txt
- nano hubzilla-config.txt
@ -100,7 +100,7 @@ Create bootable USB drive with Debian on it.You could use
Example for command dd...
su -
dd if=2017-11-29-raspbian-stretch.img of=/dev/mmcblk0
dd if=2018-10-09-raspbian-stretch.img of=/dev/mmcblk0
Do not forget to unmount the SD card before and check if unmounted like in this example...
@ -164,7 +164,7 @@ Make the directory for apache and change diretory to it
Clone hubzilla from git ("git pull" will update it later)
git clone https://framagit.org/hubzilla/core html
git clone https://framagit.org/hubzilla/core.git html
Change to the install script
@ -217,14 +217,20 @@ After the daily script was executed at 05:30 (am)
- optionally view the daily log under yourdomain.org/admin/logs/
- set the logfile to var/www/html/hubzilla-daily.log
## Install Hubzilla in a Virtual Machine for Test Purposes
Modify the file "hubzilla-config.txt".
nano hubzilla-config.txt
There use
le_domain=localhost
## Note for the Rasperry
The script was tested with an Raspberry 3 under Raspian (Debian 9.3, 2017-11-29-raspbian-stretch.img).
It is recommended to deinstall these programms to avoid endless updates. Use...
sudo apt-get purge wolfram-engine sonic-pi
sudo apt-get autoremove
The script was tested with an Raspberry 3 under Raspian (Debian 9.5, 2018-10-09-raspbian-stretch.img).
It is recommended to run the Raspi without graphical frontend (X-Server). Use...
@ -234,7 +240,7 @@ to boot the Rapsi to the client console.
DO NOT FORGET TO CHANGE THE DEFAULT PASSWORD FOR USER PI!
On a Raspian Stretch (Debian 9) the validation of the mail address fails for the very first user.
If the validation of the mail address fails for the very first registered user...
This used to happen on some *bsd distros but there was some work to fix that a year ago (2017).
So if your system isn't registered in DNS or DNS isn't active do

View File

@ -18,6 +18,8 @@ db_pass=
# Example: my.cooldomain.org
# Example: cooldomain.org
#
# Example: localhost (test installation without certificates for httpS)
#
# Email is optional
#
#

View File

@ -816,15 +816,35 @@ install_run_selfhost
ping_domain
configure_cron_freedns
configure_cron_selfhost
install_letsencrypt
configure_apache_for_https
check_https
if [ "$le_domain" != "localhost" ]
then
install_letsencrypt
configure_apache_for_https
check_https
else
print_info "is localhost - skipped installation of letsencrypt and configuration of apache for https"
fi
install_hubzilla
rewrite_to_https
install_rsnapshot
if [ "$le_domain" != "localhost" ]
then
rewrite_to_https
install_rsnapshot
else
print_info "is localhost - skipped rewrite to https and installation of rsnapshot"
fi
configure_cron_daily
install_cryptosetup
write_uninstall_script
if [ "$le_domain" != "localhost" ]
then
install_cryptosetup
write_uninstall_script
else
print_info "is localhost - skipped installation of cryptosetup"
fi
#set +x # stop debugging from here

View File

@ -2,6 +2,8 @@
namespace Zotlabs\Daemon;
use Zotlabs\Lib\DReport;
require_once('include/zot.php');
require_once('include/queue_fn.php');
@ -58,11 +60,12 @@ class Deliver {
foreach($dresult as $xx) {
if(is_array($xx) && array_key_exists('message_id',$xx)) {
if(delivery_report_is_storable($xx)) {
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s','%s','%s','%s','%s' ) ",
if(DReport::is_storable($xx)) {
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
dbesc($xx['message_id']),
dbesc($xx['location']),
dbesc($xx['recipient']),
dbesc(($xx['name']) ? $xx['name'] : EMPTY_STR),
dbesc($xx['status']),
dbesc(datetime_convert($xx['date'])),
dbesc($xx['sender'])

View File

@ -2,6 +2,8 @@
namespace Zotlabs\Daemon;
use Zotlabs\Lib\Libzot;
require_once('include/queue_fn.php');
require_once('include/html2plain.php');
require_once('include/conversation.php');
@ -344,7 +346,16 @@ class Notifier {
return;
$encoded_item = encode_item($target_item);
// activitystreams version
$m = get_iconfig($target_item,'activitystreams','signed_data');
if($m) {
$activity = json_decode($m,true);
}
else {
$activity = \Zotlabs\Lib\Activity::encode_activity($target_item);
}
// Send comments to the owner to re-deliver to everybody in the conversation
// We only do this if the item in question originated on this site. This prevents looping.
// To clarify, a site accepting a new comment is responsible for sending it to the owner for relay.
@ -561,7 +572,7 @@ class Notifier {
logger('notifier_hub: ' . $hub['hubloc_url'],LOGGER_DEBUG);
if($hub['hubloc_network'] !== 'zot') {
if(! in_array($hub['hubloc_network'], [ 'zot','zot6' ])) {
$narr = [
'channel' => $channel,
'upstream' => $upstream,
@ -610,20 +621,27 @@ class Notifier {
continue;
}
// default: zot protocol
if(! in_array($hub['hubloc_network'], [ 'zot','zot6' ])) {
continue;
}
$hash = random_string();
$hash = new_uuid();
$packet = null;
$pmsg = '';
if($packet_type === 'refresh' || $packet_type === 'purge') {
$packet = zot_build_packet($channel,$packet_type,(($packet_recips) ? $packet_recips : null));
if($hub['hubloc_network'] === 'zot6') {
$packet = Libzot::build_packet($channel, $packet_type, ids_to_array($packet_recips,'hash'));
}
else {
$packet = zot_build_packet($channel,$packet_type,(($packet_recips) ? $packet_recips : null));
}
}
if($packet_type === 'keychange') {
if($packet_type === 'keychange' && $hub['hubloc_network'] === 'zot') {
$pmsg = get_pconfig($channel['channel_id'],'system','keychange');
$packet = zot_build_packet($channel,$packet_type,(($packet_recips) ? $packet_recips : null));
}
elseif($packet_type === 'request') {
elseif($packet_type === 'request' && $hub['hubloc_network'] === 'zot') {
$env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : '');
$packet = zot_build_packet($channel,$packet_type,$env,$hub['hubloc_sitekey'],$hub['site_crypto'],
$hash, array('message_id' => $request_message_id)
@ -636,6 +654,7 @@ class Notifier {
'account_id' => $channel['channel_account_id'],
'channel_id' => $channel['channel_id'],
'posturl' => $hub['hubloc_callback'],
'driver' => $hub['hubloc_network'],
'notify' => $packet,
'msg' => (($pmsg) ? json_encode($pmsg) : '')
));
@ -643,18 +662,32 @@ class Notifier {
else {
$env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : '');
// currently zot6 delivery is only performed on normal items and not sync items or mail or anything else
// Eventually we will do this for all deliveries, but for now ensure this is precisely what we are dealing
// with before switching to zot6 as the primary zot6 handler checks for the existence of a message delivery report
// to trigger dequeue'ing
$z6 = (($encoded_item && $encoded_item['type'] === 'activity' && (! array_key_exists('allow_cid',$encoded_item))) ? true : false);
if($z6) {
$packet = zot6_build_packet($channel,'notify',$env, json_encode($encoded_item), (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'],$hash);
if($hub['hubloc_network'] === 'zot6') {
$zenv = [];
if($env) {
foreach($env as $e) {
$zenv[] = $e['hash'];
}
}
$packet_type = (($upstream || $uplink) ? 'response' : 'activity');
$packet = Libzot::build_packet($channel,$packet_type,$zenv,$activity,'activitystreams',(($private) ? $hub['hubloc_sitekey'] : null),$hub['site_crypto']);
}
else {
$packet = zot_build_packet($channel,'notify',$env, (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'],$hash);
// currently zot6 delivery is only performed on normal items and not sync items or mail or anything else
// Eventually we will do this for all deliveries, but for now ensure this is precisely what we are dealing
// with before switching to zot6 as the primary zot6 handler checks for the existence of a message delivery report
// to trigger dequeue'ing
$z6 = (($encoded_item && $encoded_item['type'] === 'activity' && (! array_key_exists('allow_cid',$encoded_item))) ? true : false);
if($z6) {
$packet = zot6_build_packet($channel,'notify',$env, json_encode($encoded_item), (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'],$hash);
}
else {
$packet = zot_build_packet($channel,'notify',$env, (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'],$hash);
}
}
queue_insert(
@ -663,6 +696,7 @@ class Notifier {
'account_id' => $target_item['aid'],
'channel_id' => $target_item['uid'],
'posturl' => $hub['hubloc_callback'],
'driver' => $hub['hubloc_network'],
'notify' => $packet,
'msg' => json_encode($encoded_item)
]

View File

@ -7,22 +7,25 @@ namespace Zotlabs\Lib;
*
* Parses an ActivityStream JSON string.
*/
class ActivityStreams {
public $raw = null;
public $data;
public $valid = false;
public $id = '';
public $type = '';
public $actor = null;
public $obj = null;
public $tgt = null;
public $origin = null;
public $owner = null;
public $signer = null;
public $ldsig = null;
public $sigok = false;
public $recips = null;
public $raw = null;
public $data = null;
public $valid = false;
public $deleted = false;
public $id = '';
public $parent_id = '';
public $type = '';
public $actor = null;
public $obj = null;
public $tgt = null;
public $origin = null;
public $owner = null;
public $signer = null;
public $ldsig = null;
public $sigok = false;
public $recips = null;
public $raw_recips = null;
/**
@ -35,16 +38,49 @@ class ActivityStreams {
function __construct($string) {
$this->raw = $string;
$this->data = json_decode($string, true);
if(is_array($string)) {
$this->data = $string;
}
else {
$this->data = json_decode($string, true);
}
if($this->data) {
// verify and unpack JSalmon signature if present
if(is_array($this->data) && array_key_exists('signed',$this->data)) {
$ret = JSalmon::verify($this->data);
$tmp = JSalmon::unpack($this->data['data']);
if($ret && $ret['success']) {
if($ret['signer']) {
$saved = json_encode($this->data,JSON_UNESCAPED_SLASHES);
$this->data = $tmp;
$this->data['signer'] = $ret['signer'];
$this->data['signed_data'] = $saved;
if($ret['hubloc']) {
$this->data['hubloc'] = $ret['hubloc'];
}
}
}
}
$this->valid = true;
if(array_key_exists('type',$this->data) && array_key_exists('actor',$this->data) && array_key_exists('object',$this->data)) {
if($this->data['type'] === 'Delete' && $this->data['actor'] === $this->data['object']) {
$this->deleted = $this->data['actor'];
$this->valid = false;
}
}
}
if($this->is_valid()) {
$this->id = $this->get_property_obj('id');
$this->type = $this->get_primary_type();
$this->actor = $this->get_compound_property('actor');
$this->actor = $this->get_actor('actor','','');
$this->obj = $this->get_compound_property('object');
$this->tgt = $this->get_compound_property('target');
$this->origin = $this->get_compound_property('origin');
@ -53,14 +89,31 @@ class ActivityStreams {
$this->ldsig = $this->get_compound_property('signature');
if($this->ldsig) {
$this->signer = $this->get_compound_property('creator',$this->ldsig);
if($this->signer && $this->signer['publicKey'] && $this->signer['publicKey']['publicKeyPem']) {
$this->sigok = \Zotlabs\Lib\LDSignatures::verify($this->data,$this->signer['publicKey']['publicKeyPem']);
if($this->signer && is_array($this->signer) && array_key_exists('publicKey',$this->signer) && is_array($this->signer['publicKey']) && $this->signer['publicKey']['publicKeyPem']) {
$this->sigok = LDSignatures::verify($this->data,$this->signer['publicKey']['publicKeyPem']);
}
}
if(($this->type === 'Note') && (! $this->obj)) {
if(! $this->obj) {
$this->obj = $this->data;
$this->type = 'Create';
if(! $this->actor) {
$this->actor = $this->get_actor('attributedTo',$this->obj);
}
}
if($this->obj && is_array($this->obj) && $this->obj['actor'])
$this->obj['actor'] = $this->get_actor('actor',$this->obj);
if($this->tgt && is_array($this->tgt) && $this->tgt['actor'])
$this->tgt['actor'] = $this->get_actor('actor',$this->tgt);
$this->parent_id = $this->get_property_obj('inReplyTo');
if((! $this->parent_id) && is_array($this->obj)) {
$this->parent_id = $this->obj['inReplyTo'];
}
if((! $this->parent_id) && is_array($this->obj)) {
$this->parent_id = $this->obj['id'];
}
}
}
@ -190,30 +243,50 @@ class ActivityStreams {
$base = (($base) ? $base : $this->data);
$propname = (($prefix) ? $prefix . ':' : '') . $property;
if(! is_array($base)) {
btlogger('not an array: ' . print_r($base,true));
return null;
}
return ((array_key_exists($propname, $base)) ? $base[$propname] : null);
}
/**
* @brief Fetches a property from an URL.
*
* @param string $url
* @return NULL|mixed
*/
function fetch_property($url) {
return self::fetch($url);
}
static function fetch($url) {
$redirects = 0;
if(! check_siteallowed($url)) {
logger('blacklisted: ' . $url);
return null;
}
logger('fetch: ' . $url, LOGGER_DEBUG);
$x = z_fetch_url($url, true, $redirects,
['headers' => [ 'Accept: application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ]]);
if($x['success'])
[ 'headers' => [ 'Accept: application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ]]);
if($x['success']) {
$y = json_decode($x['body'],true);
logger('returned: ' . json_encode($y,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES));
return json_decode($x['body'], true);
}
else {
logger('fetch failed: ' . $url);
}
return null;
}
static function is_an_actor($s) {
return(in_array($s,[ 'Application','Group','Organization','Person','Service' ]));
}
/**
* @brief
*
@ -222,12 +295,70 @@ class ActivityStreams {
* @param string $namespace (optional) default empty
* @return NULL|mixed
*/
function get_compound_property($property, $base = '', $namespace = '') {
function get_actor($property,$base='',$namespace = '') {
$x = $this->get_property_obj($property, $base, $namespace);
if($this->is_url($x)) {
// SECURITY: If we have already stored the actor profile, re-generate it
// from cached data - don't refetch it from the network
$r = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_id_url = '%s' limit 1",
dbesc($x)
);
if($r) {
$y = Activity::encode_person($r[0]);
$y['cached'] = true;
return $y;
}
}
$actor = $this->get_compound_property($property,$base,$namespace,true);
if(is_array($actor) && self::is_an_actor($actor['type'])) {
if(array_key_exists('id',$actor) && (! array_key_exists('inbox',$actor))) {
$actor = $this->fetch_property($actor['id']);
}
return $actor;
}
return null;
}
/**
* @brief
*
* @param string $property
* @param array $base
* @param string $namespace (optional) default empty
* @param boolean $first (optional) default false, if true and result is a sequential array return only the first element
* @return NULL|mixed
*/
function get_compound_property($property, $base = '', $namespace = '', $first = false) {
$x = $this->get_property_obj($property, $base, $namespace);
if($this->is_url($x)) {
$x = $this->fetch_property($x);
}
// verify and unpack JSalmon signature if present
if(is_array($x) && array_key_exists('signed',$x)) {
$ret = JSalmon::verify($x);
$tmp = JSalmon::unpack($x['data']);
if($ret && $ret['success']) {
if($ret['signer']) {
$saved = json_encode($x,JSON_UNESCAPED_SLASHES);
$x = $tmp;
$x['signer'] = $ret['signer'];
$x['signed_data'] = $saved;
if($ret['hubloc']) {
$x['hubloc'] = $ret['hubloc'];
}
}
}
}
if($first && is_array($x) && array_key_exists(0,$x)) {
return $x[0];
}
return $x;
}
@ -273,4 +404,18 @@ class ActivityStreams {
return $x;
}
static function is_as_request() {
$x = getBestSupportedMimeType([
'application/ld+json;profile="https://www.w3.org/ns/activitystreams"',
'application/activity+json',
'application/ld+json;profile="http://www.w3.org/ns/activitystreams"'
]);
return(($x) ? true : false);
}
}

View File

@ -14,6 +14,7 @@ class DReport {
$this->location = $location;
$this->sender = $sender;
$this->recipient = $recipient;
$this->name = EMPTY_STR;
$this->message_id = $message_id;
$this->status = $status;
$this->date = datetime_convert();
@ -24,8 +25,8 @@ class DReport {
$this->date = datetime_convert();
}
function addto_recipient($name) {
$this->recipient = $this->recipient . ' ' . $name;
function set_name($name) {
$this->name = $name;
}
function addto_update($status) {
@ -37,6 +38,7 @@ class DReport {
$this->location = $arr['location'];
$this->sender = $arr['sender'];
$this->recipient = $arr['recipient'];
$this->name = $arr['name'];
$this->message_id = $arr['message_id'];
$this->status = $arr['status'];
$this->date = $arr['date'];
@ -47,9 +49,87 @@ class DReport {
'location' => $this->location,
'sender' => $this->sender,
'recipient' => $this->recipient,
'name' => $this->name,
'message_id' => $this->message_id,
'status' => $this->status,
'date' => $this->date
);
}
/**
* @brief decide whether to store a returned delivery report
*
* @param array $dr
* @return boolean
*/
static function is_storable($dr) {
if(get_config('system', 'disable_dreport'))
return false;
/**
* @hooks dreport_is_storable
* Called before storing a dreport record to determine whether to store it.
* * \e array
*/
call_hooks('dreport_is_storable', $dr);
// let plugins accept or reject - if neither, continue on
if(array_key_exists('accept',$dr) && intval($dr['accept']))
return true;
if(array_key_exists('reject',$dr) && intval($dr['reject']))
return false;
if(! ($dr['sender']))
return false;
// Is the sender one of our channels?
$c = q("select channel_id from channel where channel_hash = '%s' limit 1",
dbesc($dr['sender'])
);
if(! $c)
return false;
// is the recipient one of our connections, or do we want to store every report?
$rxchan = $dr['recipient'];
$pcf = get_pconfig($c[0]['channel_id'],'system','dreport_store_all');
if($pcf)
return true;
// We always add ourself as a recipient to private and relayed posts
// So if a remote site says they can't find us, that's no big surprise
// and just creates a lot of extra report noise
if(($dr['location'] !== z_root()) && ($dr['sender'] === $rxchan) && ($dr['status'] === 'recipient_not_found'))
return false;
// If you have a private post with a recipient list, every single site is going to report
// back a failed delivery for anybody on that list that isn't local to them. We're only
// concerned about this if we have a local hubloc record which says we expected them to
// have a channel on that site.
$r = q("select hubloc_id from hubloc where hubloc_hash = '%s' and hubloc_url = '%s'",
dbesc($rxchan),
dbesc($dr['location'])
);
if((! $r) && ($dr['status'] === 'recipient_not_found'))
return false;
$r = q("select abook_id from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
dbesc($rxchan),
intval($c[0]['channel_id'])
);
if($r)
return true;
return false;
}
}

View File

@ -2,15 +2,13 @@
namespace Zotlabs\Lib;
use Zotlabs\Zot6\HTTPSig;
class JSalmon {
static function sign($data,$key_id,$key) {
static function sign($data,$key_id,$key,$data_type = 'application/x-zot+json') {
$arr = $data;
$data = json_encode($data,JSON_UNESCAPED_SLASHES);
$data = base64url_encode($data, false); // do not strip padding
$data_type = 'application/x-zot+json';
$data = base64url_encode(json_encode($data,true),true); // strip padding
$encoding = 'base64url';
$algorithm = 'RSA-SHA256';
@ -18,9 +16,9 @@ class JSalmon {
// precomputed base64url encoding of data_type, encoding, algorithm concatenated with periods
$precomputed = '.' . base64url_encode($data_type,false) . '.YmFzZTY0dXJs.UlNBLVNIQTI1Ng==';
$precomputed = '.' . base64url_encode($data_type,true) . '.YmFzZTY0dXJs.UlNBLVNIQTI1Ng';
$signature = base64url_encode(rsa_sign($data . $precomputed, $key), false);
$signature = base64url_encode(rsa_sign($data . $precomputed, $key), true);
return ([
'signed' => true,
@ -30,9 +28,45 @@ class JSalmon {
'alg' => $algorithm,
'sigs' => [
'value' => $signature,
'key_id' => base64url_encode($key_id)
'key_id' => base64url_encode($key_id, true)
]
]);
}
static function verify($x) {
logger('verify');
$ret = [ 'results' => [] ];
if(! is_array($x)) {
return $false;
}
if(! ( array_key_exists('signed',$x) && $x['signed'])) {
return $false;
}
$signed_data = preg_replace('/\s+/','',$x['data']) . '.'
. base64url_encode($x['data_type'],true) . '.'
. base64url_encode($x['encoding'],true) . '.'
. base64url_encode($x['alg'],true);
$key = HTTPSig::get_key(EMPTY_STR,base64url_decode($x['sigs']['key_id']));
logger('key: ' . print_r($key,true));
if($key['portable_id'] && $key['public_key']) {
if(rsa_verify($signed_data,base64url_decode($x['sigs']['value']),$key['public_key'])) {
logger('verified');
$ret = [ 'success' => true, 'signer' => $key['portable_id'], 'hubloc' => $key['hubloc'] ];
}
}
return $ret;
}
static function unpack($data) {
return json_decode(base64url_decode($data),true);
}
}

View File

@ -109,7 +109,7 @@ class Libzot {
$data = [
'type' => $type,
'encoding' => $encoding,
'sender' => $channel['channel_hash'],
'sender' => $channel['channel_portable_id'],
'site_id' => self::make_xchan_hash(z_root(), get_config('system','pubkey')),
'version' => System::get_zot_revision(),
];
@ -329,8 +329,14 @@ class Libzot {
return false;
if($channel && $record['data']['permissions']) {
$old_read_stream_perm = their_perms_contains($channel['channel_id'],$x['hash'],'view_stream');
set_abconfig($channel['channel_id'],$x['hash'],'system','their_perms',$record['data']['permissions']);
$permissions = explode(',',$record['data']['permissions']);
if($permissions && is_array($permissions)) {
$old_read_stream_perm = get_abconfig($channel['channel_id'],$x['hash'],'their_perms','view_stream');
foreach($permissions as $p) {
set_abconfig($channel['channel_id'],$x['hash'],'their_perms',$p,'1');
}
}
if(array_key_exists('profile',$record['data']) && array_key_exists('next_birthday',$record['data']['profile'])) {
$next_birthday = datetime_convert('UTC','UTC',$record['data']['profile']['next_birthday']);
@ -350,7 +356,7 @@ class Libzot {
);
if($r) {
logger('4');
// connection exists
// if the dob is the same as what we have stored (disregarding the year), keep the one
@ -379,14 +385,16 @@ class Libzot {
else {
$p = Permissions::connect_perms($channel['channel_id']);
$my_perms = Permissions::serialise($p['perms']);
$my_perms = $p['perms'];
$automatic = $p['automatic'];
// new connection
if($my_perms) {
set_abconfig($channel['channel_id'],$x['hash'],'system','my_perms',$my_perms);
foreach($my_perms as $k => $v) {
set_abconfig($channel['channel_id'],$x['hash'],'my_perms',$k,$v);
}
}
$closeness = get_pconfig($channel['channel_id'],'system','new_abook_closeness');
@ -409,7 +417,7 @@ class Libzot {
if($y) {
logger("New introduction received for {$channel['channel_name']}");
$new_perms = get_all_perms($channel['channel_id'],$x['hash']);
$new_perms = get_all_perms($channel['channel_id'],$x['hash'],false);
// Send a clone sync packet and a permissions update if permissions have changed
@ -425,7 +433,7 @@ class Libzot {
[
'type' => NOTIFY_INTRO,
'from_xchan' => $x['hash'],
'to_xchan' => $channel['channel_hash'],
'to_xchan' => $channel['channel_portable_id'],
'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id']
]
);
@ -500,6 +508,7 @@ class Libzot {
$r = q("select hubloc.*, site.site_crypto from hubloc left join site on hubloc_url = site_url
where hubloc_guid = '%s' and hubloc_guid_sig = '%s'
and hubloc_url = '%s' and hubloc_url_sig = '%s'
and hubloc_network = 'zot6'
and hubloc_site_id = '%s' $limit",
dbesc($arr['id']),
dbesc($arr['id_sig']),
@ -776,7 +785,7 @@ class Libzot {
// see if this is a channel clone that's hosted locally - which we treat different from other xchans/connections
$local = q("select channel_account_id, channel_id from channel where channel_hash = '%s' limit 1",
$local = q("select channel_account_id, channel_id from channel where channel_portable_id = '%s' limit 1",
dbesc($xchan_hash)
);
if($local) {
@ -966,6 +975,7 @@ class Libzot {
}
$x = crypto_unencapsulate($x, get_config('system','prvkey'));
if(! is_array($x)) {
$x = json_decode($x,true);
}
@ -996,7 +1006,7 @@ class Libzot {
dbesc($xx['recipient']),
dbesc($xx['name']),
dbesc($xx['status']),
dbesc(datetime_convert($xx['date'])),
dbesc(datetime_convert('UTC','UTC',$xx['date'])),
dbesc($xx['sender'])
);
}
@ -1129,7 +1139,7 @@ class Libzot {
if($recip_arr) {
stringify_array_elms($recip_arr,true);
$recips = implode(',',$recip_arr);
$r = q("select channel_hash as hash from channel where channel_hash in ( " . $recips . " ) and channel_removed = 0 ");
$r = q("select channel_portable_id as hash from channel where channel_portable_id in ( " . $recips . " ) and channel_removed = 0 ");
}
if(! $r) {
@ -1303,12 +1313,12 @@ class Libzot {
$r = [];
$c = q("select channel_id, channel_hash from channel where channel_removed = 0");
$c = q("select channel_id, channel_portable_id from channel where channel_removed = 0");
if($c) {
foreach($c as $cc) {
if(perm_is_allowed($cc['channel_id'],$msg['sender'],$perm)) {
$r[] = $cc['channel_hash'];
$r[] = $cc['channel_portable_id'];
}
}
}
@ -1316,7 +1326,7 @@ class Libzot {
if($include_sys) {
$sys = get_sys_channel();
if($sys)
$r[] = $sys['channel_hash'];
$r[] = $sys['channel_portable_id'];
}
@ -1332,7 +1342,7 @@ class Libzot {
if($tag['type'] === 'Mention' && (strpos($tag['href'],z_root()) !== false)) {
$address = basename($tag['href']);
if($address) {
$z = q("select channel_hash as hash from channel where channel_address = '%s'
$z = q("select channel_portable_id as hash from channel where channel_address = '%s'
and channel_removed = 0 limit 1",
dbesc($address)
);
@ -1353,7 +1363,7 @@ class Libzot {
$thread_parent = self::find_parent($msg,$act);
if($thread_parent) {
$z = q("select channel_hash as hash from channel left join item on channel.channel_id = item.uid where ( item.thr_parent = '%s' OR item.parent_mid = '%s' ) ",
$z = q("select channel_portable_id as hash from channel left join item on channel.channel_id = item.uid where ( item.thr_parent = '%s' OR item.parent_mid = '%s' ) ",
dbesc($thread_parent),
dbesc($thread_parent)
);
@ -1427,7 +1437,7 @@ class Libzot {
* access checks.
*/
if($sender === $channel['channel_hash'] && $arr['author_xchan'] === $channel['channel_hash'] && $arr['mid'] === $arr['parent_mid']) {
if($sender === $channel['channel_portable_id'] && $arr['author_xchan'] === $channel['channel_portable_id'] && $arr['mid'] === $arr['parent_mid']) {
$DR->update('self delivery ignored');
$result[] = $DR->get();
continue;
@ -1709,7 +1719,7 @@ class Libzot {
$stored = (($item_result && $item_result['item']) ? $item_result['item'] : false);
if((is_array($stored)) && ($stored['id'] != $stored['parent'])
&& ($stored['author_xchan'] === $channel['channel_hash'])) {
&& ($stored['author_xchan'] === $channel['channel_hash'] || $stored['author_xchan'] === $channel['channel_portable_id'])) {
retain_item($stored['item']['parent']);
}
@ -1809,9 +1819,9 @@ class Libzot {
}
logger('FOF Activity received: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG);
logger('FOF Activity recipient: ' . $channel['channel_hash'], LOGGER_DATA, LOG_DEBUG);
logger('FOF Activity recipient: ' . $channel['channel_portable_id'], LOGGER_DATA, LOG_DEBUG);
$result = self::process_delivery($arr['owner_xchan'],$arr, [ $channel['channel_hash'] ],false,false,true);
$result = self::process_delivery($arr['owner_xchan'],$arr, [ $channel['channel_portable_id'] ],false,false,true);
if ($result) {
$ret = array_merge($ret, $result);
}
@ -2047,7 +2057,7 @@ class Libzot {
$DR = new DReport(z_root(),$sender,$d,$arr['mid']);
$r = q("select * from channel where channel_hash = '%s' limit 1",
$r = q("select * from channel where channel_portable_id = '%s' limit 1",
dbesc($d['hash'])
);
@ -2202,7 +2212,7 @@ class Libzot {
$loc = $locations[0];
$r = q("select * from channel where channel_hash = '%s' limit 1",
$r = q("select * from channel where channel_portable_id = '%s' limit 1",
dbesc($sender_hash)
);
@ -2210,7 +2220,7 @@ class Libzot {
return;
if($loc['url'] !== z_root()) {
$x = q("update channel set channel_moved = '%s' where channel_hash = '%s' limit 1",
$x = q("update channel set channel_moved = '%s' where channel_portable_id = '%s' limit 1",
dbesc($loc['url']),
dbesc($sender_hash)
);
@ -2246,7 +2256,7 @@ class Libzot {
static function encode_locations($channel) {
$ret = [];
$x = self::get_hublocs($channel['channel_hash']);
$x = self::get_hublocs($channel['channel_portable_id']);
if($x && count($x)) {
foreach($x as $hub) {
@ -2557,6 +2567,9 @@ class Libzot {
static function zotinfo($arr) {
logger('arr: ' . print_r($arr,true));
$ret = [];
$zhash = ((x($arr,'guid_hash')) ? $arr['guid_hash'] : '');
@ -2593,13 +2606,13 @@ class Libzot {
$r = null;
if(strlen($zhash)) {
$r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash
where channel_hash = '%s' limit 1",
$r = q("select channel.*, xchan.* from channel left join xchan on channel_portable_id = xchan_hash
where channel_portable_id = '%s' limit 1",
dbesc($zhash)
);
}
elseif(strlen($zguid) && strlen($zguid_sig)) {
$r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash
$r = q("select channel.*, xchan.* from channel left join xchan on channel_portable_id = xchan_hash
where channel_guid = '%s' and channel_guid_sig = '%s' limit 1",
dbesc($zguid),
dbesc($zguid_sig)
@ -2607,7 +2620,7 @@ class Libzot {
}
elseif(strlen($zaddr)) {
if(strpos($zaddr,'[system]') === false) { /* normal address lookup */
$r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash
$r = q("select channel.*, xchan.* from channel left join xchan on channel_portable_id = xchan_hash
where ( channel_address = '%s' or xchan_addr = '%s' ) limit 1",
dbesc($zaddr),
dbesc($zaddr)
@ -2627,10 +2640,10 @@ class Libzot {
*
*/
$r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash
$r = q("select channel.*, xchan.* from channel left join xchan on channel_portable_id = xchan_hash
where channel_system = 1 order by channel_id limit 1");
if(! $r) {
$r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash
$r = q("select channel.*, xchan.* from channel left join xchan on channel_portable_id = xchan_hash
where channel_removed = 0 order by channel_id limit 1");
}
}
@ -2749,7 +2762,7 @@ class Libzot {
];
$ret['channel_role'] = get_pconfig($e['channel_id'],'system','permissions_role','custom');
$ret['protocols'] = [ 'zot6' ];
$ret['protocols'] = [ 'zot', 'zot6' ];
$ret['searchable'] = $searchable;
$ret['adult_content'] = $adult_channel;
$ret['public_forum'] = $public_forum;
@ -2774,7 +2787,7 @@ class Libzot {
if(! $ret['follow_url'])
$ret['follow_url'] = z_root() . '/follow?f=&url=%s';
$permissions = get_all_perms($e['channel_id'],$ztarget_hash,false);
$permissions = get_all_perms($e['channel_id'],$ztarget_hash,false,false);
if($ztarget_hash) {
$permissions['connected'] = false;

View File

@ -40,26 +40,17 @@ class NativeWiki {
function create_wiki($channel, $observer_hash, $wiki, $acl) {
// Generate unique resource_id using the same method as item_message_id()
do {
$dups = false;
$resource_id = random_string();
$r = q("SELECT mid FROM item WHERE resource_id = '%s' AND resource_type = '%s' AND uid = %d LIMIT 1",
dbesc($resource_id),
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
intval($channel['channel_id'])
);
if($r)
$dups = true;
} while($dups == true);
$resource_id = new_uuid();
$uuid = new_uuid();
$ac = $acl->get();
$mid = item_message_id();
$mid = z_root() . '/item/' . $uuid;
$arr = array(); // Initialize the array of parameters for the post
$item_hidden = ((intval($wiki['postVisible']) === 0) ? 1 : 0);
$wiki_url = z_root() . '/wiki/' . $channel['channel_address'] . '/' . $wiki['urlName'];
$arr['aid'] = $channel['channel_account_id'];
$arr['uuid'] = $uuid;
$arr['uid'] = $channel['channel_id'];
$arr['mid'] = $mid;
$arr['parent_mid'] = $mid;

View File

@ -39,6 +39,8 @@ class ThreadItem {
$this->data = $data;
$this->toplevel = ($this->get_id() == $this->get_data_value('parent'));
$observer = \App::get_observer();
// Prepare the children
if($data['children']) {
foreach($data['children'] as $item) {
@ -51,6 +53,7 @@ class ThreadItem {
continue;
}
$child = new ThreadItem($item);
$this->add_child($child);
}
@ -299,8 +302,10 @@ class ThreadItem {
if($keep_reports === 0)
$keep_reports = 10;
if((! get_config('system','disable_dreport')) && strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC',"now - $keep_reports days")) > 0)
if((! get_config('system','disable_dreport')) && strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC',"now - $keep_reports days")) > 0) {
$dreport = t('Delivery Report');
$dreport_link = gen_link_id($item['mid']);
}
if(strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC','now - 12 hours')) > 0)
$is_new = true;
@ -316,7 +321,7 @@ class ThreadItem {
$owner_address = substr($item['owner']['xchan_addr'],0,strpos($item['owner']['xchan_addr'],'@'));
$viewthread = $item['llink'];
if($conv->get_mode() === 'channel')
$viewthread = z_root() . '/channel/' . $owner_address . '?f=&mid=' . urlencode($item['mid']);
$viewthread = z_root() . '/channel/' . $owner_address . '?f=&mid=' . urlencode(gen_link_id($item['mid']));
$comment_count_txt = sprintf( tt('%d comment','%d comments',$total_children),$total_children );
$list_unseen_txt = (($unseen_comments) ? sprintf('%d unseen',$unseen_comments) : '');
@ -364,6 +369,7 @@ class ThreadItem {
'thread_action_menu' => thread_action_menu($item,$conv->get_mode()),
'thread_author_menu' => thread_author_menu($item,$conv->get_mode()),
'dreport' => $dreport,
'dreport_link' => $dreport_link,
'name' => $profile_name,
'thumb' => $profile_avatar,
'osparkle' => $osparkle,

View File

@ -2,7 +2,7 @@
namespace Zotlabs\Lib;
use Zotlabs\Web\HTTPSig;
use Zotlabs\Zot6\HTTPSig;
class Zotfinger {
@ -12,10 +12,19 @@ class Zotfinger {
return false;
}
if($channel) {
$m = parse_url($resource);
$data = json_encode([ 'zot_token' => random_string() ]);
if($channel && $m) {
$headers = [
'Accept' => 'application/x-zot+json',
'X-Zot-Token' => random_string(),
'Accept' => 'application/x-zot+json',
'Content-Type' => 'application/x-zot+json',
'X-Zot-Token' => random_string(),
'Digest' => HTTPSig::generate_digest_header($data),
'Host' => $m['host'],
'(request-target)' => 'post ' . get_request_string($resource)
];
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),false);
}
@ -27,7 +36,9 @@ class Zotfinger {
$redirects = 0;
$x = z_fetch_url($resource,false,$redirects, [ 'headers' => $h ] );
$x = z_post_url($resource,$data,$redirects, [ 'headers' => $h ] );
logger('fetch: ' . print_r($x,true));
if($x['success']) {
@ -39,6 +50,8 @@ class Zotfinger {
$result['data'] = json_decode(crypto_unencapsulate($result['data'],get_config('system','prvkey')),true);
}
logger('decrypted: ' . print_r($result,true));
return $result;
}

View File

@ -6,6 +6,8 @@ namespace Zotlabs\Module;
use App;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\PermissionDescription;
use Zotlabs\Zot6\HTTPSig;
use Zotlabs\Lib\Libzot;
require_once('include/items.php');
require_once('include/security.php');
@ -43,6 +45,48 @@ class Channel extends Controller {
$profile = 0;
$channel = App::get_channel();
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
$which = $channel['channel_address'];
$profile = argv(1);
}
$channel = channelx_by_nick($which);
if(! $channel) {
http_status_exit(404, 'Not found');
}
// handle zot6 channel discovery
if(Libzot::is_zot_request()) {
$sigdata = HTTPSig::verify(file_get_contents('php://input'));
if($sigdata && $sigdata['signer'] && $sigdata['header_valid']) {
$data = json_encode(Libzot::zotinfo([ 'address' => $channel['channel_address'], 'target_url' => $sigdata['signer'] ]));
$s = q("select site_crypto, hubloc_sitekey from site left join hubloc on hubloc_url = site_url where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
dbesc($sigdata['signer'])
);
if($s) {
$data = json_encode(crypto_encapsulate($data,$s[0]['hubloc_sitekey'],Libzot::best_algorithm($s[0]['site_crypto'])));
}
}
else {
$data = json_encode(Libzot::zotinfo([ 'address' => $channel['channel_address'] ]));
}
$headers = [
'Content-Type' => 'application/x-zot+json',
'Digest' => HTTPSig::generate_digest_header($data),
'(request-target)' => strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI']
];
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel));
HTTPSig::set_headers($h);
echo $data;
killme();
}
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
$which = $channel['channel_address'];
$profile = argv(1);

View File

@ -8,6 +8,7 @@ namespace Zotlabs\Module;
*/
use Zotlabs\Lib\Apps;
use Zotlabs\Lib\Libzot;
require_once('include/socgraph.php');
require_once('include/selectors.php');
@ -475,6 +476,10 @@ class Connedit extends \Zotlabs\Web\Controller {
if(! zot_refresh($orig_record[0],\App::get_channel()))
notice( t('Refresh failed - channel is currently unavailable.') );
}
elseif($orig_record[0]['xchan_network'] === 'zot6') {
if(! Libzot::refresh($orig_record[0],\App::get_channel()))
notice( t('Refresh failed - channel is currently unavailable.') );
}
else {
// if you are on a different network we'll force a refresh of the connection basic info

View File

@ -17,9 +17,17 @@ class Dreport extends \Zotlabs\Web\Controller {
$mid = ((argc() > 1) ? argv(1) : '');
if(strpos($mid,'b64.') === 0)
$mid = @base64url_decode(substr($mid,4));
if($mid === 'push') {
$table = 'push';
$mid = ((argc() > 2) ? argv(2) : '');
if(strpos($mid,'b64.') === 0)
$mid = @base64url_decode(substr($mid,4));
if($mid) {
$i = q("select id from item where mid = '%s' and uid = %d and ( author_xchan = '%s' or ( owner_xchan = '%s' and item_wall = 1 )) ",
dbesc($mid),
@ -38,6 +46,9 @@ class Dreport extends \Zotlabs\Web\Controller {
if($mid === 'mail') {
$table = 'mail';
$mid = ((argc() > 2) ? argv(2) : '');
if(strpos($mid,'b64.') === 0)
$mid = @base64url_decode(substr($mid,4));
}
@ -80,7 +91,6 @@ class Dreport extends \Zotlabs\Web\Controller {
}
for($x = 0; $x < count($r); $x++ ) {
$r[$x]['name'] = escape_tags(substr($r[$x]['dreport_recip'],strpos($r[$x]['dreport_recip'],' ')));
// This has two purposes: 1. make the delivery report strings translateable, and
// 2. assign an ordering to item delivery results so we can group them and provide
@ -138,14 +148,14 @@ class Dreport extends \Zotlabs\Web\Controller {
$entries = array();
foreach($r as $rr) {
$entries[] = [
'name' => $rr['name'],
'name' => escape_tags($rr['dreport_name'] ?: $rr['dreport_recip']),
'result' => escape_tags($rr['dreport_result']),
'time' => escape_tags(datetime_convert('UTC',date_default_timezone_get(),$rr['dreport_time']))
];
}
$o = replace_macros(get_markup_template('dreport.tpl'), array(
'$title' => sprintf( t('Delivery report for %1$s'),substr($mid,0,32)) . '...',
'$title' => sprintf( t('Delivery report for %1$s'),basename($mid)) . '...',
'$table' => $table,
'$mid' => urlencode($mid),
'$options' => t('Options'),
@ -162,9 +172,9 @@ class Dreport extends \Zotlabs\Web\Controller {
private static function dreport_gravity_sort($a,$b) {
if($a['gravity'] == $b['gravity']) {
if($a['name'] === $b['name'])
if($a['dreport_name'] === $b['dreport_name'])
return strcmp($a['dreport_time'],$b['dreport_time']);
return strcmp($a['name'],$b['name']);
return strcmp($a['dreport_name'],$b['dreport_name']);
}
return (($a['gravity'] > $b['gravity']) ? 1 : (-1));
}

View File

@ -133,9 +133,11 @@ class Impel extends \Zotlabs\Web\Controller {
$arr['author_xchan'] = (($j['author_xchan']) ? $j['author_xchan'] : get_observer_hash());
$arr['mimetype'] = (($j['mimetype']) ? $j['mimetype'] : 'text/bbcode');
if(! $j['mid'])
$j['mid'] = item_message_id();
if(! $j['mid']) {
$j['uuid'] = item_message_id();
$j['mid'] = z_root() . '/item/' . $j['uuid'];
}
$arr['uuid'] = $j['uuid'];
$arr['mid'] = $arr['parent_mid'] = $j['mid'];

View File

@ -2,6 +2,16 @@
namespace Zotlabs\Module;
use Zotlabs\Lib\IConfig;
use Zotlabs\Lib\Enotify;
use Zotlabs\Web\Controller;
use Zotlabs\Daemon\Master;
require_once('include/crypto.php');
require_once('include/items.php');
require_once('include/security.php');
/**
*
* This is the POST destination for most all locally posted
@ -17,16 +27,8 @@ namespace Zotlabs\Module;
*
*/
require_once('include/crypto.php');
require_once('include/items.php');
require_once('include/attach.php');
require_once('include/bbcode.php');
require_once('include/security.php');
use \Zotlabs\Lib as Zlib;
class Item extends \Zotlabs\Web\Controller {
class Item extends Controller {
function post() {
@ -392,6 +394,7 @@ class Item extends \Zotlabs\Web\Controller {
$verb = $orig_post['verb'];
$app = $orig_post['app'];
$title = escape_tags(trim($_REQUEST['title']));
$summary = trim($_REQUEST['summary']);
$body = trim($_REQUEST['body']);
$item_flags = $orig_post['item_flags'];
@ -454,6 +457,7 @@ class Item extends \Zotlabs\Web\Controller {
$coord = notags(trim($_REQUEST['coord']));
$verb = notags(trim($_REQUEST['verb']));
$title = escape_tags(trim($_REQUEST['title']));
$summary = trim($_REQUEST['summary']);
$body = trim($_REQUEST['body']);
$body .= trim($_REQUEST['attachment']);
$postopts = '';
@ -505,12 +509,14 @@ class Item extends \Zotlabs\Web\Controller {
&& ($channel['channel_pageflags'] & PAGE_ALLOWCODE)) ? true : false);
if($preview) {
$summary = z_input_filter($summary,$mimetype,$execflag);
$body = z_input_filter($body,$mimetype,$execflag);
}
$arr = [ 'profile_uid' => $profile_uid, 'content' => $body, 'mimetype' => $mimetype ];
$arr = [ 'profile_uid' => $profile_uid, 'summary' => $summary, 'content' => $body, 'mimetype' => $mimetype ];
call_hooks('post_content',$arr);
$summary = $arr['summary'];
$body = $arr['content'];
$mimetype = $arr['mimetype'];
@ -531,9 +537,23 @@ class Item extends \Zotlabs\Web\Controller {
// we may need virtual or template classes to implement the possible alternatives
if(strpos($body,'[/summary]') !== false) {
$match = '';
$cnt = preg_match("/\[summary\](.*?)\[\/summary\]/ism",$body,$match);
if($cnt) {
$summary .= $match[1];
}
$body_content = preg_replace("/^(.*?)\[summary\](.*?)\[\/summary\](.*?)$/ism", '',$body);
$body = trim($body_content);
}
$summary = cleanup_bbcode($summary);
$body = cleanup_bbcode($body);
// Look for tags and linkify them
$results = linkify_tags($a, $summary, ($uid) ? $uid : $profile_uid);
$results = linkify_tags($a, $body, ($uid) ? $uid : $profile_uid);
if($results) {
@ -579,6 +599,9 @@ class Item extends \Zotlabs\Web\Controller {
if(! $preview) {
fix_attached_photo_permissions($profile_uid,$owner_xchan['xchan_hash'],((strpos($body,'[/crypt]')) ? $_POST['media_str'] : $body),$str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny);
fix_attached_photo_permissions($profile_uid,$owner_xchan['xchan_hash'],((strpos($summary,'[/crypt]')) ? $_POST['media_str'] : $summary),$str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny);
fix_attached_file_permissions($channel,$observer['xchan_hash'],((strpos($body,'[/crypt]')) ? $_POST['media_str'] : $body),$str_contact_allow,$str_group_allow,$str_contact_deny,$str_group_deny);
}
@ -711,7 +734,8 @@ class Item extends \Zotlabs\Web\Controller {
$notify_type = (($parent) ? 'comment-new' : 'wall-new' );
if(! $mid) {
$mid = (($message_id) ? $message_id : item_message_id());
$uuid = (($message_id) ? $message_id : item_message_id());
$mid = z_root() . '/item/' . $uuid;
}
@ -766,6 +790,7 @@ class Item extends \Zotlabs\Web\Controller {
$datarray['aid'] = $channel['channel_account_id'];
$datarray['uid'] = $profile_uid;
$datarray['uuid'] = $uuid;
$datarray['owner_xchan'] = (($owner_hash) ? $owner_hash : $owner_xchan['xchan_hash']);
$datarray['author_xchan'] = $observer['xchan_hash'];
$datarray['created'] = $created;
@ -778,6 +803,7 @@ class Item extends \Zotlabs\Web\Controller {
$datarray['parent_mid'] = $parent_mid;
$datarray['mimetype'] = $mimetype;
$datarray['title'] = $title;
$datarray['summary'] = $summary;
$datarray['body'] = $body;
$datarray['app'] = $app;
$datarray['location'] = $location;
@ -887,12 +913,12 @@ class Item extends \Zotlabs\Web\Controller {
$datarray['title'] = mb_substr($datarray['title'],0,191);
if($webpage) {
Zlib\IConfig::Set($datarray,'system', webpage_to_namespace($webpage),
(($pagetitle) ? $pagetitle : substr($datarray['mid'],0,16)),true);
IConfig::Set($datarray,'system', webpage_to_namespace($webpage),
(($pagetitle) ? $pagetitle : basename($datarray['mid'])), true);
}
elseif($namespace) {
Zlib\IConfig::Set($datarray,'system', $namespace,
(($remote_id) ? $remote_id : substr($datarray['mid'],0,16)),true);
IConfig::Set($datarray,'system', $namespace,
(($remote_id) ? $remote_id : basename($datarray['mid'])), true);
}
@ -924,7 +950,7 @@ class Item extends \Zotlabs\Web\Controller {
}
}
if(! $nopush)
\Zotlabs\Daemon\Master::Summon(array('Notifier', 'edit_post', $post_id));
Master::Summon([ 'Notifier', 'edit_post', $post_id ]);
if($api_source)
@ -959,7 +985,7 @@ class Item extends \Zotlabs\Web\Controller {
// otherwise it will happen during delivery
if(($datarray['owner_xchan'] != $datarray['author_xchan']) && (intval($parent_item['item_wall']))) {
Zlib\Enotify::submit(array(
Enotify::submit(array(
'type' => NOTIFY_COMMENT,
'from_xchan' => $datarray['author_xchan'],
'to_xchan' => $datarray['owner_xchan'],
@ -977,7 +1003,7 @@ class Item extends \Zotlabs\Web\Controller {
$parent = $post_id;
if(($datarray['owner_xchan'] != $datarray['author_xchan']) && ($datarray['item_type'] == ITEM_TYPE_POST)) {
Zlib\Enotify::submit(array(
Enotify::submit(array(
'type' => NOTIFY_WALL,
'from_xchan' => $datarray['author_xchan'],
'to_xchan' => $datarray['owner_xchan'],
@ -1039,7 +1065,7 @@ class Item extends \Zotlabs\Web\Controller {
call_hooks('post_local_end', $datarray);
if(! $nopush)
\Zotlabs\Daemon\Master::Summon(array('Notifier', $notify_type, $post_id));
Master::Summon([ 'Notifier', $notify_type, $post_id ]);
logger('post_complete');

View File

@ -371,10 +371,13 @@ class Like extends \Zotlabs\Web\Controller {
}
}
$mid = item_message_id();
$uuid = item_message_id();
$arr = array();
$arr['uuid'] = $uuid;
$arr['mid'] = z_root() . '/item/' . $uuid;
if($extended_like) {
$arr['item_thread_top'] = 1;
$arr['item_origin'] = 1;
@ -476,7 +479,6 @@ class Like extends \Zotlabs\Web\Controller {
}
$arr['mid'] = $mid;
$arr['aid'] = (($extended_like) ? $ch[0]['channel_account_id'] : $owner_aid);
$arr['uid'] = $owner_uid;

View File

@ -70,7 +70,8 @@ class Mood extends Controller {
$poster = App::get_observer();
$mid = item_message_id();
$uuid = item_message_id();
$mid = z_root() . '/item/' . $uuid;
$action = sprintf( t('%1$s is %2$s','mood'), '[zrl=' . $poster['xchan_url'] . ']' . $poster['xchan_name'] . '[/zrl]' , $verbs[$verb]);
@ -78,6 +79,7 @@ class Mood extends Controller {
$arr['aid'] = get_account_id();
$arr['uid'] = $uid;
$arr['uuid'] = $uuid;
$arr['mid'] = $mid;
$arr['parent_mid'] = (($parent_mid) ? $parent_mid : $mid);
$arr['author_xchan'] = $poster['xchan_hash'];

View File

@ -1,15 +0,0 @@
<?php
namespace Zotlabs\Module;
class Nojs extends \Zotlabs\Web\Controller {
function init() {
$n = ((argc() > 1) ? intval(argv(1)) : 1);
setcookie('jsdisabled', $n, 0, '/');
$p = hex2bin($_GET['redir']);
$hasq = strpbrk($p,'?&');
goaway(z_root() . (($p) ? '/' . $p : '') . (($hasq) ? '' : '?f=' ) . '&jsdisabled=' . $n);
}
}

View File

@ -43,7 +43,7 @@ class Pconfig extends \Zotlabs\Web\Controller {
}
function get() {
function get() {
if(! local_channel()) {
return login();

View File

@ -44,6 +44,7 @@ class React extends \Zotlabs\Web\Controller {
return;
}
$uuid = item_message_id();
$n = array();
$n['aid'] = $channel['channel_account_id'];
@ -52,7 +53,8 @@ class React extends \Zotlabs\Web\Controller {
$n['item_type'] = $i[0]['item_type'];
$n['parent'] = $postid;
$n['parent_mid'] = $i[0]['mid'];
$n['mid'] = item_message_id();
$n['uuid'] = $uuid;
$n['mid'] = z_root() . '/item/' . $uuid;
$n['verb'] = ACTIVITY_REACT . '#' . $emoji;
$n['body'] = "\n\n[zmg=32x32]" . z_root() . '/images/emoji/' . $emoji . '.png[/zmg]' . "\n\n";
$n['author_xchan'] = $channel['channel_hash'];

View File

@ -106,8 +106,9 @@ class Subthread extends \Zotlabs\Web\Controller {
$mid = item_message_id();
$uuid = item_message_id();
$mid = z_root() . '/item/' . $uuid;
$post_type = (($item['resource_type'] === 'photo') ? t('photo') : t('status'));
$links = array(array('rel' => 'alternate','type' => 'text/html', 'href' => $item['plink']));
@ -145,6 +146,7 @@ class Subthread extends \Zotlabs\Web\Controller {
$arr = array();
$arr['uuid'] = $uuid;
$arr['mid'] = $mid;
$arr['aid'] = $owner_aid;
$arr['uid'] = $owner_uid;

View File

@ -204,6 +204,12 @@ class Wfinger extends \Zotlabs\Web\Controller {
'href' => z_root() . '/.well-known/zot-info' . '?address=' . $r[0]['xchan_addr'],
],
[
'rel' => 'http://purl.org/zot/protocol/6.0',
'type' => 'application/x-zot+json',
'href' => channel_url($r[0])
],
[
'rel' => 'http://purl.org/openwebauth/v1',
'type' => 'application/x-zot+json',

View File

@ -224,7 +224,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
}
$filesize = 0;
$hash = random_string();
$hash = new_uuid();
$f = 'store/' . $this->auth->owner_nick . '/' . (($this->os_path) ? $this->os_path . '/' : '') . $hash;

78
Zotlabs/Update/_1226.php Normal file
View File

@ -0,0 +1,78 @@
<?php
namespace Zotlabs\Update;
use Zotlabs\Lib\Libzot;
class _1226 {
function run() {
q("START TRANSACTION");
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
$r1 = q("ALTER TABLE channel ADD channel_portable_id text NOT NULL DEFAULT '' ");
$r2 = q("create index \"channel_portable_id_idx\" on channel (\"channel_portable_id\")");
$r = ($r1 && $r2);
}
else {
$r = q("ALTER TABLE `channel` ADD `channel_portable_id` char(191) NOT NULL DEFAULT '' ,
ADD INDEX `channel_portable_id` (`channel_portable_id`)");
}
if($r) {
q("COMMIT");
self::upgrade();
return UPDATE_SUCCESS;
}
q("ROLLBACK");
return UPDATE_FAILED;
}
static function upgrade() {
$r = q("select * from channel where channel_portable_id = '' ");
if($r) {
foreach($r as $rv) {
$zhash = Libzot::make_xchan_hash($rv['channel_guid'],$rv['channel_pubkey']);
q("update channel set channel_portable_id = '%s' where channel_id = %d",
dbesc($zhash),
intval($rv['channel_id'])
);
$x = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($rv['channel_hash'])
);
if($x) {
$rec = $x[0];
$rec['xchan_hash'] = $zhash;
$rec['xchan_guid_sig'] = 'sha256.' . $rec['xchan_guid_sig'];
$rec['xchan_network'] = 'zot6';
xchan_store_lowlevel($rec);
}
$x = q("select * from hubloc where hubloc_hash = '%s' and hubloc_url = '%s' limit 1",
dbesc($rv['channel_hash']),
dbesc(z_root())
);
if($x) {
$rec = $x[0];
$rec['hubloc_hash'] = $zhash;
$rec['hubloc_guid_sig'] = 'sha256.' . $rec['hubloc_guid_sig'];
$rec['hubloc_network'] = 'zot6';
$rec['hubloc_url_sig'] = 'sha256.' . $rec['hubloc_url_sig'];
$rec['hubloc_callback'] = z_root() . '/zot';
$rec['hubloc_id_url'] = channel_url($rv);
$rec['hubloc_site_id'] = Libzot::make_xchan_hash(z_root(),get_config('system','pubkey'));
hubloc_store_lowlevel($rec);
}
}
}
}
}

30
Zotlabs/Update/_1227.php Normal file
View File

@ -0,0 +1,30 @@
<?php
namespace Zotlabs\Update;
class _1227 {
function run() {
q("START TRANSACTION");
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
$r = q("ALTER TABLE dreport ADD dreport_name text NOT NULL DEFAULT '' ");
}
else {
$r = q("ALTER TABLE `dreport` ADD `dreport_name` char(191) NOT NULL DEFAULT ''");
}
if($r) {
q("COMMIT");
return UPDATE_SUCCESS;
}
q("ROLLBACK");
return UPDATE_FAILED;
}
}

36
Zotlabs/Update/_1228.php Normal file
View File

@ -0,0 +1,36 @@
<?php
namespace Zotlabs\Update;
class _1228 {
function run() {
q("START TRANSACTION");
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
$r1 = q("ALTER TABLE item ADD uuid text NOT NULL DEFAULT '' ");
$r2 = q("create index \"uuid_idx\" on channel (\"uuid\")");
$r3 = q("ALTER TABLE item add summary TEXT NOT NULL");
$r = ($r1 && $r2 && $r3);
}
else {
$r1 = q("ALTER TABLE `item` ADD `uuid` char(191) NOT NULL DEFAULT '' ,
ADD INDEX `uuid` (`uuid`)");
$r2 = q("ALTER TABLE `item` ADD `summary` mediumtext NOT NULL");
$r = ($r1 && $r2);
}
if($r) {
q("COMMIT");
return UPDATE_SUCCESS;
}
q("ROLLBACK");
return UPDATE_FAILED;
}
}

View File

@ -1,50 +0,0 @@
<?php
namespace Zotlabs\Web;
class CheckJS {
private static $jsdisabled = 0;
function __construct($test = 0) {
if(intval($_REQUEST['jsdisabled']))
$this->jsdisabled = 1;
else
$this->jsdisabled = 0;
if(intval($_COOKIE['jsdisabled']))
$this->jsdisabled = 1;
else
$this->jsdisabled = 0;
$page = bin2hex(\App::$query_string);
if(! $this->jsdisabled) {
if($test) {
$this->jsdisabled = 1;
if(array_key_exists('jsdisabled',$_COOKIE))
$this->jsdisabled = $_COOKIE['jsdisabled'];
if(! array_key_exists('jsdisabled',$_COOKIE)) {
\App::$page['htmlhead'] .= "\r\n" . '<script>document.cookie="jsdisabled=0; path=/"; var jsMatch = /\&jsdisabled=0/; if (!jsMatch.exec(location.href)) { location.href = "' . z_root() . '/nojs/0?f=&redir=' . $page . '" ; }</script>' . "\r\n";
/* emulate JS cookie if cookies are not accepted */
if (array_key_exists('jsdisabled',$_GET)) {
$_COOKIE['jsdisabled'] = $_GET['jsdisabled'];
}
}
}
else {
\App::$page['htmlhead'] .= "\r\n" . '<noscript><meta http-equiv="refresh" content="0; url=' . z_root() . '/nojs?f=&redir=' . $page . '"></noscript>' . "\r\n";
}
}
}
function disabled() {
return $this->jsdisabled;
}
}

View File

@ -342,6 +342,10 @@ class HTTPSig {
*/
static function parse_sigheader($header) {
if(is_array($header)) {
btlogger('is_array: ' . print_r($header,true));
}
$ret = [];
$matches = [];
@ -397,7 +401,7 @@ class HTTPSig {
$data = $matches[1];
if($iv && $key && $alg && $data) {
return crypto_unencapsulate([ 'iv' => $iv, 'key' => $key, 'alg' => $alg, 'data' => $data ] , $prvkey);
return crypto_unencapsulate([ 'encrypted' => true, 'iv' => $iv, 'key' => $key, 'alg' => $alg, 'data' => $data ] , $prvkey);
}
return '';

View File

@ -48,12 +48,14 @@ class HTTPSig {
$h = new HTTPHeaders($data['header']);
$headers = $h->fetcharr();
$body = $data['body'];
$headers['(request-target)'] = $data['request_target'];
}
else {
$headers = [];
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
$headers['content-type'] = $_SERVER['CONTENT_TYPE'];
$headers['content-length'] = $_SERVER['CONTENT_LENGTH'];
foreach($_SERVER as $k => $v) {
if(strpos($k,'HTTP_') === 0) {
@ -121,6 +123,17 @@ class HTTPSig {
if(array_key_exists($h,$headers)) {
$signed_data .= $h . ': ' . $headers[$h] . "\n";
}
if($h === 'date') {
$d = new \DateTime($headers[$h]);
$d->setTimeZone(new \DateTimeZone('UTC'));
$dplus = datetime_convert('UTC','UTC','now + 1 day');
$dminus = datetime_convert('UTC','UTC','now - 1 day');
$c = $d->format('Y-m-d H:i:s');
if($c > $dplus || $c < $dminus) {
logger('bad time: ' . $c);
return $result;
}
}
}
$signed_data = rtrim($signed_data,"\n");
@ -147,8 +160,15 @@ class HTTPSig {
logger('verified: ' . $x, LOGGER_DEBUG);
if(! $x)
if(! $x) {
logger('verify failed for ' . $result['signer'] . ' alg=' . $algorithm . (($key['public_key']) ? '' : ' no key'));
$sig_block['signature'] = base64_encode($sig_block['signature']);
logger('affected sigblock: ' . print_r($sig_block,true));
logger('signed_data: ' . print_r($signed_data,true));
logger('headers: ' . print_r($headers,true));
logger('server: ' . print_r($_SERVER,true));
return $result;
}
$result['portable_id'] = $key['portable_id'];
$result['header_valid'] = true;
@ -180,7 +200,9 @@ class HTTPSig {
return [ 'public_key' => $key ];
}
$key = self::get_webfinger_key($id);
if(strpos($id,'#') === false) {
$key = self::get_webfinger_key($id);
}
if(! $key) {
$key = self::get_activitystreams_key($id);
@ -216,25 +238,29 @@ class HTTPSig {
function get_activitystreams_key($id) {
// remove fragment
$url = ((strpos($id,'#')) ? substr($id,0,strpos($id,'#')) : $id);
$x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_addr = '%s' or hubloc_id_url = '%s' limit 1",
dbesc(str_replace('acct:','',$id)),
dbesc($id)
dbesc(str_replace('acct:','',$url)),
dbesc($url)
);
if($x && $x[0]['xchan_pubkey']) {
return [ 'portable_id' => $x[0]['xchan_hash'], 'public_key' => $x[0]['xchan_pubkey'] , 'hubloc' => $x[0] ];
}
$r = ActivityStreams::fetch_property($id);
$r = ActivityStreams::fetch($id);
if($r) {
if(array_key_exists('publicKey',$j) && array_key_exists('publicKeyPem',$j['publicKey']) && array_key_exists('id',$j['publicKey'])) {
if($j['publicKey']['id'] === $id || $j['id'] === $id) {
return [ 'public_key' => self::convertKey($j['publicKey']['publicKeyPem']), 'portable_id' => '', 'hubloc' => [] ];
if(array_key_exists('publicKey',$r) && array_key_exists('publicKeyPem',$r['publicKey']) && array_key_exists('id',$r['publicKey'])) {
if($r['publicKey']['id'] === $id || $r['id'] === $id) {
$portable_id = ((array_key_exists('owner',$r['publicKey'])) ? $r['publicKey']['owner'] : EMPTY_STR);
return [ 'public_key' => self::convertKey($r['publicKey']['publicKeyPem']), 'portable_id' => $portable_id, 'hubloc' => [] ];
}
}
}
return false;
}
@ -409,6 +435,8 @@ class HTTPSig {
$headers = '';
$fields = '';
logger('signing: ' . print_r($head,true), LOGGER_DATA);
if($head) {
foreach($head as $k => $v) {
$headers .= strtolower($k) . ': ' . trim($v) . "\n";

View File

@ -4,7 +4,7 @@ namespace Zotlabs\Zot6;
use Zotlabs\Lib\Config;
use Zotlabs\Lib\Libzot;
use Zotlabs\Web\HTTPSig;
class Receiver {

View File

@ -70,9 +70,10 @@ class Zot6Handler implements IHandler {
// This would be a permissions update, typically for one connection
foreach ($recipients as $recip) {
$r = q("select channel.*,xchan.* from channel
left join xchan on channel_hash = xchan_hash
where channel_hash ='%s' limit 1",
left join xchan on channel_portable_id = xchan_hash
where xchan_hash ='%s' limit 1",
dbesc($recip)
);
@ -140,7 +141,7 @@ class Zot6Handler implements IHandler {
$arr = $data['recipients'][0];
$c = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_hash = '%s' limit 1",
$c = q("select * from channel left join xchan on channel_portable_id = xchan_hash where channel_portable_id = '%s' limit 1",
dbesc($arr['portable_id'])
);
if (! $c) {
@ -230,8 +231,8 @@ class Zot6Handler implements IHandler {
// basically this means "unfriend"
foreach ($recipients as $recip) {
$r = q("select channel.*,xchan.* from channel
left join xchan on channel_hash = xchan_hash
where channel_hash = '%s' and channel_guid_sig = '%s' limit 1",
left join xchan on channel_portable_id = xchan_hash
where channel_portable_id = '%s' limit 1",
dbesc($recip)
);
if ($r) {

View File

@ -50,10 +50,10 @@ require_once('include/attach.php');
require_once('include/bbcode.php');
define ( 'PLATFORM_NAME', 'hubzilla' );
define ( 'STD_VERSION', '3.8.5' );
define ( 'STD_VERSION', '3.9.5' );
define ( 'ZOT_REVISION', '6.0a' );
define ( 'DB_UPDATE_VERSION', 1225 );
define ( 'DB_UPDATE_VERSION', 1228 );
define ( 'PROJECT_BASE', __DIR__ );

View File

@ -16,7 +16,8 @@ function profile_activity($changed, $value) {
return;
$arr = array();
$arr['mid'] = $arr['parent_mid'] = item_message_id();
$arr['uuid'] = item_message_id();
$arr['mid'] = $arr['parent_mid'] = z_root() . '/item/' . $arr['uuid'];
$arr['uid'] = local_channel();
$arr['aid'] = $self['channel_account_id'];
$arr['owner_xchan'] = $arr['author_xchan'] = $self['xchan_hash'];

View File

@ -739,7 +739,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
}
if(! $hash)
$hash = random_string();
$hash = new_uuid();
// Check storage limits
if($options !== 'update') {
@ -1122,7 +1122,7 @@ function attach_mkdir($channel, $observer_hash, $arr = null) {
return $ret;
}
$arr['hash'] = (($arr['hash']) ? $arr['hash'] : random_string());
$arr['hash'] = (($arr['hash']) ? $arr['hash'] : new_uuid());
// Check for duplicate name.
// Check both the filename and the hash as we will be making use of both.
@ -1759,16 +1759,18 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid,
$arr_allow_cid = check_list_permissions($channel_id, $arr_allow_cid, 'view_storage');
}
$mid = item_message_id();
$uuid = item_message_id();
$mid = z_root() . '/item/' . $uuid;
$objtype = ACTIVITY_OBJ_FILE;
$arr = array();
$arr['aid'] = get_account_id();
$arr['uid'] = $channel_id;
$arr['item_wall'] = 1;
$arr['item_origin'] = 1;
$arr['item_unseen'] = 1;
$arr['uuid'] = $uuid;
$arr['item_wall'] = 1;
$arr['item_origin'] = 1;
$arr['item_unseen'] = 1;
$arr['author_xchan'] = $poster['xchan_hash'];
$arr['owner_xchan'] = $poster['xchan_hash'];
$arr['title'] = '';
@ -1813,8 +1815,10 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid,
$private = (($u_arr_allow_cid[0] || $u_arr_allow_gid[0] || $u_arr_deny_cid[0] || $u_arr_deny_gid[0]) ? 1 : 0);
$u_mid = item_message_id();
$uuid = item_message_id();
$u_mid = z_root() . '/item/' . $uuid;
$arr['uuid'] = $uuid;
$arr['mid'] = $u_mid;
$arr['parent_mid'] = $u_mid;
$arr['allow_cid'] = perms2str($u_arr_allow_cid);

View File

@ -10,6 +10,7 @@ use Zotlabs\Access\Permissions;
use Zotlabs\Daemon\Master;
use Zotlabs\Lib\System;
use Zotlabs\Render\Comanche;
use Zotlabs\Lib\Libzot;
require_once('include/zot.php');
require_once('include/crypto.php');
@ -232,6 +233,7 @@ function create_identity($arr) {
$sig = base64url_encode(rsa_sign($guid,$key['prvkey']));
$hash = make_xchan_hash($guid,$sig);
$zhash = Libzot::make_xchan_hash($guid,$key['pubkey']);
// Force a few things on the short term until we can provide a theme or app with choice
@ -265,6 +267,7 @@ function create_identity($arr) {
'channel_guid' => $guid,
'channel_guid_sig' => $sig,
'channel_hash' => $hash,
'channel_portable_id' => $zhash,
'channel_prvkey' => $key['prvkey'],
'channel_pubkey' => $key['pubkey'],
'channel_pageflags' => intval($pageflags),
@ -345,30 +348,76 @@ function create_identity($arr) {
if(! $r)
logger('Unable to store hub location');
$r = hubloc_store_lowlevel(
[
'hubloc_guid' => $guid,
'hubloc_guid_sig' => 'sha256.' . $sig,
'hubloc_hash' => $zhash,
'hubloc_id_url' => channel_url($ret['channel']),
'hubloc_addr' => channel_reddress($ret['channel']),
'hubloc_primary' => intval($primary),
'hubloc_url' => z_root(),
'hubloc_url_sig' => 'sha256.' . base64url_encode(rsa_sign(z_root(),$ret['channel']['channel_prvkey'])),
'hubloc_site_id' => Libzot::make_xchan_hash(z_root(),get_config('system','pubkey')),
'hubloc_host' => App::get_hostname(),
'hubloc_callback' => z_root() . '/zot',
'hubloc_sitekey' => get_config('system','pubkey'),
'hubloc_network' => 'zot6',
'hubloc_updated' => datetime_convert()
]
);
if(! $r)
logger('Unable to store hub location');
$newuid = $ret['channel']['channel_id'];
$r = xchan_store_lowlevel(
[
'xchan_hash' => $hash,
'xchan_guid' => $guid,
'xchan_guid_sig' => $sig,
'xchan_pubkey' => $key['pubkey'],
'xchan_hash' => $hash,
'xchan_guid' => $guid,
'xchan_guid_sig' => $sig,
'xchan_pubkey' => $key['pubkey'],
'xchan_photo_mimetype' => (($photo_type) ? $photo_type : 'image/png'),
'xchan_photo_l' => z_root() . "/photo/profile/l/{$newuid}",
'xchan_photo_m' => z_root() . "/photo/profile/m/{$newuid}",
'xchan_photo_s' => z_root() . "/photo/profile/s/{$newuid}",
'xchan_addr' => channel_reddress($ret['channel']),
'xchan_url' => z_root() . '/channel/' . $ret['channel']['channel_address'],
'xchan_follow' => z_root() . '/follow?f=&url=%s',
'xchan_connurl' => z_root() . '/poco/' . $ret['channel']['channel_address'],
'xchan_name' => $ret['channel']['channel_name'],
'xchan_network' => 'zot',
'xchan_photo_date' => datetime_convert(),
'xchan_name_date' => datetime_convert(),
'xchan_system' => $system
'xchan_photo_l' => z_root() . "/photo/profile/l/{$newuid}",
'xchan_photo_m' => z_root() . "/photo/profile/m/{$newuid}",
'xchan_photo_s' => z_root() . "/photo/profile/s/{$newuid}",
'xchan_addr' => channel_reddress($ret['channel']),
'xchan_url' => z_root() . '/channel/' . $ret['channel']['channel_address'],
'xchan_follow' => z_root() . '/follow?f=&url=%s',
'xchan_connurl' => z_root() . '/poco/' . $ret['channel']['channel_address'],
'xchan_name' => $ret['channel']['channel_name'],
'xchan_network' => 'zot',
'xchan_photo_date' => datetime_convert(),
'xchan_name_date' => datetime_convert(),
'xchan_system' => $system
]
);
$r = xchan_store_lowlevel(
[
'xchan_hash' => $zhash,
'xchan_guid' => $guid,
'xchan_guid_sig' => 'sha256.' . $sig,
'xchan_pubkey' => $key['pubkey'],
'xchan_photo_mimetype' => (($photo_type) ? $photo_type : 'image/png'),
'xchan_photo_l' => z_root() . "/photo/profile/l/{$newuid}",
'xchan_photo_m' => z_root() . "/photo/profile/m/{$newuid}",
'xchan_photo_s' => z_root() . "/photo/profile/s/{$newuid}",
'xchan_addr' => channel_reddress($ret['channel']),
'xchan_url' => z_root() . '/channel/' . $ret['channel']['channel_address'],
'xchan_follow' => z_root() . '/follow?f=&url=%s',
'xchan_connurl' => z_root() . '/poco/' . $ret['channel']['channel_address'],
'xchan_name' => $ret['channel']['channel_name'],
'xchan_network' => 'zot6',
'xchan_photo_date' => datetime_convert(),
'xchan_name_date' => datetime_convert(),
'xchan_system' => $system
]
);
// Not checking return value.
// It's ok for this to fail if it's an imported channel, and therefore the hash is a duplicate
@ -2355,6 +2404,7 @@ function channel_store_lowlevel($arr) {
'channel_guid' => ((array_key_exists('channel_guid',$arr)) ? $arr['channel_guid'] : ''),
'channel_guid_sig' => ((array_key_exists('channel_guid_sig',$arr)) ? $arr['channel_guid_sig'] : ''),
'channel_hash' => ((array_key_exists('channel_hash',$arr)) ? $arr['channel_hash'] : ''),
'channel_portable_id' => ((array_key_exists('channel_portable_id',$arr)) ? $arr['channel_portable_id'] : ''),
'channel_timezone' => ((array_key_exists('channel_timezone',$arr)) ? $arr['channel_timezone'] : 'UTC'),
'channel_location' => ((array_key_exists('channel_location',$arr)) ? $arr['channel_location'] : ''),
'channel_theme' => ((array_key_exists('channel_theme',$arr)) ? $arr['channel_theme'] : ''),

View File

@ -225,9 +225,14 @@ function crypto_unencapsulate($data,$prvkey) {
if(! $data)
return;
$alg = ((array_key_exists('alg',$data)) ? $data['alg'] : 'aes256cbc');
if($alg === 'aes256cbc')
$alg = ((is_array($data) && (array_key_exists('encrypted',$data) || array_key_exists('iv',$data))) ? $data['alg'] : '');
if(! $alg) {
return $data;
}
if($alg === 'aes256cbc') {
return aes_unencapsulate($data,$prvkey);
}
return other_unencapsulate($data,$prvkey,$alg);

View File

@ -1125,11 +1125,14 @@ function event_store_item($arr, $event) {
}
}
if(! $arr['mid'])
$arr['mid'] = item_message_id();
if(! $arr['mid']) {
$arr['uuid'] = item_message_id();
$arr['mid'] = z_root() . '/item/' . $arr['uuid'];
}
$item_arr['aid'] = $z[0]['channel_account_id'];
$item_arr['uid'] = $arr['uid'];
$item_arr['uuid'] = $arr['uuid'];
$item_arr['author_xchan'] = $arr['event_xchan'];
$item_arr['mid'] = $arr['mid'];
$item_arr['parent_mid'] = $arr['mid'];

View File

@ -351,7 +351,8 @@ function store_doc_file($s) {
$x = item_store_update($item);
}
else {
$item['mid'] = $item['parent_mid'] = item_message_id();
$item['uuid'] = $item_message_id();
$item['mid'] = $item['parent_mid'] = z_root() . '/item/' . $item['uuid'];
$x = item_store($item);
}

View File

@ -1520,7 +1520,8 @@ function import_webpage_element($element, $channel, $type) {
}
else { // otherwise, generate the creation times and unique id
$arr['created'] = datetime_convert('UTC', 'UTC');
$arr['mid'] = $arr['parent_mid'] = item_message_id();
$arr['uuid'] = item_message_id();
$arr['mid'] = $arr['parent_mid'] = z_root() . '/item/' . $arr['uuid'];
}
// Update the edited time whether or not the element already exists
$arr['edited'] = datetime_convert('UTC', 'UTC');

View File

@ -393,7 +393,11 @@ function post_activity_item($arr, $allow_code = false, $deliver = true) {
if(! array_key_exists('mimetype',$arr))
$arr['mimetype'] = 'text/bbcode';
$arr['mid'] = ((x($arr,'mid')) ? $arr['mid'] : item_message_id());
if(! $arr['mid']) {
$arr['uuid'] = ((x($arr,'uuid')) ? $arr['uuid'] : item_message_id());
}
$arr['mid'] = ((x($arr,'mid')) ? $arr['mid'] : z_root() . '/item/' . $arr['uuid']);
$arr['parent_mid'] = ((x($arr,'parent_mid')) ? $arr['parent_mid'] : $arr['mid']);
$arr['thr_parent'] = ((x($arr,'thr_parent')) ? $arr['thr_parent'] : $arr['mid']);
@ -597,6 +601,7 @@ function get_item_elements($x,$allow_code = false) {
$arr = array();
$arr['body'] = $x['body'];
$arr['summary'] = $x['summary'];
$maxlen = get_max_import_size();
@ -605,6 +610,11 @@ function get_item_elements($x,$allow_code = false) {
logger('get_item_elements: message length exceeds max_import_size: truncated');
}
if($maxlen && mb_strlen($arr['summary']) > $maxlen) {
$arr['summary'] = mb_substr($arr['summary'],0,$maxlen,'UTF-8');
logger('get_item_elements: message summary length exceeds max_import_size: truncated');
}
$arr['created'] = datetime_convert('UTC','UTC',$x['created']);
$arr['edited'] = datetime_convert('UTC','UTC',$x['edited']);
@ -627,6 +637,7 @@ function get_item_elements($x,$allow_code = false) {
if(mb_strlen($arr['title']) > 255)
$arr['title'] = mb_substr($arr['title'],0,255);
$arr['uuid'] = (($x['uuid']) ? htmlspecialchars($x['uuid'], ENT_COMPAT,'UTF-8',false) : '');
$arr['app'] = (($x['app']) ? htmlspecialchars($x['app'], ENT_COMPAT,'UTF-8',false) : '');
$arr['route'] = (($x['route']) ? htmlspecialchars($x['route'], ENT_COMPAT,'UTF-8',false) : '');
$arr['mid'] = (($x['message_id']) ? htmlspecialchars($x['message_id'], ENT_COMPAT,'UTF-8',false) : '');
@ -747,9 +758,10 @@ function get_item_elements($x,$allow_code = false) {
// Do this after signature checking as the original signature
// was generated on the escaped content.
if($arr['mimetype'] === 'text/markdown')
if($arr['mimetype'] === 'text/markdown') {
$arr['summary'] = MarkdownSoap::unescape($arr['summary']);
$arr['body'] = MarkdownSoap::unescape($arr['body']);
}
if(array_key_exists('revision',$x)) {
// extended export encoding
@ -1061,6 +1073,7 @@ function encode_item($item,$mirror = false) {
$x['item_blocked'] = $item['item_blocked'];
}
$x['uuid'] = $item['uuid'];
$x['message_id'] = $item['mid'];
$x['message_top'] = $item['parent_mid'];
$x['message_parent'] = $item['thr_parent'];
@ -1071,6 +1084,7 @@ function encode_item($item,$mirror = false) {
$x['commented'] = $item['commented'];
$x['mimetype'] = $item['mimetype'];
$x['title'] = $item['title'];
$x['summary'] = $item['summary'];
$x['body'] = $item['body'];
$x['app'] = $item['app'];
$x['verb'] = $item['verb'];
@ -1629,6 +1643,7 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
}
$arr['title'] = ((array_key_exists('title',$arr) && strlen($arr['title'])) ? trim($arr['title']) : '');
$arr['summary'] = ((array_key_exists('summary',$arr) && strlen($arr['summary'])) ? trim($arr['summary']) : '');
$arr['body'] = ((array_key_exists('body',$arr) && strlen($arr['body'])) ? trim($arr['body']) : '');
$arr['allow_cid'] = ((x($arr,'allow_cid')) ? trim($arr['allow_cid']) : '');
@ -1637,6 +1652,7 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
$arr['deny_gid'] = ((x($arr,'deny_gid')) ? trim($arr['deny_gid']) : '');
$arr['postopts'] = ((x($arr,'postopts')) ? trim($arr['postopts']) : '');
$arr['route'] = ((x($arr,'route')) ? trim($arr['route']) : '');
$arr['uuid'] = ((x($arr,'uuid')) ? trim($arr['uuid']) : '');
$arr['item_private'] = ((x($arr,'item_private')) ? intval($arr['item_private']) : 0 );
$arr['item_wall'] = ((x($arr,'item_wall')) ? intval($arr['item_wall']) : 0 );
$arr['item_type'] = ((x($arr,'item_type')) ? intval($arr['item_type']) : 0 );
@ -1649,6 +1665,7 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
// apply the input filter here
$arr['summary'] = trim(z_input_filter($arr['summary'],$arr['mimetype'],$allow_exec));
$arr['body'] = trim(z_input_filter($arr['body'],$arr['mimetype'],$allow_exec));
item_sign($arr);
@ -2094,6 +2111,7 @@ function item_store_update($arr, $allow_exec = false, $deliver = true) {
// apply the input filter here
$arr['summary'] = trim(z_input_filter($arr['summary'],$arr['mimetype'],$allow_exec));
$arr['body'] = trim(z_input_filter($arr['body'],$arr['mimetype'],$allow_exec));
item_sign($arr);
@ -2170,6 +2188,7 @@ function item_store_update($arr, $allow_exec = false, $deliver = true) {
$arr['route'] = ((array_key_exists('route',$arr)) ? trim($arr['route']) : $orig[0]['route']);
$arr['location'] = ((x($arr,'location')) ? notags(trim($arr['location'])) : $orig[0]['location']);
$arr['uuid'] = ((x($arr,'uuid')) ? notags(trim($arr['uuid'])) : $orig[0]['uuid']);
$arr['coord'] = ((x($arr,'coord')) ? notags(trim($arr['coord'])) : $orig[0]['coord']);
$arr['verb'] = ((x($arr,'verb')) ? notags(trim($arr['verb'])) : $orig[0]['verb']);
$arr['obj_type'] = ((x($arr,'obj_type')) ? notags(trim($arr['obj_type'])) : $orig[0]['obj_type']);
@ -2625,28 +2644,30 @@ function tag_deliver($uid, $item_id) {
$plustagged = false;
$matches = array();
$pattern = '/[\!@]\!?\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($term['term'],'/') . '\[\/zrl\]/';
$pattern = '/[\!@]\!?\[[uz]rl\=' . preg_quote($term['url'],'/') . '\](.*?)\[\/[uz]rl\]/';
if(preg_match($pattern,$body,$matches))
$tagged = true;
// original red forum tagging sequence @forumname+
$pattern = '/\[url\=' . preg_quote($term['url'],'/') . '\]\@(.*?)\[\/url\]/';
if(preg_match($pattern,$body,$matches))
$tagged = true;
// standard forum tagging sequence !forumname
$pluspattern = '/@\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\+\[\/zrl\]/';
$forumpattern = '/\!\!?\[[uz]rl\=([^\]]*?)\]((?:.(?!\[[uz]rl\=))*?)\[\/[uz]rl\]/';
$forumpattern = '/\!\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\[\/zrl\]/';
$forumpattern2 = '/\[[uz]rl\=([^\]]*?)\]\!((?:.(?!\[[uz]rl\=))*?)\[\/[uz]rl\]/';
$found = false;
$matches = array();
if(preg_match_all($pluspattern,$body,$matches,PREG_SET_ORDER)) {
if(preg_match_all($forumpattern,$body,$matches,PREG_SET_ORDER)) {
foreach($matches as $match) {
$matched_forums ++;
if($term['url'] === $match[1] && $term['term'] === $match[2] && intval($term['ttype']) === TERM_MENTION) {
if($term['url'] === $match[1] && intval($term['ttype']) === TERM_FORUM) {
if($matched_forums <= $max_forums) {
$plustagged = true;
$found = true;
break;
}
logger('forum ' . $term['term'] . ' exceeded max_tagged_forums - ignoring');
@ -2654,13 +2675,12 @@ function tag_deliver($uid, $item_id) {
}
}
if(preg_match_all($forumpattern,$body,$matches,PREG_SET_ORDER)) {
if(preg_match_all($forumpattern2,$body,$matches,PREG_SET_ORDER)) {
foreach($matches as $match) {
$matched_forums ++;
if($term['url'] === $match[1] && $term['term'] === $match[2] && intval($term['ttype']) === TERM_FORUM) {
if($term['url'] === $match[1] && intval($term['ttype']) === TERM_FORUM) {
if($matched_forums <= $max_forums) {
$plustagged = true;
$found = true;
break;
}
logger('forum ' . $term['term'] . ' exceeded max_tagged_forums - ignoring');
@ -2882,18 +2902,19 @@ function tgroup_check($uid, $item) {
$body = preg_replace('/\[share(.*?)\[\/share\]/','',$item['body']);
$pluspattern = '/@\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\+\[\/zrl\]/';
$forumpattern = '/\!\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\[\/zrl\]/';
$forumpattern2 = '/\[zrl\=([^\]]*?)\]\!((?:.(?!\[zrl\=))*?)\[\/zrl\]/';
$found = false;
$matches = array();
if(preg_match_all($pluspattern,$body,$matches,PREG_SET_ORDER)) {
if(preg_match_all($forumpattern,$body,$matches,PREG_SET_ORDER)) {
foreach($matches as $match) {
$matched_forums ++;
if($term['url'] === $match[1] && $term['term'] === $match[2] && intval($term['ttype']) === TERM_MENTION) {
if($term['url'] === $match[1] && intval($term['ttype']) === TERM_FORUM) {
if($matched_forums <= $max_forums) {
$found = true;
break;
@ -2903,10 +2924,10 @@ function tgroup_check($uid, $item) {
}
}
if(preg_match_all($forumpattern,$body,$matches,PREG_SET_ORDER)) {
if(preg_match_all($forumpattern2,$body,$matches,PREG_SET_ORDER)) {
foreach($matches as $match) {
$matched_forums ++;
if($term['url'] === $match[1] && $term['term'] === $match[2] && intval($term['ttype']) === TERM_FORUM) {
if($term['url'] === $match[1] && intval($term['ttype']) === TERM_FORUM) {
if($matched_forums <= $max_forums) {
$found = true;
break;
@ -4744,7 +4765,8 @@ function item_create_edit_activity($post) {
$new_item['id'] = 0;
$new_item['parent'] = 0;
$new_item['mid'] = item_message_id();
$new_item['uuid'] = item_message_id();
$new_item['mid'] = z_root() . '/item/' . $new_item['uuid'];
$new_item['body'] = sprintf( t('[Edited %s]'), (($update_item['item_thread_top']) ? t('Post','edit_activity') : t('Comment','edit_activity')));

View File

@ -153,7 +153,7 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
// Pull out multiple headers, e.g. proxy and continuation headers
// allow for HTTP/2.x without fixing code
while(preg_match('/^HTTP\/[1-2].+? [1-5][0-9][0-9]/',$base)) {
while(preg_match('/^HTTP\/[1-3].+? [1-5][0-9][0-9]/',$base)) {
$chunk = substr($base,0,strpos($base,"\r\n\r\n")+4);
$header .= $chunk;
$base = substr($base,strlen($chunk));
@ -319,7 +319,7 @@ function z_post_url($url, $params, $redirects = 0, $opts = array()) {
// Pull out multiple headers, e.g. proxy and continuation headers
// allow for HTTP/2.x without fixing code
while(preg_match('/^HTTP\/[1-2].+? [1-5][0-9][0-9]/',$base)) {
while(preg_match('/^HTTP\/[1-3].+? [1-5][0-9][0-9]/',$base)) {
$chunk = substr($base,0,strpos($base,"\r\n\r\n")+4);
$header .= $chunk;
$base = substr($base,strlen($chunk));

View File

@ -441,11 +441,13 @@ function photo_upload($channel, $observer, $args) {
}
}
else {
$mid = item_message_id();
$uuid = item_message_id();
$mid = z_root() . '/item/' . $uuid;
$arr = [
'aid' => $account_id,
'uid' => $channel_id,
'uuid' => $uuid,
'mid' => $mid,
'parent_mid' => $mid,
'item_hidden' => $item_hidden,
@ -827,12 +829,14 @@ function photos_create_item($channel, $creator_hash, $photo, $visible = false) {
$item_hidden = (($visible) ? 0 : 1 );
$mid = item_message_id();
$uuid = item_message_id();
$mid = z_root() . '/item/' . $uuid;
$arr = array();
$arr['aid'] = $channel['channel_account_id'];
$arr['uid'] = $channel['channel_id'];
$arr['uuid'] = $uuid;
$arr['mid'] = $mid;
$arr['parent_mid'] = $mid;
$arr['item_wall'] = 1;

View File

@ -1,5 +1,9 @@
<?php /** @file */
use Zotlabs\Lib\Libzot;
use Zotlabs\Zot6\Receiver;
use Zotlabs\Zot6\Zot6Handler;
function update_queue_item($id, $add_priority = 0) {
logger('queue: requeue item ' . $id,LOGGER_DEBUG);
$x = q("select outq_created, outq_posturl from outq where outq_hash = '%s' limit 1",
@ -226,37 +230,85 @@ function queue_deliver($outq, $immediate = false) {
logger('deliver: dest: ' . $outq['outq_posturl'], LOGGER_DEBUG);
$channel = null;
if($outq['outq_driver'] === 'zot6') {
if($outq['outq_msg'] && $outq['outq_channel']) {
$channel = channelx_by_n($outq['outq_channel']);
}
if($outq['outq_posturl'] === z_root() . '/zot') {
// local delivery
$zot = new Receiver(new Zot6Handler(),$outq['outq_notify']);
$result = $zot->run(true);
logger('returned_json: ' . json_encode($result,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES), LOGGER_DATA);
logger('deliver: local zot6 delivery succeeded to ' . $outq['outq_posturl']);
Libzot::process_response($outq['outq_posturl'],[ 'success' => true, 'body' => json_encode($result) ], $outq);
}
else {
logger('remote');
$channel = null;
$host_crypto = null;
if($outq['outq_channel']) {
$channel = channelx_by_n($outq['outq_channel']);
}
$host_crypto = null;
if($channel && $base) {
$h = q("select hubloc_sitekey, site_crypto from hubloc left join site on hubloc_url = site_url where site_url = '%s' and hubloc_network = 'zot6' order by hubloc_id desc limit 1",
dbesc($base)
);
if($h) {
$host_crypto = $h[0];
}
}
$msg = $outq['outq_notify'];
$result = Libzot::zot($outq['outq_posturl'],$msg,$channel,$host_crypto);
if($result['success']) {
logger('deliver: remote zot6 delivery succeeded to ' . $outq['outq_posturl']);
Libzot::process_response($outq['outq_posturl'],$result, $outq);
}
else {
logger('deliver: remote zot6 delivery failed to ' . $outq['outq_posturl']);
logger('deliver: remote zot6 delivery fail data: ' . print_r($result,true), LOGGER_DATA);
update_queue_item($outq['outq_hash'],10);
}
if($channel && $base) {
$h = q("select hubloc_sitekey, site_crypto from hubloc left join site on hubloc_url = site_url where site_url = '%s' order by hubloc_id desc limit 1",
dbesc($base)
);
if($h) {
$host_crypto = $h[0];
}
}
$msg = $outq['outq_notify'];
$result = zot_zot($outq['outq_posturl'],$msg,$channel,$host_crypto);
if($result['success']) {
logger('deliver: remote zot delivery succeeded to ' . $outq['outq_posturl']);
zot_process_response($outq['outq_posturl'],$result, $outq);
return;
}
else {
logger('deliver: remote zot delivery failed to ' . $outq['outq_posturl']);
logger('deliver: remote zot delivery fail data: ' . print_r($result,true), LOGGER_DATA);
update_queue_item($outq['outq_hash'],10);
}
return;
}
$channel = null;
if($outq['outq_msg'] && $outq['outq_channel']) {
$channel = channelx_by_n($outq['outq_channel']);
}
$host_crypto = null;
if($channel && $base) {
$h = q("select hubloc_sitekey, site_crypto from hubloc left join site on hubloc_url = site_url where site_url = '%s' order by hubloc_id desc limit 1",
dbesc($base)
);
if($h) {
$host_crypto = $h[0];
}
}
$msg = $outq['outq_notify'];
$result = zot_zot($outq['outq_posturl'],$msg,$channel,$host_crypto);
if($result['success']) {
logger('deliver: remote zot delivery succeeded to ' . $outq['outq_posturl']);
zot_process_response($outq['outq_posturl'],$result, $outq);
}
else {
logger('deliver: remote zot delivery failed to ' . $outq['outq_posturl']);
logger('deliver: remote zot delivery fail data: ' . print_r($result,true), LOGGER_DATA);
update_queue_item($outq['outq_hash'],10);
}
return;
}
}

View File

@ -3,8 +3,11 @@
* @file include/text.php
*/
use \Zotlabs\Lib as Zlib;
use \Michelf\MarkdownExtra;
use Zotlabs\Lib as Zlib;
use Michelf\MarkdownExtra;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\Exception\UnsatisfiedDependencyException;
require_once("include/bbcode.php");
@ -571,18 +574,9 @@ function alt_pager($i, $more = '', $less = '') {
* @return string a unique id
*/
function item_message_id() {
do {
$dups = false;
$hash = random_string();
$mid = $hash . '@' . App::get_hostname();
$r = q("SELECT id FROM item WHERE mid = '%s' LIMIT 1",
dbesc($mid));
if($r)
$dups = true;
} while($dups == true);
return new_uuid();
return $mid;
}
/**
@ -593,17 +587,9 @@ function item_message_id() {
* @return string a uniqe hash
*/
function photo_new_resource() {
do {
$found = false;
$resource = hash('md5', uniqid(mt_rand(), true));
$r = q("SELECT id FROM photo WHERE resource_id = '%s' LIMIT 1",
dbesc($resource));
if($r)
$found = true;
} while($found === true);
return new_uuid();
return $resource;
}
/**
@ -3480,3 +3466,19 @@ function print_val($v) {
return $v;
}
/**
* @brief Generate a unique ID.
*
* @return string
*/
function new_uuid() {
try {
$hash = Uuid::uuid4()->toString();
} catch (UnsatisfiedDependencyException $e) {
$hash = random_string(48);
}
return $hash;
}

View File

@ -5,6 +5,11 @@ use Zotlabs\Zot6\HTTPSig;
function xchan_store_lowlevel($arr) {
if(! $arr['xchan_hash']) {
logger('No xchan_hash');
return false;
}
$store = [
'xchan_hash' => ((array_key_exists('xchan_hash',$arr)) ? $arr['xchan_hash'] : ''),
'xchan_guid' => ((array_key_exists('xchan_guid',$arr)) ? $arr['xchan_guid'] : ''),

View File

@ -8,6 +8,8 @@
*
*/
use Zotlabs\Lib\DReport;
require_once('include/crypto.php');
require_once('include/items.php');
require_once('include/queue_fn.php');
@ -81,7 +83,7 @@ function zot_get_hublocs($hash) {
/* Only search for active hublocs - e.g. those that haven't been marked deleted */
$ret = q("select * from hubloc where hubloc_hash = '%s' and hubloc_deleted = 0 order by hubloc_url ",
$ret = q("select * from hubloc where hubloc_hash = '%s' and hubloc_deleted = 0 and hubloc_network = 'zot' order by hubloc_url ",
dbesc($hash)
);
@ -654,7 +656,7 @@ function zot_gethub($arr, $multiple = false) {
$r = q("select hubloc.*, site.site_crypto from hubloc left join site on hubloc_url = site_url
where hubloc_guid = '%s' and hubloc_guid_sig = '%s'
and hubloc_url = '%s' and hubloc_url_sig = '%s'
and hubloc_url = '%s' and hubloc_url_sig = '%s' and hubloc_network = 'zot'
$sitekey $limit",
dbesc($arr['guid']),
dbesc($arr['guid_sig']),
@ -1119,14 +1121,15 @@ function zot_process_response($hub, $arr, $outq) {
}
foreach($x['delivery_report'] as $xx) {
call_hooks('dreport_process',$xx);
if(is_array($xx) && array_key_exists('message_id',$xx) && delivery_report_is_storable($xx)) {
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s','%s','%s','%s','%s' ) ",
call_hooks('dreport_process',$xx);
if(is_array($xx) && array_key_exists('message_id',$xx) && DReport::is_storable($xx)) {
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s','%s','%s','%s','%s','%s' ) ",
dbesc($xx['message_id']),
dbesc($xx['location']),
dbesc($xx['recipient']),
dbesc($xx['name']),
dbesc($xx['status']),
dbesc(datetime_convert($xx['date'])),
dbesc(datetime_convert('UTC','UTC',$xx['date'])),
dbesc($xx['sender'])
);
}
@ -1188,6 +1191,7 @@ function zot_fetch($arr) {
$zret = zot6_check_sig();
if($zret['success'] && $zret['hubloc'] && $zret['hubloc']['hubloc_guid'] === $arr['sender']['guid'] && $arr['msg']) {
logger('zot6_delivery',LOGGER_DEBUG);
logger('zot6_data: ' . print_r($arr,true),LOGGER_DATA);
@ -1748,7 +1752,7 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $
}
$channel = $r[0];
$DR->addto_recipient($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
$DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
/* blacklisted channels get a permission denied, no special message to tip them off */
@ -2297,7 +2301,7 @@ function process_mail_delivery($sender, $arr, $deliveries) {
}
$channel = $r[0];
$DR->addto_recipient($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
$DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
/* blacklisted channels get a permission denied, no special message to tip them off */
@ -3987,7 +3991,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
if(array_key_exists('item',$arr) && is_array($arr['item'][0])) {
$DR = new Zotlabs\Lib\DReport(z_root(),$d['hash'],$d['hash'],$arr['item'][0]['message_id'],'channel sync processed');
$DR->addto_recipient($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
$DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
}
else
$DR = new Zotlabs\Lib\DReport(z_root(),$d['hash'],$d['hash'],'sync packet','channel sync delivered');
@ -5185,7 +5189,7 @@ function zot6_check_sig() {
$sigblock = \Zotlabs\Web\HTTPSig::parse_sigheader($_SERVER['HTTP_SIGNATURE']);
if($sigblock) {
$keyId = $sigblock['keyId'];
logger('keyID: ' . $keyId);
if($keyId) {
$r = q("select hubloc.*, site_crypto from hubloc left join site on hubloc_url = site_url
where hubloc_addr = '%s' ",
@ -5195,6 +5199,7 @@ function zot6_check_sig() {
foreach($r as $hubloc) {
$verified = \Zotlabs\Web\HTTPSig::verify('',$hubloc['xchan_pubkey']);
if($verified && $verified['header_signed'] && $verified['header_valid'] && $verified['content_signed'] && $verified['content_valid']) {
logger('zot6 verified');
$ret['hubloc'] = $hubloc;
$ret['success'] = true;
return $ret;

View File

@ -247,6 +247,7 @@ CREATE TABLE IF NOT EXISTS `channel` (
`channel_guid` char(191) NOT NULL DEFAULT '',
`channel_guid_sig` text NOT NULL,
`channel_hash` char(191) NOT NULL DEFAULT '',
`channel_portable_id` char(191) NOT NULL DEFAULT '',
`channel_timezone` char(128) NOT NULL DEFAULT 'UTC',
`channel_location` char(191) NOT NULL DEFAULT '',
`channel_theme` char(191) NOT NULL DEFAULT '',
@ -306,6 +307,7 @@ CREATE TABLE IF NOT EXISTS `channel` (
KEY `channel_default_gid` (`channel_default_group`),
KEY `channel_guid` (`channel_guid`),
KEY `channel_hash` (`channel_hash`),
KEY `channel_portable_id` (`channel_portable_id`),
KEY `channel_expire_days` (`channel_expire_days`),
KEY `channel_deleted` (`channel_deleted`),
KEY `channel_active` (`channel_active`),
@ -403,6 +405,7 @@ CREATE TABLE IF NOT EXISTS `dreport` (
`dreport_site` char(191) NOT NULL DEFAULT '',
`dreport_recip` char(191) NOT NULL DEFAULT '',
`dreport_result` char(191) NOT NULL DEFAULT '',
`dreport_name` char(191) NOT NULL DEFAULT '',
`dreport_time` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`dreport_xchan` char(191) NOT NULL DEFAULT '',
`dreport_queue` char(191) NOT NULL DEFAULT '',
@ -577,6 +580,7 @@ CREATE TABLE IF NOT EXISTS `issue` (
CREATE TABLE IF NOT EXISTS `item` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`uuid` char(191) NOT NULL DEFAULT '',
`mid` char(191) NOT NULL DEFAULT '',
`aid` int(10) unsigned NOT NULL DEFAULT 0 ,
`uid` int(10) unsigned NOT NULL DEFAULT 0 ,
@ -595,6 +599,7 @@ CREATE TABLE IF NOT EXISTS `item` (
`source_xchan` char(191) NOT NULL DEFAULT '',
`mimetype` char(191) NOT NULL DEFAULT '',
`title` text NOT NULL,
`summary` mediumtext NOT NULL,
`body` mediumtext NOT NULL,
`html` mediumtext NOT NULL,
`app` char(191) NOT NULL DEFAULT '',
@ -649,6 +654,7 @@ CREATE TABLE IF NOT EXISTS `item` (
`item_pending_remove` tinyint(1) NOT NULL DEFAULT 0 ,
`item_blocked` tinyint(1) NOT NULL DEFAULT 0 ,
PRIMARY KEY (`id`),
KEY `uuid` (`uuid`),
KEY `parent` (`parent`),
KEY `created` (`created`),
KEY `edited` (`edited`),

View File

@ -242,6 +242,7 @@ CREATE TABLE "channel" (
"channel_guid" text NOT NULL DEFAULT '',
"channel_guid_sig" text NOT NULL,
"channel_hash" text NOT NULL DEFAULT '',
"channel_portable_id" text NOT NULL DEFAULT '',
"channel_timezone" varchar(128) NOT NULL DEFAULT 'UTC',
"channel_location" text NOT NULL DEFAULT '',
"channel_theme" text NOT NULL DEFAULT '',
@ -284,6 +285,7 @@ create index "channel_max_friend_req" on channel ("channel_max_friend_req");
create index "channel_default_gid" on channel ("channel_default_group");
create index "channel_guid" on channel ("channel_guid");
create index "channel_hash" on channel ("channel_hash");
create index "channel_portable_id" on channel ("channel_portable_id");
create index "channel_expire_days" on channel ("channel_expire_days");
create index "channel_deleted" on channel ("channel_deleted");
create index "channel_active" on channel ("channel_active");
@ -375,6 +377,7 @@ CREATE TABLE IF NOT EXISTS "dreport" (
"dreport_site" varchar(255) NOT NULL DEFAULT '',
"dreport_recip" varchar(255) NOT NULL DEFAULT '',
"dreport_result" varchar(255) NOT NULL DEFAULT '',
"dreport_name" varchar(255) NOT NULL DEFAULT '',
"dreport_time" timestamp NOT NULL DEFAULT '0001-01-01 00:00:00',
"dreport_xchan" varchar(255) NOT NULL DEFAULT '',
"dreport_queue" varchar(255) NOT NULL DEFAULT '',
@ -548,6 +551,7 @@ create index "issue_component" on issue ("issue_component");
CREATE TABLE "item" (
"id" serial NOT NULL,
"uuid" text NOT NULL DEFAULT '',
"mid" text NOT NULL DEFAULT '',
"aid" bigint NOT NULL DEFAULT '0',
"uid" bigint NOT NULL DEFAULT '0',
@ -566,6 +570,7 @@ CREATE TABLE "item" (
"source_xchan" text NOT NULL DEFAULT '',
"mimetype" text NOT NULL DEFAULT '',
"title" text NOT NULL,
"summary" text NOT NULL,
"body" text NOT NULL,
"html" text NOT NULL,
"app" text NOT NULL DEFAULT '',
@ -623,6 +628,7 @@ CREATE TABLE "item" (
PRIMARY KEY ("id")
);
create index "item_uid" on item ("uid");
create index "item_uuid" on item ("uuid");
create index "item_parent" on item ("parent");
create index "item_created" on item ("created");
create index "item_edited" on item ("edited");

View File

@ -91,6 +91,7 @@ class PermissionDescriptionTest extends UnitTestCase {
function testDecrypt_sigheader() {
$header = 'Header: iv="value_iv" key="value_key" alg="value_alg" data="value_data"';
$result = [
'encrypted' => true,
'iv' => 'value_iv',
'key' => 'value_key',
'alg' => 'value_alg',
@ -109,6 +110,7 @@ class PermissionDescriptionTest extends UnitTestCase {
$header = 'Header: iv="value_iv" key="value_key" alg="value_alg" data="value_data"';
$result = [
'encrypted' => true,
'iv' => 'value_iv',
'key' => 'value_key',
'alg' => 'value_alg',

File diff suppressed because it is too large Load Diff

View File

@ -470,7 +470,6 @@ App::$strings["Help:"] = "Помощь:";
App::$strings["Help"] = "Помощь";
App::$strings["Not Found"] = "Не найдено";
App::$strings["Page not found."] = "Страница не найдена.";
App::$strings["Cannot locate DNS info for database server '%s'"] = "Не удается найти DNS информацию для сервера базы данных '%s'";
App::$strings["Image/photo"] = "Изображение / фотография";
App::$strings["Encrypted content"] = "Зашифрованное содержание";
App::$strings["Install %1\$s element %2\$s"] = "Установить %1\$s элемент %2\$s";
@ -1152,8 +1151,6 @@ App::$strings["Blocked accounts"] = "Заблокированные аккаун
App::$strings["Expired accounts"] = "Просроченные аккаунты";
App::$strings["Expiring accounts"] = "Близкие к просрочке аккаунты";
App::$strings["Channels"] = "Каналы";
App::$strings["Primary"] = "Основной";
App::$strings["Clones"] = "Клоны";
App::$strings["Message queues"] = "Очередь сообщений";
App::$strings["Your software should be updated"] = "Ваше программное обеспечение должно быть обновлено";
App::$strings["Administration"] = "Администрирование";
@ -1439,6 +1436,7 @@ App::$strings["Please select another location to become primary before removing
App::$strings["Syncing locations"] = "Синхронизировать местоположение";
App::$strings["No locations found."] = "Местоположений не найдено";
App::$strings["Manage Channel Locations"] = "Управление местоположением канала";
App::$strings["Primary"] = "Основной";
App::$strings["Drop"] = "Удалить";
App::$strings["Sync Now"] = "Синхронизировать";
App::$strings["Please wait several minutes between consecutive operations."] = "Пожалуйста, подождите несколько минут между последовательными операциями.";
@ -1828,17 +1826,17 @@ App::$strings["Note: as a security measure, you should give the web server write
App::$strings["%s is writable"] = "%s доступен для записи";
App::$strings["This software uses the store directory to save uploaded files. The web server needs to have write access to the store directory under the top level web folder"] = "Эта программа использует каталог хранения для загруженных файлов. Для веб-сервера требуется доступ на запись начиная с верхнего уровня каталога хранения.";
App::$strings["store is writable"] = "хранилище доступно для записи";
App::$strings["SSL certificate cannot be validated. Fix certificate or disable https access to this site."] = "";
App::$strings["If you have https access to your website or allow connections to TCP port 443 (the https: port), you MUST use a browser-valid certificate. You MUST NOT use self-signed certificates!"] = "";
App::$strings["SSL certificate cannot be validated. Fix certificate or disable https access to this site."] = "SSL certificate cannot be validated. Замените его или отключите https доступ к этому сайту.";
App::$strings["If you have https access to your website or allow connections to TCP port 443 (the https: port), you MUST use a browser-valid certificate. You MUST NOT use self-signed certificates!"] = "Если у вас есть https-доступ к вашему сайту или разрешено подключение к TCP-порту 443 (порт https), вы ДОЛЖНЫ использовать сертификат, действительный для браузера. Вы НЕ ДОЛЖНЫ использовать самоподписанные сертификаты!";
App::$strings["This restriction is incorporated because public posts from you may for example contain references to images on your own hub."] = "Эти ограничения приняты поскольку ваши общедоступные публикации могут, например, содержать ссылки на изображения на вашем собственном хабе.";
App::$strings["If your certificate is not recognized, members of other sites (who may themselves have valid certificates) will get a warning message on their own site complaining about security issues."] = "";
App::$strings["This can cause usability issues elsewhere (not just on your own site) so we must insist on this requirement."] = "";
App::$strings["Providers are available that issue free certificates which are browser-valid."] = "";
App::$strings["If you are confident that the certificate is valid and signed by a trusted authority, check to see if you have failed to install an intermediate cert. These are not normally required by browsers, but are required for server-to-server communications."] = "";
App::$strings["SSL certificate validation"] = "";
App::$strings["Url rewrite in .htaccess is not working. Check your server configuration.Test: "] = "";
App::$strings["If your certificate is not recognized, members of other sites (who may themselves have valid certificates) will get a warning message on their own site complaining about security issues."] = "Если ваш сертификат не признан, пользователи других сайтов (которые могут сами иметь действительные сертификаты) получат предупреждающее сообщение о проблемах с безопасностью.";
App::$strings["This can cause usability issues elsewhere (not just on your own site) so we must insist on this requirement."] = "Это может привести к проблемам удобства использования из других мест (не только на вашем собственном сайте), поэтому мы настаиваем на этом требовании.";
App::$strings["Providers are available that issue free certificates which are browser-valid."] = "Доступны поставщики, которые выдают действительные для браузера бесплатные сертификаты.";
App::$strings["If you are confident that the certificate is valid and signed by a trusted authority, check to see if you have failed to install an intermediate cert. These are not normally required by browsers, but are required for server-to-server communications."] = "Если вы уверены, что сертификат действителен и подписан доверенным органом, проверьте, установлен ли промежуточные сертификаты. Обычно они не требуются браузерами, но бывают необходимы для связи между серверами.";
App::$strings["SSL certificate validation"] = "Проверка SSL сертификата";
App::$strings["Url rewrite in .htaccess is not working. Check your server configuration.Test: "] = "Перезапись URL в .htaccess не работает. Проверьте настройки вашего сервера.";
App::$strings["Url rewrite is working"] = "Перезапись URL работает";
App::$strings["The database configuration file \".htconfig.php\" could not be written. Please use the enclosed text to create a configuration file in your web server root."] = "";
App::$strings["The database configuration file \".htconfig.php\" could not be written. Please use the enclosed text to create a configuration file in your web server root."] = "Файл конфигурации базы данных \".htconfig.php\" не может быть записан. Используйте прилагаемый текст для создания файла конфигурации в корневом каталоге веб-сервера.";
App::$strings["Errors encountered creating database tables."] = "При создании базы данных возникли ошибки.";
App::$strings["<h1>What next?</h1>"] = "<h1>Что дальше? </h1>";
App::$strings["IMPORTANT: You will need to [manually] setup a scheduled task for the poller."] = "Вам понадобится [вручную] настроить запланированную задачу для опрашивателя.";
@ -2588,14 +2586,14 @@ App::$strings["Addon Features"] = "Настройки расширений";
App::$strings["App Collections"] = "Коллекции приложений";
App::$strings["Installed apps"] = "Установленные приложения";
App::$strings["Remove term"] = "Удалить термин";
App::$strings["Personal Posts"] = "Личные публикации";
App::$strings["Show posts that mention or involve me"] = "Показывать публикации где вы были упомянуты или привлечены";
App::$strings["Starred Posts"] = "Отмеченные публикации";
App::$strings["Show posts that I have starred"] = "Показывать публикации которые я отметил";
App::$strings["Show posts related to the %s privacy group"] = "Показывать публикации относящиеся к группе безопасности %s";
App::$strings["Show my privacy groups"] = "Показывать мои группы безопасности";
App::$strings["Show posts to this forum"] = "Показывать публикации этого форума";
App::$strings["Show forums"] = "Показывать форумы";
App::$strings["Starred Posts"] = "Отмеченные публикации";
App::$strings["Show posts that I have starred"] = "Показывать публикации которые я отметил";
App::$strings["Personal Posts"] = "Личные публикации";
App::$strings["Show posts that mention or involve me"] = "Показывать публикации где вы были упомянуты или привлечены";
App::$strings["Show posts that I have filed to %s"] = "Показывать публикации которые я добавил в %s";
App::$strings["Show filed post categories"] = "Показывать категории добавленных публикаций";
App::$strings["Panel search"] = "Панель поиска";
@ -2824,7 +2822,6 @@ App::$strings["Post to Dreamwidth by default"] = "Публиковать в Drea
App::$strings["Dreamwidth Post Settings"] = "Настройки публикаций в Dreamwidth";
App::$strings["Project Servers and Resources"] = "Серверы и ресурсы проекта";
App::$strings["Project Creator and Tech Lead"] = "Создатель проекта и технический руководитель";
App::$strings["Admin, developer, directorymin, support bloke"] = "Администратор, разработчик, администратор каталога, поддержка";
App::$strings["And the hundreds of other people and organisations who helped make the Hubzilla possible."] = "И сотни других людей и организаций которые помогали в создании Hubzilla.";
App::$strings["The Redmatrix/Hubzilla projects are provided primarily by volunteers giving their time and expertise - and often paying out of pocket for services they share with others."] = "Проекты Redmatrix / Hubzilla предоставляются, в основном, добровольцами, которые предоставляют свое время и опыт и, часто, оплачивают из своего кармана услуги, которыми они делятся с другими.";
App::$strings["There is no corporate funding and no ads, and we do not collect and sell your personal information. (We don't control your personal information - <strong>you do</strong>.)"] = "Здесь нет корпоративного финансирования и рекламы, мы не собираем и не продаем вашу личную информацию. (Мы не контролируем вашу личную информацию - <strong>это делаете вы</strong>.)";
@ -3102,13 +3099,12 @@ App::$strings["This will import all your cloud files from another server."] = "
App::$strings["Hubzilla Server base URL"] = "Базовый URL сервера Hubzilla";
App::$strings["Since modified date yyyy-mm-dd"] = "Начиная с даты изменений yyyy-mm-dd";
App::$strings["Until modified date yyyy-mm-dd"] = "Заканчивая датой изменений yyyy-mm-dd";
App::$strings["Post to LiveJournal"] = "Опубликовать в LiveJournal";
App::$strings["Enable LiveJournal Post Plugin"] = "Включить плагин публикаций LiveJournal";
App::$strings["LiveJournal username"] = "Имя пользователя LiveJournal";
App::$strings["LiveJournal password"] = "Пароль LiveJournal";
App::$strings["Post to LiveJournal by default"] = "Публиковать в LiveJournal по умолчанию";
App::$strings["LiveJournal Post Settings"] = "Настройки публикаций в LiveJournal";
App::$strings["LiveJournal Settings saved."] = "Настройки LiveJournal сохранены.";
App::$strings["Post to Livejournal"] = "Опубликовать в Livejournal";
App::$strings["Enable Livejournal Post Plugin"] = "Включить раширение публикаций в Livejournal";
App::$strings["Livejournal username"] = "Имя пользователя Livejournal";
App::$strings["Livejournal password"] = "Пароль Livejournal";
App::$strings["Post to Livejournal by default"] = "Публиковать в Livejournal по умолчанию";
App::$strings["Livejournal Post Settings"] = "Настройки публикации в Livejournal";
App::$strings["Post to GNU social"] = "Опубликовать в GNU Social";
App::$strings["Please contact your site administrator.<br />The provided API URL is not valid."] = "Пожалуйста свяжитесь с администратором сайта. <br />Предоставленный URL API недействителен.";
App::$strings["We could not contact the GNU social API with the Path you entered."] = "Нам не удалось установить контакт с GNU Social API по введённому вами пути";

View File

@ -181,7 +181,7 @@
{{/if}}
{{if $item.edpost && $item.dreport}}
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="dreport/{{$item.mid}}">{{$item.dreport}}</a>
<a class="dropdown-item" href="dreport/{{$item.dreport_link}}">{{$item.dreport}}</a>
{{/if}}
{{if $item.settings}}
<div class="dropdown-divider"></div>