Merge remote-tracking branch 'upstream/dev' into dev
This commit is contained in:
commit
0406e3a7dd
@ -34,6 +34,7 @@ Hubzilla 1.8
|
||||
Apps:
|
||||
Synchronise app list with changes to system apps
|
||||
Preserve existing app categories on app updates/edits
|
||||
Regression: fixed translated system app names
|
||||
Architecture:
|
||||
Provide autoloaded class files and libraries for plugins.
|
||||
Further refactoring of session driver to sort out some cookie anomolies
|
||||
@ -61,6 +62,9 @@ Hubzilla 1.8
|
||||
Block 'sys' channels from being 'random profile' candidates
|
||||
DB update failed email could be sent in the wrong language under rare circumstances
|
||||
Openid remote authentication used incorrect namespace
|
||||
URL attached to profile "things" was not linked, always showing the "thing" manage page
|
||||
New connection wasn't added to default privacy group when "auto-accept" was enabled
|
||||
Regression: iconfig sharing wasn't working properly
|
||||
Plugins:
|
||||
CalDAV/CardDAV plugin provided
|
||||
Issue sending Diaspora 'like' activities from sources that did not propagate the DCV
|
||||
|
@ -5,18 +5,18 @@ namespace Zotlabs\Lib;
|
||||
|
||||
class AbConfig {
|
||||
|
||||
static public function Load($chash,$xhash) {
|
||||
$r = q("select * from abconfig where chan = '%s' and xchan = '%s'",
|
||||
dbesc($chash),
|
||||
static public function Load($chan,$xhash) {
|
||||
$r = q("select * from abconfig where chan = %d and xchan = '%s'",
|
||||
intval($chan),
|
||||
dbesc($xhash)
|
||||
);
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
||||
static public function Get($chash,$xhash,$family,$key) {
|
||||
$r = q("select * from abconfig where chan = '%s' and xchan = '%s' and cat = '%s' and k = '%s' limit 1",
|
||||
dbesc($chash),
|
||||
static public function Get($chan,$xhash,$family,$key) {
|
||||
$r = q("select * from abconfig where chan = %d and xchan = '%s' and cat = '%s' and k = '%s' limit 1",
|
||||
intval($chan),
|
||||
dbesc($xhash),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
@ -28,14 +28,14 @@ class AbConfig {
|
||||
}
|
||||
|
||||
|
||||
static public function Set($chash,$xhash,$family,$key,$value) {
|
||||
static public function Set($chan,$xhash,$family,$key,$value) {
|
||||
|
||||
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
|
||||
if(self::Get($chash,$xhash,$family,$key) === false) {
|
||||
$r = q("insert into abconfig ( chan, xchan, cat, k, v ) values ( '%s', '%s', '%s', '%s', '%s' ) ",
|
||||
dbesc($chash),
|
||||
if(self::Get($chan,$xhash,$family,$key) === false) {
|
||||
$r = q("insert into abconfig ( chan, xchan, cat, k, v ) values ( %d, '%s', '%s', '%s', '%s' ) ",
|
||||
intval($chan),
|
||||
dbesc($xhash),
|
||||
dbesc($family),
|
||||
dbesc($key),
|
||||
@ -43,9 +43,9 @@ class AbConfig {
|
||||
);
|
||||
}
|
||||
else {
|
||||
$r = q("update abconfig set v = '%s' where chan = '%s' and xchan = '%s' and cat = '%s' and k = '%s' ",
|
||||
$r = q("update abconfig set v = '%s' where chan = %d and xchan = '%s' and cat = '%s' and k = '%s' ",
|
||||
dbesc($dbvalue),
|
||||
dbesc($chash),
|
||||
dbesc($chan),
|
||||
dbesc($xhash),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
@ -58,10 +58,10 @@ class AbConfig {
|
||||
}
|
||||
|
||||
|
||||
static public function Delete($chash,$xhash,$family,$key) {
|
||||
static public function Delete($chan,$xhash,$family,$key) {
|
||||
|
||||
$r = q("delete from abconfig where chan = '%s' and xchan = '%s' and cat = '%s' and k = '%s' ",
|
||||
dbesc($chash),
|
||||
$r = q("delete from abconfig where chan = %d and xchan = '%s' and cat = '%s' and k = '%s' ",
|
||||
intval($chan),
|
||||
dbesc($xhash),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
@ -70,4 +70,4 @@ class AbConfig {
|
||||
return $r;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
46
Zotlabs/Lib/Cache.php
Normal file
46
Zotlabs/Lib/Cache.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php /** @file */
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
/**
|
||||
* cache api
|
||||
*/
|
||||
|
||||
class Cache {
|
||||
public static function get($key) {
|
||||
$r = q("SELECT v FROM cache WHERE k = '%s' limit 1",
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
if ($r)
|
||||
return $r[0]['v'];
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function set($key,$value) {
|
||||
|
||||
$r = q("SELECT * FROM cache WHERE k = '%s' limit 1",
|
||||
dbesc($key)
|
||||
);
|
||||
if($r) {
|
||||
q("UPDATE cache SET v = '%s', updated = '%s' WHERE k = '%s'",
|
||||
dbesc($value),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($key));
|
||||
}
|
||||
else {
|
||||
q("INSERT INTO cache ( k, v, updated) VALUES ('%s','%s','%s')",
|
||||
dbesc($key),
|
||||
dbesc($value),
|
||||
dbesc(datetime_convert()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function clear() {
|
||||
q("DELETE FROM cache WHERE updated < '%s'",
|
||||
dbesc(datetime_convert('UTC','UTC',"now - 30 days")));
|
||||
}
|
||||
|
||||
}
|
||||
|
112
Zotlabs/Lib/SuperCurl.php
Normal file
112
Zotlabs/Lib/SuperCurl.php
Normal file
@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
/**
|
||||
* @brief wrapper for z_fetch_url() which can be instantiated with several built-in parameters and
|
||||
* these can be modified and re-used. Useful for CalDAV and other processes which need to authenticate
|
||||
* and set lots of CURL options (many of which stay the same from one call to the next).
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
class SuperCurl {
|
||||
|
||||
|
||||
private $auth;
|
||||
private $url;
|
||||
|
||||
private $curlopt = array();
|
||||
|
||||
private $headers = null;
|
||||
public $filepos = 0;
|
||||
public $filehandle = 0;
|
||||
public $request_data = '';
|
||||
|
||||
private $request_method = 'GET';
|
||||
private $upload = false;
|
||||
|
||||
|
||||
private function set_data($s) {
|
||||
$this->request_data = $s;
|
||||
$this->filepos = 0;
|
||||
}
|
||||
|
||||
public function curl_read($ch,$fh,$size) {
|
||||
|
||||
if($this->filepos < 0) {
|
||||
unset($fh);
|
||||
return '';
|
||||
}
|
||||
|
||||
$s = substr($this->request_data,$this->filepos,$size);
|
||||
|
||||
if(strlen($s) < $size)
|
||||
$this->filepos = (-1);
|
||||
else
|
||||
$this->filepos = $this->filepos + $size;
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
|
||||
public function __construct($opts = array()) {
|
||||
$this->set($opts);
|
||||
}
|
||||
|
||||
private function set($opts = array()) {
|
||||
if($opts) {
|
||||
foreach($opts as $k => $v) {
|
||||
switch($k) {
|
||||
case 'http_auth':
|
||||
$this->auth = $v;
|
||||
break;
|
||||
case 'custom':
|
||||
$this->request_method = $v;
|
||||
break;
|
||||
case 'url':
|
||||
$this->url = $v;
|
||||
break;
|
||||
case 'data':
|
||||
$this->set_data($v);
|
||||
if($v) {
|
||||
$this->upload = true;
|
||||
}
|
||||
else {
|
||||
$this->upload = false;
|
||||
}
|
||||
break;
|
||||
case 'headers':
|
||||
$this->headers = $v;
|
||||
break;
|
||||
default:
|
||||
$this->curlopts[$k] = $v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function exec() {
|
||||
$opts = $this->curlopts;
|
||||
if($this->auth)
|
||||
$opts['http_auth'] = $this->auth;
|
||||
if($this->custom)
|
||||
$opts['custom'] = $this->custom;
|
||||
if($this->headers)
|
||||
$opts['headers'] = $this->headers;
|
||||
if($this->upload) {
|
||||
$opts['upload'] = true;
|
||||
$opts['infile'] = $this->filehandle;
|
||||
$opts['infilesize'] = strlen($this->request_data);
|
||||
$opts['readfunc'] = [ $this, 'curl_read' ] ;
|
||||
}
|
||||
|
||||
$recurse = 0;
|
||||
return z_fetch_url($this->url,true,$recurse,(($opts) ? $opts : null));
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -122,7 +122,7 @@ class XConfig {
|
||||
);
|
||||
}
|
||||
|
||||
App::$config[$xchan][$family][$key] = $value;
|
||||
\App::$config[$xchan][$family][$key] = $value;
|
||||
|
||||
if($ret)
|
||||
return $value;
|
||||
@ -157,4 +157,4 @@ class XConfig {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -219,7 +219,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
//Update profile photo permissions
|
||||
|
||||
logger('A new profile was assigned - updating profile photos');
|
||||
profile_photo_set_profile_perms($profile_id);
|
||||
profile_photo_set_profile_perms(local_channel(),$profile_id);
|
||||
|
||||
}
|
||||
|
||||
@ -345,7 +345,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
||||
unset($clone['abook_account']);
|
||||
unset($clone['abook_channel']);
|
||||
|
||||
$abconfig = load_abconfig($channel['channel_hash'],$clone['abook_xchan']);
|
||||
$abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']);
|
||||
if($abconfig)
|
||||
$clone['abconfig'] = $abconfig;
|
||||
|
||||
|
@ -40,7 +40,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
*
|
||||
*/
|
||||
|
||||
function post() {
|
||||
function post() {
|
||||
|
||||
if(! local_channel()) {
|
||||
return;
|
||||
@ -271,7 +271,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
||||
*/
|
||||
|
||||
|
||||
function get() {
|
||||
function get() {
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL );
|
||||
|
@ -43,7 +43,7 @@ class Follow extends \Zotlabs\Web\Controller {
|
||||
unset($clone['abook_account']);
|
||||
unset($clone['abook_channel']);
|
||||
|
||||
$abconfig = load_abconfig($channel['channel_hash'],$clone['abook_xchan']);
|
||||
$abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']);
|
||||
if($abconfig)
|
||||
$clone['abconfig'] = $abconfig;
|
||||
|
||||
|
@ -131,6 +131,8 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
|
||||
// import channel
|
||||
|
||||
$relocate = ((array_key_exists('relocate',$data)) ? $data['relocate'] : null);
|
||||
|
||||
if(array_key_exists('channel',$data)) {
|
||||
|
||||
if($completed < 1) {
|
||||
@ -387,8 +389,7 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
if($abconfig) {
|
||||
// @fixme does not handle sync of del_abconfig
|
||||
foreach($abconfig as $abc) {
|
||||
if($abc['chan'] === $channel['channel_hash'])
|
||||
set_abconfig($abc['chan'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']);
|
||||
set_abconfig($channel['channel_id'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']);
|
||||
}
|
||||
}
|
||||
|
||||
@ -475,7 +476,7 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
import_events($channel,$data['event']);
|
||||
|
||||
if(is_array($data['event_item']))
|
||||
import_items($channel,$data['event_item']);
|
||||
import_items($channel,$data['event_item'],false,$relocate);
|
||||
|
||||
if(is_array($data['menu']))
|
||||
import_menus($channel,$data['menu']);
|
||||
@ -486,7 +487,7 @@ class Import extends \Zotlabs\Web\Controller {
|
||||
$saved_notification_flags = notifications_off($channel['channel_id']);
|
||||
|
||||
if($import_posts && array_key_exists('item',$data) && $data['item'])
|
||||
import_items($channel,$data['item']);
|
||||
import_items($channel,$data['item'],false,$relocate);
|
||||
|
||||
notifications_on($channel['channel_id'],$saved_notification_flags);
|
||||
|
||||
|
@ -92,7 +92,7 @@ class Import_items extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
if(array_key_exists('item',$data) && $data['item']) {
|
||||
import_items($channel,$data['item']);
|
||||
import_items($channel,$data['item'],false,((array_key_exists('relocate',$data)) ? $data['relocate'] : null));
|
||||
}
|
||||
|
||||
if(array_key_exists('item_id',$data) && $data['item_id']) {
|
||||
@ -106,7 +106,7 @@ class Import_items extends \Zotlabs\Web\Controller {
|
||||
|
||||
|
||||
|
||||
function get() {
|
||||
function get() {
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied') . EOL);
|
||||
|
@ -894,8 +894,8 @@ class Item extends \Zotlabs\Web\Controller {
|
||||
if($orig_post) {
|
||||
$datarray['id'] = $post_id;
|
||||
|
||||
item_store_update($datarray,$execflag);
|
||||
|
||||
$x = item_store_update($datarray,$execflag);
|
||||
|
||||
if(! $parent) {
|
||||
$r = q("select * from item where id = %d",
|
||||
intval($post_id)
|
||||
|
@ -20,7 +20,7 @@ class Pdledit extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
|
||||
function get() {
|
||||
function get() {
|
||||
|
||||
if(! local_channel()) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
@ -32,18 +32,18 @@ class Pdledit extends \Zotlabs\Web\Controller {
|
||||
else {
|
||||
$o .= '<div class="generic-content-wrapper-styled">';
|
||||
$o .= '<h1>' . t('Edit System Page Description') . '</h1>';
|
||||
$files = glob('mod/*');
|
||||
$files = glob('Zotlabs/Module/*.php');
|
||||
if($files) {
|
||||
foreach($files as $f) {
|
||||
$name = basename($f,'.php');
|
||||
$name = lcfirst(basename($f,'.php'));
|
||||
$x = theme_include('mod_' . $name . '.pdl');
|
||||
if($x) {
|
||||
$o .= '<a href="pdledit/' . $name . '" >' . $name . '</a><br />';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$o .= '</div>';
|
||||
|
||||
$o .= '</div>';
|
||||
|
||||
// list module pdl files
|
||||
return $o;
|
||||
|
@ -62,7 +62,7 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
intval($uid),
|
||||
intval(PHOTO_PROFILE)
|
||||
);
|
||||
if(count($r)) {
|
||||
if($r) {
|
||||
$data = dbunescbin($r[0]['content']);
|
||||
$mimetype = $r[0]['mimetype'];
|
||||
}
|
||||
@ -79,7 +79,7 @@ class Photo extends \Zotlabs\Web\Controller {
|
||||
* Other photos
|
||||
*/
|
||||
|
||||
/* Check for a cookie to indicate display pixel density, in order to detect high-resolution
|
||||
/* Check for a cookie to indicate display pixel density, in order to detect high-resolution
|
||||
displays. This procedure was derived from the "Retina Images" by Jeremey Worboys,
|
||||
used in accordance with the Creative Commons Attribution 3.0 Unported License.
|
||||
Project link: https://github.com/Retina-Images/Retina-Images
|
||||
|
@ -23,12 +23,11 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
|
||||
/* @brief Initalize the profile-photo edit view
|
||||
*
|
||||
* @param $a Current application
|
||||
* @return void
|
||||
*
|
||||
*/
|
||||
|
||||
function init() {
|
||||
function init() {
|
||||
|
||||
if(! local_channel()) {
|
||||
return;
|
||||
@ -46,7 +45,7 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
*
|
||||
*/
|
||||
|
||||
function post() {
|
||||
function post() {
|
||||
|
||||
if(! local_channel()) {
|
||||
return;
|
||||
@ -54,24 +53,7 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
|
||||
check_form_security_token_redirectOnErr('/profile_photo', 'profile_photo');
|
||||
|
||||
if((x($_POST,'cropfinal')) && ($_POST['cropfinal'] == 1)) {
|
||||
|
||||
// unless proven otherwise
|
||||
$is_default_profile = 1;
|
||||
|
||||
if($_REQUEST['profile']) {
|
||||
$r = q("select id, profile_guid, is_default, gender from profile where id = %d and uid = %d limit 1",
|
||||
intval($_REQUEST['profile']),
|
||||
intval(local_channel())
|
||||
);
|
||||
if($r) {
|
||||
$profile = $r[0];
|
||||
if(! intval($profile['is_default']))
|
||||
$is_default_profile = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if((array_key_exists('postfinal',$_POST)) && (intval($_POST['cropfinal']) == 1)) {
|
||||
|
||||
// phase 2 - we have finished cropping
|
||||
|
||||
@ -86,7 +68,23 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
$scale = substr($image_id,-1,1);
|
||||
$image_id = substr($image_id,0,-2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// unless proven otherwise
|
||||
$is_default_profile = 1;
|
||||
|
||||
if($_REQUEST['profile']) {
|
||||
$r = q("select id, profile_guid, is_default, gender from profile where id = %d and uid = %d limit 1",
|
||||
intval($_REQUEST['profile']),
|
||||
intval(local_channel())
|
||||
);
|
||||
if($r) {
|
||||
$profile = $r[0];
|
||||
if(! intval($profile['is_default']))
|
||||
$is_default_profile = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$srcX = $_POST['xstart'];
|
||||
$srcY = $_POST['ystart'];
|
||||
@ -110,30 +108,38 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
|
||||
$aid = get_account_id();
|
||||
|
||||
$p = array('aid' => $aid, 'uid' => local_channel(), 'resource_id' => $base_image['resource_id'],
|
||||
'filename' => $base_image['filename'], 'album' => t('Profile Photos'));
|
||||
$p = [
|
||||
'aid' => $aid,
|
||||
'uid' => local_channel(),
|
||||
'resource_id' => $base_image['resource_id'],
|
||||
'filename' => $base_image['filename'],
|
||||
'album' => t('Profile Photos')
|
||||
];
|
||||
|
||||
$p['imgscale'] = 4;
|
||||
$p['imgscale'] = PHOTO_RES_PROFILE_300;
|
||||
$p['photo_usage'] = (($is_default_profile) ? PHOTO_PROFILE : PHOTO_NORMAL);
|
||||
|
||||
$r1 = $im->save($p);
|
||||
|
||||
$im->scaleImage(80);
|
||||
$p['imgscale'] = 5;
|
||||
$p['imgscale'] = PHOTO_RES_PROFILE_80;
|
||||
|
||||
$r2 = $im->save($p);
|
||||
|
||||
$im->scaleImage(48);
|
||||
$p['imgscale'] = 6;
|
||||
$p['imgscale'] = PHOTO_RES_PROFILE_48;
|
||||
|
||||
$r3 = $im->save($p);
|
||||
|
||||
if($r1 === false || $r2 === false || $r3 === false) {
|
||||
// if one failed, delete them all so we can start over.
|
||||
notice( t('Image resize failed.') . EOL );
|
||||
$x = q("delete from photo where resource_id = '%s' and uid = %d and imgscale >= 4 ",
|
||||
$x = q("delete from photo where resource_id = '%s' and uid = %d and imgscale in ( %d, %d, %d ) ",
|
||||
dbesc($base_image['resource_id']),
|
||||
local_channel()
|
||||
local_channel(),
|
||||
intval(PHOTO_RES_PROFILE_300),
|
||||
intval(PHOTO_RES_PROFILE_80),
|
||||
intval(PHOTO_RES_PROFILE_48)
|
||||
);
|
||||
return;
|
||||
}
|
||||
@ -183,10 +189,7 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
|
||||
// Now copy profile-permissions to pictures, to prevent privacyleaks by automatically created folder 'Profile Pictures'
|
||||
|
||||
profile_photo_set_profile_perms($_REQUEST['profile']);
|
||||
|
||||
|
||||
|
||||
profile_photo_set_profile_perms(local_channel(),$_REQUEST['profile']);
|
||||
}
|
||||
else
|
||||
notice( t('Unable to process image') . EOL);
|
||||
@ -196,7 +199,9 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
return; // NOTREACHED
|
||||
}
|
||||
|
||||
|
||||
// A new photo was uploaded. Store it and save some important details
|
||||
// in App::$data for use in the cropping function
|
||||
|
||||
|
||||
$hash = photo_new_resource();
|
||||
$smallest = 0;
|
||||
@ -220,7 +225,7 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
$os_storage = false;
|
||||
|
||||
foreach($i as $ii) {
|
||||
if(intval($ii['imgscale']) < 2) {
|
||||
if(intval($ii['imgscale']) < PHOTO_RES_640) {
|
||||
$smallest = intval($ii['imgscale']);
|
||||
$os_storage = intval($ii['os_storage']);
|
||||
$imagedata = $ii['content'];
|
||||
@ -238,7 +243,10 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
return $this->profile_photo_crop_ui_head($a, $ph, $hash, $smallest);
|
||||
|
||||
|
||||
// This will "fall through" to the get() method, and since
|
||||
// App::$data['imagecrop'] is set, it will proceed to cropping
|
||||
// rather than present the upload form
|
||||
}
|
||||
|
||||
|
||||
@ -269,11 +277,19 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
notice( t('Permission denied.') . EOL );
|
||||
return;
|
||||
};
|
||||
|
||||
// check_form_security_token_redirectOnErr('/profile_photo', 'profile_photo');
|
||||
|
||||
|
||||
$resource_id = argv(2);
|
||||
|
||||
// When using an existing photo, we don't have a dialogue to offer a choice of profiles,
|
||||
// so it gets attached to the default
|
||||
|
||||
$p = q("select id from profile where is_default = 1 and uid = %d",
|
||||
intval(local_channel())
|
||||
);
|
||||
if($p) {
|
||||
$_REQUEST['profile'] = $p[0]['id'];
|
||||
}
|
||||
|
||||
|
||||
$r = q("SELECT id, album, imgscale FROM photo WHERE uid = %d AND resource_id = '%s' ORDER BY imgscale ASC",
|
||||
intval(local_channel()),
|
||||
@ -285,11 +301,11 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
$havescale = false;
|
||||
foreach($r as $rr) {
|
||||
if($rr['imgscale'] == 5)
|
||||
if($rr['imgscale'] == PHOTO_RES_PROFILE_80)
|
||||
$havescale = true;
|
||||
}
|
||||
|
||||
// set an already loaded photo as profile photo
|
||||
// set an already loaded and cropped photo as profile photo
|
||||
|
||||
if(($r[0]['album'] == t('Profile Photos')) && ($havescale)) {
|
||||
// unset any existing profile photos
|
||||
@ -310,7 +326,7 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
dbesc($channel['xchan_hash'])
|
||||
);
|
||||
|
||||
profile_photo_set_profile_perms(); //Reset default photo permissions to public
|
||||
profile_photo_set_profile_perms(local_channel()); // Reset default photo permissions to public
|
||||
\Zotlabs\Daemon\Master::Summon(array('Directory',local_channel()));
|
||||
goaway(z_root() . '/profiles');
|
||||
}
|
||||
@ -342,17 +358,22 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
if($i) {
|
||||
$hash = $i[0]['resource_id'];
|
||||
foreach($i as $ii) {
|
||||
if(intval($ii['imgscale']) < 2) {
|
||||
if(intval($ii['imgscale']) < PHOTO_RES_640) {
|
||||
$smallest = intval($ii['imgscale']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
profile_photo_crop_ui_head($a, $ph, $hash, $smallest);
|
||||
$this->profile_photo_crop_ui_head($a, $ph, $hash, $smallest);
|
||||
|
||||
// falls through with App::$data['imagecrop'] set so we go straight to the cropping section
|
||||
}
|
||||
|
||||
$profiles = q("select id, profile_name as name, is_default from profile where uid = %d",
|
||||
|
||||
// present an upload form
|
||||
|
||||
$profiles = q("select id, profile_name as name, is_default from profile where uid = %d order by id asc",
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
@ -379,6 +400,9 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
return $o;
|
||||
}
|
||||
else {
|
||||
|
||||
// present a cropping form
|
||||
|
||||
$filename = \App::$data['imagecrop'] . '-' . \App::$data['imagecrop_resolution'];
|
||||
$resolution = \App::$data['imagecrop_resolution'];
|
||||
$tpl = get_markup_template("cropbody.tpl");
|
||||
@ -416,13 +440,13 @@ class Profile_photo extends \Zotlabs\Web\Controller {
|
||||
if($max_length > 0)
|
||||
$ph->scaleImage($max_length);
|
||||
|
||||
$width = $ph->getWidth();
|
||||
$height = $ph->getHeight();
|
||||
\App::$data['width'] = $ph->getWidth();
|
||||
\App::$data['height'] = $ph->getHeight();
|
||||
|
||||
if($width < 500 || $height < 500) {
|
||||
if(\App::$data['width'] < 500 || \App::$data['height'] < 500) {
|
||||
$ph->scaleImageUp(400);
|
||||
$width = $ph->getWidth();
|
||||
$height = $ph->getHeight();
|
||||
\App::$data['width'] = $ph->getWidth();
|
||||
\App::$data['height'] = $ph->getHeight();
|
||||
}
|
||||
|
||||
|
||||
|
@ -97,7 +97,7 @@ class Profperm extends \Zotlabs\Web\Controller {
|
||||
|
||||
//Time to update the permissions on the profile-pictures as well
|
||||
|
||||
profile_photo_set_profile_perms($profile['id']);
|
||||
profile_photo_set_profile_perms(local_channel(),$profile['id']);
|
||||
|
||||
$r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_channel = %d AND abook_profile = '%s'",
|
||||
intval(local_channel()),
|
||||
|
@ -27,28 +27,11 @@ class Siteinfo extends \Zotlabs\Web\Controller {
|
||||
else {
|
||||
$version = $commit = '';
|
||||
}
|
||||
$visible_plugins = array();
|
||||
if(is_array(\App::$plugins) && count(\App::$plugins)) {
|
||||
$r = q("select * from addon where hidden = 0");
|
||||
if(count($r))
|
||||
foreach($r as $rr)
|
||||
$visible_plugins[] = $rr['name'];
|
||||
}
|
||||
|
||||
$plugins_list = '';
|
||||
if(count($visible_plugins)) {
|
||||
$plugins_text = t('Installed plugins/addons/apps:');
|
||||
$sorted = $visible_plugins;
|
||||
$s = '';
|
||||
sort($sorted);
|
||||
foreach($sorted as $p) {
|
||||
if(strlen($p)) {
|
||||
if(strlen($s)) $s .= ', ';
|
||||
$s .= $p;
|
||||
}
|
||||
}
|
||||
$plugins_list .= $s;
|
||||
}
|
||||
|
||||
$plugins_list = implode(', ',visible_plugin_list());
|
||||
|
||||
if($plugins_list)
|
||||
$plugins_text = t('Installed plugins/addons/apps:');
|
||||
else
|
||||
$plugins_text = t('No installed plugins/addons/apps');
|
||||
|
||||
|
@ -26,7 +26,7 @@ class Thing extends \Zotlabs\Web\Controller {
|
||||
$verb = escape_tags($_REQUEST['verb']);
|
||||
$activity = intval($_REQUEST['activity']);
|
||||
$profile_guid = escape_tags($_REQUEST['profile_assign']);
|
||||
$url = $_REQUEST['link'];
|
||||
$url = $_REQUEST['url'];
|
||||
$photo = $_REQUEST['img'];
|
||||
|
||||
$hash = random_string();
|
||||
@ -235,7 +235,7 @@ class Thing extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
|
||||
|
||||
function get() {
|
||||
function get() {
|
||||
|
||||
// @FIXME one problem with things is we can't share them unless we provide the channel in the url
|
||||
// so we can definitively lookup the owner.
|
||||
|
@ -44,7 +44,7 @@ class Uexport extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
|
||||
function get() {
|
||||
function get() {
|
||||
|
||||
$y = datetime_convert('UTC',date_default_timezone_get(),'now','Y');
|
||||
|
||||
|
@ -136,6 +136,16 @@ class Wiki extends \Zotlabs\Web\Controller {
|
||||
// Render the Markdown-formatted page content in HTML
|
||||
require_once('library/markdown.php');
|
||||
|
||||
$wikiModalID = random_string(3);
|
||||
$wikiModal = replace_macros(
|
||||
get_markup_template('generic_modal.tpl'), array(
|
||||
'$id' => $wikiModalID,
|
||||
'$title' => t('Revision Comparison'),
|
||||
'$ok' => t('Revert'),
|
||||
'$cancel' => t('Cancel')
|
||||
)
|
||||
);
|
||||
|
||||
$o .= replace_macros(get_markup_template('wiki.tpl'),array(
|
||||
'$wikiheaderName' => $wikiheaderName,
|
||||
'$wikiheaderPage' => $wikiheaderPage,
|
||||
@ -157,7 +167,10 @@ class Wiki extends \Zotlabs\Web\Controller {
|
||||
'$pageName' => array('pageName', t('Enter the name of the new page:'), '', ''),
|
||||
'$pageRename' => array('pageRename', t('Enter the new name:'), '', ''),
|
||||
'$commitMsg' => array('commitMsg', '', '', '', '', 'placeholder="(optional) Enter a custom message when saving the page..."'),
|
||||
'$pageHistory' => $pageHistory['history']
|
||||
'$pageHistory' => $pageHistory['history'],
|
||||
'$wikiModal' => $wikiModal,
|
||||
'$wikiModalID' => $wikiModalID,
|
||||
'$commit' => 'HEAD'
|
||||
));
|
||||
head_add_js('library/ace/ace.js'); // Ace Code Editor
|
||||
return $o;
|
||||
@ -412,7 +425,7 @@ class Wiki extends \Zotlabs\Web\Controller {
|
||||
json_return_and_die(array('success' => false));
|
||||
}
|
||||
}
|
||||
$reverted = wiki_revert_page(array('commitHash' => $commitHash, 'observer' => \App::get_observer(), 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName));
|
||||
$reverted = wiki_revert_page(array('commitHash' => $commitHash, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName));
|
||||
if($reverted['success']) {
|
||||
json_return_and_die(array('content' => $reverted['content'], 'message' => '', 'success' => true));
|
||||
} else {
|
||||
@ -420,6 +433,32 @@ class Wiki extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
|
||||
// Compare page revisions
|
||||
if ((argc() === 4) && (argv(2) === 'compare') && (argv(3) === 'page')) {
|
||||
$resource_id = $_POST['resource_id'];
|
||||
$pageUrlName = $_POST['name'];
|
||||
$compareCommit = $_POST['compareCommit'];
|
||||
$currentCommit = $_POST['currentCommit'];
|
||||
// Determine if observer has permission to revert pages
|
||||
$nick = argv(1);
|
||||
$channel = get_channel_by_nick($nick);
|
||||
if (local_channel() !== intval($channel['channel_id'])) {
|
||||
$observer_hash = get_observer_hash();
|
||||
$perms = wiki_get_permissions($resource_id, intval($channel['channel_id']), $observer_hash);
|
||||
if(!$perms['read']) {
|
||||
logger('Wiki read permission denied.' . EOL);
|
||||
json_return_and_die(array('success' => false));
|
||||
}
|
||||
}
|
||||
$compare = wiki_compare_page(array('currentCommit' => $currentCommit, 'compareCommit' => $compareCommit, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName));
|
||||
if($compare['success']) {
|
||||
$diffHTML = '<table class="text-center" width="100%"><tr><td class="lead" width="50%">Current Revision</td><td class="lead" width="50%">Selected Revision</td></tr></table>' . $compare['diff'];
|
||||
json_return_and_die(array('diff' => $diffHTML, 'message' => '', 'success' => true));
|
||||
} else {
|
||||
json_return_and_die(array('diff' => '', 'message' => 'Error comparing page', 'success' => false));
|
||||
}
|
||||
}
|
||||
|
||||
// Rename a page
|
||||
if ((argc() === 4) && (argv(2) === 'rename') && (argv(3) === 'page')) {
|
||||
$resource_id = $_POST['resource_id'];
|
||||
|
738
Zotlabs/Storage/CalDAVClient.php
Normal file
738
Zotlabs/Storage/CalDAVClient.php
Normal file
@ -0,0 +1,738 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Storage;
|
||||
|
||||
// The Hubzilla CalDAV client will store calendar information in the 'cal' DB table.
|
||||
// Event information will remain in the 'event' table. In order to implement CalDAV on top of our
|
||||
// existing system, there is an event table column called vdata. This will hold the "one true record"
|
||||
// of the event in VCALENDAR format. When we receive a foreign event, we will pick out the fields
|
||||
// of this entry that are important to us and use it to populate the other event table fields.
|
||||
// When we make an event change, it is required that we load this entry as a vobject, make the changes on the
|
||||
// vobject, and then store the result back in event.vdata. This will preserve foreign keys which we
|
||||
// know nothing about. Then we sync this back to the DAV server.
|
||||
|
||||
// We still need a DB update to create a 'cal' table entry for our existing events and link these together.
|
||||
// I'm currently anticipating separating tasks/to-do items from events, so each new account wil get two default calendars.
|
||||
|
||||
// We will eventually provide for magic-auth or cookie login of the CURL process so we won't be required to
|
||||
// store our hubzilla password. Currently for testing we are using HTTP BASIC-AUTH and must initialise the
|
||||
// username/password correctly to make the connection.
|
||||
|
||||
// Repeating events will be awkward because every instance has the same UUID. This would make it difficult to
|
||||
// search for upcoming events if the initial instance was created (for instance) a few years ago. So the current plan is
|
||||
// to create event instances for a prescribed time limit from now (perhaps 5-10 years for annual events).
|
||||
// This plan may change. The repurcussions of this decision mean that an edit to a recurring event must
|
||||
// edit all existing instances of the event, and only one unique instance can be used for sync.
|
||||
// Sabre vobject provides a function to automatically expand recurring events into individual event instances.
|
||||
|
||||
|
||||
|
||||
class CalDAVClient {
|
||||
|
||||
private $username;
|
||||
private $password;
|
||||
|
||||
private $url;
|
||||
|
||||
public $filepos = 0;
|
||||
public $request_data = '';
|
||||
|
||||
function __construct($user,$pass,$url) {
|
||||
$this->username = $user;
|
||||
$this->password = $pass;
|
||||
$this->url = $url;
|
||||
|
||||
}
|
||||
|
||||
private function set_data($s) {
|
||||
$this->request_data = $s;
|
||||
$this->filepos = 0;
|
||||
}
|
||||
|
||||
public function curl_read($ch,$fh,$size) {
|
||||
|
||||
if($this->filepos < 0) {
|
||||
unset($fh);
|
||||
return '';
|
||||
}
|
||||
|
||||
$s = substr($this->request_data,$this->filepos,$size);
|
||||
|
||||
if(strlen($s) < $size)
|
||||
$this->filepos = (-1);
|
||||
else
|
||||
$this->filepos = $this->filepos + $size;
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
function ctag_fetch() {
|
||||
$headers = [ 'Depth: 0', 'Prefer: return-minimal', 'Content-Type: application/xml; charset=utf-8'];
|
||||
|
||||
// recommended ctag fetch by sabre
|
||||
|
||||
$this->set_data('<?xml version="1.0"?>
|
||||
<d:propfind xmlns:d="DAV:" xmlns:cs="http://calendarserver.org/ns/">
|
||||
<d:prop>
|
||||
<d:displayname />
|
||||
<cs:getctag />
|
||||
<d:sync-token />
|
||||
</d:prop>
|
||||
</d:propfind>');
|
||||
|
||||
// thunderbird uses this - it's a bit more verbose on what capabilities
|
||||
// are provided by the server
|
||||
|
||||
$this->set_data('<?xml version="1.0" encoding="UTF-8"?>
|
||||
<D:propfind xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/" xmlns:C="urn:ietf:params:xml:ns:caldav">
|
||||
<D:prop>
|
||||
<D:resourcetype/>
|
||||
<D:owner/>
|
||||
<D:current-user-principal/>
|
||||
<D:supported-report-set/>
|
||||
<C:supported-calendar-component-set/>
|
||||
<CS:getctag/>
|
||||
</D:prop>
|
||||
</D:propfind>');
|
||||
|
||||
|
||||
|
||||
$auth = $this->username . ':' . $this->password;
|
||||
|
||||
$recurse = 0;
|
||||
|
||||
$x = z_fetch_url($this->url,true,$recurse,
|
||||
[ 'headers' => $headers,
|
||||
'http_auth' => $auth,
|
||||
'custom' => 'PROPFIND',
|
||||
'upload' => true,
|
||||
'infile' => 3,
|
||||
'infilesize' => strlen($this->request_data),
|
||||
'readfunc' => [ $this, 'curl_read' ]
|
||||
]);
|
||||
|
||||
return $x;
|
||||
|
||||
}
|
||||
|
||||
|
||||
function detail_fetch() {
|
||||
$headers = [ 'Depth: 1', 'Prefer: return-minimal', 'Content-Type: application/xml; charset=utf-8'];
|
||||
|
||||
// this query should return all objects in the given calendar, you can filter it appropriately
|
||||
// using filter options
|
||||
|
||||
$this->set_data('<?xml version="1.0"?>
|
||||
<c:calendar-query xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:cs="http://calendarserver.org/ns/">
|
||||
<d:prop>
|
||||
<d:getetag />
|
||||
<c:calendar-data />
|
||||
</d:prop>
|
||||
<c:filter>
|
||||
<c:comp-filter name="VCALENDAR" />
|
||||
</c:filter>
|
||||
</c:calendar-query>');
|
||||
|
||||
$auth = $this->username . ':' . $this->password;
|
||||
|
||||
$recurse = 0;
|
||||
$x = z_fetch_url($this->url,true,$recurse,
|
||||
[ 'headers' => $headers,
|
||||
'http_auth' => $auth,
|
||||
'custom' => 'REPORT',
|
||||
'upload' => true,
|
||||
'infile' => 3,
|
||||
'infilesize' => strlen($this->request_data),
|
||||
'readfunc' => [ $this, 'curl_read' ]
|
||||
]);
|
||||
|
||||
|
||||
return $x;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
PROPFIND /calendars/johndoe/home/ HTTP/1.1
|
||||
Depth: 0
|
||||
Prefer: return-minimal
|
||||
Content-Type: application/xml; charset=utf-8
|
||||
|
||||
<d:propfind xmlns:d="DAV:" xmlns:cs="http://calendarserver.org/ns/">
|
||||
<d:prop>
|
||||
<d:displayname />
|
||||
<cs:getctag />
|
||||
</d:prop>
|
||||
</d:propfind>
|
||||
|
||||
// Responses: success
|
||||
|
||||
HTTP/1.1 207 Multi-status
|
||||
Content-Type: application/xml; charset=utf-8
|
||||
|
||||
<d:multistatus xmlns:d="DAV:" xmlns:cs="http://calendarserver.org/ns/">
|
||||
<d:response>
|
||||
<d:href>/calendars/johndoe/home/</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:displayname>Home calendar</d:displayname>
|
||||
<cs:getctag>3145</cs:getctag>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
</d:multistatus>
|
||||
|
||||
// Responses: fail
|
||||
|
||||
HTTP/1.1 207 Multi-status
|
||||
Content-Type: application/xml; charset=utf-8
|
||||
|
||||
<d:multistatus xmlns:d="DAV:" xmlns:cs="http://calendarserver.org/ns/">
|
||||
<d:response>
|
||||
<d:href>/calendars/johndoe/home/</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:displayname />
|
||||
<cs:getctag />
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 403 Forbidden</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
</d:multistatus>
|
||||
|
||||
|
||||
// sample request body in DOM
|
||||
// prepare request body
|
||||
$doc = new DOMDocument('1.0', 'utf-8');
|
||||
$doc->formatOutput = true;
|
||||
|
||||
$query = $doc->createElement('c:calendar-query');
|
||||
$query->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:c', 'urn:ietf:params:xml:ns:caldav');
|
||||
$query->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:d', 'DAV:');
|
||||
|
||||
$prop = $doc->createElement('d:prop');
|
||||
$prop->appendChild($doc->createElement('d:getetag'));
|
||||
$prop->appendChild($doc->createElement('c:calendar-data'));
|
||||
$query->appendChild($prop);
|
||||
$doc->appendChild($query);
|
||||
$body = $doc->saveXML();
|
||||
|
||||
echo "Body: " . $body . "<br>";
|
||||
|
||||
|
||||
Now we download every single object in this calendar. To do this, we use a REPORT method.
|
||||
|
||||
REPORT /calendars/johndoe/home/ HTTP/1.1
|
||||
Depth: 1
|
||||
Prefer: return-minimal
|
||||
Content-Type: application/xml; charset=utf-8
|
||||
|
||||
<c:calendar-query xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">
|
||||
<d:prop>
|
||||
<d:getetag />
|
||||
<c:calendar-data />
|
||||
</d:prop>
|
||||
<c:filter>
|
||||
<c:comp-filter name="VCALENDAR" />
|
||||
</c:filter>
|
||||
</c:calendar-query>
|
||||
|
||||
This request will give us every object that's a VCALENDAR object, and its etag.
|
||||
|
||||
If you're only interested in VTODO (because you're writing a todo app) you can also filter for just those:
|
||||
|
||||
REPORT /calendars/johndoe/home/ HTTP/1.1
|
||||
Depth: 1
|
||||
Prefer: return-minimal
|
||||
Content-Type: application/xml; charset=utf-8
|
||||
|
||||
<c:calendar-query xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">
|
||||
<d:prop>
|
||||
<d:getetag />
|
||||
<c:calendar-data />
|
||||
</d:prop>
|
||||
<c:filter>
|
||||
<c:comp-filter name="VCALENDAR">
|
||||
<c:comp-filter name="VTODO" />
|
||||
</c:comp-filter>
|
||||
</c:filter>
|
||||
</c:calendar-query>
|
||||
|
||||
Similarly it's also possible to filter to just events, or only get events within a specific time-range.
|
||||
|
||||
This report will return a multi-status object again:
|
||||
|
||||
HTTP/1.1 207 Multi-status
|
||||
Content-Type: application/xml; charset=utf-8
|
||||
|
||||
<d:multistatus xmlns:d="DAV:" xmlns:cs="http://calendarserver.org/ns/">
|
||||
<d:response>
|
||||
<d:href>/calendars/johndoe/home/132456762153245.ics</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:getetag>"2134-314"</d:getetag>
|
||||
<c:calendar-data>BEGIN:VCALENDAR
|
||||
VERSION:2.0
|
||||
CALSCALE:GREGORIAN
|
||||
BEGIN:VTODO
|
||||
UID:132456762153245
|
||||
SUMMARY:Do the dishes
|
||||
DUE:20121028T115600Z
|
||||
END:VTODO
|
||||
END:VCALENDAR
|
||||
</c:calendar-data>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
<d:response>
|
||||
<d:href>/calendars/johndoe/home/132456-34365.ics</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:getetag>"5467-323"</d:getetag>
|
||||
<c:calendar-data>BEGIN:VCALENDAR
|
||||
VERSION:2.0
|
||||
CALSCALE:GREGORIAN
|
||||
BEGIN:VEVENT
|
||||
UID:132456-34365
|
||||
SUMMARY:Weekly meeting
|
||||
DTSTART:20120101T120000
|
||||
DURATION:PT1H
|
||||
RRULE:FREQ=WEEKLY
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
||||
</c:calendar-data>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
</d:multistatus>
|
||||
|
||||
This calendar only contained 2 objects. A todo and a weekly event.
|
||||
|
||||
So after you retrieved and processed these, for each object you must retain:
|
||||
|
||||
The calendar data itself
|
||||
The url
|
||||
The etag
|
||||
|
||||
In this case all urls ended with .ics. This is often the case, but you must not rely on this. In this case the UID in the calendar object was also identical to a part of the url. This too is often the case, but again not something you can rely on, so don't make any assumptions.
|
||||
|
||||
The url and the UID have no meaningful relationship, so treat both those items as separate unique identifiers.
|
||||
Finding out if anything changed
|
||||
|
||||
To see if anything in a calendar changed, we simply request the ctag again on the calendar. If the ctag did not change, you still have the latest copy.
|
||||
|
||||
If it did change, you must request all the etags in the entire calendar again:
|
||||
|
||||
REPORT /calendars/johndoe/home/ HTTP/1.1
|
||||
Depth: 1
|
||||
Prefer: return-minimal
|
||||
Content-Type: application/xml; charset=utf-8
|
||||
|
||||
<c:calendar-query xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">
|
||||
<d:prop>
|
||||
<d:getetag />
|
||||
</d:prop>
|
||||
<c:filter>
|
||||
<c:comp-filter name="VCALENDAR">
|
||||
<c:comp-filter name="VTODO" />
|
||||
</c:comp-filter>
|
||||
</c:filter>
|
||||
</c:calendar-query>
|
||||
|
||||
Note that this last request is extremely similar to a previous one, but we are only asking fo the etag, not the calendar-data.
|
||||
|
||||
The reason for this, is that calendars can be rather huge. It will save a TON of bandwidth to only check the etag first.
|
||||
|
||||
HTTP/1.1 207 Multi-status
|
||||
Content-Type: application/xml; charset=utf-8
|
||||
|
||||
<d:multistatus xmlns:d="DAV:" xmlns:cs="http://calendarserver.org/ns/">
|
||||
<d:response>
|
||||
<d:href>/calendars/johndoe/home/132456762153245.ics</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:getetag>"xxxx-xxx"</d:getetag>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
<d:response>
|
||||
<d:href>/calendars/johndoe/home/fancy-caldav-client-1234253678.ics</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:getetag>"5-12"</d:getetag>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
</d:multistatus>
|
||||
|
||||
Judging from this last request, 3 things have changed:
|
||||
|
||||
The etag for the task has changed, so the contents must be different
|
||||
There's a new url, some other client must have added an object
|
||||
One object is missing, something must have deleted it.
|
||||
|
||||
So based on those 3 items we know that we need to delete an object from our local list, and fetch the contents for the new item, and the updated one.
|
||||
|
||||
To fetch the data for these, you can simply issue GET requests:
|
||||
|
||||
GET /calendars/johndoe/home/132456762153245.ics HTTP/1.1
|
||||
|
||||
But, because in a worst-case scenario this could result in a LOT of GET requests we can do a 'multiget'.
|
||||
|
||||
REPORT /calendars/johndoe/home/ HTTP/1.1
|
||||
Depth: 1
|
||||
Prefer: return-minimal
|
||||
Content-Type: application/xml; charset=utf-8
|
||||
|
||||
<c:calendar-multiget xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">
|
||||
<d:prop>
|
||||
<d:getetag />
|
||||
<c:calendar-data />
|
||||
</d:prop>
|
||||
<d:href>/calendars/johndoe/home/132456762153245.ics</d:href>
|
||||
<d:href>/calendars/johndoe/home/fancy-caldav-client-1234253678.ics</d:href>
|
||||
</c:calendar-multiget>
|
||||
|
||||
This request will simply return a multi-status again with the calendar-data and etag.
|
||||
A small note about application design
|
||||
|
||||
If you read this far and understood what's been said, you may have realized that it's a bit cumbersome to have a separate step for the initial sync, and subsequent updates.
|
||||
|
||||
It would totally be possible to skip the 'initial sync', and just use calendar-query and calendar-multiget REPORTS for the initial sync as well.
|
||||
Updating a calendar object
|
||||
|
||||
Updating a calendar object is rather simple:
|
||||
|
||||
PUT /calendars/johndoe/home/132456762153245.ics HTTP/1.1
|
||||
Content-Type: text/calendar; charset=utf-8
|
||||
If-Match: "2134-314"
|
||||
|
||||
BEGIN:VCALENDAR
|
||||
....
|
||||
END:VCALENDAR
|
||||
|
||||
A response to this will be something like this:
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
ETag: "2134-315"
|
||||
|
||||
The update gave us back the new ETag. SabreDAV gives this ETag on updates back most of the time, but not always.
|
||||
|
||||
There are cases where the caldav server must modify the iCalendar object right after storage. In those cases an ETag will not be returned, and you should issue a GET request immediately to get the correct object.
|
||||
|
||||
A few notes:
|
||||
|
||||
You must not change the UID of the original object
|
||||
Every object should hold only 1 event or task.
|
||||
You cannot change an VEVENT into a VTODO.
|
||||
|
||||
Creating a calendar object
|
||||
|
||||
Creating a calendar object is almost identical, except that you don't have a url yet to a calendar object.
|
||||
|
||||
Instead, it is up to you to determine the new url.
|
||||
|
||||
PUT /calendars/johndoe/home/somerandomstring.ics HTTP/1.1
|
||||
Content-Type: text/calendar; charset=utf-8
|
||||
|
||||
BEGIN:VCALENDAR
|
||||
....
|
||||
END:VCALENDAR
|
||||
|
||||
A response to this will be something like this:
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
ETag: "21345-324"
|
||||
|
||||
Similar to updating, an ETag is often returned, but there are cases where this is not true.
|
||||
Deleting a calendar object
|
||||
|
||||
Deleting is simple enough:
|
||||
|
||||
DELETE /calendars/johndoe/home/132456762153245.ics HTTP/1.1
|
||||
If-Match: "2134-314"
|
||||
|
||||
Speeding up Sync with WebDAV-Sync
|
||||
|
||||
WebDAV-Sync is a protocol extension that is defined in rfc6578. Because this extension was defined later, some servers may not support this yet.
|
||||
|
||||
SabreDAV supports this since 2.0.
|
||||
|
||||
WebDAV-Sync allows a client to ask just for calendars that have changed. The process on a high-level is as follows:
|
||||
|
||||
Client requests sync-token from server.
|
||||
Server reports token 15.
|
||||
Some time passes.
|
||||
Client does a Sync REPORT on an calendar, and supplied token 15.
|
||||
Server returns vcard urls that have changed or have been deleted and returns token 17.
|
||||
|
||||
As you can see, after the initial sync, only items that have been created, modified or deleted will ever be sent.
|
||||
|
||||
This has a lot of advantages. The transmitted xml bodies can generally be a lot shorter, and is also easier on both client and server in terms of memory and CPU usage, because only a limited set of items will have to be compared.
|
||||
|
||||
It's important to note, that a client should only do Sync operations, if the server reports that it has support for it. The quickest way to do so, is to request {DAV}sync-token on the calendar you wish to sync.
|
||||
|
||||
Technically, a server may support 'sync' on one calendar, and it may not support it on another, although this is probably rare.
|
||||
Getting the first sync-token
|
||||
|
||||
Initially, we just request a sync token when asking for calendar information:
|
||||
|
||||
PROPFIND /calendars/johndoe/home/ HTTP/1.1
|
||||
Depth: 0
|
||||
Content-Type: application/xml; charset=utf-8
|
||||
|
||||
<d:propfind xmlns:d="DAV:" xmlns:cs="http://calendarserver.org/ns/">
|
||||
<d:prop>
|
||||
<d:displayname />
|
||||
<cs:getctag />
|
||||
<d:sync-token />
|
||||
</d:prop>
|
||||
</d:propfind>
|
||||
|
||||
This would return something as follows:
|
||||
|
||||
<d:multistatus xmlns:d="DAV:" xmlns:cs="http://calendarserver.org/ns/">
|
||||
<d:response>
|
||||
<d:href>/calendars/johndoe/home/</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:displayname>My calendar</d:displayname>
|
||||
<cs:getctag>3145</cs:getctag>
|
||||
<d:sync-token>http://sabredav.org/ns/sync-token/3145</d:sync-token>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
</d:multistatus>
|
||||
|
||||
As you can see, the sync-token is a url. It always should be a url. Even though a number appears in the url, you are not allowed to attach any meaning to that url. Some servers may have use an increasing number, another server may use a completely random string.
|
||||
Receiving changes
|
||||
|
||||
After a sync token has been obtained, and the client already has the initial copy of the calendar, the client is able to request all changes since the token was issued.
|
||||
|
||||
This is done with a REPORT request that may look like this:
|
||||
|
||||
REPORT /calendars/johndoe/home/ HTTP/1.1
|
||||
Host: dav.example.org
|
||||
Content-Type: application/xml; charset="utf-8"
|
||||
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<d:sync-collection xmlns:d="DAV:">
|
||||
<d:sync-token>http://sabredav.org/ns/sync/3145</d:sync-token>
|
||||
<d:sync-level>1</d:sync-level>
|
||||
<d:prop>
|
||||
<d:getetag/>
|
||||
</d:prop>
|
||||
</d:sync-collection>
|
||||
|
||||
This requests all the changes since sync-token identified by http://sabredav.org/ns/sync/3145, and for the calendar objects that have been added or modified, we're requesting the etag.
|
||||
|
||||
The response to a query like this is another multistatus xml body. Example:
|
||||
|
||||
HTTP/1.1 207 Multi-Status
|
||||
Content-Type: application/xml; charset="utf-8"
|
||||
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<d:multistatus xmlns:d="DAV:">
|
||||
<d:response>
|
||||
<d:href>/calendars/johndoe/home/newevent.ics</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:getetag>"33441-34321"</d:getetag>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
<d:response>
|
||||
<d:href>/calendars/johndoe/home/updatedevent.ics</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:getetag>"33541-34696"</d:getetag>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
<d:response>
|
||||
<d:href>/calendars/johndoe/home/deletedevent.ics</d:href>
|
||||
<d:status>HTTP/1.1 404 Not Found</d:status>
|
||||
</d:response>
|
||||
<d:sync-token>http://sabredav.org/ns/sync/5001</d:sync-token>
|
||||
</d:multistatus>
|
||||
|
||||
The last response reported two changes: newevent.ics and updatedevent.ics. There's no way to tell from the response wether those cards got created or updated, you, as a client can only infer this based on the vcards you are already aware of.
|
||||
|
||||
The entry with name deletedevent.ics got deleted as indicated by the 404 status. Note that the status element is here a child of d:response when in all previous examples it has been a child of d:propstat.
|
||||
|
||||
The other difference with the other multi-status examples, is that this one has a sync-token element with the latest sync-token.
|
||||
Caveats
|
||||
|
||||
Note that a server is free to 'forget' any sync-tokens that have been previously issued. In this case it may be needed to do a full-sync again.
|
||||
|
||||
In case the supplied sync-token is not recognized by the server, a HTTP error is emitted. SabreDAV emits a 403.
|
||||
Discovery
|
||||
|
||||
Ideally you will want to make sure that all the calendars in an account are automatically discovered. The best user interface would be to just have to ask for three items:
|
||||
|
||||
Username
|
||||
Password
|
||||
Server
|
||||
|
||||
And the server should be as short as possible. This is possible with most servers.
|
||||
|
||||
If, for example a user specified 'dav.example.org' for the server, the first thing you should do is attempt to send a PROPFIND request to https://dav.example.org/. Note that you SHOULD try the https url before the http url.
|
||||
|
||||
This PROPFIND request looks as follows:
|
||||
|
||||
PROPFIND / HTTP/1.1
|
||||
Depth: 0
|
||||
Prefer: return-minimal
|
||||
Content-Type: application/xml; charset=utf-8
|
||||
|
||||
<d:propfind xmlns:d="DAV:">
|
||||
<d:prop>
|
||||
<d:current-user-principal />
|
||||
</d:prop>
|
||||
</d:propfind>
|
||||
|
||||
This will return a response such as the following:
|
||||
|
||||
HTTP/1.1 207 Multi-status
|
||||
Content-Type: application/xml; charset=utf-8
|
||||
|
||||
<d:multistatus xmlns:d="DAV:" xmlns:cs="http://calendarserver.org/ns/">
|
||||
<d:response>
|
||||
<d:href>/</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:current-user-principal>
|
||||
<d:href>/principals/users/johndoe/</d:href>
|
||||
</d:current-user-principal>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
</d:multistatus>
|
||||
|
||||
A 'principal' is a user. The url that's being returned, is a url that refers to the current user. On this url you can request additional information about the user.
|
||||
|
||||
What we need from this url, is their 'calendar home'. The calendar home is a collection that contains all of the users' calendars.
|
||||
|
||||
To request that, issue the following request:
|
||||
|
||||
PROPFIND /principals/users/johndoe/ HTTP/1.1
|
||||
Depth: 0
|
||||
Prefer: return-minimal
|
||||
Content-Type: application/xml; charset=utf-8
|
||||
|
||||
<d:propfind xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">
|
||||
<d:prop>
|
||||
<c:calendar-home-set />
|
||||
</d:prop>
|
||||
</d:propfind>
|
||||
|
||||
This will return a response such as the following:
|
||||
|
||||
HTTP/1.1 207 Multi-status
|
||||
Content-Type: application/xml; charset=utf-8
|
||||
|
||||
<d:multistatus xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">
|
||||
<d:response>
|
||||
<d:href>/principals/users/johndoe/</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<c:calendar-home-set>
|
||||
<d:href>/calendars/johndoe/</d:href>
|
||||
</c:calendar-home-set>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
</d:multistatus>
|
||||
|
||||
Lastly, to list all the calendars for the user, issue a PROPFIND request with Depth: 1.
|
||||
|
||||
PROPFIND /calendars/johndoe/ HTTP/1.1
|
||||
Depth: 1
|
||||
Prefer: return-minimal
|
||||
Content-Type: application/xml; charset=utf-8
|
||||
|
||||
<d:propfind xmlns:d="DAV:" xmlns:cs="http://calendarserver.org/ns/" xmlns:c="urn:ietf:params:xml:ns:caldav">
|
||||
<d:prop>
|
||||
<d:resourcetype />
|
||||
<d:displayname />
|
||||
<cs:getctag />
|
||||
<c:supported-calendar-component-set />
|
||||
</d:prop>
|
||||
</d:propfind>
|
||||
|
||||
In that last request, we asked for 4 properties.
|
||||
|
||||
The resourcetype tells us what type of object we're getting back. You must read out the resourcetype and ensure that it contains at least a calendar element in the CalDAV namespace. Other items may be returned, including non- calendar, which your application should ignore.
|
||||
|
||||
The displayname is a human-readable string for the calendarname, the ctag was already covered in an earlier section.
|
||||
|
||||
Lastly, supported-calendar-component-set. This gives us a list of components that the calendar accepts. This could be just VTODO, VEVENT, VJOURNAL or a combination of these three.
|
||||
|
||||
If you are just creating a todo-list application, this means you should only list the calendars that support the VTODO component.
|
||||
|
||||
HTTP/1.1 207 Multi-status
|
||||
Content-Type: application/xml; charset=utf-8
|
||||
|
||||
<d:multistatus xmlns:d="DAV:" xmlns:cs="http://calendarserver.org/ns/" xmlns:c="urn:ietf:params:xml:ns:caldav">
|
||||
<d:response>
|
||||
<d:href>/calendars/johndoe/</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:resourcetype>
|
||||
<d:collection/>
|
||||
</d:resourcetype>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
<d:response>
|
||||
<d:href>/calendars/johndoe/home/</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:resourcetype>
|
||||
<d:collection/>
|
||||
<c:calendar/>
|
||||
</d:resourcetype>
|
||||
<d:displayname>Home calendar</d:displayname>
|
||||
<cs:getctag>3145</cs:getctag>
|
||||
<c:supported-calendar-component-set>
|
||||
<c:comp name="VEVENT" />
|
||||
</c:supported-calendar-component-set>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
<d:response>
|
||||
<d:href>/calendars/johndoe/tasks/</d:href>
|
||||
<d:propstat>
|
||||
<d:prop>
|
||||
<d:resourcetype>
|
||||
<d:collection/>
|
||||
<c:calendar/>
|
||||
</d:resourcetype>
|
||||
<d:displayname>My TODO list</d:displayname>
|
||||
<cs:getctag>3345</cs:getctag>
|
||||
<c:supported-calendar-component-set>
|
||||
<c:comp name="VTODO" />
|
||||
</c:supported-calendar-component-set>
|
||||
</d:prop>
|
||||
<d:status>HTTP/1.1 200 OK</d:status>
|
||||
</d:propstat>
|
||||
</d:response>
|
||||
</d:multistatus>
|
||||
*/
|
@ -21,6 +21,9 @@ class CheckJS {
|
||||
$page = urlencode(\App::$query_string);
|
||||
|
||||
if($test) {
|
||||
self::$jsdisabled = 1;
|
||||
if(array_key_exists('jsdisabled',$_COOKIE))
|
||||
self::$jsdisabled = $_COOKIE['jsdisabled'];
|
||||
|
||||
if(! array_key_exists('jsdisabled',$_COOKIE)) {
|
||||
\App::$page['htmlhead'] .= "\r\n" . '<script>document.cookie="jsdisabled=0; path=/"; var jsMatch = /\&jsdisabled=0/; if (!jsMatch.exec(location.href)) { location.href = "' . z_root() . '/nojs/0?f=&redir=' . $page . '" ; }</script>' . "\r\n";
|
||||
|
12
boot.php
12
boot.php
@ -34,7 +34,6 @@ require_once('include/text.php');
|
||||
require_once('include/datetime.php');
|
||||
require_once('include/language.php');
|
||||
require_once('include/nav.php');
|
||||
require_once('include/cache.php');
|
||||
require_once('include/permissions.php');
|
||||
require_once('library/Mobile_Detect/Mobile_Detect.php');
|
||||
require_once('include/features.php');
|
||||
@ -46,9 +45,9 @@ require_once('include/account.php');
|
||||
|
||||
define ( 'PLATFORM_NAME', 'hubzilla' );
|
||||
define ( 'STD_VERSION', '1.9' );
|
||||
define ( 'ZOT_REVISION', 1.1 );
|
||||
define ( 'ZOT_REVISION', '1.1' );
|
||||
|
||||
define ( 'DB_UPDATE_VERSION', 1177 );
|
||||
define ( 'DB_UPDATE_VERSION', 1179 );
|
||||
|
||||
|
||||
/**
|
||||
@ -771,6 +770,7 @@ class App {
|
||||
public static $groups;
|
||||
public static $language;
|
||||
public static $langsave;
|
||||
public static $rtl = false;
|
||||
public static $plugins_admin;
|
||||
public static $module_loaded = false;
|
||||
public static $query_string;
|
||||
@ -2282,6 +2282,12 @@ function construct_page(&$a) {
|
||||
$page = App::$page;
|
||||
$profile = App::$profile;
|
||||
|
||||
// There's some experimental support for right-to-left text in the view/php/default.php page template.
|
||||
// In v1.9 we started providing direction preference in the per language hstrings.php file
|
||||
// This requires somebody with fluency in a RTL language to make happen
|
||||
|
||||
$page['direction'] = 0; // ((App::$rtl) ? 1 : 0);
|
||||
|
||||
header("Content-type: text/html; charset=utf-8");
|
||||
|
||||
// security headers - see https://securityheaders.io
|
||||
|
@ -14,6 +14,7 @@
|
||||
<li>[img float=right]https://zothub.com/images/default_profile_photos/rainbow_man/48.jpg[/img] <img src="https://zothub.com/images/default_profile_photos/rainbow_man/48.jpg" style="float:right;" alt="Image/photo" /><br />
|
||||
<div style="clear:both;"></div>
|
||||
<li>[code]code[/code] <code>code</code><br />
|
||||
<li>[code=xxx]syntax highlighted code[/code] <code>supported languages php, css, mysql, sql, abap, diff, html, perl, ruby, vbscript, avrc, dtd, java, xml, cpp, python, javascript, js, json, sh</code><br />
|
||||
<li>[quote]quote[/quote] <blockquote>quote</blockquote><br />
|
||||
<li>[quote=Author]Author? Me? No, no, no...[/quote] <br /><strong class="author">Author wrote:</strong><blockquote>Author? Me? No, no, no...</blockquote><br />
|
||||
<li> [nobb] may be used to escape bbcode.</ul><br />
|
||||
@ -83,7 +84,7 @@ or<br /><br />[dl terms="b"]<br />[*= First element term] First element descript
|
||||
<li>[spoiler] for hiding spoilers<br /><br /></li>
|
||||
|
||||
<li>[rpost=title]Text to post[/rpost] The observer will be returned to their home hub to enter a post with the specified title and body. Both are optional</li>
|
||||
<li>[qr]text to post[/qr] - create a QR code.</li>
|
||||
<li>[qr]text to post[/qr] - create a QR code (if the qrator plugin is installed).</li>
|
||||
<li>[toc] - create a table of content in a webpage. Please refer to the <a href="http://ndabas.github.io/toc/" target="_blank">original jquery toc</a> to get more explanations.
|
||||
<ul>
|
||||
<li>Optional param: 'data-toc'. If ommited the default is 'body'</li>
|
||||
|
@ -1,6 +1,7 @@
|
||||
[h2]Database Tables[/h2]
|
||||
[table]
|
||||
[tr][th]Table[/th][th]Description[/th][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_abconfig]abconfig[/zrl][/td][td]arbitrary storage for connections of local channels[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_abook]abook[/zrl][/td][td]connections of local channels[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_account]account[/zrl][/td][td]service provider account[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_addon]addon[/zrl][/td][td]registered plugins[/td][/tr]
|
||||
@ -8,6 +9,7 @@
|
||||
[tr][td][zrl=[baseurl]/help/database/db_attach]attach[/zrl][/td][td]file attachments[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_auth_codes]auth_codes[/zrl][/td][td]OAuth usage[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_cache]cache[/zrl][/td][td]OEmbed cache[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_cal]cal[/zrl][/td][td]CalDAV containers for events[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_channel]channel[/zrl][/td][td]local channels[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_chat]chat[/zrl][/td][td]chat room content[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_chatpresence]chatpresence[/zrl][/td][td]channel presence information for chat[/td][/tr]
|
||||
@ -16,17 +18,14 @@
|
||||
[tr][td][zrl=[baseurl]/help/database/db_config]config[/zrl][/td][td]main configuration storage[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_conv]conv[/zrl][/td][td]Diaspora private messages meta conversation structure[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_event]event[/zrl][/td][td]Events[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_fcontact]fcontact[/zrl][/td][td]friend suggestion stuff (obsolete)[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_ffinder]ffinder[/zrl][/td][td]friend suggestion stuff (obsolete)[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_fserver]fserver[/zrl][/td][td]obsolete[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_fsuggest]fsuggest[/zrl][/td][td]friend suggestion stuff (unused)[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_group_member]group_member[/zrl][/td][td]privacy groups (collections), group info[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_groups]groups[/zrl][/td][td]privacy groups (collections), member info[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_hook]hook[/zrl][/td][td]plugin hook registry[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_hubloc]hubloc[/zrl][/td][td]xchan location storage, ties a hub location to an xchan[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_iconfig]iconfig[/zrl][/td][td]extensible arbitrary storage for items[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_issue]issue[/zrl][/td][td]future bug/issue database[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_item]item[/zrl][/td][td]all posts and webpages[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_item_id]item_id[/zrl][/td][td]other identifiers on other services for posts[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_item_id]item_id[/zrl][/td][td](deprecated by iconfig) other identifiers on other services for posts[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_likes]likes[/zrl][/td][td]likes of 'things'[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_mail]mail[/zrl][/td][td]private messages[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_menu]menu[/zrl][/td][td]webpage menu data[/td][/tr]
|
||||
@ -48,7 +47,6 @@
|
||||
[tr][td][zrl=[baseurl]/help/database/db_sign]sign[/zrl][/td][td]Diaspora signatures. To be phased out.[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_site]site[/zrl][/td][td]site table to find directory peers[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_source]source[/zrl][/td][td]channel sources data[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_spam]spam[/zrl][/td][td]unfinished[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_sys_perms]sys_perms[/zrl][/td][td]extensible permissions for OAuth[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_term]term[/zrl][/td][td]item taxonomy (categories, tags, etc.) table[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_tokens]tokens[/zrl][/td][td]OAuth usage[/td][/tr]
|
||||
@ -60,6 +58,7 @@
|
||||
[tr][td][zrl=[baseurl]/help/database/db_xconfig]xconfig[/zrl][/td][td]as pconfig but for channels with no local account[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_xign]xign[/zrl][/td][td]channels ignored by friend suggestions[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_xlink]xlink[/zrl][/td][td]"friends of friends" linkages derived from poco, also ratings storage[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_xperm]xperm[/zrl][/td][td]OAuth/OpenID-Connect extensible permissions permissions storage[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_xprof]xprof[/zrl][/td][td]if this hub is a directory server, contains basic public profile info of everybody in the network[/td][/tr]
|
||||
[tr][td][zrl=[baseurl]/help/database/db_xtag]xtag[/zrl][/td][td]if this hub is a directory server, contains tags or interests of everybody in the network[/td][/tr]
|
||||
[/table]
|
||||
|
@ -15,10 +15,6 @@
|
||||
[/td][/tr]
|
||||
[tr][td]abook_closeness[/td][td]"closeness" value for optional affinity tool, 0-99[/td][td]tinyint(3) unsigned[/td][td]NO[/td][td]MUL[/td][td]99[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]abook_rating[/td][td]The channel owner's (public) rating of this connection -10 to +10, default 0 or unrated[/td][td]int(11)[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]abook_rating_text[/td][td]The channel owner's (public) rating of this connection free form text[/td][td]text[/td][td]NO[/td][td]MUL[/td][td][/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]abook_created[/td][td]Datetime this record was created[/td][td]datetime[/td][td]NO[/td][td]MUL[/td][td]0000-00-00 00:00:00[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]abook_updated[/td][td]Datetime this record was modified[/td][td]datetime[/td][td]NO[/td][td]MUL[/td][td]0000-00-00 00:00:00[/td][td]
|
||||
@ -32,16 +28,27 @@
|
||||
[tr][td]abook_profile[/td][td]profile.guid of profile to display to this connection if authenticated[/td][td]char(64)[/td][td]NO[/td][td]MUL[/td][td][/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]abook_blocked[/td][td]Bi-directional communications with this channel are blocked, regardless of other permissions. [/td][td]int(11)[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]abook_ignored[/td][td]Incoming communications from this channel are blocked, regardless of other permissions. [/td][td]int(11)[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]abook_hidden[/td][td]This connection will not be shown as a connection to anybody but the channel owner[/td][td]int(11)[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]abook_archived[/td][td]This connection is likely non-functioning and the entry and conversations are preserved, but further polled communications will not be attempted. [/td][td]int(11)[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]abook_pending[/td][td]A connection request was received from this channel but has not been approved by the channel owner, public communications may still be visible but no additional permissions have been granted. [/td][td]int(11)[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]abook_unconnected[/td][td]currently unused. Projected usage is to indicate "one-way" connections which were insitgated on this end but are still pending on the remote end. [/td][td]int(11)[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]abook_self[/td][td]is a special case where the owner is the target. Every channel has one abook entry with abook_self and with a target abook_xchan set to channel.channel_hash . When this flag is present, abook_my_perms is the default permissions granted to all new connections and several other fields are unused.[/td][td]int(11)[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]abook_feed[/td][td]indicates this connection is an RSS/Atom feed and may trigger special handling.[/td][td]int(11)[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]abook_incl[/td][td]connection filter allow rules separated by LF[/td][td]text[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]abook_excl[/td][td]connection filter deny rules separated by LF[/td][td]text[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]abook_instance[/td][td]comma separated list of site urls of all channel clones that this connection is connected with (used only for singleton networks which don't support cloning)[/td][td]text[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[/table]
|
||||
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
[/th][/tr]
|
||||
[tr][td]id[/td][td][/td]generated index[td]int(11)[/td][td]NO[/td][td]PRI[/td][td]NULL[/td][td]auto_increment
|
||||
[/td][/tr]
|
||||
[tr][td]name[/td][td]plugin base (file)name[/td][td]char(255)[/td][td]NO[/td][td]MUL[/td][td]NULL[/td][td]
|
||||
[tr][td]aname[/td][td]plugin base (file)name[/td][td]char(255)[/td][td]NO[/td][td]MUL[/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]version[/td][td]currently unused[/td][td]char(255)[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
@ -11,7 +11,7 @@
|
||||
[/td][/tr]
|
||||
[tr][td]hidden[/td][td]currently unused[/td][td]tinyint(1)[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]timestamp[/td][td]file timestamp to check for reloads[/td][td]bigint(20)[/td][td]NO[/td][td][/td][td]0[/td][td]
|
||||
[tr][td]tstamp[/td][td]file timestamp to check for reloads[/td][td]bigint(20)[/td][td]NO[/td][td][/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]plugin_admin[/td][td]1 = has admin config, 0 = has no admin config[/td][td]tinyint(1)[/td][td]NO[/td][td][/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
|
@ -27,8 +27,20 @@
|
||||
[/td][/tr]
|
||||
[tr][td]app_page[/td][td]currently unused[/td][td]char(255)[/td][td]NO[/td][td][/td][td][/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]app_requires[/td][td]currently unused[/td][td]char(255)[/td][td]NO[/td][td][/td][td][/td][td]
|
||||
[tr][td]app_requires[/td][td]access rules[/td][td]char(255)[/td][td]NO[/td][td][/td][td][/td][td]
|
||||
[/td][/tr]
|
||||
|
||||
[tr][td]app_created[/td][td]datetime of app creation[/td][td]datetime[/td][td]NO[/td][td][/td][td][/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]app_edited[/td][td]datetime of last app edit[/td][td]datetime[/td][td]NO[/td][td][/td][td][/td][td]
|
||||
[/td][/tr]
|
||||
|
||||
[tr][td]app_deleted[/td][td]1 = deleted, 0 = normal[/td][td]int(11)[/td][td]NO[/td][td][/td][td][/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]app_system[/td][td]1 = imported system app, 0 = member created app[/td][td]int(11)[/td][td]NO[/td][td][/td][td][/td][td]
|
||||
[/td][/tr]
|
||||
|
||||
|
||||
[/table]
|
||||
|
||||
Storage for personal apps
|
||||
|
@ -29,9 +29,11 @@
|
||||
[/td][/tr]
|
||||
[tr][td]os_storage[/td][td]if 0, data contains content; if 1 data contains path to content (always 1 in hubzilla)[/td][td]tinyint[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]os_path[/td][td]under construction, store the system path[/td][td]mediumtext[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]display_path[/td][td]under construction, store the human readable path[/td][td]mediumtext[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]data[/td][td]file data or pathname to stored data if ATTACH_FLAG_OS[/td][td]longblob[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[tr][td]content[/td][td]file data or pathname to stored data if ATTACH_FLAG_OS[/td][td]longblob[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]created[/td][td]creation time[/td][td]datetime[/td][td]NO[/td][td]MUL[/td][td]0000-00-00 00:00:00[/td][td]
|
||||
[/td][/tr]
|
||||
|
@ -35,6 +35,8 @@
|
||||
[/td][/tr]
|
||||
[tr][td]channel_dirdate[/td][td]time when directory was last pinged. Must do this once a month[/td][td]datetime[/td][td]NO[/td][td]MUL[/td][td]0000-00-00 00:00:00[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]channel_lastpost[/td][td]date of last post for this channel. May not be fully implemented[/td][td]datetime[/td][td]NO[/td][td]MUL[/td][td]0000-00-00 00:00:00[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]channel_deleted[/td][td]time when channel was deleted[/td][td]datetime[/td][td]NO[/td][td]MUL[/td][td]0000-00-00 00:00:00[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]channel_max_anon_mail[/td][td]unused[/td][td]int(10) unsigned[/td][td]NO[/td][td]MUL[/td][td]10[/td][td]
|
||||
@ -95,6 +97,8 @@
|
||||
[/td][/tr]
|
||||
[tr][td]channel_system[/td][td]if 1, this is the special system channel on this site[/td][td]int(10) unsigned[/td][td]NO[/td][td]MUL[/td][td]128[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]channel_moved[/td][td]URL of relocated channel, making this instance abandoned if set[/td][td]char(255)[/td][td]NO[/td][td]MUL[/td][td][/td][td]
|
||||
[/td][/tr]
|
||||
[/table]
|
||||
|
||||
Return to [zrl=[baseurl]/help/database]database documentation[/zrl]
|
||||
|
@ -11,7 +11,7 @@
|
||||
[/td][/tr]
|
||||
[tr][td]cp_status[/td][td]text status description e.g. "online"[/td][td]char(255)[/td][td]NO[/td][td]MUL[/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]cp_client[/td][td][/td]IP address of this client[td]char(128)[/td][td]NO[/td][td][/td][td][/td][td]
|
||||
[tr][td]cp_client[/td][td]IP address of this client[/td][td]char(128)[/td][td]NO[/td][td][/td][td][/td][td]
|
||||
[/td][/tr]
|
||||
[/table]
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
[/td][/tr]
|
||||
[tr][td]redirect_uri[/td][td][/td][td]varchar(200)[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]name[/td][td][/td][td]text[/td][td]YES[/td][td][/td][td]NULL[/td][td]
|
||||
[tr][td]clname[/td][td][/td][td]text[/td][td]YES[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]icon[/td][td][/td][td]text[/td][td]YES[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
|
@ -15,9 +15,9 @@
|
||||
[/td][/tr]
|
||||
[tr][td]edited[/td][td][/td][td]datetime[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]start[/td][td][/td][td]datetime[/td][td]NO[/td][td]MUL[/td][td]NULL[/td][td]
|
||||
[tr][td]dtstart[/td][td][/td][td]datetime[/td][td]NO[/td][td]MUL[/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]finish[/td][td][/td][td]datetime[/td][td]NO[/td][td]MUL[/td][td]NULL[/td][td]
|
||||
[tr][td]dtend[/td][td][/td][td]datetime[/td][td]NO[/td][td]MUL[/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]summary[/td][td][/td][td]text[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
@ -25,13 +25,13 @@
|
||||
[/td][/tr]
|
||||
[tr][td]location[/td][td][/td][td]text[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]type[/td][td][/td][td]char(255)[/td][td]NO[/td][td]MUL[/td][td]NULL[/td][td]
|
||||
[tr][td]etype[/td][td][/td][td]char(255)[/td][td]NO[/td][td]MUL[/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]nofinish[/td][td][/td][td]tinyint(1)[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]adjust[/td][td][/td][td]tinyint(1)[/td][td]NO[/td][td]MUL[/td][td]1[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]ignore[/td][td][/td][td]tinyint(1)[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[tr][td]dismissed[/td][td][/td][td]tinyint(1)[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]allow_cid[/td][td][/td][td]mediumtext[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
@ -41,6 +41,24 @@
|
||||
[/td][/tr]
|
||||
[tr][td]deny_gid[/td][td][/td][td]mediumtext[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
|
||||
[tr][td]event_status[/td][td][/td][td]charr(255)[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]event_status_date[/td][td][/td][td]datetime[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]event_percent[/td][td][/td][td]smallint(6)[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]event_repeat[/td][td][/td][td]text[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]event_sequence[/td][td][/td][td]smallint[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]event_priority[/td][td][/td][td]smallint[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]event_vdata[/td][td][/td][td]text[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]cal_id[/td][td][/td][td]int(10)[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
|
||||
[/table]
|
||||
|
||||
Return to [zrl=[baseurl]/help/database]database documentation[/zrl]
|
@ -11,7 +11,7 @@
|
||||
[/td][/tr]
|
||||
[tr][td]deleted[/td][td]1 indicates the group has been deleted[/td][td]tinyint(1)[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]name[/td][td]human readable name of group[/td][td]char(255)[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[tr][td]gname[/td][td]human readable name of group[/td][td]char(255)[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[/table]
|
||||
|
||||
|
@ -7,9 +7,11 @@
|
||||
[/td][/tr]
|
||||
[tr][td]file[/td][td]relative filename of hook handler[/td][td]char(255)[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]function[/td][td]function name of hook handler[/td][td]char(255)[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[tr][td]fn[/td][td]function name of hook handler[/td][td]char(255)[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]priority[/td][td]not yet implemented - can be used to sort conflicts in hook handling by calling handlers in priority order[/td][td]int(11) unsigned[/td][td]NO[/td][td][/td][td]0[/td][td]
|
||||
[tr][td]priority[/td][td]can be used to sort conflicts in hook handling by calling handlers in priority order[/td][td]int(11) unsigned[/td][td]NO[/td][td][/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]hook_version[/td][td]version 0 hooks must have two arguments, the App and the hook data. version 1 hooks have 1 argument - the hook data[/td][td]int(11) unsigned[/td][td]NO[/td][td][/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[/table]
|
||||
|
||||
|
@ -51,7 +51,7 @@
|
||||
[/td][/tr]
|
||||
[tr][td]obj_type[/td][td]ActivityStreams object type (old style URI)[/td][td]char(255)[/td][td]NO[/td][td][/td][td][/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]object[/td][td]JSON encoded object structure unless it is an implied object (normal post)[/td][td]text[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[tr][td]obj[/td][td]JSON encoded object structure unless it is an implied object (normal post)[/td][td]text[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]tgt_type[/td][td]ActivityStreams target type if applicable (URI)[/td][td]char(255)[/td][td]NO[/td][td][/td][td][/td][td]
|
||||
[/td][/tr]
|
||||
|
@ -5,7 +5,7 @@
|
||||
[/td][/tr]
|
||||
[tr][td]hash[/td][td][/td][td]char(64)[/td][td]NO[/td][td]MUL[/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]name[/td][td][/td][td]char(255)[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[tr][td]xname[/td][td][/td][td]char(255)[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]url[/td][td][/td][td]char(255)[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
@ -25,7 +25,7 @@
|
||||
[/td][/tr]
|
||||
[tr][td]seen[/td][td][/td][td]tinyint(1)[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]type[/td][td][/td][td]int(11)[/td][td]NO[/td][td]MUL[/td][td]NULL[/td][td]
|
||||
[tr][td]ntype[/td][td][/td][td]int(11)[/td][td]NO[/td][td]MUL[/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]verb[/td][td][/td][td]char(255)[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
|
@ -23,15 +23,15 @@
|
||||
[/td][/tr]
|
||||
[tr][td]filename[/td][td][/td][td]char(255)[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]type[/td][td][/td][td]char(128)[/td][td]NO[/td][td]MUL[/td][td]image/jpeg[/td][td]
|
||||
[tr][td]mimetype[/td][td][/td][td]char(128)[/td][td]NO[/td][td]MUL[/td][td]image/jpeg[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]height[/td][td][/td][td]smallint(6)[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]width[/td][td][/td][td]smallint(6)[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]size[/td][td][/td][td]int(10) unsigned[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[tr][td]filesize[/td][td][/td][td]int(10) unsigned[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]data[/td][td][/td][td]mediumblob[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[tr][td]content[/td][td][/td][td]mediumblob[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]scale[/td][td][/td][td]tinyint(3)[/td][td]NO[/td][td]MUL[/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
|
@ -15,7 +15,7 @@
|
||||
[/td][/tr]
|
||||
[tr][td]hide_friends[/td][td][/td][td]tinyint(1)[/td][td]NO[/td][td]MUL[/td][td]0[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]name[/td][td][/td][td]char(255)[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[tr][td]fullname[/td][td][/td][td]char(255)[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]pdesc[/td][td][/td][td]char(255)[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
@ -41,7 +41,7 @@
|
||||
[/td][/tr]
|
||||
[tr][td]marital[/td][td][/td][td]char(255)[/td][td]NO[/td][td]MUL[/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]with[/td][td][/td][td]text[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[tr][td]partner[/td][td][/td][td]text[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]howlong[/td][td][/td][td]datetime[/td][td]NO[/td][td][/td][td]0000-00-00 00:00:00[/td][td]
|
||||
[/td][/tr]
|
||||
@ -73,7 +73,7 @@
|
||||
[/td][/tr]
|
||||
[tr][td]romance[/td][td][/td][td]text[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]work[/td][td][/td][td]text[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[tr][td]employment[/td][td][/td][td]text[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]education[/td][td][/td][td]text[/td][td]NO[/td][td][/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
|
@ -11,7 +11,7 @@
|
||||
[/td][/tr]
|
||||
[tr][td]otype[/td][td]type of linked thing[/td][td]tinyint(3) unsigned[/td][td]NO[/td][td]MUL[/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]type[/td][td]taxonomy type (See Tag/term types in boot.php)[/td][td]tinyint(3) unsigned[/td][td]NO[/td][td]MUL[/td][td]NULL[/td][td]
|
||||
[tr][td]ttype[/td][td]taxonomy type (See Tag/term types in boot.php)[/td][td]tinyint(3) unsigned[/td][td]NO[/td][td]MUL[/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
[tr][td]term[/td][td]the actual taxonomy term[/td][td]char(255)[/td][td]NO[/td][td]MUL[/td][td]NULL[/td][td]
|
||||
[/td][/tr]
|
||||
|
@ -423,6 +423,8 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
|
||||
$observer = array();
|
||||
|
||||
$dosync = ((array_key_exists('nosync',$arr) && $arr['nosync']) ? 0 : 1);
|
||||
|
||||
if($observer_hash) {
|
||||
$x = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($observer_hash)
|
||||
@ -616,7 +618,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
);
|
||||
if($r) {
|
||||
$overwrite = get_pconfig($channel_id,'system','overwrite_dup_files');
|
||||
if($overwrite) {
|
||||
if(($overwrite) || ($options === 'import')) {
|
||||
$options = 'replace';
|
||||
$existing_id = $x[0]['id'];
|
||||
$existing_size = intval($x[0]['filesize']);
|
||||
@ -800,7 +802,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
|
||||
if($is_photo) {
|
||||
|
||||
$args = array( 'source' => $source, 'visible' => $visible, 'resource_id' => $hash, 'album' => basename($pathname), 'os_path' => $os_basepath . $os_relpath, 'filename' => $filename, 'getimagesize' => $gis, 'directory' => $direct);
|
||||
$args = array( 'source' => $source, 'visible' => $visible, 'resource_id' => $hash, 'album' => basename($pathname), 'os_path' => $os_basepath . $os_relpath, 'filename' => $filename, 'getimagesize' => $gis, 'directory' => $direct, 'options' => $options );
|
||||
if($arr['contact_allow'])
|
||||
$args['contact_allow'] = $arr['contact_allow'];
|
||||
if($arr['group_allow'])
|
||||
@ -829,6 +831,8 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
if($arr['description'])
|
||||
$args['description'] = $arr['description'];
|
||||
|
||||
$args['deliver'] = $dosync;
|
||||
|
||||
$p = photo_upload($channel,$observer,$args);
|
||||
if($p['success']) {
|
||||
$ret['body'] = $p['body'];
|
||||
@ -865,10 +869,12 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
call_hooks('photo_upload_end',$ret);
|
||||
}
|
||||
|
||||
$sync = attach_export_data($channel,$hash);
|
||||
if($dosync) {
|
||||
$sync = attach_export_data($channel,$hash);
|
||||
|
||||
if($sync)
|
||||
build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
if($sync)
|
||||
build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
@ -493,7 +493,7 @@ function bb_code($match) {
|
||||
|
||||
function bb_highlight($match) {
|
||||
if(in_array(strtolower($match[1]),['php','css','mysql','sql','abap','diff','html','perl','ruby',
|
||||
'vbscript','avrc','dtd','java','xml','cpp','python','javascript','js','sh']))
|
||||
'vbscript','avrc','dtd','java','xml','cpp','python','javascript','js','json','sh']))
|
||||
return text_highlight($match[2],strtolower($match[1]));
|
||||
return $match[0];
|
||||
}
|
||||
|
@ -1,44 +0,0 @@
|
||||
<?php /** @file */
|
||||
|
||||
/**
|
||||
* cache api
|
||||
*/
|
||||
|
||||
class Cache {
|
||||
public static function get($key){
|
||||
$r = q("SELECT v FROM cache WHERE k = '%s' limit 1",
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
if ($r)
|
||||
return $r[0]['v'];
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function set($key,$value) {
|
||||
|
||||
$r = q("SELECT * FROM cache WHERE k = '%s' limit 1",
|
||||
dbesc($key)
|
||||
);
|
||||
if($r) {
|
||||
q("UPDATE cache SET v = '%s', updated = '%s' WHERE k = '%s'",
|
||||
dbesc($value),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($key));
|
||||
}
|
||||
else {
|
||||
q("INSERT INTO cache ( k, v, updated) VALUES ('%s','%s','%s')",
|
||||
dbesc($key),
|
||||
dbesc($value),
|
||||
dbesc(datetime_convert()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function clear(){
|
||||
q("DELETE FROM cache WHERE updated < '%s'",
|
||||
dbesc(datetime_convert('UTC','UTC',"now - 30 days")));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -496,8 +496,10 @@ function identity_basic_export($channel_id, $items = false) {
|
||||
$r = q("select * from channel where channel_id = %d limit 1",
|
||||
intval($channel_id)
|
||||
);
|
||||
if($r)
|
||||
if($r) {
|
||||
$ret['channel'] = $r[0];
|
||||
$ret['relocate'] = [ 'channel_address' => $r[0]['channel_address'], 'url' => z_root()];
|
||||
}
|
||||
|
||||
$r = q("select * from profile where uid = %d",
|
||||
intval($channel_id)
|
||||
@ -514,7 +516,7 @@ function identity_basic_export($channel_id, $items = false) {
|
||||
|
||||
for($x = 0; $x < count($ret['abook']); $x ++) {
|
||||
$xchans[] = $ret['abook'][$x]['abook_chan'];
|
||||
$abconfig = load_abconfig($ret['channel']['channel_hash'],$ret['abook'][$x]['abook_xchan']);
|
||||
$abconfig = load_abconfig($channel_id,$ret['abook'][$x]['abook_xchan']);
|
||||
if($abconfig)
|
||||
$ret['abook'][$x]['abconfig'] = $abconfig;
|
||||
}
|
||||
@ -717,6 +719,10 @@ function identity_export_year($channel_id,$year,$month = 0) {
|
||||
|
||||
$ret = array();
|
||||
|
||||
$ch = channelx_by_n($channel_id);
|
||||
if($ch) {
|
||||
$ret['relocate'] = [ 'channel_address' => $ch['channel_address'], 'url' => z_root()];
|
||||
}
|
||||
$mindate = datetime_convert('UTC','UTC',$year . '-' . $target_month . '-01 00:00:00');
|
||||
if($month && $month < 12)
|
||||
$maxdate = datetime_convert('UTC','UTC',$year . '-' . $target_month_plus . '-01 00:00:00');
|
||||
@ -856,7 +862,7 @@ function profile_load(&$a, $nickname, $profile = '') {
|
||||
);
|
||||
if($z) {
|
||||
$p[0]['picdate'] = $z[0]['xchan_photo_date'];
|
||||
$p[0]['reddress'] = str_replace('@','@',$z[0]['xchan_addr']);
|
||||
$p[0]['reddress'] = str_replace('@','@',$z[0]['xchan_addr']);
|
||||
}
|
||||
|
||||
// fetch user tags if this isn't the default profile
|
||||
@ -1027,6 +1033,7 @@ function profile_sidebar($profile, $block = 0, $show_connect = true, $zcard = fa
|
||||
|
||||
$diaspora = array(
|
||||
'podloc' => z_root(),
|
||||
'guid' => $profile['channel_guid'] . str_replace('.','',App::get_hostname()),
|
||||
'searchable' => (($block) ? 'false' : 'true'),
|
||||
'nickname' => $profile['channel_address'],
|
||||
'fullname' => $profile['channel_name'],
|
||||
@ -1224,6 +1231,7 @@ function advanced_profile(&$a) {
|
||||
|
||||
$things = get_things(App::$profile['profile_guid'],App::$profile['profile_uid']);
|
||||
|
||||
|
||||
// logger('mod_profile: things: ' . print_r($things,true), LOGGER_DATA);
|
||||
|
||||
return replace_macros($tpl, array(
|
||||
|
@ -98,20 +98,20 @@ function del_aconfig($account_id, $family, $key) {
|
||||
}
|
||||
|
||||
|
||||
function load_abconfig($chash,$xhash) {
|
||||
Zlib\AbConfig::Load($chash,$xhash);
|
||||
function load_abconfig($chan,$xhash) {
|
||||
Zlib\AbConfig::Load($chan,$xhash);
|
||||
}
|
||||
|
||||
function get_abconfig($chash,$xhash,$family,$key) {
|
||||
return Zlib\AbConfig::Get($chash,$xhash,$family,$key);
|
||||
function get_abconfig($chan,$xhash,$family,$key) {
|
||||
return Zlib\AbConfig::Get($chan,$xhash,$family,$key);
|
||||
}
|
||||
|
||||
function set_abconfig($chash,$xhash,$family,$key,$value) {
|
||||
return Zlib\AbConfig::Set($chash,$xhash,$family,$key,$value);
|
||||
function set_abconfig($chan,$xhash,$family,$key,$value) {
|
||||
return Zlib\AbConfig::Set($chan,$xhash,$family,$key,$value);
|
||||
}
|
||||
|
||||
function del_abconfig($chash,$xhash,$family,$key) {
|
||||
return Zlib\AbConfig::Delete($chash,$xhash,$family,$key);
|
||||
function del_abconfig($chan,$xhash,$family,$key) {
|
||||
return Zlib\AbConfig::Delete($chan,$xhash,$family,$key);
|
||||
}
|
||||
|
||||
function load_iconfig(&$item) {
|
||||
|
@ -224,7 +224,7 @@ function datetimesel($format, $min, $max, $default, $label, $id = 'datetimepicke
|
||||
|
||||
$pickers = '';
|
||||
if(!$pickdate) $pickers .= ',datepicker: false';
|
||||
if(!$picktime) $pickers .= ',timepicker: false';
|
||||
if(!$picktime) $pickers .= ',timepicker: false, closeOnDateSelect:true';
|
||||
|
||||
$extra_js = '';
|
||||
if($minfrom != '')
|
||||
|
@ -90,7 +90,7 @@ abstract class dba_driver {
|
||||
protected $db;
|
||||
protected $pdo = array();
|
||||
|
||||
public $debug = 0;
|
||||
public $debug = 0;
|
||||
public $connected = false;
|
||||
public $error = false;
|
||||
|
||||
@ -332,6 +332,9 @@ function q($sql) {
|
||||
else
|
||||
db_logger('dba: vsprintf error: ' . print_r(debug_backtrace(), true),LOGGER_NORMAL,LOG_CRIT);
|
||||
}
|
||||
if(\DBA::$dba->debug)
|
||||
db_logger('Sql: ' . $stmt, LOGGER_DEBUG, LOG_INFO);
|
||||
|
||||
return \DBA::$dba->q($stmt);
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ function group_add($uid,$name,$public = 0) {
|
||||
$z = q("SELECT * FROM `groups` WHERE `id` = %d LIMIT 1",
|
||||
intval($r)
|
||||
);
|
||||
if(count($z) && $z[0]['deleted']) {
|
||||
if(($z) && $z[0]['deleted']) {
|
||||
/*$r = q("UPDATE `groups` SET `deleted` = 0 WHERE `uid` = %d AND `gname` = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
dbesc($name)
|
||||
@ -129,7 +129,7 @@ function group_byname($uid,$name) {
|
||||
intval($uid),
|
||||
dbesc($name)
|
||||
);
|
||||
if(count($r))
|
||||
if($r)
|
||||
return $r[0]['id'];
|
||||
return false;
|
||||
}
|
||||
@ -178,11 +178,11 @@ function group_add_member($uid,$name,$member,$gid = 0) {
|
||||
intval($gid),
|
||||
dbesc($member)
|
||||
);
|
||||
if(count($r))
|
||||
if($r)
|
||||
return true; // You might question this, but
|
||||
// we indicate success because the group member was in fact created
|
||||
// -- It was just created at another time
|
||||
if(! count($r))
|
||||
if(! $r)
|
||||
$r = q("INSERT INTO `group_member` (`uid`, `gid`, `xchan`)
|
||||
VALUES( %d, %d, '%s' ) ",
|
||||
intval($uid),
|
||||
@ -205,7 +205,7 @@ function group_get_members($gid) {
|
||||
intval(local_channel()),
|
||||
intval(local_channel())
|
||||
);
|
||||
if(count($r))
|
||||
if($r)
|
||||
$ret = $r;
|
||||
}
|
||||
return $ret;
|
||||
@ -218,7 +218,7 @@ function group_get_members_xchan($gid) {
|
||||
intval($gid),
|
||||
intval(local_channel())
|
||||
);
|
||||
if(count($r)) {
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$ret[] = $rr['xchan'];
|
||||
}
|
||||
@ -236,7 +236,7 @@ function mini_group_select($uid,$group = '') {
|
||||
intval($uid)
|
||||
);
|
||||
$grps[] = array('name' => '', 'hash' => '0', 'selected' => '');
|
||||
if(count($r)) {
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$grps[] = array('name' => $rr['gname'], 'id' => $rr['hash'], 'selected' => (($group == $rr['hash']) ? 'true' : ''));
|
||||
}
|
||||
@ -279,7 +279,7 @@ function group_side($every="connections",$each="group",$edit = false, $group_id
|
||||
$member_of = groups_containing(local_channel(),$cid);
|
||||
}
|
||||
|
||||
if(count($r)) {
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$selected = (($group_id == $rr['id']) ? ' group-selected' : '');
|
||||
|
||||
@ -356,7 +356,7 @@ function groups_containing($uid,$c) {
|
||||
);
|
||||
|
||||
$ret = array();
|
||||
if(count($r)) {
|
||||
if($r) {
|
||||
foreach($r as $rr)
|
||||
$ret[] = $rr['gid'];
|
||||
}
|
||||
|
@ -553,7 +553,7 @@ function sync_chatrooms($channel,$chatrooms) {
|
||||
|
||||
|
||||
|
||||
function import_items($channel,$items,$sync = false) {
|
||||
function import_items($channel,$items,$sync = false,$relocate = null) {
|
||||
|
||||
if($channel && $items) {
|
||||
$allow_code = false;
|
||||
@ -584,13 +584,6 @@ function import_items($channel,$items,$sync = false) {
|
||||
$item['id'] = $r[0]['id'];
|
||||
$item['uid'] = $channel['channel_id'];
|
||||
$item_result = item_store_update($item,$allow_code,$deliver);
|
||||
if($sync && $item['item_wall']) {
|
||||
// deliver singletons if we have any
|
||||
if($item_result && $item_result['success']) {
|
||||
Zotlabs\Daemon\Master::Summon(array('Notifier','single_activity',$item_result['item_id']));
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -598,19 +591,37 @@ function import_items($channel,$items,$sync = false) {
|
||||
$item['uid'] = $channel['channel_id'];
|
||||
$item_result = item_store($item,$allow_code,$deliver);
|
||||
}
|
||||
|
||||
if($sync && $item['item_wall']) {
|
||||
// deliver singletons if we have any
|
||||
if($item_result && $item_result['success']) {
|
||||
Zotlabs\Daemon\Master::Summon(array('Notifier','single_activity',$item_result['item_id']));
|
||||
}
|
||||
}
|
||||
if($relocate && $item_result['item_id']) {
|
||||
$item = $item_result['item'];
|
||||
if($item['mid'] === $item['parent_mid']) {
|
||||
item_url_replace($channel,$item,$relocate['url'],z_root(),$relocate['channel_address']);
|
||||
dbesc_array($item);
|
||||
$item_id = $item_result['item_id'];
|
||||
unset($item['id']);
|
||||
$str = '';
|
||||
foreach($item as $k => $v) {
|
||||
if($str)
|
||||
$str .= ",";
|
||||
$str .= " `" . $k . "` = '" . $v . "' ";
|
||||
}
|
||||
|
||||
$r = dbq("update `item` set " . $str . " where id = " . $item_id );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function sync_items($channel,$items) {
|
||||
import_items($channel,$items,true);
|
||||
function sync_items($channel,$items,$relocate = null) {
|
||||
import_items($channel,$items,true,$relocate);
|
||||
}
|
||||
|
||||
|
||||
@ -1200,31 +1211,9 @@ function sync_files($channel,$files) {
|
||||
}
|
||||
}
|
||||
if($f['item']) {
|
||||
sync_items($channel,$f['item']);
|
||||
foreach($f['item'] as $i) {
|
||||
if($i['message_id'] !== $i['message_parent'])
|
||||
continue;
|
||||
$r = q("select * from item where mid = '%s' and uid = %d limit 1",
|
||||
dbesc($i['message_id']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if($r) {
|
||||
$item = $r[0];
|
||||
item_url_replace($channel,$item,$oldbase,z_root(),$original_channel);
|
||||
|
||||
dbesc_array($item);
|
||||
$item_id = $item['id'];
|
||||
unset($item['id']);
|
||||
$str = '';
|
||||
foreach($item as $k => $v) {
|
||||
if($str)
|
||||
$str .= ",";
|
||||
$str .= " `" . $k . "` = '" . $v . "' ";
|
||||
}
|
||||
|
||||
$r = dbq("update `item` set " . $str . " where id = " . $item_id );
|
||||
}
|
||||
}
|
||||
sync_items($channel,$f['item'],
|
||||
['channel_address' => $original_channel,'url' => $oldbase]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1889,6 +1889,7 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
|
||||
}
|
||||
|
||||
|
||||
$ret['item'] = $arr;
|
||||
|
||||
call_hooks('post_remote_end',$arr);
|
||||
|
||||
@ -2139,6 +2140,15 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
// fetch an unescaped complete copy of the stored item
|
||||
|
||||
$r = q("select * from item where id = %d",
|
||||
intval($orig_post_id)
|
||||
);
|
||||
if($r)
|
||||
$arr = $r[0];
|
||||
|
||||
|
||||
$r = q("delete from term where oid = %d and otype = %d",
|
||||
intval($orig_post_id),
|
||||
intval(TERM_OBJ_POST)
|
||||
@ -2170,6 +2180,8 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) {
|
||||
$arr['iconfig'] = $meta;
|
||||
}
|
||||
|
||||
$ret['item'] = $arr;
|
||||
|
||||
call_hooks('post_remote_update_end',$arr);
|
||||
|
||||
if($deliver) {
|
||||
|
@ -29,6 +29,8 @@ function get_capath() {
|
||||
* * \b nobody => only return the header
|
||||
* * \b filep => stream resource to write body to. header and body are not returned when using this option.
|
||||
* * \b custom => custom request method: e.g. 'PUT', 'DELETE'
|
||||
* * \b cookiejar => cookie file (write)
|
||||
* * \B cookiefile => cookie file (read)
|
||||
*
|
||||
* @return array an associative array with:
|
||||
* * \e int \b return_code => HTTP return code or 0 if timeout or failure
|
||||
@ -60,6 +62,18 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
|
||||
@curl_setopt($ch, CURLOPT_HEADER, $false);
|
||||
}
|
||||
|
||||
if(x($opts,'upload'))
|
||||
@curl_setopt($ch, CURLOPT_UPLOAD, $opts['upload']);
|
||||
|
||||
if(x($opts,'infile'))
|
||||
@curl_setopt($ch, CURLOPT_INFILE, $opts['infile']);
|
||||
|
||||
if(x($opts,'infilesize'))
|
||||
@curl_setopt($ch, CURLOPT_INFILESIZE, $opts['infilesize']);
|
||||
|
||||
if(x($opts,'readfunc'))
|
||||
@curl_setopt($ch, CURLOPT_READFUNCTION, $opts['readfunc']);
|
||||
|
||||
if(x($opts,'headers'))
|
||||
@curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['headers']);
|
||||
|
||||
@ -82,6 +96,11 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
|
||||
@curl_setopt($ch, CURLOPT_USERPWD, $opts['http_auth']);
|
||||
}
|
||||
|
||||
if(x($opts,'cookiejar'))
|
||||
@curl_setopt($ch, CURLOPT_COOKIEJAR, $opts['cookiejar']);
|
||||
if(x($opts,'cookiefile'))
|
||||
@curl_setopt($ch, CURLOPT_COOKIEFILE, $opts['cookiefile']);
|
||||
|
||||
@curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,
|
||||
((x($opts,'novalidate') && intval($opts['novalidate'])) ? false : true));
|
||||
|
||||
@ -180,6 +199,10 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
|
||||
*/
|
||||
function z_post_url($url,$params, $redirects = 0, $opts = array()) {
|
||||
|
||||
// logger('url: ' . $url);
|
||||
// logger('params: ' . print_r($params,true));
|
||||
// logger('opts: ' . print_r($opts,true));
|
||||
|
||||
$ret = array('return_code' => 0, 'success' => false, 'header' => "", 'body' => "");
|
||||
|
||||
$ch = curl_init($url);
|
||||
@ -205,14 +228,15 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) {
|
||||
|
||||
if(x($opts,'headers')) {
|
||||
@curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['headers']);
|
||||
logger('headers: ' . print_r($opts['headers'],true) . 'redir: ' . $redirects);
|
||||
}
|
||||
|
||||
if(x($opts,'nobody'))
|
||||
@curl_setopt($ch, CURLOPT_NOBODY, $opts['nobody']);
|
||||
|
||||
if(x($opts,'custom'))
|
||||
if(x($opts,'custom')) {
|
||||
@curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $opts['custom']);
|
||||
@curl_setopt($ch, CURLOPT_POST,0);
|
||||
}
|
||||
|
||||
|
||||
if(x($opts,'timeout') && intval($opts['timeout'])) {
|
||||
@ -228,6 +252,12 @@ logger('headers: ' . print_r($opts['headers'],true) . 'redir: ' . $redirects);
|
||||
@curl_setopt($ch, CURLOPT_USERPWD, $opts['http_auth']);
|
||||
}
|
||||
|
||||
|
||||
if(x($opts,'cookiejar'))
|
||||
@curl_setopt($ch, CURLOPT_COOKIEJAR, $opts['cookiejar']);
|
||||
if(x($opts,'cookiefile'))
|
||||
@curl_setopt($ch, CURLOPT_COOKIEFILE, $opts['cookiefile']);
|
||||
|
||||
@curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,
|
||||
((x($opts,'novalidate') && intval($opts['novalidate'])) ? false : true));
|
||||
|
||||
@ -1972,14 +2002,7 @@ function get_site_info() {
|
||||
else
|
||||
$service_class = false;
|
||||
|
||||
$visible_plugins = array();
|
||||
if(is_array(App::$plugins) && count(App::$plugins)) {
|
||||
$r = q("select * from addon where hidden = 0");
|
||||
if(count($r))
|
||||
foreach($r as $rr)
|
||||
$visible_plugins[] = $rr['aname'];
|
||||
}
|
||||
sort($visible_plugins);
|
||||
$visible_plugins = visible_plugin_list();
|
||||
|
||||
if(@is_dir('.git') && function_exists('shell_exec'))
|
||||
$commit = trim(@shell_exec('git log -1 --format="%h"'));
|
||||
|
@ -1,6 +1,8 @@
|
||||
<?php /** @file */
|
||||
|
||||
|
||||
use Zotlabs\Lib as Zlib;
|
||||
|
||||
function oembed_replacecb($matches){
|
||||
|
||||
$embedurl=$matches[1];
|
||||
@ -130,7 +132,7 @@ function oembed_fetch_url($embedurl){
|
||||
$txt = null;
|
||||
|
||||
if($action !== 'block') {
|
||||
$txt = Cache::get(App::$videowidth . $embedurl);
|
||||
$txt = Zlib\Cache::get('[' . App::$videowidth . '] ' . $embedurl);
|
||||
|
||||
if(strstr($txt,'youtu') && strstr(z_root(),'https:')) {
|
||||
$txt = str_replace('http:','https:',$txt);
|
||||
@ -199,7 +201,7 @@ function oembed_fetch_url($embedurl){
|
||||
//save in cache
|
||||
|
||||
if(! get_config('system','oembed_cache_disable'))
|
||||
Cache::set(App::$videowidth . $embedurl,$txt);
|
||||
Zlib\Cache::set('[' . App::$videowidth . '] ' . $embedurl,$txt);
|
||||
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,10 @@ function photo_upload($channel, $observer, $args) {
|
||||
else
|
||||
$visible = 0;
|
||||
|
||||
$deliver = true;
|
||||
if(array_key_exists('deliver',$args))
|
||||
$deliver = intval($args['deliver']);
|
||||
|
||||
// Set to default channel permissions. If the parent directory (album) has permissions set,
|
||||
// use those instead. If we have specific permissions supplied, they take precedence over
|
||||
// all other settings. 'allow_cid' being passed from an external source takes priority over channel settings.
|
||||
@ -330,7 +334,7 @@ function photo_upload($channel, $observer, $args) {
|
||||
|
||||
if($item['mid'] === $item['parent_mid']) {
|
||||
|
||||
$item['body'] = $args['body'];
|
||||
$item['body'] = $summary;
|
||||
$item['obj_type'] = ACTIVITY_OBJ_PHOTO;
|
||||
$item['obj'] = json_encode($object);
|
||||
|
||||
@ -355,14 +359,14 @@ function photo_upload($channel, $observer, $args) {
|
||||
if(($item['edited'] > $r[0]['edited']) || $force) {
|
||||
$item['id'] = $r[0]['id'];
|
||||
$item['uid'] = $channel['channel_id'];
|
||||
item_store_update($item);
|
||||
item_store_update($item,false,$deliver);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$item['aid'] = $channel['channel_account_id'];
|
||||
$item['uid'] = $channel['channel_id'];
|
||||
$item_result = item_store($item);
|
||||
$item_result = item_store($item,false,$deliver);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -414,10 +418,10 @@ function photo_upload($channel, $observer, $args) {
|
||||
|
||||
|
||||
|
||||
$result = item_store($arr);
|
||||
$result = item_store($arr,false,$deliver);
|
||||
$item_id = $result['item_id'];
|
||||
|
||||
if($visible)
|
||||
if($visible && $deliver)
|
||||
Zotlabs\Daemon\Master::Summon(array('Notifier', 'wall-new', $item_id));
|
||||
}
|
||||
|
||||
@ -703,40 +707,65 @@ function gps2Num($coordPart) {
|
||||
return floatval($parts[0]) / floatval($parts[1]);
|
||||
}
|
||||
|
||||
function profile_photo_set_profile_perms($profileid = '') {
|
||||
function profile_photo_set_profile_perms($uid, $profileid = 0) {
|
||||
|
||||
$allowcid = '';
|
||||
if (x($profileid)) {
|
||||
|
||||
$r = q("SELECT photo, profile_guid, id, is_default, uid FROM profile WHERE profile.id = %d OR profile.profile_guid = '%s' LIMIT 1", intval($profileid), dbesc($profileid));
|
||||
|
||||
} else {
|
||||
|
||||
if($profileid) {
|
||||
$r = q("SELECT photo, profile_guid, id, is_default, uid
|
||||
FROM profile WHERE uid = %d and ( profile.id = %d OR profile.profile_guid = '%s') LIMIT 1",
|
||||
intval($profileid),
|
||||
dbesc($profileid)
|
||||
);
|
||||
}
|
||||
else {
|
||||
logger('Resetting permissions on default-profile-photo for user'.local_channel());
|
||||
$r = q("SELECT photo, profile_guid, id, is_default, uid FROM profile WHERE profile.uid = %d AND is_default = 1 LIMIT 1", intval(local_channel()) ); //If no profile is given, we update the default profile
|
||||
|
||||
$r = q("SELECT photo, profile_guid, id, is_default, uid FROM profile
|
||||
WHERE profile.uid = %d AND is_default = 1 LIMIT 1",
|
||||
intval($uid)
|
||||
); //If no profile is given, we update the default profile
|
||||
}
|
||||
if(! $r)
|
||||
return;
|
||||
|
||||
$profile = $r[0];
|
||||
if(x($profile['id']) && x($profile['photo'])) {
|
||||
preg_match("@\w*(?=-\d*$)@i", $profile['photo'], $resource_id);
|
||||
$resource_id = $resource_id[0];
|
||||
|
||||
if($profile['id'] && $profile['photo']) {
|
||||
preg_match("@\w*(?=-\d*$)@i", $profile['photo'], $resource_id);
|
||||
$resource_id = $resource_id[0];
|
||||
|
||||
if (intval($profile['is_default']) != 1) {
|
||||
$r0 = q("SELECT channel_hash FROM channel WHERE channel_id = %d LIMIT 1", intval(local_channel()) );
|
||||
$r1 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%d' ", intval($profile['id'])); //Should not be needed in future. Catches old int-profile-ids.
|
||||
$r2 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%s'", dbesc($profile['profile_guid']));
|
||||
if (! intval($profile['is_default'])) {
|
||||
$r0 = q("SELECT channel_hash FROM channel WHERE channel_id = %d LIMIT 1",
|
||||
intval($uid)
|
||||
);
|
||||
//Should not be needed in future. Catches old int-profile-ids.
|
||||
$r1 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%d' ",
|
||||
intval($profile['id'])
|
||||
);
|
||||
$r2 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%s'",
|
||||
dbesc($profile['profile_guid'])
|
||||
);
|
||||
$allowcid = "<" . $r0[0]['channel_hash'] . ">";
|
||||
foreach ($r1 as $entry) {
|
||||
$allowcid .= "<" . $entry['abook_xchan'] . ">";
|
||||
}
|
||||
foreach ($r2 as $entry) {
|
||||
$allowcid .= "<" . $entry['abook_xchan'] . ">";
|
||||
}
|
||||
$allowcid .= "<" . $entry['abook_xchan'] . ">";
|
||||
}
|
||||
|
||||
q("UPDATE `photo` SET allow_cid = '%s' WHERE resource_id = '%s' AND uid = %d",dbesc($allowcid),dbesc($resource_id),intval($profile['uid']));
|
||||
q("UPDATE photo SET allow_cid = '%s' WHERE resource_id = '%s' AND uid = %d",
|
||||
dbesc($allowcid),
|
||||
dbesc($resource_id),
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
} else {
|
||||
q("UPDATE `photo` SET allow_cid = '' WHERE profile = 1 AND uid = %d",intval($profile['uid'])); //Reset permissions on default profile picture to public
|
||||
}
|
||||
else {
|
||||
//Reset permissions on default profile picture to public
|
||||
q("UPDATE photo SET allow_cid = '' WHERE photo_usage = %d AND uid = %d",
|
||||
intval(PHOTO_PROFILE),
|
||||
intval($uid)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -167,6 +167,12 @@ function reload_plugins() {
|
||||
}
|
||||
}
|
||||
|
||||
function visible_plugin_list() {
|
||||
$r = q("select * from addon where hidden = 0 order by aname asc");
|
||||
return(($r) ? ids_to_array($r,'aname') : array());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief registers a hook.
|
||||
|
@ -400,7 +400,7 @@ function get_things($profile_hash,$uid) {
|
||||
if(! $things[$rr['obj_verb']])
|
||||
$things[$rr['obj_verb']] = array();
|
||||
|
||||
$things[$rr['obj_verb']][] = array('term' => $rr['obj_term'],'url' => $rr['obj_url'],'img' => $rr['obj_imgurl'], 'profile' => $rr['profile_name'],'term_hash' => $rr['obj_obj'], 'likes' => $l,'like_count' => count($l),'like_label' => tt('Like','Likes',count($l),'noun'));
|
||||
$things[$rr['obj_verb']][] = array('term' => $rr['obj_term'],'url' => $rr['obj_url'],'img' => $rr['obj_imgurl'], 'editurl' => z_root() . '/thing/' . $rr['obj_obj'], 'profile' => $rr['profile_name'],'term_hash' => $rr['obj_obj'], 'likes' => $l,'like_count' => count($l),'like_label' => tt('Like','Likes',count($l),'noun'));
|
||||
}
|
||||
$sorted_things = array();
|
||||
if($things) {
|
||||
|
@ -376,30 +376,6 @@ function unxmlify($s) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience wrapper, reverse the operation "bin2hex"
|
||||
* This is a built-in function in php >= 5.4
|
||||
*
|
||||
* @FIXME We already have php >= 5.4 requirements, so can we remove this?
|
||||
*/
|
||||
if(! function_exists('hex2bin')) {
|
||||
function hex2bin($s) {
|
||||
if(! (is_string($s) && strlen($s)))
|
||||
return '';
|
||||
|
||||
if(strlen($s) & 1) {
|
||||
logger('hex2bin: illegal hex string: ' . $s);
|
||||
return $s;
|
||||
}
|
||||
|
||||
if(! ctype_xdigit($s)) {
|
||||
return($s);
|
||||
}
|
||||
|
||||
return(pack("H*",$s));
|
||||
}}
|
||||
|
||||
|
||||
// Automatic pagination.
|
||||
// To use, get the count of total items.
|
||||
// Then call App::set_pager_total($number_items);
|
||||
@ -1283,7 +1259,7 @@ function normalise_link($url) {
|
||||
* is https and the other isn't, or if one is www.something and the other
|
||||
* isn't - and also ignore case differences.
|
||||
*
|
||||
* @see normalis_link()
|
||||
* @see normalise_link()
|
||||
*
|
||||
* @param string $a
|
||||
* @param string $b
|
||||
@ -1635,7 +1611,7 @@ function prepare_text($text, $content_type = 'text/bbcode', $cache = false) {
|
||||
|
||||
function create_export_photo_body(&$item) {
|
||||
if(($item['verb'] === ACTIVITY_POST) && ($item['obj_type'] === ACTIVITY_OBJ_PHOTO)) {
|
||||
$j = json_decode($item['object'],true);
|
||||
$j = json_decode($item['obj'],true);
|
||||
if($j) {
|
||||
$item['body'] .= "\n\n" . (($j['body']) ? $j['body'] : $j['bbcode']);
|
||||
$item['sig'] = '';
|
||||
@ -2050,7 +2026,7 @@ function ids_to_array($arr,$idx = 'id') {
|
||||
$t = array();
|
||||
if($arr) {
|
||||
foreach($arr as $x) {
|
||||
if(! in_array($x[$idx],$t)) {
|
||||
if(array_key_exists($idx,$x) && strlen($x[$idx]) && (! in_array($x[$idx],$t))) {
|
||||
$t[] = $x[$idx];
|
||||
}
|
||||
}
|
||||
@ -2089,9 +2065,9 @@ function xchan_query(&$items,$abook = true,$effective_uid = 0) {
|
||||
}
|
||||
|
||||
foreach($items as $item) {
|
||||
if($item['owner_xchan'] && (! in_array($item['owner_xchan'],$arr)))
|
||||
if($item['owner_xchan'] && (! in_array("'" . dbesc($item['owner_xchan']) . "'",$arr)))
|
||||
$arr[] = "'" . dbesc($item['owner_xchan']) . "'";
|
||||
if($item['author_xchan'] && (! in_array($item['author_xchan'],$arr)))
|
||||
if($item['author_xchan'] && (! in_array("'" . dbesc($item['author_xchan']) . "'",$arr)))
|
||||
$arr[] = "'" . dbesc($item['author_xchan']) . "'";
|
||||
}
|
||||
}
|
||||
@ -2124,9 +2100,9 @@ function xchan_mail_query(&$item) {
|
||||
$arr = array();
|
||||
$chans = null;
|
||||
if($item) {
|
||||
if($item['from_xchan'] && (! in_array($item['from_xchan'],$arr)))
|
||||
if($item['from_xchan'] && (! in_array("'" . dbesc($item['from_xchan']) . "'",$arr)))
|
||||
$arr[] = "'" . dbesc($item['from_xchan']) . "'";
|
||||
if($item['to_xchan'] && (! in_array($item['to_xchan'],$arr)))
|
||||
if($item['to_xchan'] && (! in_array("'" . dbesc($item['to_xchan']) . "'",$arr)))
|
||||
$arr[] = "'" . dbesc($item['to_xchan']) . "'";
|
||||
}
|
||||
|
||||
@ -2887,6 +2863,12 @@ function text_highlight($s,$lang) {
|
||||
if($lang === 'js')
|
||||
$lang = 'javascript';
|
||||
|
||||
if($lang === 'json') {
|
||||
$lang = 'javascript';
|
||||
if(! strpos(trim($s),"\n"))
|
||||
$s = jindent($s);
|
||||
}
|
||||
|
||||
if(! strpos('Text_Highlighter',get_include_path())) {
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . 'library/Text_Highlighter');
|
||||
}
|
||||
@ -2899,6 +2881,11 @@ function text_highlight($s,$lang) {
|
||||
$tag_added = false;
|
||||
$s = trim(html_entity_decode($s,ENT_COMPAT));
|
||||
$s = str_replace(" ","\t",$s);
|
||||
|
||||
// The highlighter library insists on an opening php tag for php code blocks. If
|
||||
// it isn't present, nothing is highlighted. So we're going to see if it's present.
|
||||
// If not, we'll add it, and then quietly remove it after we get the processed output back.
|
||||
|
||||
if($lang === 'php') {
|
||||
if(strpos('<?php',$s) !== 0) {
|
||||
$s = '<?php' . "\n" . $s;
|
||||
|
@ -1158,7 +1158,7 @@ function widget_cover_photo($arr) {
|
||||
if(array_key_exists('subtitle', $arr) && isset($arr['subtitle']))
|
||||
$subtitle = $arr['subtitle'];
|
||||
else
|
||||
$subtitle = $channel['xchan_addr'];
|
||||
$subtitle = str_replace('@','@',$channel['xchan_addr']);
|
||||
|
||||
$c = get_cover_photo($channel_id,'html');
|
||||
|
||||
|
@ -347,7 +347,7 @@ function wiki_revert_page($arr) {
|
||||
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
|
||||
$commitHash = ((array_key_exists('commitHash',$arr)) ? $arr['commitHash'] : null);
|
||||
if (! $commitHash) {
|
||||
return array('content' => $content, 'message' => 'No commit has provided', 'success' => false);
|
||||
return array('content' => $content, 'message' => 'No commit was provided', 'success' => false);
|
||||
}
|
||||
$w = wiki_get_wiki($resource_id);
|
||||
if (!$w['path']) {
|
||||
@ -378,6 +378,48 @@ function wiki_revert_page($arr) {
|
||||
}
|
||||
}
|
||||
|
||||
function wiki_compare_page($arr) {
|
||||
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
|
||||
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
|
||||
$currentCommit = ((array_key_exists('currentCommit',$arr)) ? $arr['currentCommit'] : 'HEAD');
|
||||
$compareCommit = ((array_key_exists('compareCommit',$arr)) ? $arr['compareCommit'] : null);
|
||||
if (! $compareCommit) {
|
||||
return array('message' => 'No compare commit was provided', 'success' => false);
|
||||
}
|
||||
$w = wiki_get_wiki($resource_id);
|
||||
if (!$w['path']) {
|
||||
return array('message' => 'Error reading wiki', 'success' => false);
|
||||
}
|
||||
$page_path = $w['path'].'/'.$pageUrlName.'.md';
|
||||
if (is_readable($page_path) === true) {
|
||||
$reponame = ((array_key_exists('title', $w['wiki'])) ? urlencode($w['wiki']['title']) : 'repo');
|
||||
if($reponame === '') {
|
||||
$reponame = 'repo';
|
||||
}
|
||||
$git = new GitRepo('', null, false, $w['wiki']['title'], $w['path']);
|
||||
$compareContent = $currentContent = '';
|
||||
try {
|
||||
foreach ($git->git->tree($currentCommit) as $object) {
|
||||
if ($object['type'] == 'blob' && $object['file'] === $pageUrlName.'.md' ) {
|
||||
$currentContent = $git->git->cat->blob($object['hash']);
|
||||
}
|
||||
}
|
||||
foreach ($git->git->tree($compareCommit) as $object) {
|
||||
if ($object['type'] == 'blob' && $object['file'] === $pageUrlName.'.md' ) {
|
||||
$compareContent = $git->git->cat->blob($object['hash']);
|
||||
}
|
||||
}
|
||||
require_once('library/class.Diff.php');
|
||||
$diff = Diff::toTable(Diff::compare($currentContent, $compareContent));
|
||||
} catch (\PHPGit\Exception\GitException $e) {
|
||||
return array('message' => 'GitRepo error thrown', 'success' => false);
|
||||
}
|
||||
return array('diff' => $diff, 'message' => '', 'success' => true);
|
||||
} else {
|
||||
return array('message' => 'Page file not writable', 'success' => false);
|
||||
}
|
||||
}
|
||||
|
||||
function wiki_git_commit($arr) {
|
||||
$files = ((array_key_exists('files', $arr)) ? $arr['files'] : null);
|
||||
$all = ((array_key_exists('all', $arr)) ? $arr['all'] : false);
|
||||
|
@ -552,7 +552,7 @@ function zot_refresh($them, $channel = null, $force = false) {
|
||||
unset($new_connection[0]['abook_account']);
|
||||
unset($new_connection[0]['abook_channel']);
|
||||
|
||||
$abconfig = load_abconfig($channel['channel_hash'],$new_connection['abook_xchan']);
|
||||
$abconfig = load_abconfig($channel['channel_id'],$new_connection['abook_xchan']);
|
||||
if($abconfig)
|
||||
$new_connection['abconfig'] = $abconfig;
|
||||
|
||||
@ -3031,7 +3031,8 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
|
||||
|
||||
$info = (($packet) ? $packet : array());
|
||||
$info['type'] = 'channel_sync';
|
||||
$info['encoding'] = 'red'; // note: not zot, this packet is very red specific
|
||||
$info['encoding'] = 'red'; // note: not zot, this packet is very platform specific
|
||||
$info['relocate'] = ['channel_address' => $channel['channel_address'], 'url' => z_root() ];
|
||||
|
||||
if(array_key_exists($uid,App::$config) && array_key_exists('transient',App::$config[$uid])) {
|
||||
$settings = App::$config[$uid]['transient'];
|
||||
@ -3169,10 +3170,13 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
|
||||
sync_events($channel,$arr['event']);
|
||||
|
||||
if(array_key_exists('event_item',$arr) && $arr['event_item'])
|
||||
sync_items($channel,$arr['event_item']);
|
||||
sync_items($channel,$arr['event_item'],((array_key_exists('relocate',$arr)) ? $arr['relocate'] : null));
|
||||
|
||||
if(array_key_exists('item',$arr) && $arr['item'])
|
||||
sync_items($channel,$arr['item']);
|
||||
sync_items($channel,$arr['item'],((array_key_exists('relocate',$arr)) ? $arr['relocate'] : null));
|
||||
|
||||
// deprecated, maintaining for a few months for upward compatibility
|
||||
// this should sync webpages, but the logic is a bit subtle
|
||||
|
||||
if(array_key_exists('item_id',$arr) && $arr['item_id'])
|
||||
sync_items($channel,$arr['item_id']);
|
||||
@ -3331,8 +3335,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
|
||||
if($abconfig) {
|
||||
// @fixme does not handle sync of del_abconfig
|
||||
foreach($abconfig as $abc) {
|
||||
if($abc['chan'] === $channel['channel_hash'])
|
||||
set_abconfig($abc['chan'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']);
|
||||
set_abconfig($channel['channel_id'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3529,13 +3532,6 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(array_key_exists('item',$arr) && $arr['item'])
|
||||
sync_items($channel,$arr['item']);
|
||||
|
||||
if(array_key_exists('item_id',$arr) && $arr['item_id'])
|
||||
sync_items($channel,$arr['item_id']);
|
||||
|
||||
$addon = array('channel' => $channel,'data' => $arr);
|
||||
call_hooks('process_channel_sync_delivery',$addon);
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `abconfig` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`chan` char(255) NOT NULL DEFAULT '',
|
||||
`chan` int(10) unsigned NOT NULL DEFAULT '',
|
||||
`xchan` char(255) NOT NULL DEFAULT '',
|
||||
`cat` char(255) NOT NULL DEFAULT '',
|
||||
`k` char(255) NOT NULL DEFAULT '',
|
||||
@ -199,6 +199,26 @@ CREATE TABLE IF NOT EXISTS `cache` (
|
||||
PRIMARY KEY (`k`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `cal` (
|
||||
`cal_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`cal_aid` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`cal_uid` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`cal_hash` varchar(255) NOT NULL DEFAULT '',
|
||||
`cal_name` varchar(255) NOT NULL DEFAULT '',
|
||||
`uri` varchar(255) NOT NULL DEFAULT '',
|
||||
`logname` varchar(255) NOT NULL DEFAULT '',
|
||||
`pass` varchar(255) NOT NULL DEFAULT '',
|
||||
`ctag` varchar(255) NOT NULL DEFAULT '',
|
||||
`synctoken` varchar(255) NOT NULL DEFAULT '',
|
||||
`cal_types` varchar(255) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (`cal_id`),
|
||||
KEY `cal_aid` (`cal_aid`),
|
||||
KEY `cal_uid` (`cal_uid`),
|
||||
KEY `cal_hash` (`cal_hash`),
|
||||
KEY `cal_name` (`cal_name`),
|
||||
KEY `cal_types` (`cal_types`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `channel` (
|
||||
`channel_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`channel_account_id` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
@ -394,6 +414,7 @@ CREATE TABLE IF NOT EXISTS `event` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`aid` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`uid` int(11) NOT NULL DEFAULT '0',
|
||||
`cal_id` int(11) unsigned NOT NULL DEFAULT '0',
|
||||
`event_xchan` char(255) NOT NULL DEFAULT '',
|
||||
`event_hash` char(255) NOT NULL DEFAULT '',
|
||||
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||
@ -420,6 +441,7 @@ CREATE TABLE IF NOT EXISTS `event` (
|
||||
`event_vdata` text NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `uid` (`uid`),
|
||||
KEY `cal_id` (`cal_id`),
|
||||
KEY `etype` (`etype`),
|
||||
KEY `dtstart` (`dtstart`),
|
||||
KEY `dtend` (`dtend`),
|
||||
|
@ -1,6 +1,6 @@
|
||||
CREATE TABLE "abconfig" (
|
||||
"id" serial NOT NULL,
|
||||
"chan" text NOT NULL,
|
||||
"chan" bigint NOT NULL,
|
||||
"xchan" text NOT NULL,
|
||||
"cat" text NOT NULL,
|
||||
"k" text NOT NULL,
|
||||
@ -193,6 +193,26 @@ CREATE TABLE "cache" (
|
||||
"updated" timestamp NOT NULL,
|
||||
PRIMARY KEY ("k")
|
||||
);
|
||||
CREATE TABLE "cal" (
|
||||
"cal_id" serial NOT NULL,
|
||||
"cal_aid" bigint NOT NULL DEFAULT '0',
|
||||
"cal_uid" bigint NOT NULL DEFAULT '0',
|
||||
"cal_hash" text NOT NULL,
|
||||
"cal_name" text NOT NULL,
|
||||
"uri" text NOT NULL,
|
||||
"logname" text NOT NULL,
|
||||
"pass" text NOT NULL,
|
||||
"ctag" text NOT NULL,
|
||||
"synctoken" text NOT NULL,
|
||||
"cal_types" text NOT NULL DEFAULT "0",
|
||||
PRIMARY KEY ("cal_id")
|
||||
);
|
||||
create index "cal_hash_idx" on cal ("cal_hash");
|
||||
create index "cal_name_idx" on cal ("cal_name");
|
||||
create index "cal_types_idx" on cal ("cal_types");
|
||||
create index "cal_aid_idx" on cal ("cal_aid");
|
||||
create index "cal_uid_idx" on cal ("cal_uid");
|
||||
|
||||
CREATE TABLE "channel" (
|
||||
"channel_id" serial NOT NULL,
|
||||
"channel_account_id" bigint NOT NULL DEFAULT '0',
|
||||
@ -380,14 +400,11 @@ create index "dreport_xchan" on dreport ("dreport_xchan");
|
||||
create index "dreport_queue" on dreport ("dreport_queue");
|
||||
create index "dreport_channel" on dreport ("dreport_channel");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
CREATE TABLE "event" (
|
||||
"id" serial NOT NULL,
|
||||
"aid" bigint NOT NULL DEFAULT '0',
|
||||
"uid" bigint NOT NULL,
|
||||
"cal_id" bigint NOT NULL DEFAULT '0',
|
||||
"event_xchan" text NOT NULL DEFAULT '',
|
||||
"event_hash" text NOT NULL DEFAULT '',
|
||||
"created" timestamp NOT NULL DEFAULT '0001-01-01 00:00:00',
|
||||
@ -415,6 +432,7 @@ CREATE TABLE "event" (
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
create index "event_uid_idx" on event ("uid");
|
||||
create index "event_cal_idx" on event ("cal_id");
|
||||
create index "event_etype_idx" on event ("etype");
|
||||
create index "event_dtstart_idx" on event ("dtstart");
|
||||
create index "event_dtend_idx" on event ("dtend");
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
define( 'UPDATE_VERSION' , 1177 );
|
||||
define( 'UPDATE_VERSION' , 1179 );
|
||||
|
||||
/**
|
||||
*
|
||||
@ -2266,4 +2266,98 @@ function update_r1176() {
|
||||
}
|
||||
return UPDATE_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
function update_r1177() {
|
||||
|
||||
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
|
||||
$r1 = q("alter table event add cal_id bigint NOT NULL DEFAULT '0'");
|
||||
$r2 = q("create index \"event_cal_idx\" on event (\"cal_id\") ");
|
||||
|
||||
$r3 = q("CREATE TABLE \"cal\" (
|
||||
\"cal_id\" serial NOT NULL,
|
||||
\"cal_aid\" bigint NOT NULL DEFAULT '0',
|
||||
\"cal_uid\" bigint NOT NULL DEFAULT '0',
|
||||
\"cal_hash\" text NOT NULL,
|
||||
\"cal_name\" text NOT NULL,
|
||||
\"uri\" text NOT NULL,
|
||||
\"logname\" text NOT NULL,
|
||||
\"pass\" text NOT NULL,
|
||||
\"ctag\" text NOT NULL,
|
||||
\"synctoken\" text NOT NULL,
|
||||
\"cal_types\" text NOT NULL,
|
||||
PRIMARY KEY (\"cal_id\") ");
|
||||
$r4 = q("create index \"cal_hash_idx\" on cal (\"cal_hash\") ");
|
||||
$r5 = q("create index \"cal_name_idx\" on cal (\"cal_name\") ");
|
||||
$r6 = q("create index \"cal_types_idx\" on cal (\"cal_types\") ");
|
||||
$r7 = q("create index \"cal_aid_idx\" on cal (\"cal_aid\") ");
|
||||
$r8 = q("create index \"cal_uid_idx\" on cal (\"cal_uid\") ");
|
||||
$r = $r1 && $r2 && $r3 && $r4 && $r5 && $r6 && $r7 && $r8;
|
||||
}
|
||||
else {
|
||||
$r1 = q("alter table event add cal_id int(10) unsigned NOT NULL DEFAULT '0',
|
||||
add index ( cal_id ) ");
|
||||
|
||||
$r2 = q("CREATE TABLE IF NOT EXISTS `cal` (
|
||||
`cal_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`cal_aid` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`cal_uid` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`cal_hash` varchar(255) NOT NULL DEFAULT '',
|
||||
`cal_name` varchar(255) NOT NULL DEFAULT '',
|
||||
`uri` varchar(255) NOT NULL DEFAULT '',
|
||||
`logname` varchar(255) NOT NULL DEFAULT '',
|
||||
`pass` varchar(255) NOT NULL DEFAULT '',
|
||||
`ctag` varchar(255) NOT NULL DEFAULT '',
|
||||
`synctoken` varchar(255) NOT NULL DEFAULT '',
|
||||
`cal_types` varchar(255) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (`cal_id`),
|
||||
KEY `cal_aid` (`cal_aid`),
|
||||
KEY `cal_uid` (`cal_uid`),
|
||||
KEY `cal_hash` (`cal_hash`),
|
||||
KEY `cal_name` (`cal_name`),
|
||||
KEY `cal_types` (`cal_types`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ");
|
||||
|
||||
$r = $r1 && $r2;
|
||||
}
|
||||
|
||||
if($r)
|
||||
return UPDATE_SUCCESS;
|
||||
return UPDATE_FAILED;
|
||||
}
|
||||
|
||||
|
||||
function update_r1178() {
|
||||
|
||||
$c2 = null;
|
||||
|
||||
$c1 = q("SELECT channel_id, channel_hash from channel where true");
|
||||
if($c1) {
|
||||
$c2 = q("SELECT id, chan from abconfig where true");
|
||||
if($c2) {
|
||||
for($x = 0; $x < count($c2); $x ++) {
|
||||
foreach($c1 as $c) {
|
||||
if($c['channel_hash'] == $c2[$x]['chan']) {
|
||||
$c2[$x]['chan'] = $c['channel_id'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$r1 = q("ALTER TABLE abconfig CHANGE chan chan int(10) unsigned NOT NULL DEFAULT '0' ");
|
||||
|
||||
if($c2) {
|
||||
foreach($c2 as $c) {
|
||||
q("UPDATE abconfig SET chan = %d where id = %d",
|
||||
intval($c['chan']),
|
||||
intval($c['id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if($r1)
|
||||
return UPDATE_SUCCESS;
|
||||
return UPDATE_FAILED;
|
||||
}
|
386
library/class.Diff.php
Normal file
386
library/class.Diff.php
Normal file
@ -0,0 +1,386 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|
||||
class.Diff.php
|
||||
|
||||
A class containing a diff implementation
|
||||
|
||||
Created by Stephen Morley - http://stephenmorley.org/ - and released under the
|
||||
terms of the CC0 1.0 Universal legal code:
|
||||
|
||||
http://creativecommons.org/publicdomain/zero/1.0/legalcode
|
||||
|
||||
*/
|
||||
|
||||
// A class containing functions for computing diffs and formatting the output.
|
||||
class Diff{
|
||||
|
||||
// define the constants
|
||||
const UNMODIFIED = 0;
|
||||
const DELETED = 1;
|
||||
const INSERTED = 2;
|
||||
|
||||
/* Returns the diff for two strings. The return value is an array, each of
|
||||
* whose values is an array containing two values: a line (or character, if
|
||||
* $compareCharacters is true), and one of the constants DIFF::UNMODIFIED (the
|
||||
* line or character is in both strings), DIFF::DELETED (the line or character
|
||||
* is only in the first string), and DIFF::INSERTED (the line or character is
|
||||
* only in the second string). The parameters are:
|
||||
*
|
||||
* $string1 - the first string
|
||||
* $string2 - the second string
|
||||
* $compareCharacters - true to compare characters, and false to compare
|
||||
* lines; this optional parameter defaults to false
|
||||
*/
|
||||
public static function compare(
|
||||
$string1, $string2, $compareCharacters = false){
|
||||
|
||||
// initialise the sequences and comparison start and end positions
|
||||
$start = 0;
|
||||
if ($compareCharacters){
|
||||
$sequence1 = $string1;
|
||||
$sequence2 = $string2;
|
||||
$end1 = strlen($string1) - 1;
|
||||
$end2 = strlen($string2) - 1;
|
||||
}else{
|
||||
$sequence1 = preg_split('/\R/', $string1);
|
||||
$sequence2 = preg_split('/\R/', $string2);
|
||||
$end1 = count($sequence1) - 1;
|
||||
$end2 = count($sequence2) - 1;
|
||||
}
|
||||
|
||||
// skip any common prefix
|
||||
while ($start <= $end1 && $start <= $end2
|
||||
&& $sequence1[$start] == $sequence2[$start]){
|
||||
$start ++;
|
||||
}
|
||||
|
||||
// skip any common suffix
|
||||
while ($end1 >= $start && $end2 >= $start
|
||||
&& $sequence1[$end1] == $sequence2[$end2]){
|
||||
$end1 --;
|
||||
$end2 --;
|
||||
}
|
||||
|
||||
// compute the table of longest common subsequence lengths
|
||||
$table = self::computeTable($sequence1, $sequence2, $start, $end1, $end2);
|
||||
|
||||
// generate the partial diff
|
||||
$partialDiff =
|
||||
self::generatePartialDiff($table, $sequence1, $sequence2, $start);
|
||||
|
||||
// generate the full diff
|
||||
$diff = array();
|
||||
for ($index = 0; $index < $start; $index ++){
|
||||
$diff[] = array($sequence1[$index], self::UNMODIFIED);
|
||||
}
|
||||
while (count($partialDiff) > 0) $diff[] = array_pop($partialDiff);
|
||||
for ($index = $end1 + 1;
|
||||
$index < ($compareCharacters ? strlen($sequence1) : count($sequence1));
|
||||
$index ++){
|
||||
$diff[] = array($sequence1[$index], self::UNMODIFIED);
|
||||
}
|
||||
|
||||
// return the diff
|
||||
return $diff;
|
||||
|
||||
}
|
||||
|
||||
/* Returns the diff for two files. The parameters are:
|
||||
*
|
||||
* $file1 - the path to the first file
|
||||
* $file2 - the path to the second file
|
||||
* $compareCharacters - true to compare characters, and false to compare
|
||||
* lines; this optional parameter defaults to false
|
||||
*/
|
||||
public static function compareFiles(
|
||||
$file1, $file2, $compareCharacters = false){
|
||||
|
||||
// return the diff of the files
|
||||
return self::compare(
|
||||
file_get_contents($file1),
|
||||
file_get_contents($file2),
|
||||
$compareCharacters);
|
||||
|
||||
}
|
||||
|
||||
/* Returns the table of longest common subsequence lengths for the specified
|
||||
* sequences. The parameters are:
|
||||
*
|
||||
* $sequence1 - the first sequence
|
||||
* $sequence2 - the second sequence
|
||||
* $start - the starting index
|
||||
* $end1 - the ending index for the first sequence
|
||||
* $end2 - the ending index for the second sequence
|
||||
*/
|
||||
private static function computeTable(
|
||||
$sequence1, $sequence2, $start, $end1, $end2){
|
||||
|
||||
// determine the lengths to be compared
|
||||
$length1 = $end1 - $start + 1;
|
||||
$length2 = $end2 - $start + 1;
|
||||
|
||||
// initialise the table
|
||||
$table = array(array_fill(0, $length2 + 1, 0));
|
||||
|
||||
// loop over the rows
|
||||
for ($index1 = 1; $index1 <= $length1; $index1 ++){
|
||||
|
||||
// create the new row
|
||||
$table[$index1] = array(0);
|
||||
|
||||
// loop over the columns
|
||||
for ($index2 = 1; $index2 <= $length2; $index2 ++){
|
||||
|
||||
// store the longest common subsequence length
|
||||
if ($sequence1[$index1 + $start - 1]
|
||||
== $sequence2[$index2 + $start - 1]){
|
||||
$table[$index1][$index2] = $table[$index1 - 1][$index2 - 1] + 1;
|
||||
}else{
|
||||
$table[$index1][$index2] =
|
||||
max($table[$index1 - 1][$index2], $table[$index1][$index2 - 1]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// return the table
|
||||
return $table;
|
||||
|
||||
}
|
||||
|
||||
/* Returns the partial diff for the specificed sequences, in reverse order.
|
||||
* The parameters are:
|
||||
*
|
||||
* $table - the table returned by the computeTable function
|
||||
* $sequence1 - the first sequence
|
||||
* $sequence2 - the second sequence
|
||||
* $start - the starting index
|
||||
*/
|
||||
private static function generatePartialDiff(
|
||||
$table, $sequence1, $sequence2, $start){
|
||||
|
||||
// initialise the diff
|
||||
$diff = array();
|
||||
|
||||
// initialise the indices
|
||||
$index1 = count($table) - 1;
|
||||
$index2 = count($table[0]) - 1;
|
||||
|
||||
// loop until there are no items remaining in either sequence
|
||||
while ($index1 > 0 || $index2 > 0){
|
||||
|
||||
// check what has happened to the items at these indices
|
||||
if ($index1 > 0 && $index2 > 0
|
||||
&& $sequence1[$index1 + $start - 1]
|
||||
== $sequence2[$index2 + $start - 1]){
|
||||
|
||||
// update the diff and the indices
|
||||
$diff[] = array($sequence1[$index1 + $start - 1], self::UNMODIFIED);
|
||||
$index1 --;
|
||||
$index2 --;
|
||||
|
||||
}elseif ($index2 > 0
|
||||
&& $table[$index1][$index2] == $table[$index1][$index2 - 1]){
|
||||
|
||||
// update the diff and the indices
|
||||
$diff[] = array($sequence2[$index2 + $start - 1], self::INSERTED);
|
||||
$index2 --;
|
||||
|
||||
}else{
|
||||
|
||||
// update the diff and the indices
|
||||
$diff[] = array($sequence1[$index1 + $start - 1], self::DELETED);
|
||||
$index1 --;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// return the diff
|
||||
return $diff;
|
||||
|
||||
}
|
||||
|
||||
/* Returns a diff as a string, where unmodified lines are prefixed by ' ',
|
||||
* deletions are prefixed by '- ', and insertions are prefixed by '+ '. The
|
||||
* parameters are:
|
||||
*
|
||||
* $diff - the diff array
|
||||
* $separator - the separator between lines; this optional parameter defaults
|
||||
* to "\n"
|
||||
*/
|
||||
public static function toString($diff, $separator = "\n"){
|
||||
|
||||
// initialise the string
|
||||
$string = '';
|
||||
|
||||
// loop over the lines in the diff
|
||||
foreach ($diff as $line){
|
||||
|
||||
// extend the string with the line
|
||||
switch ($line[1]){
|
||||
case self::UNMODIFIED : $string .= ' ' . $line[0];break;
|
||||
case self::DELETED : $string .= '- ' . $line[0];break;
|
||||
case self::INSERTED : $string .= '+ ' . $line[0];break;
|
||||
}
|
||||
|
||||
// extend the string with the separator
|
||||
$string .= $separator;
|
||||
|
||||
}
|
||||
|
||||
// return the string
|
||||
return $string;
|
||||
|
||||
}
|
||||
|
||||
/* Returns a diff as an HTML string, where unmodified lines are contained
|
||||
* within 'span' elements, deletions are contained within 'del' elements, and
|
||||
* insertions are contained within 'ins' elements. The parameters are:
|
||||
*
|
||||
* $diff - the diff array
|
||||
* $separator - the separator between lines; this optional parameter defaults
|
||||
* to '<br>'
|
||||
*/
|
||||
public static function toHTML($diff, $separator = '<br>'){
|
||||
|
||||
// initialise the HTML
|
||||
$html = '';
|
||||
|
||||
// loop over the lines in the diff
|
||||
foreach ($diff as $line){
|
||||
|
||||
// extend the HTML with the line
|
||||
switch ($line[1]){
|
||||
case self::UNMODIFIED : $element = 'span'; break;
|
||||
case self::DELETED : $element = 'del'; break;
|
||||
case self::INSERTED : $element = 'ins'; break;
|
||||
}
|
||||
$html .=
|
||||
'<' . $element . '>'
|
||||
. htmlspecialchars($line[0])
|
||||
. '</' . $element . '>';
|
||||
|
||||
// extend the HTML with the separator
|
||||
$html .= $separator;
|
||||
|
||||
}
|
||||
|
||||
// return the HTML
|
||||
return $html;
|
||||
|
||||
}
|
||||
|
||||
/* Returns a diff as an HTML table. The parameters are:
|
||||
*
|
||||
* $diff - the diff array
|
||||
* $indentation - indentation to add to every line of the generated HTML; this
|
||||
* optional parameter defaults to ''
|
||||
* $separator - the separator between lines; this optional parameter
|
||||
* defaults to '<br>'
|
||||
*/
|
||||
public static function toTable($diff, $indentation = '', $separator = '<br>'){
|
||||
|
||||
// initialise the HTML
|
||||
$html = $indentation . "<table class=\"diff\">\n";
|
||||
|
||||
// loop over the lines in the diff
|
||||
$index = 0;
|
||||
while ($index < count($diff)){
|
||||
|
||||
// determine the line type
|
||||
switch ($diff[$index][1]){
|
||||
|
||||
// display the content on the left and right
|
||||
case self::UNMODIFIED:
|
||||
$leftCell =
|
||||
self::getCellContent(
|
||||
$diff, $indentation, $separator, $index, self::UNMODIFIED);
|
||||
$rightCell = $leftCell;
|
||||
break;
|
||||
|
||||
// display the deleted on the left and inserted content on the right
|
||||
case self::DELETED:
|
||||
$leftCell =
|
||||
self::getCellContent(
|
||||
$diff, $indentation, $separator, $index, self::DELETED);
|
||||
$rightCell =
|
||||
self::getCellContent(
|
||||
$diff, $indentation, $separator, $index, self::INSERTED);
|
||||
break;
|
||||
|
||||
// display the inserted content on the right
|
||||
case self::INSERTED:
|
||||
$leftCell = '';
|
||||
$rightCell =
|
||||
self::getCellContent(
|
||||
$diff, $indentation, $separator, $index, self::INSERTED);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// extend the HTML with the new row
|
||||
$html .=
|
||||
$indentation
|
||||
. " <tr>\n"
|
||||
. $indentation
|
||||
. ' <td class="diff'
|
||||
. ($leftCell == $rightCell
|
||||
? 'Unmodified'
|
||||
: ($leftCell == '' ? 'Blank' : 'Deleted'))
|
||||
. '">'
|
||||
. $leftCell
|
||||
. "</td>\n"
|
||||
. $indentation
|
||||
. ' <td class="diff'
|
||||
. ($leftCell == $rightCell
|
||||
? 'Unmodified'
|
||||
: ($rightCell == '' ? 'Blank' : 'Inserted'))
|
||||
. '">'
|
||||
. $rightCell
|
||||
. "</td>\n"
|
||||
. $indentation
|
||||
. " </tr>\n";
|
||||
|
||||
}
|
||||
|
||||
// return the HTML
|
||||
return $html . $indentation . "</table>\n";
|
||||
|
||||
}
|
||||
|
||||
/* Returns the content of the cell, for use in the toTable function. The
|
||||
* parameters are:
|
||||
*
|
||||
* $diff - the diff array
|
||||
* $indentation - indentation to add to every line of the generated HTML
|
||||
* $separator - the separator between lines
|
||||
* $index - the current index, passes by reference
|
||||
* $type - the type of line
|
||||
*/
|
||||
private static function getCellContent(
|
||||
$diff, $indentation, $separator, &$index, $type){
|
||||
|
||||
// initialise the HTML
|
||||
$html = '';
|
||||
|
||||
// loop over the matching lines, adding them to the HTML
|
||||
while ($index < count($diff) && $diff[$index][1] == $type){
|
||||
$html .=
|
||||
'<span>'
|
||||
. htmlspecialchars($diff[$index][0])
|
||||
. '</span>'
|
||||
. $separator;
|
||||
$index ++;
|
||||
}
|
||||
|
||||
// return the HTML
|
||||
return $html;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
@ -1,8 +1,51 @@
|
||||
|
||||
v2.7.3 (2016-06-02)
|
||||
-------------------
|
||||
|
||||
internal enhancements that plugins can benefit from:
|
||||
- EventEmitter not correctly working with stopListeningTo
|
||||
- normalizeEvent hook for manipulating event data
|
||||
|
||||
|
||||
v2.7.2 (2016-05-20)
|
||||
-------------------
|
||||
|
||||
- fixed desktops/laptops with touch support not accepting mouse events for
|
||||
dayClick/dragging/resizing (#3154, #3149)
|
||||
- fixed dayClick incorrectly triggered on touch scroll (#3152)
|
||||
- fixed touch event dragging wrongfully beginning upon scrolling document (#3160)
|
||||
- fixed minified JS still contained comments
|
||||
- UI change: mouse users must hover over an event to reveal its resizers
|
||||
|
||||
|
||||
v2.7.1 (2016-05-01)
|
||||
-------------------
|
||||
|
||||
- dayClick not firing on touch devices (#3138)
|
||||
- icons for prev/next not working in MS Edge (#2852)
|
||||
- fix bad languages troubles with firewalls (#3133, #3132)
|
||||
- update all dev dependencies (#3145, #3010, #2901, #251)
|
||||
- git-ignore npm debug logs (#3011)
|
||||
- misc automated test updates (#3139, #3147)
|
||||
- Google Calendar htmlLink not always defined (#2844)
|
||||
|
||||
|
||||
v2.7.0 (2016-04-23)
|
||||
-------------------
|
||||
|
||||
touch device support (#994):
|
||||
- smoother scrolling
|
||||
- interactions initiated via "long press":
|
||||
- event drag-n-drop
|
||||
- event resize
|
||||
- time-range selecting
|
||||
- `longPressDelay`
|
||||
|
||||
|
||||
v2.6.1 (2016-02-17)
|
||||
-------------------
|
||||
|
||||
- make nowIndicator positioning refresh on window resize
|
||||
- make `nowIndicator` positioning refresh on window resize
|
||||
|
||||
|
||||
v2.6.0 (2016-01-07)
|
||||
|
@ -41,7 +41,7 @@ Also, you will need the [grunt-cli][grunt-cli] and [bower][bower] packages insta
|
||||
|
||||
Then, clone FullCalendar's git repo:
|
||||
|
||||
git clone git://github.com/arshaw/fullcalendar.git
|
||||
git clone git://github.com/fullcalendar/fullcalendar.git
|
||||
|
||||
Enter the directory and install FullCalendar's development dependencies:
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* FullCalendar v2.6.1 Stylesheet
|
||||
* FullCalendar v2.7.3 Stylesheet
|
||||
* Docs & License: http://fullcalendar.io/
|
||||
* (c) 2015 Adam Shaw
|
||||
* (c) 2016 Adam Shaw
|
||||
*/
|
||||
|
||||
|
||||
@ -28,6 +28,7 @@ body .fc { /* extra precedence to overcome jqui */
|
||||
.fc-unthemed tbody,
|
||||
.fc-unthemed .fc-divider,
|
||||
.fc-unthemed .fc-row,
|
||||
.fc-unthemed .fc-content, /* for gutter border */
|
||||
.fc-unthemed .fc-popover {
|
||||
border-color: #ddd;
|
||||
}
|
||||
@ -72,7 +73,6 @@ body .fc { /* extra precedence to overcome jqui */
|
||||
|
||||
.fc-icon {
|
||||
display: inline-block;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
line-height: 1em;
|
||||
font-size: 1em;
|
||||
@ -99,7 +99,6 @@ NOTE: use percentage font sizes or else old IE chokes
|
||||
|
||||
.fc-icon:after {
|
||||
position: relative;
|
||||
margin: 0 -1em; /* ensures character will be centered, regardless of width */
|
||||
}
|
||||
|
||||
.fc-icon-left-single-arrow:after {
|
||||
@ -107,7 +106,6 @@ NOTE: use percentage font sizes or else old IE chokes
|
||||
font-weight: bold;
|
||||
font-size: 200%;
|
||||
top: -7%;
|
||||
left: 3%;
|
||||
}
|
||||
|
||||
.fc-icon-right-single-arrow:after {
|
||||
@ -115,7 +113,6 @@ NOTE: use percentage font sizes or else old IE chokes
|
||||
font-weight: bold;
|
||||
font-size: 200%;
|
||||
top: -7%;
|
||||
left: -3%;
|
||||
}
|
||||
|
||||
.fc-icon-left-double-arrow:after {
|
||||
@ -134,14 +131,12 @@ NOTE: use percentage font sizes or else old IE chokes
|
||||
content: "\25C4";
|
||||
font-size: 125%;
|
||||
top: 3%;
|
||||
left: -2%;
|
||||
}
|
||||
|
||||
.fc-icon-right-triangle:after {
|
||||
content: "\25BA";
|
||||
font-size: 125%;
|
||||
top: 3%;
|
||||
left: 2%;
|
||||
}
|
||||
|
||||
.fc-icon-down-triangle:after {
|
||||
@ -491,15 +486,15 @@ temporary rendered events).
|
||||
/* Scrolling Container
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
|
||||
.fc-scroller { /* this class goes on elements for guaranteed vertical scrollbars */
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
.fc-scroller {
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.fc-scroller > * { /* we expect an immediate inner element */
|
||||
/* TODO: move to agenda/basic */
|
||||
.fc-scroller > .fc-day-grid,
|
||||
.fc-scroller > .fc-time-grid {
|
||||
position: relative; /* re-scope all positions */
|
||||
width: 100%; /* hack to force re-sizing this inner element when scrollbars appear/disappear */
|
||||
overflow: hidden; /* don't let negative margins or absolute positioning create further scroll */
|
||||
}
|
||||
|
||||
|
||||
@ -547,15 +542,68 @@ temporary rendered events).
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* resizer (cursor AND touch devices) */
|
||||
|
||||
.fc-event .fc-resizer {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
/* resizer (touch devices) */
|
||||
|
||||
.fc-event .fc-resizer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.fc-event.fc-allow-mouse-resize .fc-resizer,
|
||||
.fc-event.fc-selected .fc-resizer {
|
||||
/* only show when hovering or selected (with touch) */
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* hit area */
|
||||
|
||||
.fc-event.fc-selected .fc-resizer:before {
|
||||
/* 40x40 touch area */
|
||||
content: "";
|
||||
position: absolute;
|
||||
z-index: 9999; /* user of this util can scope within a lower z-index */
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-left: -20px;
|
||||
margin-top: -20px;
|
||||
}
|
||||
|
||||
|
||||
/* Event Selection (only for touch devices)
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
|
||||
.fc-event.fc-selected {
|
||||
z-index: 9999 !important; /* overcomes inline z-index */
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.fc-event.fc-selected.fc-dragging {
|
||||
box-shadow: 0 2px 7px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
|
||||
/* Horizontal Events
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
|
||||
/* bigger touch area when selected */
|
||||
.fc-h-event.fc-selected:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
z-index: 3; /* below resizers */
|
||||
top: -10px;
|
||||
bottom: -10px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
/* events that are continuing to/from another week. kill rounded corners and butt up against edge */
|
||||
|
||||
.fc-ltr .fc-h-event.fc-not-start,
|
||||
@ -576,36 +624,56 @@ temporary rendered events).
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
/* resizer */
|
||||
|
||||
.fc-h-event .fc-resizer { /* positioned it to overcome the event's borders */
|
||||
top: -1px;
|
||||
bottom: -1px;
|
||||
left: -1px;
|
||||
right: -1px;
|
||||
width: 5px;
|
||||
}
|
||||
/* resizer (cursor AND touch devices) */
|
||||
|
||||
/* left resizer */
|
||||
.fc-ltr .fc-h-event .fc-start-resizer,
|
||||
.fc-ltr .fc-h-event .fc-start-resizer:before,
|
||||
.fc-ltr .fc-h-event .fc-start-resizer:after,
|
||||
.fc-rtl .fc-h-event .fc-end-resizer,
|
||||
.fc-rtl .fc-h-event .fc-end-resizer:before,
|
||||
.fc-rtl .fc-h-event .fc-end-resizer:after {
|
||||
right: auto; /* ignore the right and only use the left */
|
||||
.fc-rtl .fc-h-event .fc-end-resizer {
|
||||
cursor: w-resize;
|
||||
left: -1px; /* overcome border */
|
||||
}
|
||||
|
||||
/* right resizer */
|
||||
.fc-ltr .fc-h-event .fc-end-resizer,
|
||||
.fc-ltr .fc-h-event .fc-end-resizer:before,
|
||||
.fc-ltr .fc-h-event .fc-end-resizer:after,
|
||||
.fc-rtl .fc-h-event .fc-start-resizer,
|
||||
.fc-rtl .fc-h-event .fc-start-resizer:before,
|
||||
.fc-rtl .fc-h-event .fc-start-resizer:after {
|
||||
left: auto; /* ignore the left and only use the right */
|
||||
.fc-rtl .fc-h-event .fc-start-resizer {
|
||||
cursor: e-resize;
|
||||
right: -1px; /* overcome border */
|
||||
}
|
||||
|
||||
/* resizer (mouse devices) */
|
||||
|
||||
.fc-h-event.fc-allow-mouse-resize .fc-resizer {
|
||||
width: 7px;
|
||||
top: -1px; /* overcome top border */
|
||||
bottom: -1px; /* overcome bottom border */
|
||||
}
|
||||
|
||||
/* resizer (touch devices) */
|
||||
|
||||
.fc-h-event.fc-selected .fc-resizer {
|
||||
/* 8x8 little dot */
|
||||
border-radius: 4px;
|
||||
border-width: 1px;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-style: solid;
|
||||
border-color: inherit;
|
||||
background: #fff;
|
||||
/* vertically center */
|
||||
top: 50%;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
/* left resizer */
|
||||
.fc-ltr .fc-h-event.fc-selected .fc-start-resizer,
|
||||
.fc-rtl .fc-h-event.fc-selected .fc-end-resizer {
|
||||
margin-left: -4px; /* centers the 8x8 dot on the left edge */
|
||||
}
|
||||
|
||||
/* right resizer */
|
||||
.fc-ltr .fc-h-event.fc-selected .fc-end-resizer,
|
||||
.fc-rtl .fc-h-event.fc-selected .fc-start-resizer {
|
||||
margin-right: -4px; /* centers the 8x8 dot on the right edge */
|
||||
}
|
||||
|
||||
|
||||
@ -620,6 +688,20 @@ be a descendant of the grid when it is being dragged.
|
||||
padding: 0 1px;
|
||||
}
|
||||
|
||||
.fc-day-grid-event.fc-selected:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
z-index: 1; /* same z-index as fc-bg, behind text */
|
||||
/* overcome the borders */
|
||||
top: -1px;
|
||||
right: -1px;
|
||||
bottom: -1px;
|
||||
left: -1px;
|
||||
/* darkening effect */
|
||||
background: #000;
|
||||
opacity: .25;
|
||||
filter: alpha(opacity=25); /* for IE */
|
||||
}
|
||||
|
||||
.fc-day-grid-event .fc-content { /* force events to be one-line tall */
|
||||
white-space: nowrap;
|
||||
@ -630,10 +712,18 @@ be a descendant of the grid when it is being dragged.
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.fc-day-grid-event .fc-resizer { /* enlarge the default hit area */
|
||||
left: -3px;
|
||||
right: -3px;
|
||||
width: 7px;
|
||||
/* resizer (cursor devices) */
|
||||
|
||||
/* left resizer */
|
||||
.fc-ltr .fc-day-grid-event.fc-allow-mouse-resize .fc-start-resizer,
|
||||
.fc-rtl .fc-day-grid-event.fc-allow-mouse-resize .fc-end-resizer {
|
||||
margin-left: -2px; /* to the day cell's edge */
|
||||
}
|
||||
|
||||
/* right resizer */
|
||||
.fc-ltr .fc-day-grid-event.fc-allow-mouse-resize .fc-end-resizer,
|
||||
.fc-rtl .fc-day-grid-event.fc-allow-mouse-resize .fc-start-resizer {
|
||||
margin-right: -2px; /* to the day cell's edge */
|
||||
}
|
||||
|
||||
|
||||
@ -681,6 +771,20 @@ a.fc-more:hover {
|
||||
border: 0 solid red;
|
||||
}
|
||||
|
||||
|
||||
/* Utilities
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
|
||||
.fc-unselectable {
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/* Toolbar
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
|
||||
@ -1031,6 +1135,20 @@ be a descendant of the grid when it is being dragged.
|
||||
overflow: hidden; /* don't let the bg flow over rounded corners */
|
||||
}
|
||||
|
||||
.fc-time-grid-event.fc-selected {
|
||||
/* need to allow touch resizers to extend outside event's bounding box */
|
||||
/* common fc-selected styles hide the fc-bg, so don't need this anyway */
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.fc-time-grid-event.fc-selected .fc-bg {
|
||||
display: none; /* hide semi-white background, to appear darker */
|
||||
}
|
||||
|
||||
.fc-time-grid-event .fc-content {
|
||||
overflow: hidden; /* for when .fc-selected */
|
||||
}
|
||||
|
||||
.fc-time-grid-event .fc-time,
|
||||
.fc-time-grid-event .fc-title {
|
||||
padding: 0 1px;
|
||||
@ -1072,9 +1190,9 @@ be a descendant of the grid when it is being dragged.
|
||||
padding: 0; /* undo padding from above */
|
||||
}
|
||||
|
||||
/* resizer */
|
||||
/* resizer (cursor device) */
|
||||
|
||||
.fc-time-grid-event .fc-resizer {
|
||||
.fc-time-grid-event.fc-allow-mouse-resize .fc-resizer {
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
@ -1087,10 +1205,28 @@ be a descendant of the grid when it is being dragged.
|
||||
cursor: s-resize;
|
||||
}
|
||||
|
||||
.fc-time-grid-event .fc-resizer:after {
|
||||
.fc-time-grid-event.fc-allow-mouse-resize .fc-resizer:after {
|
||||
content: "=";
|
||||
}
|
||||
|
||||
/* resizer (touch device) */
|
||||
|
||||
.fc-time-grid-event.fc-selected .fc-resizer {
|
||||
/* 10x10 dot */
|
||||
border-radius: 5px;
|
||||
border-width: 1px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-style: solid;
|
||||
border-color: inherit;
|
||||
background: #fff;
|
||||
/* horizontally center */
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
/* center on the bottom edge */
|
||||
bottom: -5px;
|
||||
}
|
||||
|
||||
|
||||
/* Now Indicator
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
|
File diff suppressed because it is too large
Load Diff
6
library/fullcalendar/fullcalendar.min.css
vendored
6
library/fullcalendar/fullcalendar.min.css
vendored
File diff suppressed because one or more lines are too long
12
library/fullcalendar/fullcalendar.min.js
vendored
12
library/fullcalendar/fullcalendar.min.js
vendored
File diff suppressed because one or more lines are too long
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* FullCalendar v2.6.1 Print Stylesheet
|
||||
* FullCalendar v2.7.3 Print Stylesheet
|
||||
* Docs & License: http://fullcalendar.io/
|
||||
* (c) 2015 Adam Shaw
|
||||
* (c) 2016 Adam Shaw
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* FullCalendar v2.6.1 Google Calendar Plugin
|
||||
* FullCalendar v2.7.3 Google Calendar Plugin
|
||||
* Docs & License: http://fullcalendar.io/
|
||||
* (c) 2015 Adam Shaw
|
||||
* (c) 2016 Adam Shaw
|
||||
*/
|
||||
|
||||
(function(factory) {
|
||||
@ -136,10 +136,10 @@ function transformOptions(sourceOptions, start, end, timezone, calendar) {
|
||||
}
|
||||
else if (data.items) {
|
||||
$.each(data.items, function(i, entry) {
|
||||
var url = entry.htmlLink;
|
||||
var url = entry.htmlLink || null;
|
||||
|
||||
// make the URLs for each event show times in the correct timezone
|
||||
if (timezoneArg) {
|
||||
if (timezoneArg && url !== null) {
|
||||
url = injectQsComponent(url, 'ctz=' + timezoneArg);
|
||||
}
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
9890
util/hmessages.po
9890
util/hmessages.po
File diff suppressed because it is too large
Load Diff
@ -3,14 +3,21 @@
|
||||
|
||||
function po2php_run($argc,$argv) {
|
||||
|
||||
if ($argc!=2) {
|
||||
if ($argc < 2) {
|
||||
print "Usage: ".$argv[0]." <file.po>\n\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$rtl = false;
|
||||
|
||||
$pofile = $argv[1];
|
||||
$outfile = dirname($pofile)."/hstrings.php";
|
||||
|
||||
if($argc > 2) {
|
||||
if($argv[2] === 'rtl')
|
||||
$rtl = true;
|
||||
}
|
||||
|
||||
if(strstr($outfile,'util'))
|
||||
$lang = 'en';
|
||||
else
|
||||
@ -53,6 +60,7 @@ function po2php_run($argc,$argv) {
|
||||
$out .= ' return '.$cond.';'."\n";
|
||||
$out .= '}}'."\n";
|
||||
}
|
||||
$out .= 'App::$rtl = ' . intval($rtl) . ';';
|
||||
|
||||
if ($k!="" && substr($l,0,7)=="msgstr "){
|
||||
if ($ink) { $ink = False; $out .= 'App::$strings["'.$k.'"] = '; }
|
||||
|
17998
view/ca/hmessages.po
17998
view/ca/hmessages.po
File diff suppressed because it is too large
Load Diff
3828
view/ca/hstrings.php
3828
view/ca/hstrings.php
File diff suppressed because it is too large
Load Diff
12782
view/ca/messages.po
12782
view/ca/messages.po
File diff suppressed because it is too large
Load Diff
2912
view/ca/strings.php
2912
view/ca/strings.php
File diff suppressed because it is too large
Load Diff
4618
view/cs/hmessages.po
4618
view/cs/hmessages.po
File diff suppressed because it is too large
Load Diff
1044
view/cs/hstrings.php
1044
view/cs/hstrings.php
File diff suppressed because it is too large
Load Diff
@ -1,82 +0,0 @@
|
||||
<?php
|
||||
|
||||
// Set the following for your MySQL installation
|
||||
// Copy or rename this file to .htconfig.php
|
||||
|
||||
$db_host = '{{$dbhost}}';
|
||||
$db_port = '{{$dbport}}';
|
||||
$db_user = '{{$dbuser}}';
|
||||
$db_pass = '{{$dbpass}}';
|
||||
$db_data = '{{$dbdata}}';
|
||||
$db_type = '{{$dbtype}}'; // an integer. 0 or unset for mysql, 1 for postgres
|
||||
|
||||
define( 'UNO', {{$uno}} );
|
||||
|
||||
/*
|
||||
* Notice: Many of the following settings will be available in the admin panel
|
||||
* after a successful site install. Once they are set in the admin panel, they
|
||||
* are stored in the DB - and the DB setting will over-ride any corresponding
|
||||
* setting in this file
|
||||
*
|
||||
* The command-line tool util/config is able to query and set the DB items
|
||||
* directly if for some reason the admin panel is not available and a system
|
||||
* setting requires modification.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// Choose a legal default timezone. If you are unsure, use "America/Los_Angeles".
|
||||
// It can be changed later and only applies to timestamps for anonymous viewers.
|
||||
|
||||
App::$config['system']['timezone'] = '{{$timezone}}';
|
||||
|
||||
// What is your site name?
|
||||
|
||||
App::$config['system']['baseurl'] = '{{$siteurl}}';
|
||||
App::$config['system']['sitename'] = "Hubzilla";
|
||||
App::$config['system']['location_hash'] = '{{$site_id}}';
|
||||
|
||||
// These lines set additional security headers to be sent with all responses
|
||||
// You may wish to set transport_security_header to 0 if your server already sends
|
||||
// this header. content_security_policy may need to be disabled if you wish to
|
||||
// run the piwik analytics plugin or include other offsite resources on a page
|
||||
|
||||
App::$config['system']['transport_security_header'] = 1;
|
||||
App::$config['system']['content_security_policy'] = 1;
|
||||
|
||||
|
||||
// Your choices are REGISTER_OPEN, REGISTER_APPROVE, or REGISTER_CLOSED.
|
||||
// Be certain to create your own personal account before setting
|
||||
// REGISTER_CLOSED. 'register_text' (if set) will be displayed prominently on
|
||||
// the registration page. REGISTER_APPROVE requires you set 'admin_email'
|
||||
// to the email address of an already registered person who can authorise
|
||||
// and/or approve/deny the request.
|
||||
|
||||
App::$config['system']['register_policy'] = REGISTER_OPEN;
|
||||
App::$config['system']['register_text'] = '';
|
||||
App::$config['system']['admin_email'] = '{{$adminmail}}';
|
||||
|
||||
// Maximum size of an imported message, 0 is unlimited
|
||||
|
||||
App::$config['system']['max_import_size'] = 200000;
|
||||
|
||||
// maximum size of uploaded photos
|
||||
|
||||
App::$config['system']['maximagesize'] = 8000000;
|
||||
|
||||
// Location of PHP command line processor
|
||||
|
||||
App::$config['system']['php_path'] = '{{$phpath}}';
|
||||
|
||||
// Configure how we communicate with directory servers.
|
||||
// DIRECTORY_MODE_NORMAL = directory client, we will find a directory
|
||||
// DIRECTORY_MODE_SECONDARY = caching directory or mirror
|
||||
// DIRECTORY_MODE_PRIMARY = main directory server
|
||||
// DIRECTORY_MODE_STANDALONE = "off the grid" or private directory services
|
||||
|
||||
App::$config['system']['directory_mode'] = DIRECTORY_MODE_NORMAL;
|
||||
|
||||
// default system theme
|
||||
|
||||
App::$config['system']['theme'] = 'redbasic';
|
||||
|
@ -1,32 +0,0 @@
|
||||
|
||||
Dear {{$username}},
|
||||
A request was recently received at {{$sitename}} to reset your account
|
||||
password. In order to confirm this request, please select the verification link
|
||||
below or paste it into your web browser address bar.
|
||||
|
||||
If you did NOT request this change, please DO NOT follow the link
|
||||
provided and ignore and/or delete this email.
|
||||
|
||||
Your password will not be changed unless we can verify that you
|
||||
issued this request.
|
||||
|
||||
Follow this link to verify your identity:
|
||||
|
||||
{{$reset_link}}
|
||||
|
||||
You will then receive a follow-up message containing the new password.
|
||||
|
||||
You may change that password from your account settings page after logging in.
|
||||
|
||||
The login details are as follows:
|
||||
|
||||
Site Location: {{$siteurl}}
|
||||
Login Name: {{$email}}
|
||||
|
||||
|
||||
|
||||
|
||||
Sincerely,
|
||||
{{$sitename}} Administrator
|
||||
|
||||
|
4618
view/cs/messages.po
4618
view/cs/messages.po
File diff suppressed because it is too large
Load Diff
@ -1,20 +0,0 @@
|
||||
|
||||
Dear {{$username}},
|
||||
Your password has been changed as requested. Please retain this
|
||||
information for your records (or change your password immediately to
|
||||
something that you will remember).
|
||||
|
||||
|
||||
Your login details are as follows:
|
||||
|
||||
Site Location: {{$siteurl}}
|
||||
Login Name: {{$email}}
|
||||
Password: {{$new_password}}
|
||||
|
||||
You may change that password from your account settings page after logging in.
|
||||
|
||||
|
||||
Sincerely,
|
||||
{{$sitename}} Administrator
|
||||
|
||||
|
@ -1,19 +0,0 @@
|
||||
|
||||
An account has been created at {{$sitename}} for this email address.
|
||||
The login details are as follows:
|
||||
|
||||
Site Location: {{$siteurl}}
|
||||
Login: {{$email}}
|
||||
Password: (the password which was provided during registration)
|
||||
|
||||
If this account was created without your knowledge and is not desired, you may
|
||||
visit this site and reset the password. This will allow you to remove the
|
||||
account from the links on the Settings page, and we
|
||||
apologise for any inconvenience.
|
||||
|
||||
Thank you and welcome to {{$sitename}}.
|
||||
|
||||
Sincerely,
|
||||
{{$sitename}} Administrator
|
||||
|
||||
|
@ -1,25 +0,0 @@
|
||||
|
||||
A new user registration request was received at {{$sitename}} which requires
|
||||
your approval.
|
||||
|
||||
|
||||
The login details are as follows:
|
||||
|
||||
Site Location: {{$siteurl}}
|
||||
Login Name: {{$email}}
|
||||
IP Address: {{$details}}
|
||||
|
||||
To approve this request please visit the following link:
|
||||
|
||||
|
||||
{{$siteurl}}/regmod/allow/{{$hash}}
|
||||
|
||||
|
||||
To deny the request and remove the account, please visit:
|
||||
|
||||
|
||||
{{$siteurl}}/regmod/deny/{{$hash}}
|
||||
|
||||
|
||||
Thank you.
|
||||
|
1044
view/cs/strings.php
1044
view/cs/strings.php
File diff suppressed because it is too large
Load Diff
@ -1,13 +0,0 @@
|
||||
Hey,
|
||||
I'm the web server at {{$sitename}};
|
||||
|
||||
The Hubzilla developers released update {{$update}} recently,
|
||||
but when I tried to install it, something went terribly wrong.
|
||||
This needs to be fixed soon and it requires human intervention.
|
||||
Please contact a Red developer if you can not figure out how to
|
||||
fix it on your own. My database might be invalid.
|
||||
|
||||
The error message is '{{$error}}'.
|
||||
|
||||
Apologies for the inconvenience,
|
||||
your web server at {{$siteurl}}
|
@ -1,3 +1,7 @@
|
||||
.fc-scroller {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
/* fix borders */
|
||||
|
||||
.fc th:first-child,
|
||||
|
@ -1,3 +1,7 @@
|
||||
.fc-scroller {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
/* fix borders */
|
||||
|
||||
.fc th:first-child,
|
||||
|
11401
view/de/hmessages.po
11401
view/de/hmessages.po
File diff suppressed because it is too large
Load Diff
2665
view/de/hstrings.php
2665
view/de/hstrings.php
File diff suppressed because it is too large
Load Diff
7714
view/eo/hmessages.po
7714
view/eo/hmessages.po
File diff suppressed because it is too large
Load Diff
1771
view/eo/hstrings.php
1771
view/eo/hstrings.php
File diff suppressed because it is too large
Load Diff
@ -1,82 +0,0 @@
|
||||
<?php
|
||||
|
||||
// Set the following for your MySQL installation
|
||||
// Copy or rename this file to .htconfig.php
|
||||
|
||||
$db_host = '{{$dbhost}}';
|
||||
$db_port = '{{$dbport}}';
|
||||
$db_user = '{{$dbuser}}';
|
||||
$db_pass = '{{$dbpass}}';
|
||||
$db_data = '{{$dbdata}}';
|
||||
$db_type = '{{$dbtype}}'; // an integer. 0 or unset for mysql, 1 for postgres
|
||||
|
||||
define( 'UNO', {{$uno}} );
|
||||
|
||||
/*
|
||||
* Notice: Many of the following settings will be available in the admin panel
|
||||
* after a successful site install. Once they are set in the admin panel, they
|
||||
* are stored in the DB - and the DB setting will over-ride any corresponding
|
||||
* setting in this file
|
||||
*
|
||||
* The command-line tool util/config is able to query and set the DB items
|
||||
* directly if for some reason the admin panel is not available and a system
|
||||
* setting requires modification.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// Choose a legal default timezone. If you are unsure, use "America/Los_Angeles".
|
||||
// It can be changed later and only applies to timestamps for anonymous viewers.
|
||||
|
||||
App::$config['system']['timezone'] = '{{$timezone}}';
|
||||
|
||||
// What is your site name?
|
||||
|
||||
App::$config['system']['baseurl'] = '{{$siteurl}}';
|
||||
App::$config['system']['sitename'] = "Hubzilla";
|
||||
App::$config['system']['location_hash'] = '{{$site_id}}';
|
||||
|
||||
|
||||
// These lines set additional security headers to be sent with all responses
|
||||
// You may wish to set transport_security_header to 0 if your server already sends
|
||||
// this header. content_security_policy may need to be disabled if you wish to
|
||||
// run the piwik analytics plugin or include other offsite resources on a page
|
||||
|
||||
App::$config['system']['transport_security_header'] = 1;
|
||||
App::$config['system']['content_security_policy'] = 1;
|
||||
|
||||
// Your choices are REGISTER_OPEN, REGISTER_APPROVE, or REGISTER_CLOSED.
|
||||
// Be certain to create your own personal account before setting
|
||||
// REGISTER_CLOSED. 'register_text' (if set) will be displayed prominently on
|
||||
// the registration page. REGISTER_APPROVE requires you set 'admin_email'
|
||||
// to the email address of an already registered person who can authorise
|
||||
// and/or approve/deny the request.
|
||||
|
||||
App::$config['system']['register_policy'] = REGISTER_OPEN;
|
||||
App::$config['system']['register_text'] = '';
|
||||
App::$config['system']['admin_email'] = '{{$adminmail}}';
|
||||
|
||||
// Maximum size of an imported message, 0 is unlimited
|
||||
|
||||
App::$config['system']['max_import_size'] = 200000;
|
||||
|
||||
// maximum size of uploaded photos
|
||||
|
||||
App::$config['system']['maximagesize'] = 8000000;
|
||||
|
||||
// Location of PHP command line processor
|
||||
|
||||
App::$config['system']['php_path'] = '{{$phpath}}';
|
||||
|
||||
// Configure how we communicate with directory servers.
|
||||
// DIRECTORY_MODE_NORMAL = directory client, we will find a directory
|
||||
// DIRECTORY_MODE_SECONDARY = caching directory or mirror
|
||||
// DIRECTORY_MODE_PRIMARY = main directory server
|
||||
// DIRECTORY_MODE_STANDALONE = "off the grid" or private directory services
|
||||
|
||||
App::$config['system']['directory_mode'] = DIRECTORY_MODE_NORMAL;
|
||||
|
||||
// default system theme
|
||||
|
||||
App::$config['system']['theme'] = 'redbasic';
|
||||
|
@ -1,32 +0,0 @@
|
||||
|
||||
Dear {{$username}},
|
||||
A request was recently received at {{$sitename}} to reset your account
|
||||
password. In order to confirm this request, please select the verification link
|
||||
below or paste it into your web browser address bar.
|
||||
|
||||
If you did NOT request this change, please DO NOT follow the link
|
||||
provided and ignore and/or delete this email.
|
||||
|
||||
Your password will not be changed unless we can verify that you
|
||||
issued this request.
|
||||
|
||||
Follow this link to verify your identity:
|
||||
|
||||
{{$reset_link}}
|
||||
|
||||
You will then receive a follow-up message containing the new password.
|
||||
|
||||
You may change that password from your account settings page after logging in.
|
||||
|
||||
The login details are as follows:
|
||||
|
||||
Site Location: {{$siteurl}}
|
||||
Login Name: {{$email}}
|
||||
|
||||
|
||||
|
||||
|
||||
Sincerely,
|
||||
{{$sitename}} Administrator
|
||||
|
||||
|
7714
view/eo/messages.po
7714
view/eo/messages.po
File diff suppressed because it is too large
Load Diff
@ -1,20 +0,0 @@
|
||||
|
||||
Dear {{$username}},
|
||||
Your password has been changed as requested. Please retain this
|
||||
information for your records (or change your password immediately to
|
||||
something that you will remember).
|
||||
|
||||
|
||||
Your login details are as follows:
|
||||
|
||||
Site Location: {{$siteurl}}
|
||||
Login Name: {{$email}}
|
||||
Password: {{$new_password}}
|
||||
|
||||
You may change that password from your account settings page after logging in.
|
||||
|
||||
|
||||
Sincerely,
|
||||
{{$sitename}} Administrator
|
||||
|
||||
|
@ -1,19 +0,0 @@
|
||||
|
||||
An account has been created at {{$sitename}} for this email address.
|
||||
The login details are as follows:
|
||||
|
||||
Site Location: {{$siteurl}}
|
||||
Login: {{$email}}
|
||||
Password: (the password which was provided during registration)
|
||||
|
||||
If this account was created without your knowledge and is not desired, you may
|
||||
visit this site and reset the password. This will allow you to remove the
|
||||
account from the links on the Settings page, and we
|
||||
apologise for any inconvenience.
|
||||
|
||||
Thank you and welcome to {{$sitename}}.
|
||||
|
||||
Sincerely,
|
||||
{{$sitename}} Administrator
|
||||
|
||||
|
@ -1,25 +0,0 @@
|
||||
|
||||
A new user registration request was received at {{$sitename}} which requires
|
||||
your approval.
|
||||
|
||||
|
||||
The login details are as follows:
|
||||
|
||||
Site Location: {{$siteurl}}
|
||||
Login Name: {{$email}}
|
||||
IP Address: {{$details}}
|
||||
|
||||
To approve this request please visit the following link:
|
||||
|
||||
|
||||
{{$siteurl}}/regmod/allow/{{$hash}}
|
||||
|
||||
|
||||
To deny the request and remove the account, please visit:
|
||||
|
||||
|
||||
{{$siteurl}}/regmod/deny/{{$hash}}
|
||||
|
||||
|
||||
Thank you.
|
||||
|
1771
view/eo/strings.php
1771
view/eo/strings.php
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user