aboutsummaryrefslogtreecommitdiffstats
path: root/Zotlabs/Lib
diff options
context:
space:
mode:
Diffstat (limited to 'Zotlabs/Lib')
-rw-r--r--Zotlabs/Lib/Apps.php10
-rw-r--r--Zotlabs/Lib/Config.php4
-rw-r--r--Zotlabs/Lib/DB_Upgrade.php134
-rw-r--r--Zotlabs/Lib/DReport.php55
-rw-r--r--Zotlabs/Lib/Enotify.php72
-rw-r--r--Zotlabs/Lib/Img_filesize.php122
-rw-r--r--Zotlabs/Lib/MarkdownSoap.php65
-rw-r--r--Zotlabs/Lib/Permcat.php78
-rw-r--r--Zotlabs/Lib/ProtoDriver.php19
-rw-r--r--Zotlabs/Lib/Share.php141
-rw-r--r--Zotlabs/Lib/ThreadItem.php4
-rw-r--r--Zotlabs/Lib/Verify.php63
-rw-r--r--Zotlabs/Lib/ZotDriver.php30
13 files changed, 613 insertions, 184 deletions
diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php
index 457b85b62..f91dc8e49 100644
--- a/Zotlabs/Lib/Apps.php
+++ b/Zotlabs/Lib/Apps.php
@@ -119,6 +119,7 @@ class Apps {
static public function parse_app_description($f,$translate = true) {
+
$ret = array();
$baseurl = z_root();
@@ -194,6 +195,10 @@ class Apps {
if(! is_public_profile())
unset($ret);
break;
+ case 'public_stream':
+ if(! can_view_public_stream())
+ unset($ret);
+ break;
case 'observer':
if(! $observer)
unset($ret);
@@ -221,6 +226,7 @@ class Apps {
static public function translate_system_apps(&$arr) {
$apps = array(
'Apps' => t('Apps'),
+ 'Articles' => t('Articles'),
'Cards' => t('Cards'),
'Admin' => t('Site Admin'),
'Report Bug' => t('Report Bug'),
@@ -345,6 +351,10 @@ class Apps {
if(! is_public_profile())
return '';
break;
+ case 'public_stream':
+ if(! can_view_public_stream())
+ return '';
+ break;
case 'observer':
$observer = \App::get_observer();
if(! $observer)
diff --git a/Zotlabs/Lib/Config.php b/Zotlabs/Lib/Config.php
index f9f22ba3a..c00b8efb6 100644
--- a/Zotlabs/Lib/Config.php
+++ b/Zotlabs/Lib/Config.php
@@ -142,9 +142,9 @@ class Config {
/**
- * @brief Returns a value directly from the database configuration storage.
+ * @brief Returns a record directly from the database configuration storage.
*
- * This function queries directly the database and bypasses the chached storage
+ * This function queries directly the database and bypasses the cached storage
* from get_config($family, $key).
*
* @param string $family
diff --git a/Zotlabs/Lib/DB_Upgrade.php b/Zotlabs/Lib/DB_Upgrade.php
index 8f0488f6f..4038a2d53 100644
--- a/Zotlabs/Lib/DB_Upgrade.php
+++ b/Zotlabs/Lib/DB_Upgrade.php
@@ -10,22 +10,12 @@ class DB_Upgrade {
function __construct($db_revision) {
- $platform_name = System::get_platform_name();
+ $this->config_name = 'db_version';
+ $this->func_prefix = '_';
- $update_file = 'install/' . $platform_name . '/update.php';
- if(! file_exists($update_file)) {
- $update_file = 'install/update.php';
- $this->config_name = 'db_version';
- $this->func_prefix = 'update_r';
- }
- else {
- $this->config_name = $platform_name . '_db_version';
- $this->func_prefix = $platform_name . '_update_';
- }
-
- $build = get_config('system', $this->config_name, 0);
+ $build = get_config('system', 'db_version', 0);
if(! intval($build))
- $build = set_config('system', $this->config_name, $db_revision);
+ $build = set_config('system', 'db_version', $db_revision);
if($build == $db_revision) {
// Nothing to be done.
@@ -40,82 +30,78 @@ class DB_Upgrade {
$current = intval($db_revision);
- if(($stored < $current) && file_exists($update_file)) {
+ if($stored < $current) {
- Config::Load('database');
+ // The last update we performed was $stored.
+ // Start at $stored + 1 and continue until we have completed $current
- // We're reporting a different version than what is currently installed.
- // Run any existing update scripts to bring the database up to current.
-
- require_once($update_file);
+ for($x = $stored + 1; $x <= $current; $x ++) {
+ $s = '_' . $x;
+ $cls = '\\Zotlabs\Update\\' . $s ;
+ if(! class_exists($cls)) {
+ return;
+ }
- // make sure that boot.php and update.php are the same release, we might be
- // updating from git right this very second and the correct version of the update.php
- // file may not be here yet. This can happen on a very busy site.
+ // There could be a lot of processes running or about to run.
+ // We want exactly one process to run the update command.
+ // So store the fact that we're taking responsibility
+ // after first checking to see if somebody else already has.
- if($db_revision == UPDATE_VERSION) {
- for($x = $stored; $x < $current; $x ++) {
- $func = $this->func_prefix . $x;
- if(function_exists($func)) {
- // There could be a lot of processes running or about to run.
- // We want exactly one process to run the update command.
- // So store the fact that we're taking responsibility
- // after first checking to see if somebody else already has.
+ // If the update fails or times-out completely you may need to
+ // delete the config entry to try again.
- // If the update fails or times-out completely you may need to
- // delete the config entry to try again.
+ Config::Load('database');
- if(get_config('database', $func))
- break;
- set_config('database',$func, '1');
- // call the specific update
+ if(get_config('database', $s))
+ break;
+ set_config('database',$s, '1');
+
- $retval = $func();
- if($retval) {
+ $c = new $cls();
+ $retval = $c->run();
- // Prevent sending hundreds of thousands of emails by creating
- // a lockfile.
+ if($retval != UPDATE_SUCCESS) {
- $lockfile = 'store/[data]/mailsent';
+ // Prevent sending hundreds of thousands of emails by creating
+ // a lockfile.
- if ((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 86400)))
- return;
- @unlink($lockfile);
- //send the administrator an e-mail
- file_put_contents($lockfile, $x);
-
- $r = q("select account_language from account where account_email = '%s' limit 1",
- dbesc(\App::$config['system']['admin_email'])
- );
- push_lang(($r) ? $r[0]['account_language'] : 'en');
+ $lockfile = 'store/[data]/mailsent';
- z_mail(
+ if ((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 86400)))
+ return;
+ @unlink($lockfile);
+ //send the administrator an e-mail
+ file_put_contents($lockfile, $x);
+
+ $r = q("select account_language from account where account_email = '%s' limit 1",
+ dbesc(\App::$config['system']['admin_email'])
+ );
+ push_lang(($r) ? $r[0]['account_language'] : 'en');
+ z_mail(
+ [
+ 'toEmail' => \App::$config['system']['admin_email'],
+ 'messageSubject' => sprintf( t('Update Error at %s'), z_root()),
+ 'textVersion' => replace_macros(get_intltext_template('update_fail_eml.tpl'),
[
- 'toEmail' => \App::$config['system']['admin_email'],
- 'messageSubject' => sprintf( t('Update Error at %s'), z_root()),
- 'textVersion' => replace_macros(get_intltext_template('update_fail_eml.tpl'),
- [
- '$sitename' => \App::$config['system']['sitename'],
- '$siteurl' => z_root(),
- '$update' => $x,
- '$error' => sprintf( t('Update %s failed. See error logs.'), $x)
- ]
- )
+ '$sitename' => \App::$config['system']['sitename'],
+ '$siteurl' => z_root(),
+ '$update' => $x,
+ '$error' => sprintf( t('Update %s failed. See error logs.'), $x)
]
- );
-
- //try the logger
- logger('CRITICAL: Update Failed: ' . $x);
- pop_lang();
- }
- else {
- set_config('database',$func, 'success');
- }
- }
+ )
+ ]
+ );
+
+ //try the logger
+ logger('CRITICAL: Update Failed: ' . $x);
+ pop_lang();
+ }
+ else {
+ set_config('database',$s, 'success');
}
- set_config('system', $this->config_name, $db_revision);
}
}
+ set_config('system', 'db_version', $db_revision);
}
}
} \ No newline at end of file
diff --git a/Zotlabs/Lib/DReport.php b/Zotlabs/Lib/DReport.php
new file mode 100644
index 000000000..a68d6c18f
--- /dev/null
+++ b/Zotlabs/Lib/DReport.php
@@ -0,0 +1,55 @@
+<?php
+namespace Zotlabs\Lib;
+
+class DReport {
+
+ private $location;
+ private $sender;
+ private $recipient;
+ private $message_id;
+ private $status;
+ private $date;
+
+ function __construct($location,$sender,$recipient,$message_id,$status = 'deliver') {
+ $this->location = $location;
+ $this->sender = $sender;
+ $this->recipient = $recipient;
+ $this->message_id = $message_id;
+ $this->status = $status;
+ $this->date = datetime_convert();
+ }
+
+ function update($status) {
+ $this->status = $status;
+ $this->date = datetime_convert();
+ }
+
+ function addto_recipient($name) {
+ $this->recipient = $this->recipient . ' ' . $name;
+ }
+
+ function addto_update($status) {
+ $this->status = $this->status . ' ' . $status;
+ }
+
+
+ function set($arr) {
+ $this->location = $arr['location'];
+ $this->sender = $arr['sender'];
+ $this->recipient = $arr['recipient'];
+ $this->message_id = $arr['message_id'];
+ $this->status = $arr['status'];
+ $this->date = $arr['date'];
+ }
+
+ function get() {
+ return array(
+ 'location' => $this->location,
+ 'sender' => $this->sender,
+ 'recipient' => $this->recipient,
+ 'message_id' => $this->message_id,
+ 'status' => $this->status,
+ 'date' => $this->date
+ );
+ }
+}
diff --git a/Zotlabs/Lib/Enotify.php b/Zotlabs/Lib/Enotify.php
index a7b4f28e8..61c98c881 100644
--- a/Zotlabs/Lib/Enotify.php
+++ b/Zotlabs/Lib/Enotify.php
@@ -63,7 +63,9 @@ class Enotify {
$thanks = t('Thank You,');
$sitename = get_config('system','sitename');
$site_admin = sprintf( t('%s Administrator'), $sitename);
-
+ $opt_out1 = sprintf( t('This email was sent by %1$s at %2$s.'), t('$Projectname'), \App::get_hostname());
+ $opt_out2 = sprintf( t('To stop receiving these messages, please adjust your Notification Settings at %s'), z_root() . '/settings');
+ $hopt_out2 = sprintf( t('To stop receiving these messages, please adjust your %s.'), '<a href="' . z_root() . '/settings' . '">' . t('Notification Settings') . '</a>');
$sender_name = $product;
$hostname = \App::get_hostname();
if(strpos($hostname,':'))
@@ -112,6 +114,8 @@ class Enotify {
}
+ $always_show_in_notices = get_pconfig($recip['channel_id'],'system','always_show_in_notices');
+
// e.g. "your post", "David's photo", etc.
$possess_desc = t('%s <!item_type!>');
@@ -128,18 +132,28 @@ class Enotify {
}
if ($params['type'] == NOTIFY_COMMENT) {
-// logger("notification: params = " . print_r($params, true), LOGGER_DEBUG);
+ //logger("notification: params = " . print_r($params, true), LOGGER_DEBUG);
$moderated = (($params['item']['item_blocked'] == ITEM_MODERATED) ? true : false);
$itemlink = $params['link'];
- // ignore like/unlike activity on posts - they probably require a separate notification preference
+ $action = t('commented on');
+
+ if(array_key_exists('item',$params) && in_array($params['item']['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) {
+
+ if(! $always_show_in_notices) {
+ logger('notification: not a visible activity. Ignoring.');
+ pop_lang();
+ return;
+ }
+
+ if(activity_match($params['verb'], ACTIVITY_LIKE))
+ $action = t('liked');
+
+ if(activity_match($params['verb'], ACTIVITY_DISLIKE))
+ $action = t('disliked');
- if (array_key_exists('item',$params) && (! visible_activity($params['item']))) {
- logger('notification: not a visible activity. Ignoring.');
- pop_lang();
- return;
}
$parent_mid = $params['parent_mid'];
@@ -181,26 +195,29 @@ class Enotify {
//$possess_desc = str_replace('<!item_type!>',$possess_desc);
// "a post"
- $dest_str = sprintf(t('%1$s, %2$s commented on [zrl=%3$s]a %4$s[/zrl]'),
+ $dest_str = sprintf(t('%1$s, %2$s %3$s [zrl=%4$s]a %5$s[/zrl]'),
$recip['channel_name'],
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
+ $action,
$itemlink,
$item_post_type);
// "George Bull's post"
if($p)
- $dest_str = sprintf(t('%1$s, %2$s commented on [zrl=%3$s]%4$s\'s %5$s[/zrl]'),
+ $dest_str = sprintf(t('%1$s, %2$s %3$s [zrl=%4$s]%5$s\'s %6$s[/zrl]'),
$recip['channel_name'],
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
+ $action,
$itemlink,
$p[0]['author']['xchan_name'],
$item_post_type);
// "your post"
if($p[0]['owner']['xchan_name'] == $p[0]['author']['xchan_name'] && intval($p[0]['item_wall']))
- $dest_str = sprintf(t('%1$s, %2$s commented on [zrl=%3$s]your %4$s[/zrl]'),
+ $dest_str = sprintf(t('%1$s, %2$s %3$s [zrl=%4$s]your %5$s[/zrl]'),
$recip['channel_name'],
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
+ $action,
$itemlink,
$item_post_type);
@@ -231,12 +248,12 @@ class Enotify {
$itemlink = $params['link'];
- // ignore like/unlike activity on posts - they probably require a separate notification preference
-
if (array_key_exists('item',$params) && (! activity_match($params['item']['verb'],ACTIVITY_LIKE))) {
- logger('notification: not a like activity. Ignoring.');
- pop_lang();
- return;
+ if(! $always_show_in_notices) {
+ logger('notification: not a visible activity. Ignoring.');
+ pop_lang();
+ return;
+ }
}
$parent_mid = $params['parent_mid'];
@@ -496,8 +513,6 @@ class Enotify {
// Another option would be to not add them to the DB, and change how emails are handled
// (probably would be better that way)
- $always_show_in_notices = get_pconfig($recip['channel_id'],'system','always_show_in_notices');
-
if (!$always_show_in_notices) {
if (($params['type'] == NOTIFY_WALL) || ($params['type'] == NOTIFY_MAIL) || ($params['type'] == NOTIFY_INTRO)) {
$seen = 1;
@@ -600,6 +615,9 @@ class Enotify {
$datarray['titemlink'] = $itemlink;
$datarray['thanks'] = $thanks;
$datarray['site_admin'] = $site_admin;
+ $datarray['opt_out1'] = $opt_out1;
+ $datarray['opt_out2'] = $opt_out2;
+ $datarray['hopt_out2'] = $hopt_out2;
$datarray['title'] = stripslashes($title);
$datarray['htmlversion'] = $htmlversion;
$datarray['textversion'] = $textversion;
@@ -657,6 +675,8 @@ class Enotify {
'$hitemlink' => $datarray['hitemlink'],
'$thanks' => $datarray['thanks'],
'$site_admin' => $datarray['site_admin'],
+ '$opt_out1' => $datarray['opt_out1'],
+ '$opt_out2' => $datarray['hopt_out2'],
'$title' => $datarray['title'],
'$htmlversion' => $datarray['htmlversion'],
));
@@ -677,6 +697,8 @@ class Enotify {
'$titemlink' => $datarray['titemlink'],
'$thanks' => $datarray['thanks'],
'$site_admin' => $datarray['site_admin'],
+ '$opt_out1' => $datarray['opt_out1'],
+ '$opt_out2' => $datarray['opt_out2'],
'$title' => $datarray['title'],
'$textversion' => $datarray['textversion'],
));
@@ -794,6 +816,20 @@ class Enotify {
: sprintf( t('commented on %s\'s post'), $item['owner']['xchan_name']));
}
+ $edit = false;
+
+ if($item['edited'] > $item['created']) {
+ if($item['item_thread_top']) {
+ $itemem_text = sprintf( t('edited a post dated %s'), relative_date($item['created']));
+ $edit = true;
+ }
+ else {
+ $itemem_text = sprintf( t('edited a comment dated %s'), relative_date($item['created']));
+ $edit = true;
+ }
+ }
+
+
// convert this logic into a json array just like the system notifications
return array(
@@ -801,7 +837,7 @@ class Enotify {
'name' => $item['author']['xchan_name'],
'url' => $item['author']['xchan_url'],
'photo' => $item['author']['xchan_photo_s'],
- 'when' => relative_date($item['created']),
+ 'when' => relative_date(($edit)? $item['edited'] : $item['created']),
'class' => (intval($item['item_unseen']) ? 'notify-unseen' : 'notify-seen'),
'b64mid' => ((in_array($item['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) ? 'b64.' . base64url_encode($item['thr_parent']) : 'b64.' . base64url_encode($item['mid'])),
'notify_id' => 'undefined',
diff --git a/Zotlabs/Lib/Img_filesize.php b/Zotlabs/Lib/Img_filesize.php
new file mode 100644
index 000000000..196697733
--- /dev/null
+++ b/Zotlabs/Lib/Img_filesize.php
@@ -0,0 +1,122 @@
+<?php
+
+namespace Zotlabs\Lib;
+
+class Img_filesize {
+
+ private $url;
+
+ function __construct($url) {
+ $this->url = $url;
+ }
+
+ function getSize() {
+ $size = null;
+
+ if(stripos($this->url,z_root() . '/photo') !== false) {
+ $size = self::getLocalFileSize($this->url);
+ }
+ if(! $size) {
+ $size = getRemoteFileSize($this->url);
+ }
+
+ return $size;
+ }
+
+
+ static function getLocalFileSize($url) {
+
+ $fname = basename($url);
+ $resolution = 0;
+
+ if(strpos($fname,'.') !== false)
+ $fname = substr($fname,0,strpos($fname,'.'));
+
+ if(substr($fname,-2,1) == '-') {
+ $resolution = intval(substr($fname,-1,1));
+ $fname = substr($fname,0,-2);
+ }
+
+ $r = q("SELECT filesize FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1",
+ dbesc($fname),
+ intval($resolution)
+ );
+ if($r) {
+ return $r[0]['filesize'];
+ }
+ return null;
+ }
+
+}
+
+/**
+ * Try to determine the size of a remote file by making an HTTP request for
+ * a byte range, or look for the content-length header in the response.
+ * The function aborts the transfer as soon as the size is found, or if no
+ * length headers are returned, it aborts the transfer.
+ *
+ * @return int|null null if size could not be determined, or length of content
+ */
+function getRemoteFileSize($url)
+{
+ $ch = curl_init($url);
+
+ $headers = array(
+ 'Range: bytes=0-1',
+ 'Connection: close',
+ );
+
+ $in_headers = true;
+ $size = null;
+
+ curl_setopt($ch, CURLOPT_HEADER, 1);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2450.0 Iron/46.0.2450.0');
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($ch, CURLOPT_VERBOSE, 0); // set to 1 to debug
+ curl_setopt($ch, CURLOPT_STDERR, fopen('php://output', 'r'));
+
+ curl_setopt($ch, CURLOPT_HEADERFUNCTION, function($curl, $line) use (&$in_headers, &$size) {
+ $length = strlen($line);
+
+ if (trim($line) == '') {
+ $in_headers = false;
+ }
+
+ list($header, $content) = explode(':', $line, 2);
+ $header = strtolower(trim($header));
+
+ if ($header == 'content-range') {
+ // found a content-range header
+ list($rng, $s) = explode('/', $content, 2);
+ $size = (int)$s;
+ return 0; // aborts transfer
+ } else if ($header == 'content-length' && 206 != curl_getinfo($curl, CURLINFO_HTTP_CODE)) {
+ // found content-length header and this is not a 206 Partial Content response (range response)
+ $size = (int)$content;
+ return 0;
+ } else {
+ // continue
+ return $length;
+ }
+ });
+
+ curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($curl, $data) use ($in_headers) {
+ if (!$in_headers) {
+ // shouldn't be here unless we couldn't determine file size
+ // abort transfer
+ return 0;
+ }
+
+ // write function is also called when reading headers
+ return strlen($data);
+ });
+
+ curl_exec($ch);
+ curl_getinfo($ch);
+ curl_close($ch);
+
+ return $size;
+} \ No newline at end of file
diff --git a/Zotlabs/Lib/MarkdownSoap.php b/Zotlabs/Lib/MarkdownSoap.php
index fa279b07c..a58a5753a 100644
--- a/Zotlabs/Lib/MarkdownSoap.php
+++ b/Zotlabs/Lib/MarkdownSoap.php
@@ -3,51 +3,66 @@
namespace Zotlabs\Lib;
/**
- * MarkdownSoap
+ * @brief MarkdownSoap class.
+ *
* Purify Markdown for storage
+ * @code{.php}
* $x = new MarkdownSoap($string_to_be_cleansed);
* $text = $x->clean();
- *
+ * @endcode
* What this does:
* 1. extracts code blocks and privately escapes them from processing
* 2. Run html purifier on the content
* 3. put back the code blocks
* 4. run htmlspecialchars on the entire content for safe storage
*
- * At render time:
+ * At render time:
+ * @code{.php}
* $markdown = \Zotlabs\Lib\MarkdownSoap::unescape($text);
* $html = \Michelf\MarkdownExtra::DefaultTransform($markdown);
+ * @endcode
*/
-
-
-
class MarkdownSoap {
+ /**
+ * @var string
+ */
+ private $str;
+ /**
+ * @var string
+ */
private $token;
- private $str;
function __construct($s) {
- $this->str = $s;
+ $this->str = $s;
$this->token = random_string(20);
}
-
function clean() {
$x = $this->extract_code($this->str);
$x = $this->purify($x);
- $x = $this->putback_code($x);
+ $x = $this->putback_code($x);
$x = $this->escape($x);
-
+
return $x;
}
+ /**
+ * @brief Extracts code blocks and privately escapes them from processing.
+ *
+ * @see encode_code()
+ * @see putback_code()
+ *
+ * @param string $s
+ * @return string
+ */
function extract_code($s) {
-
+
$text = preg_replace_callback('{
(?:\n\n|\A\n?)
( # $1 = the code block -- one or more lines, starting with a space/tab
@@ -62,7 +77,7 @@ class MarkdownSoap {
return $text;
}
-
+
function encode_code($matches) {
return $this->token . ';' . base64_encode($matches[0]) . ';' ;
}
@@ -71,8 +86,17 @@ class MarkdownSoap {
return base64_decode($matches[1]);
}
+ /**
+ * @brief Put back the code blocks.
+ *
+ * @see extract_code()
+ * @see decode_code()
+ *
+ * @param string $s
+ * @return string
+ */
function putback_code($s) {
- $text = preg_replace_callback('{' . $this->token . '\;(.*?)\;}xm',[ $this, 'decode_code' ], $s);
+ $text = preg_replace_callback('{' . $this->token . '\;(.*?)\;}xm', [ $this, 'decode_code' ], $s);
return $text;
}
@@ -84,20 +108,25 @@ class MarkdownSoap {
}
function protect_autolinks($s) {
- $s = preg_replace('/\<(https?\:\/\/)(.*?)\>/','[$1$2]($1$2)',$s);
+ $s = preg_replace('/\<(https?\:\/\/)(.*?)\>/', '[$1$2]($1$2)', $s);
return $s;
}
function unprotect_autolinks($s) {
return $s;
-
}
function escape($s) {
- return htmlspecialchars($s,ENT_QUOTES,'UTF-8',false);
+ return htmlspecialchars($s, ENT_QUOTES, 'UTF-8', false);
}
+ /**
+ * @brief Converts special HTML entities back to characters.
+ *
+ * @param string $s
+ * @return string
+ */
static public function unescape($s) {
- return htmlspecialchars_decode($s,ENT_QUOTES);
+ return htmlspecialchars_decode($s, ENT_QUOTES);
}
}
diff --git a/Zotlabs/Lib/Permcat.php b/Zotlabs/Lib/Permcat.php
index 505ee2cfc..ca4aed9ed 100644
--- a/Zotlabs/Lib/Permcat.php
+++ b/Zotlabs/Lib/Permcat.php
@@ -2,12 +2,36 @@
namespace Zotlabs\Lib;
-use \Zotlabs\Access as Zaccess;
-
+use Zotlabs\Access\PermissionRoles;
+use Zotlabs\Access\Permissions;
+
+/**
+ * @brief Permission Categories. Permission rules for various classes of connections.
+ *
+ * Connection permissions answer the question "Can Joe view my photos?"
+ *
+ * Some permissions may be inherited from the channel's "privacy settings"
+ * (@ref ::Zotlabs::Access::PermissionLimits "PermissionLimits") "Who can view my
+ * photos (at all)?" which have higher priority than individual connection settings.
+ * We evaluate permission limits first, and then fall through to connection
+ * permissions if the permission limits didn't already make a definitive decision.
+ *
+ * After PermissionLimits and connection permissions are evaluated, individual
+ * content ACLs are evaluated (@ref ::Zotlabs::Access::AccessList "AccessList").
+ * These answer the question "Can Joe view *this* album/photo?".
+ */
class Permcat {
+ /**
+ * @var array
+ */
private $permcats = [];
+ /**
+ * @brief Permcat constructor.
+ *
+ * @param int $channel_id
+ */
public function __construct($channel_id) {
$perms = [];
@@ -16,16 +40,16 @@ class Permcat {
$role = get_pconfig($channel_id,'system','permissions_role');
if($role) {
- $x = Zaccess\PermissionRoles::role_perms($role);
+ $x = PermissionRoles::role_perms($role);
if($x['perms_connect']) {
- $perms = Zaccess\Permissions::FilledPerms($x['perms_connect']);
+ $perms = Permissions::FilledPerms($x['perms_connect']);
}
}
// if no role perms it may be a custom role, see if there any autoperms
if(! $perms) {
- $perms = Zaccess\Permissions::FilledAutoPerms($channel_id);
+ $perms = Permissions::FilledAutoPerms($channel_id);
}
// if no autoperms it may be a custom role with manual perms
@@ -50,13 +74,13 @@ class Permcat {
// nothing was found - create a filled permission array where all permissions are 0
if(! $perms) {
- $perms = Zaccess\Permissions::FilledPerms([]);
+ $perms = Permissions::FilledPerms([]);
}
$this->permcats[] = [
'name' => 'default',
'localname' => t('default','permcat'),
- 'perms' => Zaccess\Permissions::Operms($perms),
+ 'perms' => Permissions::Operms($perms),
'system' => 1
];
@@ -67,26 +91,39 @@ class Permcat {
$this->permcats[] = [
'name' => $p[$x][0],
'localname' => $p[$x][1],
- 'perms' => Zaccess\Permissions::Operms(Zaccess\Permissions::FilledPerms($p[$x][2])),
+ 'perms' => Permissions::Operms(Permissions::FilledPerms($p[$x][2])),
'system' => intval($p[$x][3])
];
}
}
}
-
+ /**
+ * @brief Return array with permcats.
+ *
+ * @return array
+ */
public function listing() {
return $this->permcats;
}
+ /**
+ * @brief
+ *
+ * @param string $name
+ * @return array
+ * * \e array with permcats
+ * * \e bool \b error if $name not found in permcats true
+ */
public function fetch($name) {
if($name && $this->permcats) {
foreach($this->permcats as $permcat) {
- if(strcasecmp($permcat['name'],$name) === 0) {
+ if(strcasecmp($permcat['name'], $name) === 0) {
return $permcat;
}
}
}
+
return ['error' => true];
}
@@ -118,29 +155,32 @@ class Permcat {
$permcats[] = [ $xv['k'], $xv['k'], $value, 0 ];
}
}
- }
+ }
- call_hooks('permcats',$permcats);
+ /**
+ * @hooks permcats
+ * * \e array
+ */
+ call_hooks('permcats', $permcats);
return $permcats;
-
}
- static public function find_permcat($arr,$name) {
+ static public function find_permcat($arr, $name) {
if((! $arr) || (! $name))
return false;
+
foreach($arr as $p)
if($p['name'] == $name)
return $p['value'];
}
- static public function update($channel_id, $name,$permarr) {
- PConfig::Set($channel_id,'permcat',$name,$permarr);
+ static public function update($channel_id, $name, $permarr) {
+ PConfig::Set($channel_id, 'permcat', $name, $permarr);
}
- static public function delete($channel_id,$name) {
- PConfig::Delete($channel_id,'permcat',$name);
+ static public function delete($channel_id, $name) {
+ PConfig::Delete($channel_id, 'permcat', $name);
}
-
} \ No newline at end of file
diff --git a/Zotlabs/Lib/ProtoDriver.php b/Zotlabs/Lib/ProtoDriver.php
deleted file mode 100644
index daf887dbb..000000000
--- a/Zotlabs/Lib/ProtoDriver.php
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php /** @file */
-
-namespace Zotlabs\Lib;
-
-/*
- * Abstraction class for dealing with alternate networks (which of course do not exist, hence the abstraction)
- */
-
-
-abstract class ProtoDriver {
- abstract protected function discover($channel,$location);
- abstract protected function deliver($item,$channel,$recipients);
- abstract protected function collect($channel,$connection);
- abstract protected function change_permissions($permissions,$channel,$recipient);
- abstract protected function acknowledge_permissions($permissions,$channel,$recipient);
- abstract protected function deliver_private($item,$channel,$recipients);
- abstract protected function collect_private($channel,$connection);
-
-}
diff --git a/Zotlabs/Lib/Share.php b/Zotlabs/Lib/Share.php
new file mode 100644
index 000000000..b5341e662
--- /dev/null
+++ b/Zotlabs/Lib/Share.php
@@ -0,0 +1,141 @@
+<?php
+
+namespace Zotlabs\Lib;
+
+
+class Share {
+
+ private $item = null;
+
+
+ public function __construct($post_id) {
+
+ if(! $post_id)
+ return;
+
+ if(! (local_channel() || remote_channel()))
+ return;
+
+ $r = q("SELECT * from item left join xchan on author_xchan = xchan_hash WHERE id = %d LIMIT 1",
+ intval($post_id)
+ );
+ if(! $r)
+ return;
+
+ if(($r[0]['item_private']) && ($r[0]['xchan_network'] !== 'rss'))
+ return;
+
+ $sql_extra = item_permissions_sql($r[0]['uid']);
+
+ $r = q("select * from item where id = %d $sql_extra",
+ intval($post_id)
+ );
+ if(! $r)
+ return;
+
+ if($r[0]['mimetype'] !== 'text/bbcode')
+ return;
+
+ /** @FIXME eventually we want to post remotely via rpost on your home site */
+ // When that works remove this next bit:
+
+ if(! local_channel())
+ return;
+
+ xchan_query($r);
+
+ $this->item = $r[0];
+ return;
+ }
+
+ public function obj() {
+ $obj = [];
+
+ if(! $this->item)
+ return $obj;
+
+ $obj['type'] = $this->item['obj_type'];
+ $obj['id'] = $this->item['mid'];
+ $obj['content'] = $this->item['body'];
+ $obj['content_type'] = $this->item['mimetype'];
+ $obj['title'] = $this->item['title'];
+ $obj['created'] = $this->item['created'];
+ $obj['edited'] = $this->item['edited'];
+ $obj['author'] = [
+ 'name' => $this->item['author']['xchan_name'],
+ 'address' => $this->item['author']['xchan_addr'],
+ 'network' => $this->item['author']['xchan_network'],
+ 'link' => [
+ [
+ 'rel' => 'alternate',
+ 'type' => 'text/html',
+ 'href' => $this->item['author']['xchan_url']
+ ],
+ [
+ 'rel' => 'photo',
+ 'type' => $this->item['author']['xchan_photo_mimetype'],
+ 'href' => $this->item['author']['xchan_photo_m']
+ ]
+ ]
+ ];
+
+ $obj['owner'] = [
+ 'name' => $this->item['owner']['xchan_name'],
+ 'address' => $this->item['owner']['xchan_addr'],
+ 'network' => $this->item['owner']['xchan_network'],
+ 'link' => [
+ [
+ 'rel' => 'alternate',
+ 'type' => 'text/html',
+ 'href' => $this->item['owner']['xchan_url']
+ ],
+ [
+ 'rel' => 'photo',
+ 'type' => $this->item['owner']['xchan_photo_mimetype'],
+ 'href' => $this->item['owner']['xchan_photo_m']
+ ]
+ ]
+ ];
+
+ $obj['link'] = [
+ 'rel' => 'alternate',
+ 'type' => 'text/html',
+ 'href' => $this->item['plink']
+ ];
+
+ return $obj;
+ }
+
+ public function bbcode() {
+ $bb = NULL_STR;
+
+ if(! $this->item)
+ return $bb;
+
+ $is_photo = (($this->item['obj_type'] === ACTIVITY_OBJ_PHOTO) ? true : false);
+ if($is_photo) {
+ $object = json_decode($this->item['obj'],true);
+ $photo_bb = $object['body'];
+ }
+
+ if (strpos($this->item['body'], "[/share]") !== false) {
+ $pos = strpos($this->item['body'], "[share");
+ $bb = substr($this->item['body'], $pos);
+ } else {
+ $bb = "[share author='".urlencode($this->item['author']['xchan_name']).
+ "' profile='".$this->item['author']['xchan_url'] .
+ "' avatar='".$this->item['author']['xchan_photo_s'].
+ "' link='".$this->item['plink'].
+ "' posted='".$this->item['created'].
+ "' message_id='".$this->item['mid']."']";
+ if($this->item['title'])
+ $bb .= '[b]'.$this->item['title'].'[/b]'."\r\n";
+ $bb .= (($is_photo) ? $photo_bb . "\r\n" . $this->item['body'] : $this->item['body']);
+ $bb .= "[/share]";
+ }
+
+ return $bb;
+
+ }
+
+} \ No newline at end of file
diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php
index 748edcdb7..d35d4732a 100644
--- a/Zotlabs/Lib/ThreadItem.php
+++ b/Zotlabs/Lib/ThreadItem.php
@@ -730,9 +730,6 @@ class ThreadItem {
$observer = $conv->get_observer();
- $qc = ((local_channel()) ? get_pconfig(local_channel(),'system','qcomment') : null);
- $qcomment = (($qc) ? explode("\n",$qc) : null);
-
$arr = array('comment_buttons' => '','id' => $this->get_id());
call_hooks('comment_buttons',$arr);
$comment_buttons = $arr['comment_buttons'];
@@ -744,7 +741,6 @@ class ThreadItem {
'$type' => (($conv->get_mode() === 'channel') ? 'wall-comment' : 'net-comment'),
'$id' => $this->get_id(),
'$parent' => $this->get_id(),
- '$qcomment' => $qcomment,
'$comment_buttons' => $comment_buttons,
'$profile_uid' => $conv->get_profile_owner(),
'$mylink' => $observer['xchan_url'],
diff --git a/Zotlabs/Lib/Verify.php b/Zotlabs/Lib/Verify.php
new file mode 100644
index 000000000..8703e29e6
--- /dev/null
+++ b/Zotlabs/Lib/Verify.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace Zotlabs\Lib;
+
+
+class Verify {
+
+ function create($type,$channel_id,$token,$meta) {
+ return q("insert into verify ( vtype, channel, token, meta, created ) values ( '%s', %d, '%s', '%s', '%s' )",
+ dbesc($type),
+ intval($channel_id),
+ dbesc($token),
+ dbesc($meta),
+ dbesc(datetime_convert())
+ );
+ }
+
+ function match($type,$channel_id,$token,$meta) {
+ $r = q("select id from verify where vtype = '%s' and channel = %d and token = '%s' and meta = '%s' limit 1",
+ dbesc($type),
+ intval($channel_id),
+ dbesc($token),
+ dbesc($meta)
+ );
+ if($r) {
+ q("delete from verify where id = %d",
+ intval($r[0]['id'])
+ );
+ return true;
+ }
+ return false;
+ }
+
+ function get_meta($type,$channel_id,$token) {
+ $r = q("select id, meta from verify where vtype = '%s' and channel = %d and token = '%s' limit 1",
+ dbesc($type),
+ intval($channel_id),
+ dbesc($token)
+ );
+ if($r) {
+ q("delete from verify where id = %d",
+ intval($r[0]['id'])
+ );
+ return $r[0]['meta'];
+ }
+ return false;
+ }
+
+ /**
+ * @brief Purge entries of a verify-type older than interval.
+ *
+ * @param string $type Verify type
+ * @param string $interval SQL compatible time interval
+ */
+ function purge($type, $interval) {
+ q("delete from verify where vtype = '%s' and created < %s - INTERVAL %s",
+ dbesc($type),
+ db_utcnow(),
+ db_quoteinterval($interval)
+ );
+ }
+
+} \ No newline at end of file
diff --git a/Zotlabs/Lib/ZotDriver.php b/Zotlabs/Lib/ZotDriver.php
deleted file mode 100644
index e14cc7f35..000000000
--- a/Zotlabs/Lib/ZotDriver.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php /** @file */
-
-namespace Zotlabs\Lib;
-
-
-class ZotDriver extends ProtoDriver {
-
- protected function discover($channel,$location) {
-
- }
- protected function deliver($item,$channel,$recipients) {
-
- }
- protected function collect($channel,$connection) {
-
- }
- protected function change_permissions($permissions,$channel,$recipient) {
-
- }
- protected function acknowledge_permissions($permissions,$channel,$recipient) {
-
- }
- protected function deliver_private($item,$channel,$recipients) {
-
- }
- protected function collect_private($channel,$connection) {
-
- }
-
-}