Merge branch 'dev' into auto-save

This commit is contained in:
Andrew Manning 2018-04-07 17:48:48 -04:00
commit be6dcb5d0a
37 changed files with 928 additions and 87 deletions

View File

@ -132,7 +132,7 @@ class Display extends \Zotlabs\Web\Controller {
$y = q("select * from iconfig left join item on iconfig.iid = item.id $y = q("select * from iconfig left join item on iconfig.iid = item.id
where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'WEBPAGE' and item.id = %d limit 1", where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'WEBPAGE' and item.id = %d limit 1",
intval($target_item['uid']), intval($target_item['uid']),
intval($target_item['id']) intval($target_item['parent'])
); );
if($x && $y) { if($x && $y) {
goaway(z_root() . '/page/' . $x[0]['channel_address'] . '/' . $y[0]['v']); goaway(z_root() . '/page/' . $x[0]['channel_address'] . '/' . $y[0]['v']);
@ -149,7 +149,7 @@ class Display extends \Zotlabs\Web\Controller {
$y = q("select * from iconfig left join item on iconfig.iid = item.id $y = q("select * from iconfig left join item on iconfig.iid = item.id
where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'ARTICLE' and item.id = %d limit 1", where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'ARTICLE' and item.id = %d limit 1",
intval($target_item['uid']), intval($target_item['uid']),
intval($target_item['id']) intval($target_item['parent'])
); );
if($x && $y) { if($x && $y) {
goaway(z_root() . '/articles/' . $x[0]['channel_address'] . '/' . $y[0]['v']); goaway(z_root() . '/articles/' . $x[0]['channel_address'] . '/' . $y[0]['v']);
@ -166,7 +166,7 @@ class Display extends \Zotlabs\Web\Controller {
$y = q("select * from iconfig left join item on iconfig.iid = item.id $y = q("select * from iconfig left join item on iconfig.iid = item.id
where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'CARD' and item.id = %d limit 1", where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'CARD' and item.id = %d limit 1",
intval($target_item['uid']), intval($target_item['uid']),
intval($target_item['id']) intval($target_item['parent'])
); );
if($x && $y) { if($x && $y) {
goaway(z_root() . '/cards/' . $x[0]['channel_address'] . '/' . $y[0]['v']); goaway(z_root() . '/cards/' . $x[0]['channel_address'] . '/' . $y[0]['v']);

View File

@ -82,7 +82,7 @@ class Editpost extends \Zotlabs\Web\Controller {
'editor_autocomplete'=> true, 'editor_autocomplete'=> true,
'bbco_autocomplete'=> 'bbcode', 'bbco_autocomplete'=> 'bbcode',
'return_path' => $_SESSION['return_url'], 'return_path' => $_SESSION['return_url'],
'button' => t('Edit'), 'button' => t('Submit'),
'hide_voting' => true, 'hide_voting' => true,
'hide_future' => true, 'hide_future' => true,
'hide_location' => true, 'hide_location' => true,

View File

@ -468,6 +468,7 @@ class Item extends \Zotlabs\Web\Controller {
$private = intval($acl->is_private() || $parent_item['item_private']); $private = intval($acl->is_private() || $parent_item['item_private']);
$public_policy = $parent_item['public_policy']; $public_policy = $parent_item['public_policy'];
$owner_hash = $parent_item['owner_xchan']; $owner_hash = $parent_item['owner_xchan'];
$webpage = $parent_item['item_type'];
} }
if((! $allow_empty) && (! strlen($body))) { if((! $allow_empty) && (! strlen($body))) {

View File

@ -300,6 +300,7 @@ class Like extends \Zotlabs\Web\Controller {
$r = q("select * from xchan where xchan_hash = '%s' limit 1", $r = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($item['owner_xchan']) dbesc($item['owner_xchan'])
); );
if($r) if($r)
$thread_owner = $r[0]; $thread_owner = $r[0];
else else
@ -418,6 +419,7 @@ class Like extends \Zotlabs\Web\Controller {
$arr['item_origin'] = 1; $arr['item_origin'] = 1;
$arr['item_notshown'] = 1; $arr['item_notshown'] = 1;
$arr['item_type'] = $item['item_type'];
if(intval($item['item_wall'])) if(intval($item['item_wall']))
$arr['item_wall'] = 1; $arr['item_wall'] = 1;

View File

@ -695,8 +695,8 @@ class Photos extends \Zotlabs\Web\Controller {
'$newalbum_label' => t('Enter an album name'), '$newalbum_label' => t('Enter an album name'),
'$newalbum_placeholder' => t('or select an existing album (doubleclick)'), '$newalbum_placeholder' => t('or select an existing album (doubleclick)'),
'$visible' => array('visible', t('Create a status post for this upload'), 0,'', array(t('No'), t('Yes')), 'onclick="showHideBodyTextarea();"'), '$visible' => array('visible', t('Create a status post for this upload'), 0,'', array(t('No'), t('Yes')), 'onclick="showHideBodyTextarea();"'),
'$caption' => array('description', t('Caption (optional):')), '$caption' => array('description', t('Title (optional)')),
'$body' => array('body', t('Description (optional):'),'', 'Description will only appear in the status post'), '$body' => array('body', t('Description (optional)'),'', 'Description will only appear in the status post'),
'$albums' => $albums['albums'], '$albums' => $albums['albums'],
'$selname' => $selname, '$selname' => $selname,
'$permissions' => t('Permissions'), '$permissions' => t('Permissions'),
@ -841,7 +841,7 @@ class Photos extends \Zotlabs\Web\Controller {
'$album_id' => $datum, '$album_id' => $datum,
'$album_edit' => array(t('Edit Album'), $album_edit), '$album_edit' => array(t('Edit Album'), $album_edit),
'$can_post' => $can_post, '$can_post' => $can_post,
'$upload' => array(t('Upload'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/upload/' . $datum), '$upload' => array(t('Add Photos'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/upload/' . $datum),
'$order' => $order, '$order' => $order,
'$upload_form' => $upload_form, '$upload_form' => $upload_form,
'$usage' => $usage_message '$usage' => $usage_message
@ -1065,7 +1065,7 @@ class Photos extends \Zotlabs\Web\Controller {
'newalbum_placeholder' => t('or select an existing one (doubleclick)'), 'newalbum_placeholder' => t('or select an existing one (doubleclick)'),
'nickname' => \App::$data['channel']['channel_address'], 'nickname' => \App::$data['channel']['channel_address'],
'resource_id' => $ph[0]['resource_id'], 'resource_id' => $ph[0]['resource_id'],
'capt_label' => t('Caption'), 'capt_label' => t('Title (optional)'),
'caption' => $caption_e, 'caption' => $caption_e,
'tag_label' => t('Add a Tag'), 'tag_label' => t('Add a Tag'),
'permissions' => t('Permissions'), 'permissions' => t('Permissions'),
@ -1378,7 +1378,7 @@ class Photos extends \Zotlabs\Web\Controller {
'$title' => t('Recent Photos'), '$title' => t('Recent Photos'),
'$album_id' => bin2hex(t('Recent Photos')), '$album_id' => bin2hex(t('Recent Photos')),
'$can_post' => $can_post, '$can_post' => $can_post,
'$upload' => array(t('Upload'), z_root().'/photos/'.\App::$data['channel']['channel_address'].'/upload'), '$upload' => array(t('Add Photos'), z_root().'/photos/'.\App::$data['channel']['channel_address'].'/upload'),
'$photos' => $photos, '$photos' => $photos,
'$upload_form' => $upload_form, '$upload_form' => $upload_form,
'$usage' => $usage_message '$usage' => $usage_message

View File

@ -732,7 +732,7 @@ class Profiles extends \Zotlabs\Web\Controller {
'$addthing' => t('Add profile things'), '$addthing' => t('Add profile things'),
'$personal' => t('Personal'), '$personal' => t('Personal'),
'$location' => t('Location'), '$location' => t('Location'),
'$relation' => t('Relation'), '$relation' => t('Relationship'),
'$miscellaneous'=> t('Miscellaneous'), '$miscellaneous'=> t('Miscellaneous'),
'$exportable' => feature_enabled(local_channel(),'profile_export'), '$exportable' => feature_enabled(local_channel(),'profile_export'),
'$lbl_import' => t('Import profile from file'), '$lbl_import' => t('Import profile from file'),

View File

@ -49,6 +49,7 @@ class React extends \Zotlabs\Web\Controller {
$n['aid'] = $channel['channel_account_id']; $n['aid'] = $channel['channel_account_id'];
$n['uid'] = $channel['channel_id']; $n['uid'] = $channel['channel_id'];
$n['item_origin'] = true; $n['item_origin'] = true;
$n['item_type'] = $i[0]['item_type'];
$n['parent'] = $postid; $n['parent'] = $postid;
$n['parent_mid'] = $i[0]['mid']; $n['parent_mid'] = $i[0]['mid'];
$n['mid'] = item_message_id(); $n['mid'] = item_message_id();

View File

@ -23,11 +23,12 @@ class Oauth {
check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth'); check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth');
$name = ((x($_POST,'name')) ? $_POST['name'] : ''); $name = ((x($_POST,'name')) ? escape_tags($_POST['name']) : '');
$key = ((x($_POST,'key')) ? $_POST['key'] : ''); $key = ((x($_POST,'key')) ? escape_tags($_POST['key']) : '');
$secret = ((x($_POST,'secret')) ? $_POST['secret'] : ''); $secret = ((x($_POST,'secret')) ? escape_tags($_POST['secret']) : '');
$redirect = ((x($_POST,'redirect')) ? $_POST['redirect'] : ''); $redirect = ((x($_POST,'redirect')) ? escape_tags($_POST['redirect']) : '');
$icon = ((x($_POST,'icon')) ? $_POST['icon'] : ''); $icon = ((x($_POST,'icon')) ? escape_tags($_POST['icon']) : '');
$oauth2 = ((x($_POST,'oauth2')) ? intval($_POST['oauth2']) : 0);
$ok = true; $ok = true;
if($name == '') { if($name == '') {
$ok = false; $ok = false;

View File

@ -0,0 +1,160 @@
<?php
namespace Zotlabs\Module\Settings;
class Oauth2 {
function post() {
if(x($_POST,'remove')){
check_form_security_token_redirectOnErr('/settings/oauth2', 'settings_oauth2');
$key = $_POST['remove'];
q("DELETE FROM tokens WHERE id='%s' AND uid=%d",
dbesc($key),
local_channel());
goaway(z_root()."/settings/oauth2/");
return;
}
if((argc() > 2) && (argv(2) === 'edit' || argv(2) === 'add') && x($_POST,'submit')) {
check_form_security_token_redirectOnErr('/settings/oauth2', 'settings_oauth2');
$name = ((x($_POST,'name')) ? escape_tags(trim($_POST['name'])) : '');
$secret = ((x($_POST,'secret')) ? escape_tags(trim($_POST['secret'])) : '');
$redirect = ((x($_POST,'redirect')) ? escape_tags(trim($_POST['redirect'])) : '');
$grant = ((x($_POST,'grant')) ? escape_tags(trim($_POST['grant'])) : '');
$scope = ((x($_POST,'scope')) ? escape_tags(trim($_POST['scope'])) : '');
$ok = true;
if($name == '' || $secret == '') {
$ok = false;
notice( t('Name and Secret are required') . EOL);
}
if($ok) {
if ($_POST['submit']==t("Update")){
$r = q("UPDATE oauth_clients SET
client_id = '%s',
client_secret = '%s',
redirect_uri = '%s',
grant_types = '%s',
scope = '%s',
user_id = '%s'
WHERE client_id='%s'",
dbesc($name),
dbesc($secret),
dbesc($redirect),
dbesc($grant),
dbesc($scope),
dbesc(local_channel()),
dbesc($name));
} else {
$r = q("INSERT INTO oauth_clients (client_id, client_secret, redirect_uri, grant_types, scope, user_id)
VALUES ('%s','%s','%s','%s','%s','%s')",
dbesc($name),
dbesc($secret),
dbesc($redirect),
dbesc($grant),
dbesc($scope),
dbesc(local_channel())
);
$r = q("INSERT INTO xperm (xp_client, xp_channel, xp_perm) VALUES ('%s', %d, '%s') ",
dbesc($name),
intval(local_channel()),
dbesc('all')
);
}
}
goaway(z_root()."/settings/oauth2/");
return;
}
}
function get() {
if((argc() > 2) && (argv(2) === 'add')) {
$tpl = get_markup_template("settings_oauth2_edit.tpl");
$o .= replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("settings_oauth2"),
'$title' => t('Add OAuth2 application'),
'$submit' => t('Submit'),
'$cancel' => t('Cancel'),
'$name' => array('name', t('Name'), '', t('Name of application')),
'$secret' => array('secret', t('Consumer Secret'), random_string(16), t('Automatically generated - change if desired. Max length 20')),
'$redirect' => array('redirect', t('Redirect'), '', t('Redirect URI - leave blank unless your application specifically requires this')),
'$grant' => array('grant', t('Grant Types'), '', t('leave blank unless your application sepcifically requires this')),
'$scope' => array('scope', t('Authorization scope'), '', t('leave blank unless your application sepcifically requires this')),
));
return $o;
}
if((argc() > 3) && (argv(2) === 'edit')) {
$r = q("SELECT * FROM oauth_clients WHERE client_id='%s' AND user_id= '%s'",
dbesc(argv(3)),
dbesc(local_channel())
);
if (! $r){
notice(t('OAuth2 Application not found.'));
return;
}
$app = $r[0];
$tpl = get_markup_template("settings_oauth2_edit.tpl");
$o .= replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("settings_oauth2"),
'$title' => t('Add application'),
'$submit' => t('Update'),
'$cancel' => t('Cancel'),
'$name' => array('name', t('Name'), $app['client_id'], t('Name of application')),
'$secret' => array('secret', t('Consumer Secret'), $app['client_secret'], t('Automatically generated - change if desired. Max length 20')),
'$redirect' => array('redirect', t('Redirect'), $app['redirect_uri'], t('Redirect URI - leave blank unless your application specifically requires this')),
'$grant' => array('grant', t('Grant Types'), $app['grant_types'], t('leave blank unless your application sepcifically requires this')),
'$scope' => array('scope', t('Authorization scope'), $app['scope'], t('leave blank unless your application sepcifically requires this')),
));
return $o;
}
if((argc() > 3) && (argv(2) === 'delete')) {
check_form_security_token_redirectOnErr('/settings/oauth2', 'settings_oauth2', 't');
$r = q("DELETE FROM oauth_clients WHERE client_id = '%s' AND user_id = '%s'",
dbesc(argv(3)),
dbesc(local_channel())
);
goaway(z_root()."/settings/oauth2/");
return;
}
$r = q("SELECT oauth_clients.*, oauth_access_tokens.access_token as oauth_token, (oauth_clients.user_id = '%s') AS my
FROM oauth_clients
LEFT JOIN oauth_access_tokens ON oauth_clients.client_id=oauth_access_tokens.client_id
WHERE oauth_clients.user_id IN ('%s',0)",
dbesc(local_channel()),
dbesc(local_channel())
);
$tpl = get_markup_template("settings_oauth2.tpl");
$o .= replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("settings_oauth2"),
'$baseurl' => z_root(),
'$title' => t('Connected OAuth2 Apps'),
'$add' => t('Add application'),
'$edit' => t('Edit'),
'$delete' => t('Delete'),
'$consumerkey' => t('Client key starts with'),
'$noname' => t('No name'),
'$remove' => t('Remove authorization'),
'$apps' => $r,
));
return $o;
}
}

View File

@ -26,7 +26,6 @@ class Well_known extends \Zotlabs\Web\Controller {
killme(); killme();
} }
switch(argv(1)) { switch(argv(1)) {
case 'zot-info': case 'zot-info':
\App::$argc -= 1; \App::$argc -= 1;
@ -52,6 +51,10 @@ class Well_known extends \Zotlabs\Web\Controller {
$module->init(); $module->init();
break; break;
case 'dnt-policy.txt':
echo file_get_contents('doc/dnt-policy.txt');
killme();
default: default:
if(file_exists(\App::$cmd)) { if(file_exists(\App::$cmd)) {
echo file_get_contents(\App::$cmd); echo file_get_contents(\App::$cmd);

View File

@ -274,7 +274,7 @@ class Browser extends DAV\Browser\Plugin {
'$actionspanel' => $output, '$actionspanel' => $output,
'$shared' => t('Shared'), '$shared' => t('Shared'),
'$create' => t('Create'), '$create' => t('Create'),
'$upload' => t('Upload'), '$upload' => t('Add Files'),
'$is_owner' => $is_owner, '$is_owner' => $is_owner,
'$parentpath' => $parentpath, '$parentpath' => $parentpath,
'$cpath' => bin2hex(\App::$query_string), '$cpath' => bin2hex(\App::$query_string),

View File

@ -81,12 +81,20 @@ class Settings_menu {
if(feature_enabled(local_channel(),'oauth_clients')) { if(feature_enabled(local_channel(),'oauth_clients')) {
$tabs[] = array( $tabs[] = array(
'label' => t('Connected apps'), 'label' => t('OAuth1 apps'),
'url' => z_root() . '/settings/oauth', 'url' => z_root() . '/settings/oauth',
'selected' => ((argv(1) === 'oauth') ? 'active' : ''), 'selected' => ((argv(1) === 'oauth') ? 'active' : ''),
); );
} }
if(feature_enabled(local_channel(),'oauth2_clients')) {
$tabs[] = array(
'label' => t('OAuth2 apps'),
'url' => z_root() . '/settings/oauth2',
'selected' => ((argv(1) === 'oauth2') ? 'active' : ''),
);
}
if(feature_enabled(local_channel(),'access_tokens')) { if(feature_enabled(local_channel(),'access_tokens')) {
$tabs[] = array( $tabs[] = array(
'label' => t('Guest Access Tokens'), 'label' => t('Guest Access Tokens'),

218
doc/dnt-policy.txt Normal file
View File

@ -0,0 +1,218 @@
Do Not Track Compliance Policy
Version 1.0
This domain complies with user opt-outs from tracking via the "Do Not Track"
or "DNT" header [http://www.w3.org/TR/tracking-dnt/]. This file will always
be posted via HTTPS at https://example-domain.com/.well-known/dnt-policy.txt
to indicate this fact.
SCOPE
This policy document allows an operator of a Fully Qualified Domain Name
("domain") to declare that it respects Do Not Track as a meaningful privacy
opt-out of tracking, so that privacy-protecting software can better determine
whether to block or anonymize communications with this domain. This policy is
intended first and foremost to be posted on domains that publish ads, widgets,
images, scripts and other third-party embedded hypertext (for instance on
widgets.example.com), but it can be posted on any domain, including those users
visit directly (such as www.example.com). The policy may be applied to some
domains used by a company, site, or service, and not to others. Do Not Track
may be sent by any client that uses the HTTP protocol, including websites,
mobile apps, and smart devices like TVs. Do Not Track also works with all
protocols able to read HTTP headers, including SPDY.
NOTE: This policy contains both Requirements and Exceptions. Where possible
terms are defined in the text, but a few additional definitions are included
at the end.
REQUIREMENTS
When this domain receives Web requests from a user who enables DNT by actively
choosing an opt-out setting in their browser or by installing software that is
primarily designed to protect privacy ("DNT User"), we will take the following
measures with respect to those users' data, subject to the Exceptions, also
listed below:
1. END USER IDENTIFIERS:
a. If a DNT User has logged in to our service, all user identifiers, such as
unique or nearly unique cookies, "supercookies" and fingerprints are
discarded as soon as the HTTP(S) response is issued.
Data structures which associate user identifiers with accounts may be
employed to recognize logged in users per Exception 4 below, but may not
be associated with records of the user's activities unless otherwise
excepted.
b. If a DNT User is not logged in to our service, we will take steps to ensure
that no user identifiers are transmitted to us at all.
2. LOG RETENTION:
a. Logs with DNT Users' identifiers removed (but including IP addresses and
User Agent strings) may be retained for a period of 10 days or less,
unless an Exception (below) applies. This period of time balances privacy
concerns with the need to ensure that log processing systems have time to
operate; that operations engineers have time to monitor and fix technical
and performance problems; and that security and data aggregation systems
have time to operate.
b. These logs will not be used for any other purposes.
3. OTHER DOMAINS:
a. If this domain transfers identifiable user data about DNT Users to
contractors, affiliates or other parties, or embeds from or posts data to
other domains, we will either:
b. ensure that the operators of those domains abide by this policy overall
by posting it at /.well-known/dnt-policy.txt via HTTPS on the domains in
question,
OR
ensure that the recipient's policies and practices require the recipient
to respect the policy for our DNT Users' data.
OR
obtain a contractual commitment from the recipient to respect this policy
for our DNT Users' data.
NOTE: if an “Other Domain” does not receive identifiable user information
from the domain because such information has been removed, because the
Other Domain does not log that information, or for some other reason, these
requirements do not apply.
c. "Identifiable" means any records which are not Anonymized or otherwise
covered by the Exceptions below.
4. PERIODIC REASSERTION OF COMPLIANCE:
At least once every 12 months, we will take reasonable steps commensurate
with the size of our organization and the nature of our service to confirm
our ongoing compliance with this document, and we will publicly reassert our
compliance.
5. USER NOTIFICATION:
a. If we are required by law to retain or disclose user identifiers, we will
attempt to provide the users with notice (unless we are prohibited or it
would be futile) that a request for their information has been made in
order to give the users an opportunity to object to the retention or
disclosure.
b. We will attempt to provide this notice by email, if the users have given
us an email address, and by postal mail if the users have provided a
postal address.
c. If the users do not challenge the disclosure request, we may be legally
required to turn over their information.
d. We may delay notice if we, in good faith, believe that an emergency
involving danger of death or serious physical injury to any person
requires disclosure without delay of information relating to the
emergency.
EXCEPTIONS
Data from DNT Users collected by this domain may be logged or retained only in
the following specific situations:
1. CONSENT / "OPT BACK IN"
a. DNT Users are opting out from tracking across the Web. It is possible
that for some feature or functionality, we will need to ask a DNT User to
"opt back in" to be tracked by us across the entire Web.
b. If we do that, we will take reasonable steps to verify that the users who
select this option have genuinely intended to opt back in to tracking.
One way to do this is by performing scientifically reasonable user
studies with a representative sample of our users, but smaller
organizations can satisfy this requirement by other means.
c. Where we believe that we have opt back in consent, our server will
send a tracking value status header "Tk: C" as described in section 6.2
of the W3C Tracking Preference Expression draft:
http://www.w3.org/TR/tracking-dnt/#tracking-status-value
2. TRANSACTIONS
If a DNT User actively and knowingly enters a transaction with our
services (for instance, clicking on a clearly-labeled advertisement,
posting content to a widget, or purchasing an item), we will retain
necessary data for as long as required to perform the transaction. This
may for example include keeping auditing information for clicks on
advertising links; keeping a copy of posted content and the name of the
posting user; keeping server-side session IDs to recognize logged in
users; or keeping a copy of the physical address to which a purchased
item will be shipped. By their nature, some transactions will require data
to be retained indefinitely.
3. TECHNICAL AND SECURITY LOGGING:
a. If, during the processing of the initial request (for unique identifiers)
or during the subsequent 10 days (for IP addresses and User Agent strings),
we obtain specific information that causes our employees or systems to
believe that a request is, or is likely to be, part of a security attack,
spam submission, or fraudulent transaction, then logs of those requests
are not subject to this policy.
b. If we encounter technical problems with our site, then, in rare
circumstances, we may retain logs for longer than 10 days, if that is
necessary to diagnose and fix those problems, but this practice will not be
routinized and we will strive to delete such logs as soon as possible.
4. AGGREGATION:
a. We may retain and share anonymized datasets, such as aggregate records of
readership patterns; statistical models of user behavior; graphs of system
variables; data structures to count active users on monthly or yearly
bases; database tables mapping authentication cookies to logged in
accounts; non-unique data structures constructed within browsers for tasks
such as ad frequency capping or conversion tracking; or logs with truncated
and/or encrypted IP addresses and simplified User Agent strings.
b. "Anonymized" means we have conducted risk mitigation to ensure
that the dataset, plus any additional information that is in our
possession or likely to be available to us, does not allow the
reconstruction of reading habits, online or offline activity of groups of
fewer than 5000 individuals or devices.
c. If we generate anonymized datasets under this exception we will publicly
document our anonymization methods in sufficient detail to allow outside
experts to evaluate the effectiveness of those methods.
5. ERRORS:
From time to time, there may be errors by which user data is temporarily
logged or retained in violation of this policy. If such errors are
inadvertent, rare, and made in good faith, they do not constitute a breach
of this policy. We will delete such data as soon as practicable after we
become aware of any error and take steps to ensure that it is deleted by any
third-party who may have had access to the data.
ADDITIONAL DEFINITIONS
"Fully Qualified Domain Name" means a domain name that addresses a computer
connected to the Internet. For instance, example1.com; www.example1.com;
ads.example1.com; and widgets.example2.com are all distinct FQDNs.
"Supercookie" means any technology other than an HTTP Cookie which can be used
by a server to associate identifiers with the clients that visit it. Examples
of supercookies include Flash LSO cookies, DOM storage, HTML5 storage, or
tricks to store information in caches or etags.
"Risk mitigation" means an engineering process that evaluates the possibility
and likelihood of various adverse outcomes, considers the available methods of
making those adverse outcomes less likely, and deploys sufficient mitigations
to bring the probability and harm from adverse outcomes below an acceptable
threshold.
"Reading habits" includes amongst other things lists of visited DNS names, if
those domains pertain to specific topics or activities, but records of visited
DNS names are not reading habits if those domain names serve content of a very
diverse and general nature, thereby revealing minimal information about the
opinions, interests or activities of the user.

View File

@ -0,0 +1,41 @@
## Access Control and Permissions
### Privacy Groups
Enable management and selection of privacy groups.
<!-- TODO: full description for Privacy Groups -->
Minimum required technical skill level to see this feature: 0
### Multiple Profiles
Ability to create multiple profiles.
<!-- TODO: full description for Multiple Profiles -->
Minimum required technical skill level to see this feature: 3
### Permission Groups
Provide alternate connection permission roles.
<!-- TODO: full description for Permission Groups -->
Minimum required technical skill level to see this feature: 2
### OAuth Clients
Manage authenticatication tokens for mobile and remote apps.
<!-- TODO: full description for OAuth Clients -->
Minimum required technical skill level to see this feature: 1
### Access Tokens
Create access tokens so that non-members can access private content.
<!-- TODO: full description for Access Tokens -->
Minimum required technical skill level to see this feature: 2

View File

@ -0,0 +1,67 @@
## Post Composition Features
### Large Photos
Include large (1024px) photo thumbnails in posts.
If not enabled, use small (640px) photo thumbnails
<!-- TODO: full description for Large Photos -->
Minimum required technical skill level to see this feature: 1
### Channel Sources
Automatically import channel content from other channels or feeds
<!-- TODO: full description for Channel Sources -->
Minimum required technical skill level to see this feature: 3
### Even More Encryption
Allow optional encryption of content end-to-end with a shared secret key
<!-- TODO: full description for Even More Encryption -->
Minimum required technical skill level to see this feature: 3
### Enable Voting Tools
Provide a class of post which others can vote on
<!-- TODO: full description for Enable Voting Tools -->
Minimum required technical skill level to see this feature: 3
### Disable Comments
Provide the option to disable comments for a post
<!-- TODO: full description for Disable Comments -->
Minimum required technical skill level to see this feature: 2
### Delayed Posting
Allow posts to be published at a later date
<!-- TODO: full description for Delayed Posting -->
Minimum required technical skill level to see this feature: 2
### Content Expiration
Remove posts/comments and/or private messages at a future time
<!-- TODO: full description for Content Expiration -->
Minimum required technical skill level to see this feature: 1
### Suppress Duplicate Posts/Comments
Prevent posts with identical content to be published
with less than two minutes in between submissions.
<!-- TODO: full description for Suppress Duplicate Posts/Comments -->
Minimum required technical skill level to see this feature: 1

View File

@ -0,0 +1,57 @@
## Network and Stream Filtering
### Search by Date
Ability to select posts by date ranges
<!-- TODO: full description for Search by Date -->
Minimum required technical skill level to see this feature: 1
### Saved Searches
Save search terms for re-use
<!-- TODO: full description for Saved Searches -->
Minimum required technical skill level to see this feature: 2
### Network Personal Tab
Enable tab to display only Network posts that you've interacted on
<!-- TODO: full description for Network Personal Tab -->
Minimum required technical skill level to see this feature: 1
### Network New Tab
Enable tab to display all new Network activity
<!-- TODO: full description for Network New Tab -->
Minimum required technical skill level to see this feature: 2
### Affinity Tool
Filter stream activity by depth of relationships
<!-- TODO: full description for Affinity Tool -->
Minimum required technical skill level to see this feature: 1
### Suggest Channels
Show friend and connection suggestions
<!-- TODO: full description for Suggest Channels -->
Minimum required technical skill level to see this feature: 1
### Connection Filtering
Filter incoming posts from connections based on keywords/content
<!-- TODO: full description for Connection Filtering -->
Minimum required technical skill level to see this feature: 3

View File

@ -0,0 +1,130 @@
## General Features
### New Member Links
Display new member quick links menu.
<!-- TODO: full description for New Member Links -->
Minimum required technical skill level to see this feature: 1
### Advanced Profiles
Additional profile sections and selections
<!-- TODO: full description for Advanced Profiles -->
Minimum required technical skill level to see this feature: 1
### Profile Import/Export
Save and load profile details across sites/channels
<!-- TODO: full description for Profile Import/Export -->
Minimum required technical skill level to see this feature: 3
### Web Pages
Provide managed web pages on your channel
<!-- TODO: full description for Web Pages -->
Minimum required technical skill level to see this feature: 3
### Wiki
Provide a wiki for your channel
<!-- TODO: full description for Wiki -->
Minimum required technical skill level to see this feature: 2
### Private Notes
Enables a tool to store notes and reminders (note: not encrypted)
<!-- TODO: full description for Private Notes -->
Minimum required technical skill level to see this feature: 1
### Cards
Create personal planning cards
<!-- TODO: full description for Cards -->
Minimum required technical skill level to see this feature: 1
### Articles
Create interactive articles
<!-- TODO: full description for Articles -->
Minimum required technical skill level to see this feature: 1
### Navigation Channel Select
Change channels directly from within the navigation dropdown menu
<!-- TODO: full description for Navigation Channel Select -->
Minimum required technical skill level to see this feature: 3
### Photo Location
If location data is available on uploaded photos, link this to a map.
<!-- TODO: full description for Photo Location -->
Minimum required technical skill level to see this feature: 2
### Access Controlled Chatrooms
Provide chatrooms and chat services with access control.
<!-- TODO: full description for Access Controlled Chatrooms -->
Minimum required technical skill level to see this feature: 1
### Smart Birthdays
Make birthday events timezone aware in case your friends are scattered across the planet.
<!-- TODO: full description for Smart Birthdays -->
Minimum required technical skill level to see this feature: 2
### Event Timezone Selection
Allow event creation in timezones other than your own.
<!-- TODO: full description for Event Timezone Selection -->
Minimum required technical skill level to see this feature: 2
### Premium Channel
Allows you to set restrictions and terms
on those that connect with your channel
<!-- TODO: full description for Premium Channel -->
Minimum required technical skill level to see this feature: 4
### Advanced Directory Search
Allows creation of complex directory search queries
<!-- TODO: full description for Advanced Directory Search -->
Minimum required technical skill level to see this feature: 4
### Advanced Theme and Layout Settings
Allows fine tuning of themes and page layouts
<!-- TODO: full description for Advanced Theme and Layout Settings -->
Minimum required technical skill level to see this feature: 4

View File

@ -0,0 +1,33 @@
[chset]: /settings "Channel Settings"
[ftset]: /settings/features "Additional Features Settings"
[ftgen]: /help/feature/additional/general "General Features"
[ftacc]: /help/feature/additional/access "Access Control and Permissions"
[ftcom]: /help/feature/additional/composition "Post Composition Features"
[ftfil]: /help/feature/additional/filtering "Network and Stream Filtering"
[ftpos]: /help/feature/additional/posts "Post/Comment Tools"
# Additional Features
<!-- TODO: Introduction to additional features -->
<!-- TODO: Short info and crosslink on techlevels -->
You can switch the features on and off from the
[Additional Features][ftset] link in the [Channel Settings][chset].
<!-- TODO: Infos about feature visibility and causes/dependencies -->
The following pages decribe all the available features
grouped in the same way as they are with the accordion tabs on the
[Additional Features][ftset] settings page:
[General Features][ftgen]
[Access Control and Permissions][ftacc]
[Post Composition Features][ftcom]
[Network and Stream Filtering][ftfil]
[Post/Comment Tools][ftpos]

View File

@ -0,0 +1,57 @@
## Post/Comment Tools
### Community Tagging
Ability to tag existing posts
<!-- TODO: full description for Community Tagging -->
Minimum required technical skill level to see this feature: 1
### Post Categories
Add categories to your posts
<!-- TODO: full description for Post Categories -->
Minimum required technical skill level to see this feature: 1
### Emoji Reactions
Add emoji reaction ability to posts
<!-- TODO: full description for Emoji Reactions -->
Minimum required technical skill level to see this feature: 1
### Saved Folders
Ability to file posts under folders
<!-- TODO: full description for Saved Folders -->
Minimum required technical skill level to see this feature: 2
### Dislike Posts
Ability to dislike posts/comments
<!-- TODO: full description for Dislike Posts -->
Minimum required technical skill level to see this feature: 1
### Star Posts
Ability to mark special posts with a star indicator
<!-- TODO: full description for Star Posts -->
Minimum required technical skill level to see this feature: 1
### Tag Cloud
Provide a personal tag cloud on your channel page
<!-- TODO: full description for Tag Cloud -->
Minimum required technical skill level to see this feature: 2

View File

@ -21,6 +21,7 @@
<div class="flex-column"> <div class="flex-column">
<a class="nav-link" href="/help/member/member_guide">Guide</a> <a class="nav-link" href="/help/member/member_guide">Guide</a>
<a class="nav-link" href="/help/member/bbcode">BBcode Reference</a> <a class="nav-link" href="/help/member/bbcode">BBcode Reference</a>
<a class="nav-link" href="/help/feature/additional/overview">Additional Features</a>
<a class="nav-link" href="/help/bugs">Reporting Bugs</a> <a class="nav-link" href="/help/bugs">Reporting Bugs</a>
<a class="nav-link" href="/help/member/member_faq">FAQ</a> <a class="nav-link" href="/help/member/member_faq">FAQ</a>
</div> </div>

View File

@ -193,26 +193,18 @@ require_once('include/api_zot.php');
$redirect = trim($_REQUEST['redirect_uris'][0]); $redirect = trim($_REQUEST['redirect_uris'][0]);
else else
$redirect = trim($_REQUEST['redirect_uris']); $redirect = trim($_REQUEST['redirect_uris']);
$grant_types = trim($_REQUEST['grant_types']);
$scope = trim($_REQUEST['scope']);
$icon = trim($_REQUEST['logo_uri']); $icon = trim($_REQUEST['logo_uri']);
if($oauth2) { $r = q("INSERT INTO oauth_clients (client_id, client_secret, redirect_uri, grant_types, scope, user_id)
$r = q("INSERT INTO oauth_clients (client_id, client_secret, redirect_uri, grant_types, scope, user_id) VALUES ( '%s', '%s', '%s', '%s', '%s', '%s' ) ",
VALUES ( '%s', '%s', '%s', null, null, null ) ", dbesc($key),
dbesc($key), dbesc($secret),
dbesc($secret), dbesc($redirect),
dbesc($redirect) dbesc($grant_types),
); dbesc($scope),
} dbesc((string) api_user())
else { );
$r = q("INSERT INTO clients (client_id, pw, clname, redirect_uri, icon, uid)
VALUES ('%s','%s','%s','%s','%s',%d)",
dbesc($key),
dbesc($secret),
dbesc($name),
dbesc($redirect),
dbesc($icon),
intval(0)
);
}
$ret['client_id'] = $key; $ret['client_id'] = $key;
$ret['client_secret'] = $secret; $ret['client_secret'] = $secret;

View File

@ -780,10 +780,16 @@ function parseIdentityAwareHTML($Text) {
function bbcode($Text, $options = []) { function bbcode($Text, $options = []) {
if(! is_array($options)) {
$options = [];
}
$preserve_nl = ((array_key_exists('preserve_nl',$options)) ? $options['preserve_nl'] : false); $preserve_nl = ((array_key_exists('preserve_nl',$options)) ? $options['preserve_nl'] : false);
$tryoembed = ((array_key_exists('tryoembed',$options)) ? $options['tryoembed'] : true); $tryoembed = ((array_key_exists('tryoembed',$options)) ? $options['tryoembed'] : true);
$cache = ((array_key_exists('cache',$options)) ? $options['cache'] : false); $cache = ((array_key_exists('cache',$options)) ? $options['cache'] : false);
$newwin = ((array_key_exists('newwin',$options)) ? $options['newwin'] : true);
$target = (($newwin) ? ' target="_blank" ' : '');
call_hooks('bbcode_filter', $Text); call_hooks('bbcode_filter', $Text);
@ -934,7 +940,7 @@ function bbcode($Text, $options = []) {
if($tryoembed) { if($tryoembed) {
$Text = preg_replace_callback("/([^\]\='".'"'."\/]|^|\#\^)(https?\:\/\/$urlchars+)/ismu", 'tryoembed', $Text); $Text = preg_replace_callback("/([^\]\='".'"'."\/]|^|\#\^)(https?\:\/\/$urlchars+)/ismu", 'tryoembed', $Text);
} }
$Text = preg_replace("/([^\]\='".'"'."\/]|^|\#\^)(https?\:\/\/$urlchars+)/ismu", '$1<a href="$2" target="_blank" rel="nofollow noopener">$2</a>', $Text); $Text = preg_replace("/([^\]\='".'"'."\/]|^|\#\^)(https?\:\/\/$urlchars+)/ismu", '$1<a href="$2" ' . $target . ' rel="nofollow noopener">$2</a>', $Text);
} }
if (strpos($Text,'[/share]') !== false) { if (strpos($Text,'[/share]') !== false) {
@ -946,16 +952,16 @@ function bbcode($Text, $options = []) {
} }
} }
if (strpos($Text,'[/url]') !== false) { if (strpos($Text,'[/url]') !== false) {
$Text = preg_replace("/\#\^\[url\]([$URLSearchString]*)\[\/url\]/ism", '<span class="bookmark-identifier">#^</span><a class="bookmark" href="$1" target="_blank" rel="nofollow noopener" >$1</a>', $Text); $Text = preg_replace("/\#\^\[url\]([$URLSearchString]*)\[\/url\]/ism", '<span class="bookmark-identifier">#^</span><a class="bookmark" href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>', $Text);
$Text = preg_replace("/\#\^\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '<span class="bookmark-identifier">#^</span><a class="bookmark" href="$1" target="_blank" rel="nofollow noopener" >$2</a>', $Text); $Text = preg_replace("/\#\^\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '<span class="bookmark-identifier">#^</span><a class="bookmark" href="$1" ' . $target . ' rel="nofollow noopener" >$2</a>', $Text);
$Text = preg_replace("/\[url\]([$URLSearchString]*)\[\/url\]/ism", '<a href="$1" target="_blank" rel="nofollow noopener" >$1</a>', $Text); $Text = preg_replace("/\[url\]([$URLSearchString]*)\[\/url\]/ism", '<a href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>', $Text);
$Text = preg_replace("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '<a href="$1" target="_blank" rel="nofollow noopener" >$2</a>', $Text); $Text = preg_replace("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '<a href="$1" ' . $target . ' rel="nofollow noopener" >$2</a>', $Text);
} }
if (strpos($Text,'[/zrl]') !== false) { if (strpos($Text,'[/zrl]') !== false) {
$Text = preg_replace("/\#\^\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" target="_blank" rel="nofollow noopener" >$1</a>', $Text); $Text = preg_replace("/\#\^\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>', $Text);
$Text = preg_replace("/\#\^\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" target="_blank" rel="nofollow noopener" >$2</a>', $Text); $Text = preg_replace("/\#\^\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" ' . $target . ' rel="nofollow noopener" >$2</a>', $Text);
$Text = preg_replace("/\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '<a class="zrl" href="$1" target="_blank" rel="nofollow noopener" >$1</a>', $Text); $Text = preg_replace("/\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '<a class="zrl" href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>', $Text);
$Text = preg_replace("/\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<a class="zrl" href="$1" target="_blank" rel="nofollow noopener" >$2</a>', $Text); $Text = preg_replace("/\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<a class="zrl" href="$1" ' . $target . ' rel="nofollow noopener" >$2</a>', $Text);
} }
if (get_account_techlevel() < 2) if (get_account_techlevel() < 2)
@ -963,8 +969,8 @@ function bbcode($Text, $options = []) {
// Perform MAIL Search // Perform MAIL Search
if (strpos($Text,'[/mail]') !== false) { if (strpos($Text,'[/mail]') !== false) {
$Text = preg_replace("/\[mail\]([$MAILSearchString]*)\[\/mail\]/", '<a href="mailto:$1" target="_blank" rel="nofollow noopener" >$1</a>', $Text); $Text = preg_replace("/\[mail\]([$MAILSearchString]*)\[\/mail\]/", '<a href="mailto:$1" ' . $target . ' rel="nofollow noopener" >$1</a>', $Text);
$Text = preg_replace("/\[mail\=([$MAILSearchString]*)\](.*?)\[\/mail\]/", '<a href="mailto:$1" target="_blank" rel="nofollow noopener" >$2</a>', $Text); $Text = preg_replace("/\[mail\=([$MAILSearchString]*)\](.*?)\[\/mail\]/", '<a href="mailto:$1" ' . $target . ' rel="nofollow noopener" >$2</a>', $Text);
} }
@ -1286,29 +1292,19 @@ function bbcode($Text, $options = []) {
// if video couldn't be embedded, link to it instead. // if video couldn't be embedded, link to it instead.
if (strpos($Text,'[/video]') !== false) { if (strpos($Text,'[/video]') !== false) {
$Text = preg_replace("/\[video\](.*?)\[\/video\]/", '<a href="$1" target="_blank" rel="nofollow noopener" >$1</a>', $Text); $Text = preg_replace("/\[video\](.*?)\[\/video\]/", '<a href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>', $Text);
} }
if (strpos($Text,'[/audio]') !== false) { if (strpos($Text,'[/audio]') !== false) {
$Text = preg_replace("/\[audio\](.*?)\[\/audio\]/", '<a href="$1" target="_blank" rel="nofollow noopener" >$1</a>', $Text); $Text = preg_replace("/\[audio\](.*?)\[\/audio\]/", '<a href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>', $Text);
} }
if (strpos($Text,'[/zvideo]') !== false) { if (strpos($Text,'[/zvideo]') !== false) {
$Text = preg_replace("/\[zvideo\](.*?)\[\/zvideo\]/", '<a class="zid" href="$1" target="_blank" rel="nofollow noopener" >$1</a>', $Text); $Text = preg_replace("/\[zvideo\](.*?)\[\/zvideo\]/", '<a class="zid" href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>', $Text);
} }
if (strpos($Text,'[/zaudio]') !== false) { if (strpos($Text,'[/zaudio]') !== false) {
$Text = preg_replace("/\[zaudio\](.*?)\[\/zaudio\]/", '<a class="zid" href="$1" target="_blank" rel="nofollow noopener" >$1</a>', $Text); $Text = preg_replace("/\[zaudio\](.*?)\[\/zaudio\]/", '<a class="zid" href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>', $Text);
} }
// if ($tryoembed){
// if (strpos($Text,'[/iframe]') !== false) {
// $Text = preg_replace_callback("/\[iframe\](.*?)\[\/iframe\]/ism", 'bb_iframe', $Text);
// }
// } else {
// if (strpos($Text,'[/iframe]') !== false) {
// $Text = preg_replace("/\[iframe\](.*?)\[\/iframe\]/ism", '<a href="$1" target="_blank" rel="nofollow noopener" >$1</a>', $Text);
// }
// }
// oembed tag // oembed tag
$Text = oembed_bbcode2html($Text); $Text = oembed_bbcode2html($Text);

View File

@ -780,7 +780,7 @@ function identity_basic_export($channel_id, $sections = null) {
} }
} }
if(in_array('channel',$sections)) { if(in_array('channel',$sections) || in_array('profile',$sections)) {
$r = q("select * from profile where uid = %d", $r = q("select * from profile where uid = %d",
intval($channel_id) intval($channel_id)
); );

View File

@ -1615,7 +1615,7 @@ function prepare_page($item) {
// prepare_body calls unobscure() as a side effect. Do it here so that // prepare_body calls unobscure() as a side effect. Do it here so that
// the template will get passed an unobscured title. // the template will get passed an unobscured title.
$body = prepare_body($item, true); $body = prepare_body($item, [ 'newwin' => false ]);
if(App::$page['template'] == 'none') { if(App::$page['template'] == 'none') {
$tpl = 'page_display_empty.tpl'; $tpl = 'page_display_empty.tpl';

View File

@ -246,13 +246,22 @@ function get_features($filtered = true) {
[ [
'oauth_clients', 'oauth_clients',
t('OAuth Clients'), t('OAuth1 Clients'),
t('Manage authenticatication tokens for mobile and remote apps.'), t('Manage OAuth1 authenticatication tokens for mobile and remote apps.'),
false, false,
get_config('feature_lock','oauth_clients'), get_config('feature_lock','oauth_clients'),
feature_level('oauth_clients',1), feature_level('oauth_clients',1),
], ],
[
'oauth2_clients',
t('OAuth2 Clients'),
t('Manage OAuth2 authenticatication tokens for mobile and remote apps.'),
false,
get_config('feature_lock','oauth2_clients'),
feature_level('oauth2_clients',1),
],
[ [
'access_tokens', 'access_tokens',
t('Access Tokens'), t('Access Tokens'),

View File

@ -306,7 +306,7 @@ function store_doc_file($s) {
require_once('include/html2plain.php'); require_once('include/html2plain.php');
$item['body'] = html2plain(prepare_text(file_get_contents($s),$mimetype, true)); $item['body'] = html2plain(prepare_text(file_get_contents($s),$mimetype, [ 'cache' => true ]));
$item['mimetype'] = 'text/plain'; $item['mimetype'] = 'text/plain';
$item['plink'] = z_root() . '/' . str_replace('doc','help',$s); $item['plink'] = z_root() . '/' . str_replace('doc','help',$s);

View File

@ -99,7 +99,7 @@ function import_channel($channel, $account_id, $seize) {
} }
if($clean) { if($clean) {
create_table_from_array('channel',$clean); channel_store_lowlevel($clean);
} }
$r = q("select * from channel where channel_account_id = %d and channel_guid = '%s' limit 1", $r = q("select * from channel where channel_account_id = %d and channel_guid = '%s' limit 1",
@ -180,7 +180,7 @@ function import_profiles($channel, $profiles) {
$profile['thumb'] = z_root() . '/photo/' . basename($profile['thumb']); $profile['thumb'] = z_root() . '/photo/' . basename($profile['thumb']);
} }
create_table_from_array('profile', $profile); profile_store_lowlevel($profile);
} }
} }
} }

View File

@ -1607,6 +1607,7 @@ function get_site_info() {
'register_policy' => $register_policy[get_config('system','register_policy')], 'register_policy' => $register_policy[get_config('system','register_policy')],
'invitation_only' => (bool) intval(get_config('system','invitation_only')), 'invitation_only' => (bool) intval(get_config('system','invitation_only')),
'directory_mode' => $directory_mode[get_config('system','directory_mode')], 'directory_mode' => $directory_mode[get_config('system','directory_mode')],
'directory_server' => get_config('system','directory_server'),
'language' => get_config('system','language'), 'language' => get_config('system','language'),
'rss_connections' => (bool) intval(get_config('system','feed_contacts')), 'rss_connections' => (bool) intval(get_config('system','feed_contacts')),
'expiration' => $site_expire, 'expiration' => $site_expire,

View File

@ -1588,7 +1588,7 @@ function generate_named_map($location) {
} }
function prepare_body(&$item,$attach = false) { function prepare_body(&$item,$attach = false,$opts = false) {
call_hooks('prepare_body_init', $item); call_hooks('prepare_body_init', $item);
@ -1616,7 +1616,7 @@ function prepare_body(&$item,$attach = false) {
$s .= prepare_binary($item); $s .= prepare_binary($item);
} }
else { else {
$s .= prepare_text($item['body'],$item['mimetype'], false); $s .= prepare_text($item['body'],$item['mimetype'], $opts);
} }
$event = (($item['obj_type'] === ACTIVITY_OBJ_EVENT) ? format_event_obj($item['obj']) : false); $event = (($item['obj_type'] === ACTIVITY_OBJ_EVENT) ? format_event_obj($item['obj']) : false);
@ -1698,7 +1698,8 @@ function prepare_binary($item) {
* *
* @return string * @return string
*/ */
function prepare_text($text, $content_type = 'text/bbcode', $cache = false) { function prepare_text($text, $content_type = 'text/bbcode', $opts = false) {
switch($content_type) { switch($content_type) {
case 'text/plain': case 'text/plain':
@ -1742,7 +1743,7 @@ function prepare_text($text, $content_type = 'text/bbcode', $cache = false) {
if(stristr($text,'[nosmile]')) if(stristr($text,'[nosmile]'))
$s = bbcode($text, [ 'cache' => $cache ]); $s = bbcode($text, [ 'cache' => $cache ]);
else else
$s = smilies(bbcode($text, [ 'cache' => $cache ])); $s = smilies(bbcode($text, ((is_array($opts)) ? $opts : [] )));
$s = zidify_links($s); $s = zidify_links($s);
@ -2576,6 +2577,9 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $d
// The @! tag will alter permissions // The @! tag will alter permissions
$exclusive = (((! $grouptag) && (strpos($tag,'!') === 1) && (! $diaspora)) ? true : false); $exclusive = (((! $grouptag) && (strpos($tag,'!') === 1) && (! $diaspora)) ? true : false);
if(($grouptag) && (strpos($tag,'!!') === 0)) {
$exclusive = true;
}
//is it already replaced? //is it already replaced?
if(strpos($tag,'[zrl=')) if(strpos($tag,'[zrl='))
@ -2748,8 +2752,8 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $d
$profile = str_replace(',','%2c',$profile); $profile = str_replace(',','%2c',$profile);
$url = $profile; $url = $profile;
if($grouptag) { if($grouptag) {
$newtag = '!' . '[zrl=' . $profile . ']' . $newname . '[/zrl]'; $newtag = '!' . (($exclusive) ? '!' : '') . '[zrl=' . $profile . ']' . $newname . '[/zrl]';
$body = str_replace('!' . $name, $newtag, $body); $body = str_replace('!' . (($exclusive) ? '!' : '') . $name, $newtag, $body);
} }
else { else {
$newtag = '@' . (($exclusive) ? '!' : '') . '[zrl=' . $profile . ']' . $newname . (($forum && ! $trailing_plus_name) ? '+' : '') . '[/zrl]'; $newtag = '@' . (($exclusive) ? '!' : '') . '[zrl=' . $profile . ']' . $newname . (($forum && ! $trailing_plus_name) ? '+' : '') . '[/zrl]';
@ -2799,6 +2803,7 @@ function linkify_tags($a, &$body, $uid, $diaspora = false) {
continue; continue;
$success = handle_tag($a, $body, $access_tag, $str_tags, ($uid) ? $uid : App::$profile_uid , $tag, $diaspora); $success = handle_tag($a, $body, $access_tag, $str_tags, ($uid) ? $uid : App::$profile_uid , $tag, $diaspora);
$results[] = array('success' => $success, 'access_tag' => $access_tag); $results[] = array('success' => $success, 'access_tag' => $access_tag);
if($success['replaced']) $tagged[] = $tag; if($success['replaced']) $tagged[] = $tag;
} }

View File

@ -3855,11 +3855,14 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
intval($channel['channel_id']) intval($channel['channel_id'])
); );
if(! $x) { if(! $x) {
q("insert into profile ( profile_guid, aid, uid ) values ('%s', %d, %d)", profile_store_lowlevel(
dbesc($profile['profile_guid']), [
intval($channel['channel_account_id']), 'aid' => $channel['channel_account_id'],
intval($channel['channel_id']) 'uid' => $channel['channel_id'],
'profile_guid' => $profile['profile_guid'],
]
); );
$x = q("select * from profile where profile_guid = '%s' and uid = %d limit 1", $x = q("select * from profile where profile_guid = '%s' and uid = %d limit 1",
dbesc($profile['profile_guid']), dbesc($profile['profile_guid']),
intval($channel['channel_id']) intval($channel['channel_id'])

View File

@ -198,7 +198,7 @@ function string2bb(element) {
// Autocomplete forums // Autocomplete forums
forums = { forums = {
match: /(^|\s)(\!)([^ \n]+)$/, match: /(^|\s)(\!\!*)([^ \n]+)$/,
index: 3, index: 3,
search: function(term, callback) { contact_search(term, callback, backend_url, 'f', extra_channels, spinelement=false); }, search: function(term, callback) { contact_search(term, callback, backend_url, 'f', extra_channels, spinelement=false); },
replace: editor_replace, replace: editor_replace,

View File

@ -6,7 +6,7 @@
<a href="/sharedwithme" class="btn btn-sm btn-outline-secondary"><i class="fa fa-cloud-download"></i>&nbsp;{{$shared}}</a> <a href="/sharedwithme" class="btn btn-sm btn-outline-secondary"><i class="fa fa-cloud-download"></i>&nbsp;{{$shared}}</a>
{{/if}} {{/if}}
<button id="files-create-btn" class="btn btn-sm btn-primary" onclick="openClose('files-mkdir-tools'); closeMenu('files-upload-tools');"><i class="fa fa-folder-o"></i>&nbsp;{{$create}}</button> <button id="files-create-btn" class="btn btn-sm btn-primary" onclick="openClose('files-mkdir-tools'); closeMenu('files-upload-tools');"><i class="fa fa-folder-o"></i>&nbsp;{{$create}}</button>
<button id="files-upload-btn" class="btn btn-sm btn-success" onclick="openClose('files-upload-tools'); closeMenu('files-mkdir-tools');"><i class="fa fa-arrow-circle-o-up"></i>&nbsp;{{$upload}}</button> <button id="files-upload-btn" class="btn btn-sm btn-success" onclick="openClose('files-upload-tools'); closeMenu('files-mkdir-tools');"><i class="fa fa-plus-circle"></i>&nbsp;{{$upload}}</button>
{{/if}} {{/if}}
</div> </div>

View File

@ -9,7 +9,7 @@
<i class="fa fa-pencil btn btn-outline-secondary btn-sm" title="{{$album_edit.0}}" onclick="openClose('photo-album-edit-wrapper'); closeMenu('photo-upload-form');"></i> <i class="fa fa-pencil btn btn-outline-secondary btn-sm" title="{{$album_edit.0}}" onclick="openClose('photo-album-edit-wrapper'); closeMenu('photo-upload-form');"></i>
{{/if}} {{/if}}
{{if $can_post}} {{if $can_post}}
<button class="btn btn-sm btn-success btn-sm" title="{{$usage}}" onclick="openClose('photo-upload-form'); {{if $album_edit.1}}closeMenu('photo-album-edit-wrapper');{{/if}}"><i class="fa fa-arrow-circle-o-up"></i>&nbsp;{{$upload.0}}</button> <button class="btn btn-sm btn-success btn-sm" title="{{$usage}}" onclick="openClose('photo-upload-form'); {{if $album_edit.1}}closeMenu('photo-album-edit-wrapper');{{/if}}"><i class="fa fa-plus-circle"></i>&nbsp;{{$upload.0}}</button>
{{/if}} {{/if}}
</div> </div>
</div> </div>

View File

@ -2,7 +2,7 @@
<div class="section-title-wrapper"> <div class="section-title-wrapper">
<div class="pull-right"> <div class="pull-right">
{{if $can_post}} {{if $can_post}}
<button class="btn btn-sm btn-success acl-form-trigger" title="{{$usage}}" onclick="openClose('photo-upload-form');" data-form_id="photos-upload-form"><i class="fa fa-arrow-circle-o-up"></i>&nbsp;{{$upload.0}}</button> <button class="btn btn-sm btn-success acl-form-trigger" title="{{$usage}}" onclick="openClose('photo-upload-form');" data-form_id="photos-upload-form"><i class="fa fa-plus-circle"></i>&nbsp;{{$upload.0}}</button>
{{/if}} {{/if}}
</div> </div>
<h2>{{$title}}</h2> <h2>{{$title}}</h2>

35
view/tpl/settings_oauth2.tpl Executable file
View File

@ -0,0 +1,35 @@
<div class="generic-content-wrapper">
<div class="section-title-wrapper">
<h2>{{$title}}</h2>
</div>
<div class="section-content-tools-wrapper">
<form action="settings/oauth2" method="post" autocomplete="off">
<input type='hidden' name='form_security_token' value='{{$form_security_token}}'>
<div id="profile-edit-links">
<ul>
<li>
<a id="profile-edit-view-link" href="{{$baseurl}}/settings/oauth2/add">{{$add}}</a>
</li>
</ul>
</div>
{{foreach $apps as $app}}
<div class='oauthapp'>
{{if $app.client_id}}<h4>{{$app.client_id}}</h4>{{else}}<h4>{{$noname}}</h4>{{/if}}
{{if $app.my}}
{{if $app.oauth_token}}
<div class="settings-submit-wrapper" ><button class="settings-submit" type="submit" name="remove" value="{{$app.oauth_token}}">{{$remove}}</button></div>
{{/if}}
{{/if}}
{{if $app.my}}
<a href="{{$baseurl}}/settings/oauth2/edit/{{$app.client_id}}" title="{{$edit}}"><i class="fa fa-pencil btn btn-outline-secondary"></i></a>
<a href="{{$baseurl}}/settings/oauth2/delete/{{$app.client_id}}?t={{$form_security_token}}" title="{{$delete}}"><i class="fa fa-trash-o btn btn-outline-secondary"></i></a>
{{/if}}
</div>
{{/foreach}}
</form>
</div>
</div>

View File

@ -0,0 +1,21 @@
<div class="generic-content-wrapper">
<div class="section-title-wrapper">
<h2>{{$title}}</h2>
</div>
<div class="section-content-tools-wrapper">
<form method="POST">
<input type='hidden' name='form_security_token' value='{{$form_security_token}}'>
{{include file="field_input.tpl" field=$name}}
{{include file="field_input.tpl" field=$secret}}
{{include file="field_input.tpl" field=$redirect}}
{{include file="field_input.tpl" field=$grant}}
{{include file="field_input.tpl" field=$scope}}
<div class="settings-submit-wrapper" >
<input type="submit" name="submit" class="settings-submit" value="{{$submit}}" />
<input type="submit" name="cancel" class="settings-submit" value="{{$cancel}}" />
</div>
</form>
</div>
</div>

View File

@ -5,7 +5,6 @@
<div class="section-content-tools-wrapper"> <div class="section-content-tools-wrapper">
<form method="POST"> <form method="POST">
<input type='hidden' name='form_security_token' value='{{$form_security_token}}'> <input type='hidden' name='form_security_token' value='{{$form_security_token}}'>
{{include file="field_input.tpl" field=$name}} {{include file="field_input.tpl" field=$name}}
{{include file="field_input.tpl" field=$key}} {{include file="field_input.tpl" field=$key}}
{{include file="field_input.tpl" field=$secret}} {{include file="field_input.tpl" field=$secret}}