commit
a7ff2cc5ea
@ -266,7 +266,7 @@ class Chatroom {
|
||||
intval($room_id),
|
||||
dbesc($xchan),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($arr['chat_text'])
|
||||
dbesc(str_rot47(base64url_encode($arr['chat_text'])))
|
||||
);
|
||||
|
||||
$ret['success'] = true;
|
||||
|
@ -95,7 +95,7 @@ class Acl extends \Zotlabs\Web\Controller {
|
||||
. "' IN xchan_name) else position('" . protect_sprintf(dbesc(punify($search))) . "' IN xchan_addr) end, ";
|
||||
|
||||
$col = ((strpos($search,'@') !== false) ? 'xchan_addr' : 'xchan_name' );
|
||||
$sql_extra3 = "AND $col like " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " ";
|
||||
$sql_extra3 = "AND $col like " . protect_sprintf( "'%" . dbesc(($col === 'xchan_addr') ? punify($search) : $search) . "%'" ) . " ";
|
||||
|
||||
}
|
||||
else {
|
||||
|
@ -4,60 +4,89 @@ namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Identity\OAuth2Storage;
|
||||
|
||||
|
||||
class Authorize extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
function get() {
|
||||
if (!local_channel()) {
|
||||
return login();
|
||||
} else {
|
||||
// TODO: Fully implement the dynamic client registration protocol:
|
||||
// OpenID Connect Dynamic Client Registration 1.0 Client Metadata
|
||||
// http://openid.net/specs/openid-connect-registration-1_0.html
|
||||
$app = array(
|
||||
'name' => (x($_REQUEST, 'client_name') ? urldecode($_REQUEST['client_name']) : t('Unknown App')),
|
||||
'icon' => (x($_REQUEST, 'logo_uri') ? urldecode($_REQUEST['logo_uri']) : z_root() . '/images/icons/plugin.png'),
|
||||
'url' => (x($_REQUEST, 'client_uri') ? urldecode($_REQUEST['client_uri']) : ''),
|
||||
);
|
||||
$o .= replace_macros(get_markup_template('oauth_authorize.tpl'), array(
|
||||
'$title' => t('Authorize'),
|
||||
'$authorize' => sprintf( t('Do you authorize the app %s to access your channel data?'), '<a style="float: none;" href="' . $app['url'] . '">' . $app['name'] . '</a> '),
|
||||
'$app' => $app,
|
||||
'$yes' => t('Allow'),
|
||||
'$no' => t('Deny'),
|
||||
'$client_id' => (x($_REQUEST, 'client_id') ? $_REQUEST['client_id'] : ''),
|
||||
'$redirect_uri' => (x($_REQUEST, 'redirect_uri') ? $_REQUEST['redirect_uri'] : ''),
|
||||
'$state' => (x($_REQUEST, 'state') ? $_REQUEST['state'] : ''),
|
||||
));
|
||||
return $o;
|
||||
}
|
||||
}
|
||||
|
||||
// workaround for HTTP-auth in CGI mode
|
||||
if (x($_SERVER, 'REDIRECT_REMOTE_USER')) {
|
||||
$userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"], 6)) ;
|
||||
if(strlen($userpass)) {
|
||||
list($name, $password) = explode(':', $userpass);
|
||||
$_SERVER['PHP_AUTH_USER'] = $name;
|
||||
$_SERVER['PHP_AUTH_PW'] = $password;
|
||||
}
|
||||
function post() {
|
||||
if (! local_channel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (x($_SERVER, 'HTTP_AUTHORIZATION')) {
|
||||
$userpass = base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"], 6)) ;
|
||||
if(strlen($userpass)) {
|
||||
list($name, $password) = explode(':', $userpass);
|
||||
$_SERVER['PHP_AUTH_USER'] = $name;
|
||||
$_SERVER['PHP_AUTH_PW'] = $password;
|
||||
}
|
||||
}
|
||||
$storage = new OAuth2Storage(\DBA::$dba->db);
|
||||
$s = new \Zotlabs\Identity\OAuth2Server($storage);
|
||||
|
||||
$s = new \Zotlabs\Identity\OAuth2Server(new OAuth2Storage(\DBA::$dba->db));
|
||||
// TODO: The automatic client registration protocol below should adhere more
|
||||
// closely to "OAuth 2.0 Dynamic Client Registration Protocol" defined
|
||||
// at https://tools.ietf.org/html/rfc7591
|
||||
|
||||
// If no client_id was provided, generate a new one.
|
||||
if (x($_POST, 'client_id')) {
|
||||
$client_id = $_POST['client_id'];
|
||||
} else {
|
||||
$client_id = $_POST['client_id'] = random_string(16);
|
||||
}
|
||||
// If no redirect_uri was provided, generate a fake one.
|
||||
if (x($_POST, 'redirect_uri')) {
|
||||
$redirect_uri = $_POST['redirect_uri'];
|
||||
} else {
|
||||
$redirect_uri = $_POST['redirect_uri'] = 'https://fake.example.com/oauth';
|
||||
}
|
||||
|
||||
$request = \OAuth2\Request::createFromGlobals();
|
||||
$response = new \OAuth2\Response();
|
||||
|
||||
// If the client is not registered, add to the database
|
||||
if (!$client = $storage->getClientDetails($client_id)) {
|
||||
$client_secret = random_string(16);
|
||||
// Client apps are registered per channel
|
||||
$user_id = local_channel();
|
||||
$storage->setClientDetails($client_id, $client_secret, $redirect_uri, 'authorization_code', null, $user_id);
|
||||
|
||||
}
|
||||
if (!$client = $storage->getClientDetails($client_id)) {
|
||||
// There was an error registering the client.
|
||||
$response->send();
|
||||
killme();
|
||||
}
|
||||
$response->setParameter('client_secret', $client['client_secret']);
|
||||
|
||||
// validate the authorize request
|
||||
if (! $s->validateAuthorizeRequest($request, $response)) {
|
||||
if (!$s->validateAuthorizeRequest($request, $response)) {
|
||||
$response->send();
|
||||
killme();
|
||||
}
|
||||
|
||||
// display an authorization form
|
||||
if (empty($_POST)) {
|
||||
|
||||
return '
|
||||
<form method="post">
|
||||
<label>Do You Authorize TestClient?</label><br />
|
||||
<input type="submit" name="authorized" value="yes">
|
||||
<input type="submit" name="authorized" value="no">
|
||||
</form>';
|
||||
}
|
||||
|
||||
// print the authorization code if the user has authorized your client
|
||||
$is_authorized = ($_POST['authorized'] === 'yes');
|
||||
$is_authorized = ($_POST['authorize'] === 'allow');
|
||||
$s->handleAuthorizeRequest($request, $response, $is_authorized, local_channel());
|
||||
if ($is_authorized) {
|
||||
// this is only here so that you get to see your code in the cURL request. Otherwise,
|
||||
// we'd redirect back to the client
|
||||
$code = substr($response->getHttpHeader('Location'), strpos($response->getHttpHeader('Location'), 'code=')+5, 40);
|
||||
echo("SUCCESS! Authorization Code: $code");
|
||||
$code = substr($response->getHttpHeader('Location'), strpos($response->getHttpHeader('Location'), 'code=') + 5, 40);
|
||||
logger('Authorization Code: ' . $code);
|
||||
}
|
||||
|
||||
$response->send();
|
||||
|
@ -60,7 +60,7 @@ class Chatsvc extends \Zotlabs\Web\Controller {
|
||||
intval(\App::$data['chat']['room_id']),
|
||||
dbesc(get_observer_hash()),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($arr['chat_text'])
|
||||
dbesc(str_rot47(base64url_encode($arr['chat_text'])))
|
||||
);
|
||||
|
||||
$ret['success'] = true;
|
||||
@ -157,7 +157,7 @@ class Chatsvc extends \Zotlabs\Web\Controller {
|
||||
'name' => $rr['xchan_name'],
|
||||
'isotime' => datetime_convert('UTC', date_default_timezone_get(), $rr['created'], 'c'),
|
||||
'localtime' => datetime_convert('UTC', date_default_timezone_get(), $rr['created'], 'r'),
|
||||
'text' => zidify_links(smilies(bbcode($rr['chat_text']))),
|
||||
'text' => zidify_links(smilies(bbcode(base64url_decode(str_rot47($rr['chat_text']))))),
|
||||
'self' => ((get_observer_hash() == $rr['chat_xchan']) ? 'self' : '')
|
||||
);
|
||||
}
|
||||
|
@ -828,7 +828,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
|
||||
$locstr = locations_by_netid($contact['xchan_hash']);
|
||||
if(! $locstr)
|
||||
$locstr = $contact['xchan_url'];
|
||||
$locstr = unpunify($contact['xchan_url']);
|
||||
|
||||
$clone_warn = '';
|
||||
$clonable = (in_array($contact['xchan_network'],['zot','rss']) ? true : false);
|
||||
@ -852,8 +852,8 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
'$permcat' => [ 'permcat', t('Permission role'), '', '<span class="loading invisible">' . t('Loading') . '<span class="jumping-dots"><span class="dot-1">.</span><span class="dot-2">.</span><span class="dot-3">.</span></span></span>',$permcats ],
|
||||
'$permcat_new' => t('Add permission role'),
|
||||
'$permcat_enable' => feature_enabled(local_channel(),'permcats'),
|
||||
'$addr' => $contact['xchan_addr'],
|
||||
'$primeurl' => $contact['xchan_url'],
|
||||
'$addr' => unpunify($contact['xchan_addr']),
|
||||
'$primeurl' => unpunify($contact['xchan_url']),
|
||||
'$section' => $section,
|
||||
'$sections' => $sections,
|
||||
'$vcard' => $vcard,
|
||||
|
@ -299,9 +299,9 @@ class Directory extends \Zotlabs\Web\Controller {
|
||||
if(strlen($out))
|
||||
$out .= ', ';
|
||||
if($marr && in_arrayi($k,$marr))
|
||||
$out .= '<strong>' . $k . '</strong>';
|
||||
$out .= '<a href="' . z_root() . '/directory/f=&keywords=' . urlencode($k) .'"><strong>' . $k . '</strong></a>';
|
||||
else
|
||||
$out .= $k;
|
||||
$out .= '<a href="' . z_root() . '/directory/f=&keywords=' . urlencode($k) .'">' . $k . '</a>';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,8 @@ class Display extends \Zotlabs\Web\Controller {
|
||||
dbesc($target_item['author_xchan'])
|
||||
);
|
||||
if($x) {
|
||||
\App::$poi = $x[0];
|
||||
// not yet ready for prime time
|
||||
// \App::$poi = $x[0];
|
||||
}
|
||||
|
||||
//if the item is to be moderated redirect to /moderate
|
||||
|
@ -18,7 +18,7 @@ class Hashtags extends \Zotlabs\Web\Controller {
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rv) {
|
||||
$result[] = [ 'text' => strtolower($rv['term']) ];
|
||||
$result[] = [ 'text' => $rv['term'] ];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -542,7 +542,7 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
|
||||
// Look for tags and linkify them
|
||||
$results = linkify_tags($a, $body, ($uid) ? $uid : $profile_uid);
|
||||
|
||||
|
||||
if($results) {
|
||||
|
||||
// Set permissions based on tag replacements
|
||||
|
@ -296,10 +296,11 @@ class Like extends \Zotlabs\Web\Controller {
|
||||
notice( t('Permission denied') . EOL);
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($item['owner_xchan'])
|
||||
);
|
||||
|
||||
if($r)
|
||||
$thread_owner = $r[0];
|
||||
else
|
||||
|
@ -67,14 +67,14 @@ class Mail extends \Zotlabs\Web\Controller {
|
||||
if(! $recipient) {
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$j = \Zotlabs\Zot\Finger::run($rstr,$channel);
|
||||
$j = \Zotlabs\Zot\Finger::run(punify($rstr),$channel);
|
||||
|
||||
if(! $j['success']) {
|
||||
notice( t('Unable to lookup recipient.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
logger('message_post: lookup: ' . $url . ' ' . print_r($j,true));
|
||||
logger('message_post: lookup: ' . $rstr . ' ' . print_r($j,true));
|
||||
|
||||
if(! $j['guid']) {
|
||||
notice( t('Unable to communicate with requested channel.'));
|
||||
|
151
Zotlabs/Module/Oauth2testvehicle.php
Normal file
151
Zotlabs/Module/Oauth2testvehicle.php
Normal file
@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
/**
|
||||
* The OAuth2TestVehicle class is a way to test the registration of an OAuth2
|
||||
* client app. It allows you to walk through the steps of registering a client,
|
||||
* requesting an authorization code for that client, and then requesting an
|
||||
* access token for use in authentication against the Hubzilla API endpoints.
|
||||
*/
|
||||
class OAuth2TestVehicle extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
killme();
|
||||
|
||||
// If there is a 'code' and 'state' parameter then this is a client app
|
||||
// callback issued after the authorization code request
|
||||
// TODO: Check state value and compare to original sent value
|
||||
// "You should first compare this state value to ensure it matches the
|
||||
// one you started with. You can typically store the state value in a
|
||||
// cookie, and compare it when the user comes back. This ensures your
|
||||
// redirection endpoint isn't able to be tricked into attempting to
|
||||
// exchange arbitrary authorization codes."
|
||||
$_SESSION['redirect_uri'] = z_root() . '/oauth2testvehicle';
|
||||
$_SESSION['authorization_code'] = (x($_REQUEST, 'code') ? $_REQUEST['code'] : $_SESSION['authorization_code']);
|
||||
$_SESSION['state'] = (x($_REQUEST, 'state') ? $_REQUEST['state'] : $_SESSION['state'] );
|
||||
$_SESSION['client_id'] = (x($_REQUEST, 'client_id') ? $_REQUEST['client_id'] : $_SESSION['client_id'] );
|
||||
$_SESSION['client_secret'] = (x($_REQUEST, 'client_secret') ? $_REQUEST['client_secret'] : $_SESSION['client_secret']);
|
||||
$_SESSION['access_token'] = (x($_REQUEST, 'access_token') ? $_REQUEST['access_token'] : $_SESSION['access_token'] );
|
||||
$_SESSION['api_response'] = (x($_SESSION, 'api_response') ? $_SESSION['api_response'] : '');
|
||||
}
|
||||
function get() {
|
||||
|
||||
$o .= replace_macros(get_markup_template('oauth2testvehicle.tpl'), array(
|
||||
'$baseurl' => z_root(),
|
||||
'$api_response' => $_SESSION['api_response'],
|
||||
/*
|
||||
endpoints => array(
|
||||
array(
|
||||
'path_to_endpoint',
|
||||
array(
|
||||
array('field_name_1', 'value'),
|
||||
array('field_name_2', 'value'),
|
||||
...
|
||||
),
|
||||
'submit_button_name',
|
||||
'Description of API action'
|
||||
)
|
||||
)
|
||||
*/
|
||||
'$endpoints' => array(
|
||||
array(
|
||||
'authorize',
|
||||
array(
|
||||
array('response_type', 'code'),
|
||||
array('client_id', (x($_REQUEST, 'client_id') ? $_REQUEST['client_id'] : 'oauth2_test_app')),
|
||||
array('redirect_uri', $_SESSION['redirect_uri']),
|
||||
array('state', 'xyz'),
|
||||
// OpenID Connect Dynamic Client Registration 1.0 Client Metadata
|
||||
// http://openid.net/specs/openid-connect-registration-1_0.html
|
||||
array('client_name', 'OAuth2 Test App'),
|
||||
array('logo_uri', urlencode(z_root() . '/images/icons/plugin.png')),
|
||||
array('client_uri', urlencode('https://client.example.com/website')),
|
||||
array('application_type', 'web'), // would be 'native' for mobile app
|
||||
),
|
||||
'oauth_authorize',
|
||||
'Authorize a test client app',
|
||||
'GET',
|
||||
(($_REQUEST['code'] && $_REQUEST['state']) ? true : false),
|
||||
),
|
||||
array(
|
||||
'oauth2testvehicle',
|
||||
array(
|
||||
array('action', 'request_token'),
|
||||
array('grant_type', 'authorization_code'),
|
||||
array('code', $_SESSION['authorization_code']),
|
||||
array('redirect_uri', $_SESSION['redirect_uri']),
|
||||
array('client_id', ($_SESSION['client_id'] ? $_SESSION['client_id'] : 'oauth2_test_app')),
|
||||
array('client_secret', $_SESSION['client_secret']),
|
||||
),
|
||||
'oauth_token_request',
|
||||
'Request a token',
|
||||
'POST',
|
||||
($_SESSION['success'] === 'request_token'),
|
||||
),
|
||||
array(
|
||||
'oauth2testvehicle',
|
||||
array(
|
||||
array('action', 'api_files'),
|
||||
array('access_token', $_SESSION['access_token']),
|
||||
),
|
||||
'oauth_api_files',
|
||||
'API: Get channel files',
|
||||
'POST',
|
||||
($_SESSION['success'] === 'api_files'),
|
||||
)
|
||||
)
|
||||
));
|
||||
$_SESSION['success'] = '';
|
||||
return $o;
|
||||
}
|
||||
|
||||
function post() {
|
||||
|
||||
switch ($_POST['action']) {
|
||||
case 'api_files':
|
||||
$access_token = $_SESSION['access_token'];
|
||||
$url = z_root() . '/api/z/1.0/files/';
|
||||
$headers = [];
|
||||
$headers[] = 'Authorization: Bearer ' . $access_token;
|
||||
$post = z_fetch_url($url, false, 0, array(
|
||||
'custom' => 'GET',
|
||||
'headers' => $headers,
|
||||
));
|
||||
logger(json_encode($post, JSON_PRETTY_PRINT), LOGGER_DEBUG);
|
||||
$response = json_decode($post['body'], true);
|
||||
$_SESSION['api_response'] = json_encode($response, JSON_PRETTY_PRINT);
|
||||
break;
|
||||
case 'request_token':
|
||||
$grant_type = (x($_POST, 'grant_type') ? $_POST['grant_type'] : '');
|
||||
$redirect_uri = (x($_POST, 'redirect_uri') ? $_POST['redirect_uri'] : '');
|
||||
$client_id = (x($_POST, 'client_id') ? $_POST['client_id'] : '');
|
||||
$code = (x($_POST, 'code') ? $_POST['code'] : '');
|
||||
$client_secret = (x($_POST, 'client_secret') ? $_POST['client_secret'] : '');
|
||||
$url = z_root() . '/token/';
|
||||
$params = http_build_query(array(
|
||||
'grant_type' => $grant_type,
|
||||
'redirect_uri' => urlencode($redirect_uri),
|
||||
'client_id' => $client_id,
|
||||
'code' => $code,
|
||||
));
|
||||
$post = z_post_url($url, $params, 0, array(
|
||||
'http_auth' => $client_id . ':' . $client_secret,
|
||||
));
|
||||
logger(json_encode($post, JSON_PRETTY_PRINT), LOGGER_DEBUG);
|
||||
$response = json_decode($post['body'], true);
|
||||
logger(json_encode($response, JSON_PRETTY_PRINT), LOGGER_DEBUG);
|
||||
if($response['access_token']) {
|
||||
info('Access token received: ' . $response['access_token'] . EOL);
|
||||
$_SESSION['success'] = 'request_token';
|
||||
$_SESSION['access_token'] = $response['access_token'];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -412,12 +412,16 @@ class Channel {
|
||||
));
|
||||
|
||||
$subdir = ((strlen(\App::get_path())) ? '<br />' . t('or') . ' ' . z_root() . '/channel/' . $nickname : '');
|
||||
|
||||
$webbie = $nickname . '@' . \App::get_hostname();
|
||||
$intl_nickname = unpunify($nickname) . '@' . unpunify(\App::get_hostname());
|
||||
|
||||
|
||||
$tpl_addr = get_markup_template("settings_nick_set.tpl");
|
||||
|
||||
$prof_addr = replace_macros($tpl_addr,array(
|
||||
'$desc' => t('Your channel address is'),
|
||||
'$nickname' => $nickname,
|
||||
'$nickname' => (($intl_nickname === $webbie) ? $webbie : $intl_nickname . ' (' . $webbie . ')'),
|
||||
'$subdir' => $subdir,
|
||||
'$davdesc' => t('Your files/photos are accessible via WebDAV at'),
|
||||
'$davpath' => ((get_account_techlevel() > 3) ? z_root() . '/dav/' . $nickname : ''),
|
||||
|
@ -80,6 +80,8 @@ class Tagger extends \Zotlabs\Web\Controller {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
$clean_term = trim($term,'"\' ');
|
||||
|
||||
$links = array(array('rel' => 'alternate','type' => 'text/html',
|
||||
'href' => z_root() . '/display/' . gen_link_id($item['mid'])));
|
||||
@ -103,15 +105,15 @@ class Tagger extends \Zotlabs\Web\Controller {
|
||||
),
|
||||
));
|
||||
|
||||
$tagid = z_root() . '/search?tag=' . $term;
|
||||
$tagid = z_root() . '/search?tag=' . $clean_term;
|
||||
$objtype = ACTIVITY_OBJ_TAGTERM;
|
||||
|
||||
$obj = json_encode(array(
|
||||
'type' => $objtype,
|
||||
'id' => $tagid,
|
||||
'link' => array(array('rel' => 'alternate','type' => 'text/html', 'href' => $tagid)),
|
||||
'title' => $term,
|
||||
'content' => $term
|
||||
'title' => $clean_term,
|
||||
'content' => $clean_term
|
||||
));
|
||||
|
||||
$bodyverb = t('%1$s tagged %2$s\'s %3$s with %4$s');
|
||||
@ -119,7 +121,7 @@ class Tagger extends \Zotlabs\Web\Controller {
|
||||
// saving here for reference
|
||||
// also check out x22d5 and x2317 and x0d6b and x0db8 and x24d0 and xff20 !!!
|
||||
|
||||
$termlink = html_entity_decode('⋕') . '[zrl=' . z_root() . '/search?tag=' . urlencode($term) . ']'. $term . '[/zrl]';
|
||||
$termlink = html_entity_decode('⋕') . '[zrl=' . z_root() . '/search?tag=' . urlencode($clean_term) . ']'. $clean_term . '[/zrl]';
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
@ -143,8 +145,7 @@ class Tagger extends \Zotlabs\Web\Controller {
|
||||
$arr['obj_type'] = $objtype;
|
||||
$arr['obj'] = $obj;
|
||||
$arr['parent_mid'] = $item['mid'];
|
||||
|
||||
store_item_tag($item['uid'],$item['id'],TERM_OBJ_POST,TERM_COMMUNITYTAG,$term,$tagid);
|
||||
store_item_tag($item['uid'],$item['id'],TERM_OBJ_POST,TERM_COMMUNITYTAG,$clean_term,$tagid);
|
||||
$ret = post_activity_item($arr);
|
||||
|
||||
if($ret['success']) {
|
||||
|
@ -29,7 +29,8 @@ class Token extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
$s = new \Zotlabs\Identity\OAuth2Server(new OAuth2Storage(\DBA::$dba->db));
|
||||
$s->handleTokenRequest(\OAuth2\Request::createFromGlobals())->send();
|
||||
$request = \OAuth2\Request::createFromGlobals();
|
||||
$s->handleTokenRequest($request)->send();
|
||||
|
||||
killme();
|
||||
}
|
||||
|
@ -284,6 +284,8 @@ class Wiki extends \Zotlabs\Web\Controller {
|
||||
$wikiheaderPage = urldecode($pageUrlName);
|
||||
|
||||
$renamePage = (($wikiheaderPage === 'Home') ? '' : t('Rename page'));
|
||||
$sharePage = t('Share');
|
||||
|
||||
$p = [];
|
||||
|
||||
if(! $ignore_language) {
|
||||
@ -354,6 +356,8 @@ class Wiki extends \Zotlabs\Web\Controller {
|
||||
'$wikiheaderName' => $wikiheaderName,
|
||||
'$wikiheaderPage' => $wikiheaderPage,
|
||||
'$renamePage' => $renamePage,
|
||||
'$sharePage' => $sharePage,
|
||||
'$shareLink' => urlencode('#^[zrl=' . z_root() . '/wiki/' . argv(1) . '/' . $wikiUrlName . '/' . $pageUrlName . ']' . '[ ' . $owner['channel_name'] . ' ] ' . $wikiheaderName . ' - ' . $wikiheaderPage . '[/zrl]'),
|
||||
'$showPageControls' => $showPageControls,
|
||||
'$editOrSourceLabel' => (($showPageControls) ? t('Edit') : t('Source')),
|
||||
'$tools_label' => 'Page Tools',
|
||||
|
10
Zotlabs/Storage/ZotOauth2Pdo.php
Normal file
10
Zotlabs/Storage/ZotOauth2Pdo.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Storage;
|
||||
|
||||
class ZotOauth2Pdo extends \OAuth2\Storage\Pdo {
|
||||
public function getConfig()
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
}
|
78
Zotlabs/Update/_1210.php
Normal file
78
Zotlabs/Update/_1210.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Update;
|
||||
|
||||
class _1210 {
|
||||
|
||||
function run() {
|
||||
|
||||
$sql = "CREATE TABLE oauth_clients (
|
||||
client_id VARCHAR(80) NOT NULL,
|
||||
client_secret VARCHAR(80),
|
||||
redirect_uri VARCHAR(2000),
|
||||
grant_types VARCHAR(80),
|
||||
scope VARCHAR(4000),
|
||||
user_id VARCHAR(80),
|
||||
PRIMARY KEY (client_id)
|
||||
);
|
||||
|
||||
CREATE TABLE oauth_access_tokens (
|
||||
access_token VARCHAR(40) NOT NULL,
|
||||
client_id VARCHAR(80) NOT NULL,
|
||||
user_id VARCHAR(255),
|
||||
expires TIMESTAMP NOT NULL,
|
||||
scope VARCHAR(4000),
|
||||
PRIMARY KEY (access_token)
|
||||
);
|
||||
|
||||
CREATE TABLE oauth_authorization_codes (
|
||||
authorization_code VARCHAR(40) NOT NULL,
|
||||
client_id VARCHAR(80) NOT NULL,
|
||||
user_id VARCHAR(255),
|
||||
redirect_uri VARCHAR(2000),
|
||||
expires TIMESTAMP NOT NULL,
|
||||
scope VARCHAR(4000),
|
||||
id_token VARCHAR(1000),
|
||||
PRIMARY KEY (authorization_code)
|
||||
);
|
||||
|
||||
CREATE TABLE oauth_refresh_tokens (
|
||||
refresh_token VARCHAR(40) NOT NULL,
|
||||
client_id VARCHAR(80) NOT NULL,
|
||||
user_id VARCHAR(255),
|
||||
expires TIMESTAMP NOT NULL,
|
||||
scope VARCHAR(4000),
|
||||
PRIMARY KEY (refresh_token)
|
||||
);
|
||||
|
||||
CREATE TABLE oauth_scopes (
|
||||
scope VARCHAR(191) NOT NULL,
|
||||
is_default SMALLINT,
|
||||
PRIMARY KEY (scope)
|
||||
);
|
||||
|
||||
CREATE TABLE oauth_jwt (
|
||||
client_id VARCHAR(80) NOT NULL,
|
||||
subject VARCHAR(80),
|
||||
public_key VARCHAR(2000) NOT NULL
|
||||
);
|
||||
";
|
||||
|
||||
$arr = explode(';', $sql);
|
||||
$errors = 0;
|
||||
foreach($arr as $a) {
|
||||
if(strlen(trim($a))) {
|
||||
$r = dbq(trim($a));
|
||||
if(! $r) {
|
||||
$errors ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(! $errors)
|
||||
return UPDATE_SUCCESS;
|
||||
return UPDATE_FAILED;
|
||||
|
||||
}
|
||||
|
||||
}
|
7
boot.php
7
boot.php
@ -54,7 +54,7 @@ define ( 'STD_VERSION', '3.3.3' );
|
||||
define ( 'ZOT_REVISION', '6.0a' );
|
||||
|
||||
|
||||
define ( 'DB_UPDATE_VERSION', 1209 );
|
||||
define ( 'DB_UPDATE_VERSION', 1210 );
|
||||
|
||||
define ( 'PROJECT_BASE', __DIR__ );
|
||||
|
||||
@ -954,7 +954,10 @@ class App {
|
||||
&& is_array(self::$config['system'])
|
||||
&& array_key_exists('baseurl',self::$config['system'])
|
||||
&& strlen(self::$config['system']['baseurl'])) {
|
||||
$url = punify(self::$config['system']['baseurl']);
|
||||
// get_baseurl() is a heavily used function.
|
||||
// Do not use punify() here until we find a library that performs better than what we have now.
|
||||
//$url = punify(self::$config['system']['baseurl']);
|
||||
$url = self::$config['system']['baseurl'];
|
||||
$url = trim($url,'\\/');
|
||||
return $url;
|
||||
}
|
||||
|
41
doc/feature/additional/access.md
Normal file
41
doc/feature/additional/access.md
Normal 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
|
67
doc/feature/additional/composition.md
Normal file
67
doc/feature/additional/composition.md
Normal 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
|
57
doc/feature/additional/filtering.md
Normal file
57
doc/feature/additional/filtering.md
Normal 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
|
130
doc/feature/additional/general.md
Normal file
130
doc/feature/additional/general.md
Normal 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
|
33
doc/feature/additional/overview.md
Normal file
33
doc/feature/additional/overview.md
Normal 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]
|
57
doc/feature/additional/posts.md
Normal file
57
doc/feature/additional/posts.md
Normal 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
|
@ -21,7 +21,8 @@
|
||||
<div class="flex-column">
|
||||
<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/bugs">Reporting Bugs</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/member/member_faq">FAQ</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -193,26 +193,18 @@ require_once('include/api_zot.php');
|
||||
$redirect = trim($_REQUEST['redirect_uris'][0]);
|
||||
else
|
||||
$redirect = trim($_REQUEST['redirect_uris']);
|
||||
$grant_types = trim($_REQUEST['grant_types']);
|
||||
$scope = trim($_REQUEST['scope']);
|
||||
$icon = trim($_REQUEST['logo_uri']);
|
||||
if($oauth2) {
|
||||
$r = q("INSERT INTO oauth_clients (client_id, client_secret, redirect_uri, grant_types, scope, user_id)
|
||||
VALUES ( '%s', '%s', '%s', null, null, null ) ",
|
||||
dbesc($key),
|
||||
dbesc($secret),
|
||||
dbesc($redirect)
|
||||
);
|
||||
}
|
||||
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)
|
||||
);
|
||||
}
|
||||
$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($key),
|
||||
dbesc($secret),
|
||||
dbesc($redirect),
|
||||
dbesc($grant_types),
|
||||
dbesc($scope),
|
||||
dbesc((string) api_user())
|
||||
);
|
||||
|
||||
$ret['client_id'] = $key;
|
||||
$ret['client_secret'] = $secret;
|
||||
|
@ -14,25 +14,58 @@ function api_login(&$a){
|
||||
|
||||
// login with oauth
|
||||
try {
|
||||
$oauth = new ZotOAuth1();
|
||||
$req = OAuth1Request::from_request();
|
||||
// OAuth 2.0
|
||||
$storage = new \Zotlabs\Identity\OAuth2Storage(\DBA::$dba->db);
|
||||
$server = new \Zotlabs\Identity\OAuth2Server($storage);
|
||||
$request = \OAuth2\Request::createFromGlobals();
|
||||
if ($server->verifyResourceRequest($request)) {
|
||||
$token = $server->getAccessTokenData($request);
|
||||
$uid = $token['user_id'];
|
||||
$r = q("SELECT * FROM channel WHERE channel_id = %d LIMIT 1",
|
||||
intval($uid)
|
||||
);
|
||||
if (count($r)) {
|
||||
$record = $r[0];
|
||||
} else {
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
echo('This api requires login');
|
||||
killme();
|
||||
}
|
||||
|
||||
list($consumer,$token) = $oauth->verify_request($req);
|
||||
$_SESSION['uid'] = $record['channel_id'];
|
||||
$_SESSION['addr'] = $_SERVER['REMOTE_ADDR'];
|
||||
|
||||
if (!is_null($token)){
|
||||
$oauth->loginUser($token->uid);
|
||||
$x = q("select * from account where account_id = %d LIMIT 1",
|
||||
intval($record['channel_account_id'])
|
||||
);
|
||||
if ($x) {
|
||||
require_once('include/security.php');
|
||||
authenticate_success($x[0], null, true, false, true, true);
|
||||
$_SESSION['allow_api'] = true;
|
||||
call_hooks('logged_in', App::$user);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// OAuth 1.0
|
||||
$oauth = new ZotOAuth1();
|
||||
$req = OAuth1Request::from_request();
|
||||
|
||||
App::set_oauth_key($consumer->key);
|
||||
list($consumer, $token) = $oauth->verify_request($req);
|
||||
|
||||
call_hooks('logged_in', App::$user);
|
||||
return;
|
||||
if (!is_null($token)) {
|
||||
$oauth->loginUser($token->uid);
|
||||
|
||||
App::set_oauth_key($consumer->key);
|
||||
|
||||
call_hooks('logged_in', App::$user);
|
||||
return;
|
||||
}
|
||||
killme();
|
||||
}
|
||||
killme();
|
||||
}
|
||||
catch(Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
logger($e->getMessage());
|
||||
}
|
||||
|
||||
|
||||
// workarounds for HTTP-auth in CGI mode
|
||||
|
||||
foreach([ 'REDIRECT_REMOTE_USER', 'HTTP_AUTHORIZATION' ] as $head) {
|
||||
|
@ -780,10 +780,16 @@ function parseIdentityAwareHTML($Text) {
|
||||
|
||||
function bbcode($Text, $options = []) {
|
||||
|
||||
if(! is_array($options)) {
|
||||
$options = [];
|
||||
}
|
||||
|
||||
$preserve_nl = ((array_key_exists('preserve_nl',$options)) ? $options['preserve_nl'] : false);
|
||||
$tryoembed = ((array_key_exists('tryoembed',$options)) ? $options['tryoembed'] : true);
|
||||
$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);
|
||||
|
||||
@ -934,7 +940,7 @@ function bbcode($Text, $options = []) {
|
||||
if($tryoembed) {
|
||||
$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) {
|
||||
@ -946,16 +952,16 @@ function bbcode($Text, $options = []) {
|
||||
}
|
||||
}
|
||||
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="_blank" 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="_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" >$1</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 . ' rel="nofollow noopener" >$1</a>', $Text);
|
||||
$Text = preg_replace("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '<a href="$1" ' . $target . ' rel="nofollow noopener" >$2</a>', $Text);
|
||||
}
|
||||
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="_blank" 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="_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" >$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" >$2</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 . ' rel="nofollow noopener" >$2</a>', $Text);
|
||||
}
|
||||
|
||||
if (get_account_techlevel() < 2)
|
||||
@ -963,8 +969,8 @@ function bbcode($Text, $options = []) {
|
||||
|
||||
// Perform MAIL Search
|
||||
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="_blank" rel="nofollow noopener" >$2</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 . ' 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 (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) {
|
||||
$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) {
|
||||
$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) {
|
||||
$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
|
||||
$Text = oembed_bbcode2html($Text);
|
||||
|
||||
|
@ -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",
|
||||
intval($channel_id)
|
||||
);
|
||||
@ -1573,14 +1573,25 @@ function advanced_profile() {
|
||||
$profile['howlong'] = relative_date(App::$profile['howlong'], t('for %1$d %2$s'));
|
||||
}
|
||||
|
||||
if(App::$profile['keywords']) {
|
||||
$keywords = str_replace(',',' ', App::$profile['keywords']);
|
||||
$keywords = str_replace(' ',' ', $keywords);
|
||||
$karr = explode(' ', $keywords);
|
||||
if($karr) {
|
||||
for($cnt = 0; $cnt < count($karr); $cnt ++) {
|
||||
$karr[$cnt] = '<a href="' . z_root() . '/directory/f=&keywords=' . trim($karr[$cnt]) . '">' . $karr[$cnt] . '</a>';
|
||||
}
|
||||
}
|
||||
$profile['keywords'] = array( t('Tags:'), implode(' ', $karr));
|
||||
}
|
||||
|
||||
|
||||
if(App::$profile['sexual']) $profile['sexual'] = array( t('Sexual Preference:'), App::$profile['sexual'] );
|
||||
|
||||
if(App::$profile['homepage']) $profile['homepage'] = array( t('Homepage:'), linkify(App::$profile['homepage']) );
|
||||
|
||||
if(App::$profile['hometown']) $profile['hometown'] = array( t('Hometown:'), linkify(App::$profile['hometown']) );
|
||||
|
||||
if(App::$profile['keywords']) $profile['keywords'] = array( t('Tags:'), App::$profile['keywords']);
|
||||
|
||||
if(App::$profile['politic']) $profile['politic'] = array( t('Political Views:'), App::$profile['politic']);
|
||||
|
||||
if(App::$profile['religion']) $profile['religion'] = array( t('Religion:'), App::$profile['religion']);
|
||||
|
@ -1607,7 +1607,7 @@ function prepare_page($item) {
|
||||
// prepare_body calls unobscure() as a side effect. Do it here so that
|
||||
// the template will get passed an unobscured title.
|
||||
|
||||
$body = prepare_body($item, true);
|
||||
$body = prepare_body($item, [ 'newwin' => false ]);
|
||||
if(App::$page['template'] == 'none') {
|
||||
$tpl = 'page_display_empty.tpl';
|
||||
|
||||
|
@ -125,10 +125,16 @@ function datetime_convert($from = 'UTC', $to = 'UTC', $s = 'now', $fmt = "Y-m-d
|
||||
*/
|
||||
function dob($dob) {
|
||||
|
||||
$y = substr($dob,0,4);
|
||||
if((! ctype_digit($y)) || ($y < 1900))
|
||||
$ignore_year = true;
|
||||
else
|
||||
$ignore_year = false;
|
||||
|
||||
if ($dob === '0000-00-00' || $dob === '')
|
||||
$value = '';
|
||||
else
|
||||
$value = (($year) ? datetime_convert('UTC','UTC',$dob,'Y-m-d') : datetime_convert('UTC','UTC',$dob,'m-d'));
|
||||
$value = (($ignore_year) ? datetime_convert('UTC','UTC',$dob,'m-d') : datetime_convert('UTC','UTC',$dob,'Y-m-d'));
|
||||
|
||||
$o = replace_macros(get_markup_template("field_input.tpl"), [
|
||||
'$field' => [ 'dob', t('Birthday'), $value, ((intval($value)) ? t('Age: ') . age($value,App::$user['timezone'],App::$user['timezone']) : ''), '', 'placeholder="' . t('YYYY-MM-DD or MM-DD') .'"' ]
|
||||
|
@ -306,7 +306,7 @@ function store_doc_file($s) {
|
||||
|
||||
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['plink'] = z_root() . '/' . str_replace('doc','help',$s);
|
||||
|
@ -270,7 +270,8 @@ function locations_by_netid($netid) {
|
||||
dbesc($netid)
|
||||
);
|
||||
|
||||
return array_elm_to_str($locs,'location',', ');
|
||||
|
||||
return array_elm_to_str($locs,'location',', ','trim_and_unpunify');
|
||||
|
||||
}
|
||||
|
||||
|
@ -2532,43 +2532,7 @@ function tag_deliver($uid, $item_id) {
|
||||
*/
|
||||
|
||||
if($item['obj_type'] === ACTIVITY_OBJ_TAGTERM) {
|
||||
|
||||
// We received a community tag activity for a post.
|
||||
// See if we are the owner of the parent item and have given permission to tag our posts.
|
||||
// If so tag the parent post.
|
||||
|
||||
logger('tag_deliver: community tag activity received');
|
||||
|
||||
if(($item['owner_xchan'] === $u[0]['channel_hash']) && (! get_pconfig($u[0]['channel_id'],'system','blocktags'))) {
|
||||
logger('tag_deliver: community tag recipient: ' . $u[0]['channel_name']);
|
||||
$j_tgt = json_decode($item['target'],true);
|
||||
if($j_tgt && $j_tgt['id']) {
|
||||
$p = q("select * from item where mid = '%s' and uid = %d limit 1",
|
||||
dbesc($j_tgt['id']),
|
||||
intval($u[0]['channel_id'])
|
||||
);
|
||||
if($p) {
|
||||
$j_obj = json_decode($item['obj'],true);
|
||||
logger('tag_deliver: tag object: ' . print_r($j_obj,true), LOGGER_DATA);
|
||||
if($j_obj && $j_obj['id'] && $j_obj['title']) {
|
||||
if(is_array($j_obj['link']))
|
||||
$taglink = get_rel_link($j_obj['link'],'alternate');
|
||||
|
||||
store_item_tag($u[0]['channel_id'],$p[0]['id'],TERM_OBJ_POST,TERM_COMMUNITYTAG,$j_obj['title'],$j_obj['id']);
|
||||
$x = q("update item set edited = '%s', received = '%s', changed = '%s' where mid = '%s' and uid = %d",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($j_tgt['id']),
|
||||
intval($u[0]['channel_id'])
|
||||
);
|
||||
Zotlabs\Daemon\Master::Summon(array('Notifier','edit_post',$p[0]['id']));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
logger('Tag permission denied for ' . $u[0]['channel_address']);
|
||||
item_community_tag($u[0],$item);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2763,6 +2727,61 @@ function tag_deliver($uid, $item_id) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
function item_community_tag($channel,$item) {
|
||||
|
||||
|
||||
// We received a community tag activity for a post.
|
||||
// See if we are the owner of the parent item and have given permission to tag our posts.
|
||||
// If so tag the parent post.
|
||||
|
||||
logger('tag_deliver: community tag activity received: channel: ' . $channel['channel_name']);
|
||||
|
||||
$tag_the_post = false;
|
||||
$p = null;
|
||||
|
||||
$j_obj = json_decode($item['obj'],true);
|
||||
$j_tgt = json_decode($item['target'],true);
|
||||
if($j_tgt && $j_tgt['id']) {
|
||||
$p = q("select * from item where mid = '%s' and uid = %d limit 1",
|
||||
dbesc($j_tgt['id']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
}
|
||||
if($p) {
|
||||
xchan_query($p);
|
||||
$items = fetch_post_tags($p,true);
|
||||
$pitem = $items[0];
|
||||
$auth = get_iconfig($item,'system','communitytagauth');
|
||||
if($auth) {
|
||||
if(rsa_verify('tagauth.' . $item['mid'],base64url_decode($auth),$pitem['owner']['xchan_pubkey']) || rsa_verify('tagauth.' . $item['mid'],base64url_decode($auth),$pitem['author']['xchan_pubkey'])) {
|
||||
logger('tag_deliver: tagging the post: ' . $channel['channel_name']);
|
||||
$tag_the_post = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(($pitem['owner_xchan'] === $channel['channel_hash']) && (! intval(get_pconfig($channel['channel_id'],'system','blocktags')))) {
|
||||
logger('tag_deliver: community tag recipient: ' . $channel['channel_name']);
|
||||
$tag_the_post = true;
|
||||
$sig = rsa_sign('tagauth.' . $item['mid'],$channel['channel_prvkey']);
|
||||
logger('tag_deliver: setting iconfig for ' . $item['id']);
|
||||
set_iconfig($item['id'],'system','communitytagauth',base64url_encode($sig),1);
|
||||
}
|
||||
}
|
||||
|
||||
if($tag_the_post) {
|
||||
store_item_tag($channel['channel_id'],$pitem['id'],TERM_OBJ_POST,TERM_COMMUNITYTAG,$j_obj['title'],$j_obj['id']);
|
||||
}
|
||||
else {
|
||||
logger('Tag permission denied for ' . $channel['channel_address']);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function is called pre-deliver to see if a post matches the criteria to be tag delivered.
|
||||
*
|
||||
|
@ -1873,7 +1873,7 @@ function probe_api_path($host) {
|
||||
foreach($paths as $path) {
|
||||
$curpath = $scheme . '://' . $host . $path;
|
||||
$x = z_fetch_url($curpath);
|
||||
if($x['success'] && ! strlen($x['body'], 'not implemented'))
|
||||
if($x['success'] && ! strpos($x['body'], 'not implemented'))
|
||||
return str_replace('version', '', $curpath);
|
||||
}
|
||||
}
|
||||
|
@ -17,23 +17,10 @@ function update_channels_active_halfyear_stat() {
|
||||
db_utcnow(), db_quoteinterval('6 MONTH')
|
||||
);
|
||||
if($r) {
|
||||
$s = '';
|
||||
foreach($r as $rr) {
|
||||
if($s)
|
||||
$s .= ',';
|
||||
$s .= intval($rr['channel_id']);
|
||||
}
|
||||
$x = q("select uid from item where uid in ( $s ) and item_wall = 1 and created > %s - INTERVAL %s group by uid",
|
||||
db_utcnow(), db_quoteinterval('6 MONTH')
|
||||
);
|
||||
if($x) {
|
||||
$channels_active_halfyear_stat = count($x);
|
||||
set_config('system','channels_active_halfyear_stat',$channels_active_halfyear_stat);
|
||||
} else {
|
||||
set_config('system','channels_active_halfyear_stat',0);
|
||||
}
|
||||
} else {
|
||||
set_config('system','channels_active_halfyear_stat',0);
|
||||
set_config('system','channels_active_halfyear_stat',count($r));
|
||||
}
|
||||
else {
|
||||
set_config('system','channels_active_halfyear_stat','0');
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,28 +30,15 @@ function update_channels_active_monthly_stat() {
|
||||
db_utcnow(), db_quoteinterval('1 MONTH')
|
||||
);
|
||||
if($r) {
|
||||
$s = '';
|
||||
foreach($r as $rr) {
|
||||
if($s)
|
||||
$s .= ',';
|
||||
$s .= intval($rr['channel_id']);
|
||||
}
|
||||
$x = q("select uid from item where uid in ( $s ) and item_wall = 1 and created > %s - INTERVAL %s group by uid",
|
||||
db_utcnow(), db_quoteinterval('1 MONTH')
|
||||
);
|
||||
if($x) {
|
||||
$channels_active_monthly_stat = count($x);
|
||||
set_config('system','channels_active_monthly_stat',$channels_active_monthly_stat);
|
||||
} else {
|
||||
set_config('system','channels_active_monthly_stat',0);
|
||||
}
|
||||
} else {
|
||||
set_config('system','channels_active_monthly_stat',0);
|
||||
set_config('system','channels_active_monthly_stat',count($r));
|
||||
}
|
||||
else {
|
||||
set_config('system','channels_active_monthly_stat','0');
|
||||
}
|
||||
}
|
||||
|
||||
function update_local_posts_stat() {
|
||||
$posts = q("SELECT COUNT(*) AS local_posts FROM item WHERE item_wall = 1 ");
|
||||
$posts = q("SELECT COUNT(*) AS local_posts FROM item WHERE item_wall = 1 and id = parent");
|
||||
if (is_array($posts)) {
|
||||
$local_posts_stat = intval($posts[0]["local_posts"]);
|
||||
set_config('system','local_posts_stat',$local_posts_stat);
|
||||
|
@ -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);
|
||||
|
||||
@ -1616,7 +1616,7 @@ function prepare_body(&$item,$attach = false) {
|
||||
$s .= prepare_binary($item);
|
||||
}
|
||||
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);
|
||||
@ -1698,7 +1698,8 @@ function prepare_binary($item) {
|
||||
*
|
||||
* @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) {
|
||||
case 'text/plain':
|
||||
@ -1742,7 +1743,7 @@ function prepare_text($text, $content_type = 'text/bbcode', $cache = false) {
|
||||
if(stristr($text,'[nosmile]'))
|
||||
$s = bbcode($text, [ 'cache' => $cache ]);
|
||||
else
|
||||
$s = smilies(bbcode($text, [ 'cache' => $cache ]));
|
||||
$s = smilies(bbcode($text, ((is_array($opts)) ? $opts : [] )));
|
||||
|
||||
$s = zidify_links($s);
|
||||
|
||||
@ -2189,13 +2190,13 @@ function ids_to_querystr($arr,$idx = 'id',$quote = false) {
|
||||
* @returns string
|
||||
*/
|
||||
|
||||
function array_elm_to_str($arr,$elm,$delim = ',') {
|
||||
function array_elm_to_str($arr,$elm,$delim = ',',$each = 'trim') {
|
||||
|
||||
$tmp = [];
|
||||
if($arr && is_array($arr)) {
|
||||
foreach($arr as $x) {
|
||||
if(is_array($x) && array_key_exists($elm,$x)) {
|
||||
$z = trim($x[$elm]);
|
||||
$z = $each($x[$elm]);
|
||||
if(($z) && (! in_array($z,$tmp))) {
|
||||
$tmp[] = $z;
|
||||
}
|
||||
@ -2205,7 +2206,9 @@ function array_elm_to_str($arr,$elm,$delim = ',') {
|
||||
return implode($delim,$tmp);
|
||||
}
|
||||
|
||||
|
||||
function trim_and_unpunify($s) {
|
||||
return unpunify(trim($s));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@ -2574,6 +2577,9 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $d
|
||||
|
||||
// The @! tag will alter permissions
|
||||
$exclusive = (((! $grouptag) && (strpos($tag,'!') === 1) && (! $diaspora)) ? true : false);
|
||||
if(($grouptag) && (strpos($tag,'!!') === 0)) {
|
||||
$exclusive = true;
|
||||
}
|
||||
|
||||
//is it already replaced?
|
||||
if(strpos($tag,'[zrl='))
|
||||
@ -2746,8 +2752,8 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $d
|
||||
$profile = str_replace(',','%2c',$profile);
|
||||
$url = $profile;
|
||||
if($grouptag) {
|
||||
$newtag = '!' . '[zrl=' . $profile . ']' . $newname . '[/zrl]';
|
||||
$body = str_replace('!' . $name, $newtag, $body);
|
||||
$newtag = '!' . (($exclusive) ? '!' : '') . '[zrl=' . $profile . ']' . $newname . '[/zrl]';
|
||||
$body = str_replace('!' . (($exclusive) ? '!' : '') . $name, $newtag, $body);
|
||||
}
|
||||
else {
|
||||
$newtag = '@' . (($exclusive) ? '!' : '') . '[zrl=' . $profile . ']' . $newname . (($forum && ! $trailing_plus_name) ? '+' : '') . '[/zrl]';
|
||||
@ -2797,6 +2803,7 @@ function linkify_tags($a, &$body, $uid, $diaspora = false) {
|
||||
continue;
|
||||
|
||||
$success = handle_tag($a, $body, $access_tag, $str_tags, ($uid) ? $uid : App::$profile_uid , $tag, $diaspora);
|
||||
|
||||
$results[] = array('success' => $success, 'access_tag' => $access_tag);
|
||||
if($success['replaced']) $tagged[] = $tag;
|
||||
}
|
||||
|
@ -1597,3 +1597,55 @@ CREATE TABLE if not exists calendarinstances (
|
||||
UNIQUE(calendarid, principaluri),
|
||||
UNIQUE(calendarid, share_href)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
|
||||
CREATE TABLE if not exists oauth_clients (
|
||||
client_id VARCHAR(80) NOT NULL,
|
||||
client_secret VARCHAR(80),
|
||||
redirect_uri VARCHAR(2000),
|
||||
grant_types VARCHAR(80),
|
||||
scope VARCHAR(4000),
|
||||
user_id VARCHAR(80),
|
||||
PRIMARY KEY (client_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE if not exists oauth_access_tokens (
|
||||
access_token VARCHAR(40) NOT NULL,
|
||||
client_id VARCHAR(80) NOT NULL,
|
||||
user_id VARCHAR(255),
|
||||
expires TIMESTAMP NOT NULL,
|
||||
scope VARCHAR(4000),
|
||||
PRIMARY KEY (access_token)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE if not exists oauth_authorization_codes (
|
||||
authorization_code VARCHAR(40) NOT NULL,
|
||||
client_id VARCHAR(80) NOT NULL,
|
||||
user_id VARCHAR(255),
|
||||
redirect_uri VARCHAR(2000),
|
||||
expires TIMESTAMP NOT NULL,
|
||||
scope VARCHAR(4000),
|
||||
id_token VARCHAR(1000),
|
||||
PRIMARY KEY (authorization_code)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE if not exists oauth_refresh_tokens (
|
||||
refresh_token VARCHAR(40) NOT NULL,
|
||||
client_id VARCHAR(80) NOT NULL,
|
||||
user_id VARCHAR(255),
|
||||
expires TIMESTAMP NOT NULL,
|
||||
scope VARCHAR(4000),
|
||||
PRIMARY KEY (refresh_token)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE if not exists oauth_scopes (
|
||||
scope VARCHAR(191) NOT NULL,
|
||||
is_default TINYINT(1),
|
||||
PRIMARY KEY (scope)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE if not exists oauth_jwt (
|
||||
client_id VARCHAR(80) NOT NULL,
|
||||
subject VARCHAR(80),
|
||||
public_key VARCHAR(2000) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
@ -1610,3 +1610,57 @@ ALTER TABLE ONLY users
|
||||
|
||||
CREATE UNIQUE INDEX users_ukey
|
||||
ON users USING btree (username);
|
||||
|
||||
|
||||
CREATE TABLE oauth_clients (
|
||||
client_id VARCHAR(80) NOT NULL,
|
||||
client_secret VARCHAR(80),
|
||||
redirect_uri VARCHAR(2000),
|
||||
grant_types VARCHAR(80),
|
||||
scope VARCHAR(4000),
|
||||
user_id VARCHAR(80),
|
||||
PRIMARY KEY (client_id)
|
||||
);
|
||||
|
||||
CREATE TABLE oauth_access_tokens (
|
||||
access_token VARCHAR(40) NOT NULL,
|
||||
client_id VARCHAR(80) NOT NULL,
|
||||
user_id VARCHAR(255),
|
||||
expires TIMESTAMP NOT NULL,
|
||||
scope VARCHAR(4000),
|
||||
PRIMARY KEY (access_token)
|
||||
);
|
||||
|
||||
CREATE TABLE oauth_authorization_codes (
|
||||
authorization_code VARCHAR(40) NOT NULL,
|
||||
client_id VARCHAR(80) NOT NULL,
|
||||
user_id VARCHAR(255),
|
||||
redirect_uri VARCHAR(2000),
|
||||
expires TIMESTAMP NOT NULL,
|
||||
scope VARCHAR(4000),
|
||||
id_token VARCHAR(1000),
|
||||
PRIMARY KEY (authorization_code)
|
||||
);
|
||||
|
||||
CREATE TABLE oauth_refresh_tokens (
|
||||
refresh_token VARCHAR(40) NOT NULL,
|
||||
client_id VARCHAR(80) NOT NULL,
|
||||
user_id VARCHAR(255),
|
||||
expires TIMESTAMP NOT NULL,
|
||||
scope VARCHAR(4000),
|
||||
PRIMARY KEY (refresh_token)
|
||||
);
|
||||
|
||||
CREATE TABLE oauth_scopes (
|
||||
scope VARCHAR(191) NOT NULL,
|
||||
is_default SMALLINT,
|
||||
PRIMARY KEY (scope)
|
||||
);
|
||||
|
||||
CREATE TABLE oauth_jwt (
|
||||
client_id VARCHAR(80) NOT NULL,
|
||||
subject VARCHAR(80),
|
||||
public_key VARCHAR(2000) NOT NULL
|
||||
);
|
||||
|
||||
|
||||
|
4
view/css/mod_oauth2testvehicle.css
Normal file
4
view/css/mod_oauth2testvehicle.css
Normal file
@ -0,0 +1,4 @@
|
||||
.oath2test-form-box {
|
||||
border: #ccc thin solid;
|
||||
padding: 1em;
|
||||
}
|
@ -198,7 +198,7 @@ function string2bb(element) {
|
||||
|
||||
// Autocomplete forums
|
||||
forums = {
|
||||
match: /(^|\s)(\!)([^ \n]+)$/,
|
||||
match: /(^|\s)(\!\!*)([^ \n]+)$/,
|
||||
index: 3,
|
||||
search: function(term, callback) { contact_search(term, callback, backend_url, 'f', extra_channels, spinelement=false); },
|
||||
replace: editor_replace,
|
||||
@ -210,7 +210,7 @@ function string2bb(element) {
|
||||
tags = {
|
||||
match: /(^|\s)(\#)([^ \n]{2,})$/,
|
||||
index: 3,
|
||||
search: function(term, callback) { $.getJSON('/hashtags/' + '$f=&t=' + term).done(function(data) { callback($.map(data, function(entry) { return entry.text.indexOf(term) === 0 ? entry : null; })); }); },
|
||||
search: function(term, callback) { $.getJSON('/hashtags/' + '$f=&t=' + term).done(function(data) { callback($.map(data, function(entry) { return entry.text.toLowerCase().indexOf(term.toLowerCase()) === 0 ? entry : null; })); }); },
|
||||
replace: function(item) { return "$1$2" + item.text + ' '; },
|
||||
context: function(text) { return text.toLowerCase(); },
|
||||
template: tag_format
|
||||
|
@ -91,7 +91,7 @@
|
||||
<div class="collapse navbar-collapse" id="navbar-collapse-1">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
{{if $nav.login && !$userinfo}}
|
||||
<li class="nav-item d-none d-xl-flex">
|
||||
<li class="nav-item d-lg-flex">
|
||||
{{if $nav.loginmenu.1.4}}
|
||||
<a class="nav-link" href="#" title="{{$nav.loginmenu.1.3}}" id="{{$nav.loginmenu.1.4}}" data-toggle="modal" data-target="#nav-login">
|
||||
{{$nav.loginmenu.1.1}}
|
||||
@ -104,12 +104,12 @@
|
||||
</li>
|
||||
{{/if}}
|
||||
{{if $nav.register}}
|
||||
<li class="nav-item {{$nav.register.2}} d-none d-xl-flex">
|
||||
<li class="nav-item {{$nav.register.2}} d-lg-flex">
|
||||
<a class="nav-link" href="{{$nav.register.0}}" title="{{$nav.register.3}}" id="{{$nav.register.4}}">{{$nav.register.1}}</a>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{if $nav.alogout}}
|
||||
<li class="nav-item {{$nav.alogout.2}} d-none d-xl-flex">
|
||||
<li class="nav-item {{$nav.alogout.2}} d-lg-flex">
|
||||
<a class="nav-link" href="{{$nav.alogout.0}}" title="{{$nav.alogout.3}}" id="{{$nav.alogout.4}}">{{$nav.alogout.1}}</a>
|
||||
</li>
|
||||
{{/if}}
|
||||
|
@ -91,7 +91,7 @@
|
||||
<div class="collapse navbar-collapse" id="navbar-collapse-1">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
{{if $nav.login && !$userinfo}}
|
||||
<li class="nav-item d-none d-xl-flex">
|
||||
<li class="nav-item d-lg-flex">
|
||||
{{if $nav.loginmenu.1.4}}
|
||||
<a class="nav-link" href="#" title="{{$nav.loginmenu.1.3}}" id="{{$nav.loginmenu.1.4}}" data-toggle="modal" data-target="#nav-login">
|
||||
{{$nav.loginmenu.1.1}}
|
||||
@ -104,12 +104,12 @@
|
||||
</li>
|
||||
{{/if}}
|
||||
{{if $nav.register}}
|
||||
<li class="nav-item {{$nav.register.2}} d-none d-xl-flex">
|
||||
<li class="nav-item {{$nav.register.2}} d-lg-flex">
|
||||
<a class="nav-link" href="{{$nav.register.0}}" title="{{$nav.register.3}}" id="{{$nav.register.4}}">{{$nav.register.1}}</a>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{if $nav.alogout}}
|
||||
<li class="nav-item {{$nav.alogout.2}} d-none d-xl-flex">
|
||||
<li class="nav-item {{$nav.alogout.2}} d-none d-lg-flex">
|
||||
<a class="nav-link" href="{{$nav.alogout.0}}" title="{{$nav.alogout.3}}" id="{{$nav.alogout.4}}">{{$nav.alogout.1}}</a>
|
||||
</li>
|
||||
{{/if}}
|
||||
|
21
view/tpl/oauth2testvehicle.tpl
Normal file
21
view/tpl/oauth2testvehicle.tpl
Normal file
@ -0,0 +1,21 @@
|
||||
<h1>OAuth 2.0 Test Vehicle</h1>
|
||||
|
||||
{{foreach $endpoints as $ept}}
|
||||
<div class="oath2test-form-box">
|
||||
<form action="{{$baseurl}}/{{$ept.0}}/" method="{{$ept.4}}">
|
||||
<h3>{{$ept.3}}</h3>
|
||||
{{$baseurl}}/{{$ept.0}}/?{{foreach $ept.1 as $field}}{{$field.0}}={{$field.1}}&<input type="hidden" name="{{$field.0}}" value="{{$field.1}}" />{{/foreach}}
|
||||
<br>
|
||||
<button type="submit" name="{{$ept.2}}_submit" value="submit" class="btn btn-med" title="">Submit</button>
|
||||
<span style="display: {{if $ept.5}}inline{{else}}none{{/if}}; font-size: 2em;"> <i class="fa fa-check"></i></span>
|
||||
</form>
|
||||
</div>
|
||||
{{/foreach}}
|
||||
<div>
|
||||
<h3>API response</h3>
|
||||
<pre style="display: inline-block; overflow-x: auto; white-space: nowrap; width: 100%;">
|
||||
<code>
|
||||
{{$api_response}}
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
@ -2,9 +2,15 @@
|
||||
|
||||
<div class='oauthapp'>
|
||||
<img src='{{$app.icon}}'>
|
||||
<h4>{{$app.name}}</h4>
|
||||
</div>
|
||||
<h3>{{$authorize}}</h3>
|
||||
<form method="POST">
|
||||
<div class="settings-submit-wrapper"><input class="settings-submit" type="submit" name="oauth_yes" value="{{$yes}}" /></div>
|
||||
</form>
|
||||
<h3>{{$app.name}}</h3>
|
||||
<p class="descriptive-paragraph">{{$authorize}}</p>
|
||||
<form method="POST">
|
||||
<div class="settings-submit-wrapper">
|
||||
<input type="hidden" name="client_id" value="{{$client_id}}" />
|
||||
<input type="hidden" name="redirect_uri" value="{{$redirect_uri}}" />
|
||||
<input type="hidden" name="state" value="{{$state}}" />
|
||||
<button class="btn btn-lg btn-danger" name="authorize" value="deny" type="submit">{{$no}}</button>
|
||||
<button class="btn btn-lg btn-success" name="authorize" value="allow" type="submit">{{$yes}}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
@ -1,5 +1,5 @@
|
||||
<div id="settings-nick-wrapper" class="section-content-info-wrapper">
|
||||
<div id="settings-nickname-desc">{{$desc}} <strong>'{{$nickname}}@{{$basepath}}'</strong></div>
|
||||
<div id="settings-nickname-desc">{{$desc}} <strong>{{$nickname}}</strong></div>
|
||||
{{if $davpath}}
|
||||
<br>
|
||||
<div id="settings-dav-desc">{{$davdesc}} <strong>'{{$davpath}}'</strong></div>
|
||||
|
@ -15,6 +15,7 @@
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm" title="{{$sharePage}}" onclick="window.location.href='rpost?f=&body={{$shareLink}}';"><i class="fa fa-fw fa-share"></i></button>
|
||||
<button id="fullscreen-btn" type="button" class="btn btn-outline-secondary btn-sm" onclick="makeFullScreen(); adjustFullscreenEditorHeight();"><i class="fa fa-expand"></i></button>
|
||||
<button id="inline-btn" type="button" class="btn btn-outline-secondary btn-sm" onclick="makeFullScreen(false); adjustInlineEditorHeight()"><i class="fa fa-compress"></i></button>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user