Merge remote-tracking branch 'upstream/dev' into dev

This commit is contained in:
zottel 2016-08-12 20:43:05 +02:00
commit e4bdc92834
14 changed files with 377 additions and 234 deletions

View File

@ -1,3 +1,28 @@
Hubzilla 1.12
- extensible permissions so you can create a new permission rule such as "can write to my wiki" or "can see me naked".
- guest access tokens can do anything you let them, including create posts and administer your channel
- ACLs can be set on files and directories prior to creation.
- ACL tool can now be used in multiple forms within a page
- a myriad of new drag/drop features (drop files or photos into /cloud or a post, or drop link into a post or comment, etc.)
- multiple file uploads
- improvements to website import
- UNO replaced with extensible server roles
- select bbcode elements (such as baseurl) supported in wiki pages
- addons:
Diaspora Protocol - additional updates to maintain compatibility with 0.6.0.0 and stop showing likes as wall-to-wall comments (except when the liker does not have any Diaspora protocol ability)
Cdav - continued improvements to the web UI
Pong - the classic pong game
Dfedfix - removed, no longer needed
Openid - moved from core to addon
- bugfixes
unable to delete privacy groups
weird display interaction with code blocks and escaped base64 content containing 8 - O
workaround WordPress oembeds which are almost completely javascript and therefore filtered
restrict oembed cache url to 254 chars to avoid spurious failures caching google map urls
"Page not found" appeared twice
birthdays weren't being automatically added to event calendar
some iCal entries had malformed descriptions
Hubzilla 1.10
Wiki:
Lots of enhanced functionality, usability improvements, and bugfixes from v1.8

View File

@ -102,11 +102,20 @@ class Onepoll {
$fetch_feed = true;
$x = null;
// They haven't given us permission to see their stream
$can_view_stream = intval(get_abconfig($importer_uid,$contact['abook_xchan'],'their_perms','view_stream'));
if(! $can_view_stream)
$fetch_feed = false;
// we haven't given them permission to send us their stream
$can_send_stream = intval(get_abconfig($importer_uid,$contact['abook_xchan'],'my_perms','send_stream'));
if(! $can_send_stream)
$fetch_feed = false;
if($fetch_feed) {
$feedurl = str_replace('/poco/','/zotfeed/',$contact['xchan_connurl']);

View File

@ -0,0 +1,24 @@
<?php
namespace Zotlabs\Lib;
class Api_router {
static private $routes = array();
static function register($path,$fn,$auth_required) {
self::$routes[$path] = [ 'func' => $fn, 'auth' => $auth_required ];
}
static function find($path) {
if(array_key_exists($path,self::$routes))
return self::$routes[$path];
return null;
}
static function dbg() {
return self::$routes;
}
}

View File

@ -8,20 +8,15 @@ require_once('include/api.php');
class Api extends \Zotlabs\Web\Controller {
function post() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
if(count(\App::$user) && x(\App::$user,'uid') && \App::$user['uid'] != local_channel()) {
notice( t('Permission denied.') . EOL);
return;
}
}
function get() {
function get() {
if(\App::$cmd=='api/oauth/authorize'){
/*
@ -33,7 +28,8 @@ class Api extends \Zotlabs\Web\Controller {
// get consumer/client from request token
try {
$request = OAuth1Request::from_request();
} catch(Exception $e) {
}
catch(Exception $e) {
echo "<pre>"; var_dump($e); killme();
}
@ -41,17 +37,20 @@ class Api extends \Zotlabs\Web\Controller {
if(x($_POST,'oauth_yes')){
$app = $this->oauth_get_client($request);
if (is_null($app)) return "Invalid request. Unknown token.";
if (is_null($app))
return "Invalid request. Unknown token.";
$consumer = new OAuth1Consumer($app['client_id'], $app['pw'], $app['redirect_uri']);
$verifier = md5($app['secret'].local_channel());
set_config("oauth", $verifier, local_channel());
if($consumer->callback_url!=null) {
if($consumer->callback_url != null) {
$params = $request->get_parameters();
$glue="?";
if (strstr($consumer->callback_url,$glue)) $glue="?";
$glue = '?';
if(strstr($consumer->callback_url,$glue))
$glue = '?';
goaway($consumer->callback_url . $glue . "oauth_token=" . OAuth1Util::urlencode_rfc3986($params['oauth_token']) . "&oauth_verifier=" . OAuth1Util::urlencode_rfc3986($verifier));
killme();
}
@ -59,7 +58,7 @@ class Api extends \Zotlabs\Web\Controller {
$tpl = get_markup_template("oauth_authorize_done.tpl");
$o = replace_macros($tpl, array(
'$title' => t('Authorize application connection'),
'$info' => t('Return to your app and insert this Securty Code:'),
'$info' => t('Return to your app and insert this Security Code:'),
'$code' => $verifier,
));
@ -72,14 +71,11 @@ class Api extends \Zotlabs\Web\Controller {
notice( t('Please login to continue.') . EOL );
return login(false,'api-login',$request->get_parameters());
}
//FKOAuth1::loginUser(4);
$app = $this->oauth_get_client($request);
if (is_null($app)) return "Invalid request. Unknown token.";
if (is_null($app))
return "Invalid request. Unknown token.";
$tpl = get_markup_template('oauth_authorize.tpl');
$o = replace_macros($tpl, array(
'$title' => t('Authorize application connection'),
@ -94,29 +90,24 @@ class Api extends \Zotlabs\Web\Controller {
return $o;
}
echo api_call($a);
echo api_call();
killme();
}
function oauth_get_client($request){
$params = $request->get_parameters();
$token = $params['oauth_token'];
$token = $params['oauth_token'];
$r = q("SELECT `clients`.*
FROM `clients`, `tokens`
WHERE `clients`.`client_id`=`tokens`.`client_id`
AND `tokens`.`id`='%s' AND `tokens`.`auth_scope`='request'",
dbesc($token));
$r = q("SELECT clients.* FROM clients, tokens WHERE clients.client_id = tokens.client_id
AND tokens.id = '%s' AND tokens.auth_scope = 'request' ",
dbesc($token)
);
if($r)
return $r[0];
if (!count($r))
return null;
return null;
return $r[0];
}
}

View File

@ -21,18 +21,23 @@ class File_upload extends \Zotlabs\Web\Controller {
$_REQUEST['source'] = 'file_upload';
if($channel['channel_id'] != local_channel()) {
$_REQUEST['contact_allow'] = expand_acl($channel['channel_allow_cid']);
$_REQUEST['group_allow'] = expand_acl($channel['channel_allow_gid']);
$_REQUEST['contact_deny'] = expand_acl($channel['channel_deny_cid']);
$_REQUEST['group_deny'] = expand_acl($channel['channel_deny_gid']);
}
if($channel['channel_id'] != local_channel()) {
$_REQUEST['contact_allow'] = expand_acl($channel['channel_allow_cid']);
$_REQUEST['group_allow'] = expand_acl($channel['channel_allow_gid']);
$_REQUEST['contact_deny'] = expand_acl($channel['channel_deny_cid']);
$_REQUEST['group_deny'] = expand_acl($channel['channel_deny_gid']);
}
if($_REQUEST['directory_name'])
if($_REQUEST['filename']) {
$_REQUEST['allow_cid'] = perms2str($_REQUEST['contact_allow']);
$_REQUEST['allow_gid'] = perms2str($_REQUEST['group_allow']);
$_REQUEST['deny_cid'] = perms2str($_REQUEST['contact_deny']);
$_REQUEST['deny_gid'] = perms2str($_REQUEST['group_deny']);
$r = attach_mkdir($channel,get_observer_hash(),$_REQUEST);
else
}
else {
$r = attach_store($channel,get_observer_hash(), '', $_REQUEST);
}
goaway(z_root() . '/' . $_REQUEST['return_url']);
}

View File

@ -316,6 +316,8 @@ class Browser extends DAV\Browser\Plugin {
$quota['desc'] = $quotaDesc;
$quota['warning'] = ((($limit) && ((round($used / $limit, 1) * 100) >= 90)) ? t('WARNING:') : ''); // 10485760 bytes = 100MB
$path = trim(str_replace('cloud/' . $this->auth->owner_nick, '', $path),'/');
$output .= replace_macros(get_markup_template('cloud_actionspanel.tpl'), array(
'$folder_header' => t('Create new folder'),
'$folder_submit' => t('Create'),
@ -330,7 +332,8 @@ class Browser extends DAV\Browser\Plugin {
'$deny_gid' => acl2json($channel_acl['deny_gid']),
'$lockstate' => $lockstate,
'$return_url' => \App::$cmd,
'$path' => trim(str_replace('cloud/' . $this->auth->owner_nick, '', $path),'/'),
'$path' => $path,
'$folder' => find_folder_hash_by_path($this->auth->owner_id, $path),
'$dragdroptext' => t('Drop files here to immediately upload')
));
}

View File

@ -44,7 +44,7 @@ require_once('include/account.php');
define ( 'PLATFORM_NAME', 'hubzilla' );
define ( 'STD_VERSION', '1.11' );
define ( 'STD_VERSION', '1.13' );
define ( 'ZOT_REVISION', '1.1' );
define ( 'DB_UPDATE_VERSION', 1181 );

View File

@ -61,10 +61,8 @@ require_once('include/api_auth.php');
}
function api_register_func($path, $func, $auth=false){
global $API;
$API[$path] = array('func'=>$func,
'auth'=>$auth);
function api_register_func($path, $func, $auth=false) {
\Zotlabs\Lib\Api_router::register($path,$func,$auth);
}
@ -72,76 +70,86 @@ require_once('include/api_auth.php');
* MAIN API ENTRY POINT *
**************************/
function api_call($a){
GLOBAL $API, $called_api;
function api_call(){
// preset
$type="json";
$p = App::$cmd;
$type = null;
foreach ($API as $p=>$info){
if (strpos(App::$query_string, $p)===0){
$called_api= explode("/",$p);
//unset($_SERVER['PHP_AUTH_USER']);
if ($info['auth'] === true && api_user() === false) {
api_login($a);
}
load_contact_links(api_user());
$channel = App::get_channel();
logger('API call for ' . $channel['channel_name'] . ': ' . App::$query_string);
logger('API parameters: ' . print_r($_REQUEST,true));
$type="json";
if (strpos(App::$query_string, ".xml")>0) $type="xml";
if (strpos(App::$query_string, ".json")>0) $type="json";
if (strpos(App::$query_string, ".rss")>0) $type="rss";
if (strpos(App::$query_string, ".atom")>0) $type="atom";
if (strpos(App::$query_string, ".as")>0) $type="as";
$r = call_user_func($info['func'], $a, $type);
if ($r===false) return;
switch($type){
case "xml":
$r = mb_convert_encoding($r, "UTF-8",mb_detect_encoding($r));
header ("Content-Type: text/xml");
return '<?xml version="1.0" encoding="UTF-8"?>'."\n".$r;
break;
case "json":
header ("Content-Type: application/json");
foreach($r as $rr) {
if(! $rr)
$rr = array();
$json = json_encode($rr);
}
if ($_GET['callback'])
$json = $_GET['callback']."(".$json.")";
return $json;
break;
case "rss":
header ("Content-Type: application/rss+xml");
return '<?xml version="1.0" encoding="UTF-8"?>'."\n".$r;
break;
case "atom":
header ("Content-Type: application/atom+xml");
return '<?xml version="1.0" encoding="UTF-8"?>'."\n".$r;
break;
case "as":
//header ("Content-Type: application/json");
//foreach($r as $rr)
// return json_encode($rr);
return json_encode($r);
break;
}
//echo "<pre>"; var_dump($r); die();
if(strrpos($p,'.')) {
$type = substr($p,strrpos($p,'.')+1);
if(strpos($type,'/') === false) {
$p = substr($p,0,strrpos($p,'.'));
// recalculate App argc,argv since we just extracted the type from it
App::$argv = explode('/',$p);
App::$argc = count(App::$argv);
}
}
if((! $type) || (! in_array($type, [ 'json', 'xml', 'rss', 'as', 'atom' ])))
$type = 'json';
$info = \Zotlabs\Lib\Api_router::find($p);
logger('info: ' . $p . ' type: ' . $type . ' ' . print_r($info,true));
if($info) {
if ($info['auth'] === true && api_user() === false) {
api_login($a);
}
load_contact_links(api_user());
$channel = App::get_channel();
logger('API call for ' . $channel['channel_name'] . ': ' . App::$query_string);
logger('API parameters: ' . print_r($_REQUEST,true));
$r = call_user_func($info['func'],$type);
if($r === false)
return;
switch($type) {
case "xml":
$r = mb_convert_encoding($r, "UTF-8",mb_detect_encoding($r));
header ("Content-Type: text/xml");
return '<?xml version="1.0" encoding="UTF-8"?>'."\n".$r;
break;
case "json":
header ("Content-Type: application/json");
foreach($r as $rr) {
if(! $rr)
$rr = array();
$json = json_encode($rr);
}
// Lookup JSONP to understand these lines. They provide cross-domain AJAX ability.
if ($_GET['callback'])
$json = $_GET['callback'] . '(' . $json . ')' ;
return $json;
break;
case "rss":
header ("Content-Type: application/rss+xml");
return '<?xml version="1.0" encoding="UTF-8"?>'."\n".$r;
break;
case "atom":
header ("Content-Type: application/atom+xml");
return '<?xml version="1.0" encoding="UTF-8"?>'."\n".$r;
break;
case "as":
//header ("Content-Type: application/json");
//foreach($r as $rr)
// return json_encode($rr);
return json_encode($r);
break;
}
}
header("HTTP/1.1 404 Not Found");
logger('API call not implemented: '.App::$query_string." - ".print_r($_REQUEST,true));
logger('API call not implemented: ' . App::$query_string . ' - ' . print_r($_REQUEST,true));
$r = '<status><error>not implemented</error></status>';
switch($type){
case "xml":
@ -166,7 +174,8 @@ require_once('include/api_auth.php');
/**
* RSS extra info
*/
function api_rss_extra($a, $arr, $user_info){
function api_rss_extra( $arr, $user_info){
if (is_null($user_info)) $user_info = api_get_user($a);
$arr['$user'] = $user_info;
$arr['$rss'] = array(
@ -186,8 +195,8 @@ require_once('include/api_auth.php');
* Returns user info array.
*/
function api_get_user($a, $contact_id = null, $contact_xchan = null){
global $called_api;
function api_get_user( $contact_id = null, $contact_xchan = null){
$user = null;
$extra_query = "";
@ -212,26 +221,12 @@ require_once('include/api_auth.php');
if (api_user()!==false)
$extra_query .= " AND abook_channel = ".intval(api_user());
}
if (is_null($user) && argc() > (count($called_api)-1) && (strstr(App::$cmd,'/users'))){
$argid = count($called_api);
list($xx, $null) = explode(".",argv($argid));
if(is_numeric($xx)){
$user = intval($xx);
$extra_query = " AND abook_id = %d ";
} else {
$user = dbesc($xx);
$extra_query = " AND xchan_addr like '%s@%%' ";
if (api_user() !== false)
$extra_query .= " AND abook_channel = ".intval(api_user());
}
}
}
if (! $user) {
if (api_user() === false) {
api_login($a);
return False;
return false;
} else {
$user = local_channel();
$extra_query = " AND abook_channel = %d AND abook_self = 1 ";
@ -239,7 +234,8 @@ require_once('include/api_auth.php');
}
logger('api_user: ' . $extra_query . ', user: ' . $user);
logger('api_user: ' . $extra_query . ', user: ' . $user, LOGGER_DATA, LOG_INFO);
// user info
$uinfo = q("SELECT * from abook left join xchan on abook_xchan = xchan_hash
@ -356,7 +352,7 @@ require_once('include/api_auth.php');
}
function api_client_register($a,$type) {
function api_client_register($type) {
$ret = array();
$key = random_string(16);
@ -389,12 +385,12 @@ require_once('include/api_auth.php');
function api_item_get_user($a, $item) {
function api_item_get_user( $item) {
// The author is our direct contact, in a conversation with us.
if($item['author']['abook_id']) {
return api_get_user($a,$item['author']['abook_id']);
return api_get_user($item['author']['abook_id']);
}
// We don't know this person directly.
@ -473,7 +469,7 @@ require_once('include/api_auth.php');
* returns a 401 status code and an error message if not.
* http://developer.twitter.com/doc/get/account/verify_credentials
*/
function api_account_verify_credentials($a, $type){
function api_account_verify_credentials( $type){
if (api_user()===false) return false;
$user_info = api_get_user($a);
@ -483,7 +479,7 @@ require_once('include/api_auth.php');
api_register_func('api/account/verify_credentials','api_account_verify_credentials', true);
function api_account_logout($a, $type){
function api_account_logout( $type){
require_once('include/auth.php');
App::$session->nuke();
return api_apply_template("user", $type, array('$user' => null));
@ -507,7 +503,7 @@ require_once('include/api_auth.php');
* Red basic channel export
*/
function api_export_basic($a, $type) {
function api_export_basic( $type) {
if(api_user() === false) {
logger('api_export_basic: no user');
return false;
@ -519,9 +515,10 @@ require_once('include/api_auth.php');
}
api_register_func('api/export/basic','api_export_basic', true);
api_register_func('api/red/channel/export/basic','api_export_basic', true);
api_register_func('api/hz/1.0/channel/export/basic','api_export_basic', true);
function api_channel_stream($a, $type) {
function api_channel_stream( $type) {
if(api_user() === false) {
logger('api_channel_stream: no user');
return false;
@ -536,18 +533,20 @@ require_once('include/api_auth.php');
}
}
api_register_func('api/red/channel/stream','api_channel_stream', true);
api_register_func('api/hz/1.0/channel/stream','api_channel_stream', true);
function api_attach_list($a,$type) {
function api_attach_list($type) {
logger('api_user: ' . api_user());
json_return_and_die(attach_list_files(api_user(),get_observer_hash(),'','','','created asc'));
}
api_register_func('api/red/files','api_attach_list', true);
api_register_func('api/hz/1.0/files','api_attach_list', true);
function api_file_meta($a,$type) {
function api_file_meta($type) {
if (api_user()===false) return false;
if(! $_REQUEST['file_id']) return false;
$r = q("select * from attach where uid = %d and hash = '%s' limit 1",
@ -563,9 +562,10 @@ require_once('include/api_auth.php');
}
api_register_func('api/red/filemeta', 'api_file_meta', true);
api_register_func('api/hz/1.0/filemeta', 'api_file_meta', true);
function api_file_data($a,$type) {
function api_file_data($type) {
if (api_user()===false) return false;
if(! $_REQUEST['file_id']) return false;
$start = (($_REQUEST['start']) ? intval($_REQUEST['start']) : 0);
@ -606,10 +606,11 @@ require_once('include/api_auth.php');
}
api_register_func('api/red/filedata', 'api_file_data', true);
api_register_func('api/hz/1.0/filedata', 'api_file_data', true);
function api_file_detail($a,$type) {
function api_file_detail($type) {
if (api_user()===false) return false;
if(! $_REQUEST['file_id']) return false;
$r = q("select * from attach where uid = %d and hash = '%s' limit 1",
@ -631,20 +632,23 @@ require_once('include/api_auth.php');
}
api_register_func('api/red/file', 'api_file_detail', true);
api_register_func('api/hz/1.0/file', 'api_file_detail', true);
function api_albums($a,$type) {
function api_albums($type) {
json_return_and_die(photos_albums_list(App::get_channel(),App::get_observer()));
}
api_register_func('api/red/albums','api_albums', true);
api_register_func('api/hz/1.0/albums','api_albums', true);
function api_photos($a,$type) {
function api_photos($type) {
$album = $_REQUEST['album'];
json_return_and_die(photos_list_photos(App::get_channel(),App::get_observer(),$album));
}
api_register_func('api/red/photos','api_photos', true);
api_register_func('api/hz/1.0/photos','api_photos', true);
function api_photo_detail($a,$type) {
function api_photo_detail($type) {
if (api_user()===false) return false;
if(! $_REQUEST['photo_id']) return false;
$scale = ((array_key_exists('scale',$_REQUEST)) ? intval($_REQUEST['scale']) : 0);
@ -684,9 +688,10 @@ require_once('include/api_auth.php');
}
api_register_func('api/red/photo', 'api_photo_detail', true);
api_register_func('api/hz/1.0/photo', 'api_photo_detail', true);
function api_group_members($a,$type) {
function api_group_members($type) {
if(api_user() === false)
return false;
@ -706,11 +711,12 @@ require_once('include/api_auth.php');
}
api_register_func('api/red/group_members','api_group_members', true);
api_register_func('api/hz/1.0/group_members','api_group_members', true);
function api_group($a,$type) {
function api_group($type) {
if(api_user() === false)
return false;
@ -720,9 +726,10 @@ require_once('include/api_auth.php');
json_return_and_die($r);
}
api_register_func('api/red/group','api_group', true);
api_register_func('api/hz/1.0/group','api_group', true);
function api_red_xchan($a,$type) {
function api_red_xchan($type) {
logger('api_xchan');
if(api_user() === false)
@ -738,9 +745,10 @@ require_once('include/api_auth.php');
};
api_register_func('api/red/xchan','api_red_xchan',true);
api_register_func('api/hz/1.0/xchan','api_red_xchan',true);
function api_statuses_mediap($a, $type) {
function api_statuses_mediap( $type) {
if (api_user() === false) {
logger('api_statuses_update: no user');
return false;
@ -782,11 +790,11 @@ require_once('include/api_auth.php');
$mod->post();
// this should output the last post (the one we just posted).
return api_status_show($a,$type);
return api_status_show($type);
}
api_register_func('api/statuses/mediap','api_statuses_mediap', true);
function api_statuses_update($a, $type) {
function api_statuses_update( $type) {
if (api_user() === false) {
logger('api_statuses_update: no user');
return false;
@ -901,13 +909,13 @@ require_once('include/api_auth.php');
$mod->post();
// this should output the last post (the one we just posted).
return api_status_show($a,$type);
return api_status_show($type);
}
api_register_func('api/statuses/update_with_media','api_statuses_update', true);
api_register_func('api/statuses/update','api_statuses_update', true);
function red_item_new($a, $type) {
function red_item_new( $type) {
if (api_user() === false) {
logger('api_red_item_new: no user');
@ -939,9 +947,10 @@ require_once('include/api_auth.php');
}
api_register_func('api/red/item/new','red_item_new', true);
api_register_func('api/hz/1.0/item/new','red_item_new', true);
function red_item($a, $type) {
function red_item( $type) {
if (api_user() === false) {
logger('api_red_item_full: no user');
@ -977,6 +986,7 @@ require_once('include/api_auth.php');
}
api_register_func('api/red/item/full','red_item', true);
api_register_func('api/hz/1.0/item/full','red_item', true);
@ -1042,7 +1052,7 @@ require_once('include/api_auth.php');
return $status_info;
}
function api_status_show($a, $type){
function api_status_show( $type){
$user_info = api_get_user($a);
// get last public message
@ -1120,7 +1130,7 @@ require_once('include/api_auth.php');
// FIXME - this is essentially the same as api_status_show except for the template formatting at the end. Consolidate.
function api_users_show($a, $type){
function api_users_show( $type){
$user_info = api_get_user($a);
require_once('include/security.php');
@ -1192,7 +1202,7 @@ require_once('include/api_auth.php');
* TODO: Add reply info
*/
function api_statuses_home_timeline($a, $type){
function api_statuses_home_timeline( $type){
if (api_user() === false)
return false;
@ -1259,10 +1269,10 @@ require_once('include/api_auth.php');
switch($type){
case "atom":
case "rss":
$data = api_rss_extra($a, $data, $user_info);
$data = api_rss_extra( $data, $user_info);
break;
case "as":
$as = api_format_as($a, $ret, $user_info);
$as = api_format_as( $ret, $user_info);
$as['title'] = App::$config['sitename']." Home Timeline";
$as['link']['url'] = z_root()."/".$user_info["screen_name"]."/all";
return($as);
@ -1274,7 +1284,7 @@ require_once('include/api_auth.php');
api_register_func('api/statuses/home_timeline','api_statuses_home_timeline', true);
api_register_func('api/statuses/friends_timeline','api_statuses_home_timeline', true);
function api_statuses_public_timeline($a, $type){
function api_statuses_public_timeline( $type){
if (api_user()===false) return false;
$user_info = api_get_user($a);
@ -1320,10 +1330,10 @@ require_once('include/api_auth.php');
switch($type){
case "atom":
case "rss":
$data = api_rss_extra($a, $data, $user_info);
$data = api_rss_extra( $data, $user_info);
break;
case "as":
$as = api_format_as($a, $ret, $user_info);
$as = api_format_as( $ret, $user_info);
$as['title'] = App::$config['sitename']. " " . t('Public Timeline');
$as['link']['url'] = z_root()."/";
return($as);
@ -1338,7 +1348,7 @@ require_once('include/api_auth.php');
*
*/
function api_statuses_show($a, $type){
function api_statuses_show( $type){
if (api_user()===false) return false;
$user_info = api_get_user($a);
@ -1377,7 +1387,7 @@ require_once('include/api_auth.php');
/*switch($type){
case "atom":
case "rss":
$data = api_rss_extra($a, $data, $user_info);
$data = api_rss_extra( $data, $user_info);
}*/
return api_apply_template("status", $type, $data);
}
@ -1388,7 +1398,7 @@ require_once('include/api_auth.php');
/**
*
*/
function api_statuses_repeat($a, $type){
function api_statuses_repeat( $type){
if (api_user()===false) return false;
$user_info = api_get_user($a);
@ -1434,7 +1444,7 @@ require_once('include/api_auth.php');
*
*/
function api_statuses_destroy($a, $type){
function api_statuses_destroy( $type){
if (api_user()===false) return false;
$user_info = api_get_user($a);
@ -1498,7 +1508,7 @@ require_once('include/api_auth.php');
*/
function api_statuses_mentions($a, $type){
function api_statuses_mentions( $type){
if (api_user()===false) return false;
$user_info = api_get_user($a);
@ -1548,10 +1558,10 @@ require_once('include/api_auth.php');
switch($type){
case "atom":
case "rss":
$data = api_rss_extra($a, $data, $user_info);
$data = api_rss_extra( $data, $user_info);
break;
case "as":
$as = api_format_as($a, $ret, $user_info);
$as = api_format_as( $ret, $user_info);
$as["title"] = App::$config['sitename']." Mentions";
$as['link']['url'] = z_root()."/";
return($as);
@ -1565,7 +1575,7 @@ require_once('include/api_auth.php');
api_register_func('api/statuses/replies','api_statuses_mentions', true);
function api_statuses_user_timeline($a, $type){
function api_statuses_user_timeline( $type){
if (api_user()===false) return false;
$user_info = api_get_user($a);
@ -1633,7 +1643,7 @@ require_once('include/api_auth.php');
switch($type){
case "atom":
case "rss":
$data = api_rss_extra($a, $data, $user_info);
$data = api_rss_extra( $data, $user_info);
}
return api_apply_template("timeline", $type, $data);
@ -1649,7 +1659,7 @@ require_once('include/api_auth.php');
*
* api v1 : https://web.archive.org/web/20131019055350/https://dev.twitter.com/docs/api/1/post/favorites/create/%3Aid
*/
function api_favorites_create_destroy($a, $type){
function api_favorites_create_destroy( $type){
logger('favorites_create_destroy');
@ -1706,7 +1716,7 @@ require_once('include/api_auth.php');
switch($type){
case "atom":
case "rss":
$data = api_rss_extra($a, $data, $user_info);
$data = api_rss_extra( $data, $user_info);
}
return api_apply_template("status", $type, $data);
@ -1717,7 +1727,7 @@ require_once('include/api_auth.php');
function api_favorites($a, $type){
function api_favorites( $type){
if (api_user()===false)
return false;
@ -1770,10 +1780,10 @@ require_once('include/api_auth.php');
switch($type){
case "atom":
case "rss":
$data = api_rss_extra($a, $data, $user_info);
$data = api_rss_extra( $data, $user_info);
break;
case "as":
$as = api_format_as($a, $ret, $user_info);
$as = api_format_as( $ret, $user_info);
$as['title'] = App::$config['sitename']." Home Timeline";
$as['link']['url'] = z_root()."/".$user_info["screen_name"]."/all";
return($as);
@ -1789,7 +1799,7 @@ require_once('include/api_auth.php');
function api_format_as($a, $ret, $user_info) {
function api_format_as( $ret, $user_info) {
$as = array();
$as['title'] = App::$config['sitename']." Public Timeline";
@ -1907,7 +1917,7 @@ require_once('include/api_auth.php');
localize_item($item);
$status_user = (($item['author_xchan']==$user_info['guid'])?$user_info: api_item_get_user($a,$item));
$status_user = (($item['author_xchan']==$user_info['guid'])?$user_info: api_item_get_user($item));
if(array_key_exists('status',$status_user))
unset($status_user['status']);
@ -1986,7 +1996,7 @@ require_once('include/api_auth.php');
}
function api_account_rate_limit_status($a,$type) {
function api_account_rate_limit_status($type) {
$hash = array(
'reset_time_in_seconds' => strtotime('now + 1 hour'),
@ -2002,7 +2012,7 @@ require_once('include/api_auth.php');
}
api_register_func('api/account/rate_limit_status','api_account_rate_limit_status',true);
function api_help_test($a,$type) {
function api_help_test($type) {
if ($type == 'xml')
$ok = "true";
@ -2019,7 +2029,7 @@ require_once('include/api_auth.php');
* This function is deprecated by Twitter
* returns: json, xml
**/
function api_statuses_f($a, $type, $qtype) {
function api_statuses_f( $type, $qtype) {
if (api_user()===false) return false;
$user_info = api_get_user($a);
@ -2054,20 +2064,20 @@ require_once('include/api_auth.php');
$ret = array();
foreach($r as $cid){
$ret[] = api_get_user($a, $cid['abook_id']);
$ret[] = api_get_user( $cid['abook_id']);
}
return array('$users' => $ret);
}
function api_statuses_friends($a, $type){
$data = api_statuses_f($a,$type,"friends");
function api_statuses_friends( $type){
$data = api_statuses_f($type,"friends");
if ($data===false) return false;
return api_apply_template("friends", $type, $data);
}
function api_statuses_followers($a, $type){
$data = api_statuses_f($a,$type,"followers");
function api_statuses_followers( $type){
$data = api_statuses_f($type,"followers");
if ($data===false) return false;
return api_apply_template("friends", $type, $data);
}
@ -2079,7 +2089,7 @@ require_once('include/api_auth.php');
function api_statusnet_config($a,$type) {
function api_statusnet_config($type) {
load_config('system');
@ -2115,8 +2125,9 @@ require_once('include/api_auth.php');
api_register_func('api/statusnet/config','api_statusnet_config',false);
api_register_func('api/friendica/config','api_statusnet_config',false);
api_register_func('api/red/config','api_statusnet_config',false);
api_register_func('api/hz/1.0/config','api_statusnet_config',false);
function api_statusnet_version($a,$type) {
function api_statusnet_version($type) {
// liar
@ -2134,7 +2145,7 @@ require_once('include/api_auth.php');
api_register_func('api/statusnet/version','api_statusnet_version',false);
function api_friendica_version($a,$type) {
function api_friendica_version($type) {
if($type === 'xml') {
header("Content-type: application/xml");
@ -2149,9 +2160,10 @@ require_once('include/api_auth.php');
}
api_register_func('api/friendica/version','api_friendica_version',false);
api_register_func('api/red/version','api_friendica_version',false);
api_register_func('api/hz/1.0/version','api_friendica_version',false);
function api_ff_ids($a,$type,$qtype) {
function api_ff_ids($type,$qtype) {
if(! api_user())
return false;
@ -2187,17 +2199,17 @@ require_once('include/api_auth.php');
}
}
function api_friends_ids($a,$type) {
api_ff_ids($a,$type,'friends');
function api_friends_ids($type) {
api_ff_ids($type,'friends');
}
function api_followers_ids($a,$type) {
api_ff_ids($a,$type,'followers');
function api_followers_ids($type) {
api_ff_ids($type,'followers');
}
api_register_func('api/friends/ids','api_friends_ids',true);
api_register_func('api/followers/ids','api_followers_ids',true);
function api_direct_messages_new($a, $type) {
function api_direct_messages_new( $type) {
if (api_user()===false) return false;
if (!x($_POST, "text") || !x($_POST,"screen_name")) return;
@ -2213,7 +2225,7 @@ require_once('include/api_auth.php');
dbesc($_POST['screen_name'] . '@%')
);
$recipient = api_get_user($a, $r[0]['abook_id']);
$recipient = api_get_user( $r[0]['abook_id']);
$replyto = '';
$sub = '';
if (x($_REQUEST,'replyto')) {
@ -2247,7 +2259,7 @@ require_once('include/api_auth.php');
switch($type){
case "atom":
case "rss":
$data = api_rss_extra($a, $data, $user_info);
$data = api_rss_extra( $data, $user_info);
}
return api_apply_template("direct_messages", $type, $data);
@ -2255,7 +2267,7 @@ require_once('include/api_auth.php');
}
api_register_func('api/direct_messages/new','api_direct_messages_new',true);
function api_direct_messages_box($a, $type, $box) {
function api_direct_messages_box( $type, $box) {
if (api_user()===false) return false;
$user_info = api_get_user($a);
@ -2292,10 +2304,10 @@ require_once('include/api_auth.php');
foreach($r as $item) {
if ($item['from_xchan'] == $channel['channel_hash']) {
$sender = $user_info;
$recipient = api_get_user($a, null, $item['to_xchan']);
$recipient = api_get_user( null, $item['to_xchan']);
}
else {
$sender = api_get_user($a, null, $item['from_xchan']);
$sender = api_get_user( null, $item['from_xchan']);
$recipient = $user_info;
}
@ -2308,24 +2320,24 @@ require_once('include/api_auth.php');
switch($type){
case "atom":
case "rss":
$data = api_rss_extra($a, $data, $user_info);
$data = api_rss_extra( $data, $user_info);
}
return api_apply_template("direct_messages", $type, $data);
}
function api_direct_messages_sentbox($a, $type){
return api_direct_messages_box($a, $type, "sentbox");
function api_direct_messages_sentbox( $type){
return api_direct_messages_box( $type, "sentbox");
}
function api_direct_messages_inbox($a, $type){
return api_direct_messages_box($a, $type, "inbox");
function api_direct_messages_inbox( $type){
return api_direct_messages_box( $type, "inbox");
}
function api_direct_messages_all($a, $type){
return api_direct_messages_box($a, $type, "all");
function api_direct_messages_all( $type){
return api_direct_messages_box( $type, "all");
}
function api_direct_messages_conversation($a, $type){
return api_direct_messages_box($a, $type, "conversation");
function api_direct_messages_conversation( $type){
return api_direct_messages_box( $type, "conversation");
}
api_register_func('api/direct_messages/conversation','api_direct_messages_conversation',true);
api_register_func('api/direct_messages/all','api_direct_messages_all',true);
@ -2333,7 +2345,7 @@ require_once('include/api_auth.php');
api_register_func('api/direct_messages','api_direct_messages_inbox',true);
function api_oauth_request_token($a, $type){
function api_oauth_request_token( $type){
try{
$oauth = new ZotOAuth1();
$req = OAuth1Request::from_request();
@ -2348,7 +2360,7 @@ require_once('include/api_auth.php');
killme();
}
function api_oauth_access_token($a, $type){
function api_oauth_access_token( $type){
try{
$oauth = new ZotOAuth1();
$req = OAuth1Request::from_request();

View File

@ -1438,6 +1438,22 @@ logger('attach_hash: ' . $attachHash);
return $hash;
}
function find_folder_hash_by_path($channel_id, $path) {
$filename = end(explode('/', $path));
$r = q("SELECT hash FROM attach WHERE uid = %d AND filename = '%s' LIMIT 1",
intval($channel_id),
dbesc($filename)
);
$hash = '';
if($r && $r[0]['hash']) {
$hash = $r[0]['hash'];
}
return $hash;
}
/**
* @brief Returns the filename of an attachment in a given channel.
*

View File

@ -1,8 +1,10 @@
<?php /** @file */
use Zotlabs\Lib as Zlib;
require_once('include/hubloc.php');
function oembed_replacecb($matches){
$embedurl=$matches[1];
@ -130,6 +132,9 @@ function oembed_fetch_url($embedurl){
$txt = null;
// we should try to cache this and avoid a lookup on each render
$zrl = is_matrix_url($embedurl);
if($action !== 'block') {
$txt = Zlib\Cache::get('[' . App::$videowidth . '] ' . $embedurl);
@ -142,15 +147,11 @@ function oembed_fetch_url($embedurl){
$txt = "";
$furl = $embedurl;
$zrl = false;
if(local_channel()) {
require_once('include/hubloc.php');
$zrl = is_matrix_url($furl);
if($zrl)
$furl = zid($furl);
}
logger('local_channel: ' . local_channel());
if(local_channel() && $zrl)
$furl = zid($furl);
if ($action !== 'block') {
// try oembed autodiscovery
@ -216,14 +217,17 @@ function oembed_fetch_url($embedurl){
logger('oembed html was purified. original: ' . $orig . ' purified: ' . $j->html, LOGGER_DEBUG, LOG_INFO);
}
$orig_len = mb_strlen(trim($orig));
$new_len = mb_strlen(trim($j->html));
if(! $new_len)
$orig_len = mb_strlen(preg_replace('/\s+/','',$orig));
$new_len = mb_strlen(preg_replace('/\s+/','',$j->html));
if(stripos($orig,'<script') || (! $new_len))
$j->type = 'error';
elseif($orig_len) {
$ratio = $new_len / $orig_len;
if($ratio < 0.8)
if($ratio < 0.5) {
$j->type = 'error';
logger('oembed html truncated: ' . $ratio, LOGGER_DEBUG, LOG_INFO);
}
}
}
@ -231,7 +235,7 @@ function oembed_fetch_url($embedurl){
$j->embedurl = $embedurl;
// logger('fetch return: ' . print_r($j,true));
// logger('fetch return: ' . print_r($j,true));
return $j;

View File

@ -2975,3 +2975,38 @@ function text_highlight($s,$lang) {
return('<code>' . $o . '</code>');
}
// function to convert multi-dimensional array to xml
// create new instance of simplexml
// $xml = new SimpleXMLElement('<root/>');
// function callback
// array2XML($xml, $my_array);
// save as xml file
// echo (($xml->asXML('data.xml')) ? 'Your XML file has been generated successfully!' : 'Error generating XML file!');
function arrtoxml($root_elem,$arr) {
$xml = new SimpleXMLElement('<' . $root_elem . '/>');
array2XML($xml,$arr);
return $xml->asXML();
}
function array2XML($obj, $array)
{
foreach ($array as $key => $value)
{
if(is_numeric($key))
$key = 'item' . $key;
if (is_array($value))
{
$node = $obj->addChild($key);
array2XML($node, $value);
}
else
{
$obj->addChild($key, htmlspecialchars($value));
}
}
}

View File

@ -3784,9 +3784,11 @@ function zotinfo($arr) {
// check if it has characteristics of a public forum based on custom permissions.
$t = q("select * from abconfig where abconfig.cat = 'my_perms' and abconfig.chan = %d and abconfig.xchan = '%s' and abconfig.k in ('tag_deliver', 'send_stream') ",
intval($e['channel_id']),
intval($e['channel_hash'])
dbesc($e['channel_hash'])
);
$ch = 0;
if($t) {
foreach($t as $tt) {
if($tt['k'] == 'tag_deliver' && $tt['v'] == 1)

View File

@ -1,15 +1,27 @@
<div id="files-mkdir-tools" class="section-content-tools-wrapper">
<label for="files-mkdir">{{$folder_header}}</label>
<form method="post" action="">
<input type="hidden" name="sabreAction" value="mkcol">
<input id="files-mkdir" type="text" name="name" class="form-control form-group">
<button class="btn btn-primary btn-sm pull-right" type="submit" value="{{$folder_submit}}">{{$folder_submit}}</button>
<form id="mkdir-form" method="post" action="file_upload" class="acl-form" data-form_id="mkdir-form" data-allow_cid='{{$allow_cid}}' data-allow_gid='{{$allow_gid}}' data-deny_cid='{{$deny_cid}}' data-deny_gid='{{$deny_gid}}'>
<!--input type="hidden" name="sabreAction" value="mkcol"-->
<input type="hidden" name="folder" value="{{$folder}}" />
<input type="hidden" name="channick" value="{{$channick}}" />
<input type="hidden" name="return_url" value="{{$return_url}}" />
<input id="files-mkdir" type="text" name="filename" class="form-control form-group">
<div class="pull-right btn-group">
<div class="btn-group">
{{if $lockstate}}
<button class="btn btn-default btn-sm" data-toggle="modal" data-target="#aclModal" type="button">
<i class="jot-perms-icon fa fa-{{$lockstate}}"></i>
</button>
{{/if}}
<button class="btn btn-primary btn-sm pull-right" type="submit" value="{{$folder_submit}}">{{$folder_submit}}</button>
</div>
</div>
</form>
<div class="clear"></div>
</div>
<div id="files-upload-tools" class="section-content-tools-wrapper">
{{if $quota.limit || $quota.used}}<div class="{{if $quota.warning}}section-content-danger-wrapper{{else}}section-content-info-wrapper{{/if}}">{{if $quota.warning}}<strong>{{$quota.warning}} </strong>{{/if}}{{$quota.desc}}</div>{{/if}}
<form id="ajax-upload-files" method="post" action="file_upload" enctype="multipart/form-data" class="acl-form" data-form_id="ajax-upload-files" data-allow_cid='{{$allow_cid}}' data-allow_gid='{{$allow_gid}}' data-deny_cid='{{$deny_cid}}' data-deny_gid='{{$deny_gid}}'>
<form id="ajax-upload-files" method="post" action="file_upload" enctype="multipart/form-data" class="acl-form" data-form_id="ajax-upload-files" data-allow_cid='{{$allow_cid}}' data-allow_gid='{{$allow_gid}}' data-deny_cid='{{$deny_cid}}' data-deny_gid='{{$deny_gid}}'>
<input type="hidden" name="directory" value="{{$path}}" />
<input type="hidden" name="channick" value="{{$channick}}" />
<input type="hidden" name="return_url" value="{{$return_url}}" />
@ -18,8 +30,8 @@
<div class="pull-right btn-group">
<div class="btn-group">
{{if $lockstate}}
<button id="dbtn-acl" class="btn btn-default btn-sm" data-toggle="modal" data-target="#aclModal" onclick="return false;">
<i id="jot-perms-icon" class="fa fa-{{$lockstate}}"></i>
<button class="btn btn-default btn-sm" data-toggle="modal" data-target="#aclModal" type="button">
<i class="jot-perms-icon fa fa-{{$lockstate}}"></i>
</button>
{{/if}}
<button id="upload-submit" class="btn btn-primary btn-sm pull-right" type="submit" name="submit" value="{{$upload_submit}}">{{$upload_submit}}</button>

View File

@ -503,6 +503,7 @@ function enableOnUser(){
// cancel event and hover styling
DragDropUploadFileHover(e);
if (!editor) $("#profile-jot-text").val("");
// fetch FileList object
@ -527,7 +528,11 @@ function enableOnUser(){
xhr.addEventListener('load', function (e) {
//console.log('xhr upload complete', e);
window.fileUploadsCompleted = window.fileUploadsCompleted + 1;
addeditortext(xhr.responseText);
initEditor(function() {
addeditortext(xhr.responseText);
});
$('#jot-media').val($('#jot-media').val() + xhr.responseText);
// When all the uploads have completed, refresh the page
if (window.filesToUpload > 0 && window.fileUploadsCompleted === window.filesToUpload) {