several issues plus some cleanup

This commit is contained in:
zotlabs 2020-05-05 21:34:31 -07:00
parent 724708dbcc
commit 1c5b210d0d
10 changed files with 289 additions and 216 deletions

View file

@ -95,7 +95,8 @@ class LDSignatures {
$d = jsonld_normalize($data,[ 'algorithm' => 'URDNA2015', 'format' => 'application/nquads' ]);
}
catch (\Exception $e) {
logger('normalise error:' . print_r($e,true));
// Don't log the exception - this can exhaust memory
// logger('normalise error:' . print_r($e,true));
logger('normalise error: ' . print_r($data,true));
}

View file

@ -1,4 +1,6 @@
<?php
namespace Zotlabs\Module;
/**
* @file Zotlabs/Module/Dav.php
* @brief Initialize Hubzilla's cloud (SabreDAV).
@ -6,8 +8,8 @@
* Module for accessing the DAV storage area from a DAV client.
*/
namespace Zotlabs\Module;
use App;
use Sabre\DAV as SDAV;
use Zotlabs\Storage;
use Zotlabs\Lib\Libprofile;
@ -96,8 +98,8 @@ class Dav extends Controller {
$auth = new \Zotlabs\Storage\BasicAuth();
$auth->observer = get_observer_hash();
// $auth->observer = get_observer_hash();
$auth->setRealm(ucfirst(\Zotlabs\Lib\System::get_platform_name()) . ' ' . 'WebDAV');
$rootDirectory = new \Zotlabs\Storage\Directory('/', $auth);

View file

@ -856,7 +856,7 @@ class Item extends Controller {
if($cnt) {
$summary .= $match[1];
}
$body_content = preg_replace("/^(.*?)\[summary\](.*?)\[\/summary\](.*?)$/ism", '',$body);
$body_content = preg_replace("/^(.*?)\[summary\](.*?)\[\/summary\]/ism", '',$body);
$body = trim($body_content);
}

View file

@ -2,6 +2,7 @@
namespace Zotlabs\Storage;
use App;
use Sabre\DAV;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;
@ -128,6 +129,16 @@ class BasicAuth extends DAV\Auth\Backend\AbstractBasic {
$this->channel_name = $r['channel_address'];
$this->channel_id = $r['channel_id'];
$this->channel_hash = $this->observer = $r['channel_hash'];
if ($this->observer) {
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($this->observer)
);
if ($r) {
App::set_observer(array_shift($r));
}
}
$_SESSION['uid'] = $r['channel_id'];
$_SESSION['account_id'] = $r['channel_account_id'];
$_SESSION['authenticated'] = true;

View file

@ -2,8 +2,13 @@
namespace Zotlabs\Storage;
use App;
use Sabre\DAV;
use Zotlabs\Lib\Libsync;
use Zotlabs\Daemon\Master;
require_once('include/photos.php');
/**
* @brief RedDirectory class.
@ -14,7 +19,6 @@ use Zotlabs\Lib\Libsync;
* @implements \\Sabre\\DAV\\ICollection
* @implements \\Sabre\\DAV\\IQuota
*
* @link http://github.com/friendica/red
* @license http://opensource.org/licenses/mit-license.php The MIT License (MIT)
*/
class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMoveTarget {
@ -54,9 +58,9 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
logger('directory ' . $ext_path, LOGGER_DATA);
$this->ext_path = $ext_path;
// remove "/cloud" from the beginning of the path
$modulename = \App::$module;
$modulename = App::$module;
$this->red_path = ((strpos($ext_path, '/' . $modulename) === 0) ? substr($ext_path, strlen($modulename) + 1) : $ext_path);
if(! $this->red_path) {
if (! $this->red_path) {
$this->red_path = '/';
}
$this->auth = $auth_plugin;
@ -114,7 +118,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
throw new DAV\Exception\Forbidden('Permission denied.');
}
$modulename = \App::$module;
$modulename = App::$module;
if ($this->red_path === '/' && $name === $modulename) {
return new Directory('/' . $modulename, $this->auth);
}
@ -133,7 +137,6 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
* @return string
*/
public function getName() {
//logger(basename($this->red_path), LOGGER_DATA);
return (basename($this->red_path));
}
@ -179,8 +182,9 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
$ch = channelx_by_n($this->auth->owner_id);
if ($ch) {
$sync = attach_export_data($ch, $this->folder_hash);
if ($sync)
if ($sync) {
Libsync::build_sync_packet($ch['channel_id'], array('file' => array($sync)));
}
}
$this->red_path = $new_path;
@ -215,11 +219,9 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
$mimetype = z_mime_content_type($name);
$c = q("SELECT * FROM channel WHERE channel_id = %d AND channel_removed = 0 LIMIT 1",
intval($this->auth->owner_id)
);
$channel = channelx_by_n($this->auth->owner_id);
if (! $c) {
if (! $channel) {
logger('no channel');
throw new DAV\Exception\Forbidden('Permission denied.');
}
@ -234,29 +236,32 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
if ($this->folder_hash) {
$r = q("select * from attach where hash = '%s' and is_dir = 1 and uid = %d limit 1",
dbesc($this->folder_hash),
intval($c[0]['channel_id'])
intval($channel['channel_id'])
);
if ($r)
$direct = $r[0];
if ($r) {
$direct = array_shift($r);
}
}
if (($direct) && (($direct['allow_cid']) || ($direct['allow_gid']) || ($direct['deny_cid']) || ($direct['deny_gid']))) {
$allow_cid = $direct['allow_cid'];
$allow_gid = $direct['allow_gid'];
$deny_cid = $direct['deny_cid'];
$deny_gid = $direct['deny_gid'];
$deny_cid = $direct['deny_cid'];
$deny_gid = $direct['deny_gid'];
}
else {
$allow_cid = $c[0]['channel_allow_cid'];
$allow_gid = $c[0]['channel_allow_gid'];
$deny_cid = $c[0]['channel_deny_cid'];
$deny_gid = $c[0]['channel_deny_gid'];
$allow_cid = $channel['channel_allow_cid'];
$allow_gid = $channel['channel_allow_gid'];
$deny_cid = $channel['channel_deny_cid'];
$deny_gid = $channel['channel_deny_gid'];
}
$created = $edited = datetime_convert();
$r = q("INSERT INTO attach ( aid, uid, hash, creator, filename, folder, os_storage, filetype, filesize, revision, is_photo, content, created, edited, os_path, display_path, allow_cid, allow_gid, deny_cid, deny_gid )
VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
intval($c[0]['channel_account_id']),
intval($c[0]['channel_id']),
intval($channel['channel_account_id']),
intval($channel['channel_id']),
dbesc($hash),
dbesc($this->auth->observer),
dbesc($name),
@ -265,10 +270,10 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
dbesc($mimetype),
intval($filesize),
intval(0),
intval($is_photo),
intval(0),
dbesc($f),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
dbesc($created),
dbesc($edited),
'',
'',
dbesc($allow_cid),
@ -281,95 +286,111 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
$xpath = attach_syspaths($this->auth->owner_id, $hash);
// returns the number of bytes that were written to the file, or FALSE on failure
$size = file_put_contents($f, $data);
if (is_resource($data)) {
$fp = fopen($f,'wb');
if ($fp) {
pipe_streams($data,$fp);
fclose($fp);
}
$size = filesize($f);
}
else {
$size = file_put_contents($f, $data);
}
// delete attach entry if file_put_contents() failed
if ($size === false) {
logger('file_put_contents() failed to ' . $f);
attach_delete($c[0]['channel_id'], $hash);
attach_delete($channel['channel_id'], $hash);
return;
}
// returns now
$edited = datetime_convert();
$is_photo = 0;
$gis = @getimagesize($f);
logger('getimagesize: ' . print_r($gis,true), LOGGER_DATA);
if (($gis) && ($gis[2] === IMAGETYPE_GIF || $gis[2] === IMAGETYPE_JPEG || $gis[2] === IMAGETYPE_PNG)) {
if (($gis) && supported_imagetype($gis[2])) {
$is_photo = 1;
}
// If we know it's a photo, over-ride the type in case the source system could not determine what it was
if($is_photo) {
if ($is_photo) {
q("update attach set filetype = '%s' where hash = '%s' and uid = %d",
dbesc($gis['mime']),
dbesc($hash),
intval($c[0]['channel_id'])
intval($channel['channel_id'])
);
}
// updates entry with filesize and timestamp
$d = q("UPDATE attach SET filesize = '%s', os_path = '%s', display_path = '%s', is_photo = %d, edited = '%s' WHERE hash = '%s' AND uid = %d",
// updates entry with path and filesize
$d = q("UPDATE attach SET filesize = '%s', os_path = '%s', display_path = '%s', is_photo = %d WHERE hash = '%s' AND uid = %d",
dbesc($size),
dbesc($xpath['os_path']),
dbesc($xpath['display_path']),
dbesc($xpath['path']),
intval($is_photo),
dbesc($edited),
dbesc($hash),
intval($c[0]['channel_id'])
intval($channel['channel_id'])
);
// update the folder's lastmodified timestamp
// update the parent folder's lastmodified timestamp
$e = q("UPDATE attach SET edited = '%s' WHERE hash = '%s' AND uid = %d",
dbesc($edited),
dbesc($this->folder_hash),
intval($c[0]['channel_id'])
intval($channel['channel_id'])
);
$maxfilesize = get_config('system', 'maxfilesize');
if (($maxfilesize) && ($size > $maxfilesize)) {
attach_delete($c[0]['channel_id'], $hash);
logger('system maxfilesize exceeded. Deleting uploaded file.');
attach_delete($channel['channel_id'], $hash);
return;
}
// check against service class quota
$limit = engr_units_to_bytes(service_class_fetch($c[0]['channel_id'], 'attach_upload_limit'));
$limit = engr_units_to_bytes(service_class_fetch($channel['channel_id'], 'attach_upload_limit'));
if ($limit !== false) {
$z = q("SELECT SUM(filesize) AS total FROM attach WHERE aid = %d ",
intval($c[0]['channel_account_id'])
intval($channel['channel_account_id'])
);
if (($z) && ($z[0]['total'] + $size > $limit)) {
logger('service class limit exceeded for ' . $c[0]['channel_name'] . ' total usage is ' . $z[0]['total'] . ' limit is ' . userReadableSize($limit));
attach_delete($c[0]['channel_id'], $hash);
logger('service class limit exceeded for ' . $channel['channel_name'] . ' total usage is ' . $z[0]['total'] . ' limit is ' . userReadableSize($limit));
attach_delete($channel['channel_id'], $hash);
return;
}
}
if($is_photo) {
if ($is_photo) {
$album = '';
if ($this->folder_hash) {
$f1 = q("select filename, display_path from attach WHERE hash = '%s' AND uid = %d",
dbesc($this->folder_hash),
intval($c[0]['channel_id'])
intval($channel['channel_id'])
);
if ($f1)
if ($f1) {
$album = (($f1[0]['display_path']) ? $f1[0]['display_path'] : $f1[0]['filename']);
}
}
require_once('include/photos.php');
$args = array( 'resource_id' => $hash, 'album' => $album, 'os_syspath' => $f, 'os_path' => $xpath['os_path'], 'display_path' => $xpath['path'], 'filename' => $name, 'getimagesize' => $gis, 'directory' => $direct);
$p = photo_upload($c[0], \App::get_observer(), $args);
$args = [
'resource_id' => $hash,
'album' => $album,
'os_syspath' => $f,
'os_path' => $xpath['os_path'],
'display_path' => $xpath['path'],
'filename' => $name,
'getimagesize' => $gis,
'directory' => $direct
];
$p = photo_upload($channel, App::get_observer(), $args);
}
\Zotlabs\Daemon\Master::Summon([ 'Thumbnail' , $this->folder_hash ]);
Master::Summon([ 'Thumbnail' , $hash ]);
$sync = attach_export_data($c[0], $hash);
$sync = attach_export_data($channel, $hash);
if ($sync)
Libsync::build_sync_packet($c[0]['channel_id'], array('file' => array($sync)));
if ($sync) {
Libsync::build_sync_packet($channel['channel_id'], array('file' => array($sync)));
}
}
/**
@ -385,24 +406,22 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
throw new DAV\Exception\Forbidden('Permission denied.');
}
$r = q("SELECT * FROM channel WHERE channel_id = %d AND channel_removed = 0 LIMIT 1",
intval($this->auth->owner_id)
);
$channel = channelx_by_n($this->auth->owner_id);
if ($r) {
if ($channel) {
// When initiated from DAV, set the 'force' flag on attach_mkdir(). This will cause the operation to report success even if the
// folder already exists.
require_once('include/attach.php');
$result = attach_mkdir($r[0], $this->auth->observer, array('filename' => $name, 'folder' => $this->folder_hash, 'force' => true));
$result = attach_mkdir($channel, $this->auth->observer, array('filename' => $name, 'folder' => $this->folder_hash, 'force' => true));
if($result['success']) {
$sync = attach_export_data($r[0],$result['data']['hash']);
if ($result['success']) {
$sync = attach_export_data($channel,$result['data']['hash']);
logger('createDirectory: attach_export_data returns $sync:' . print_r($sync, true), LOGGER_DEBUG);
if($sync) {
Libsync::build_sync_packet($r[0]['channel_id'], array('file' => array($sync)));
if ($sync) {
Libsync::build_sync_packet($channel['channel_id'], array('file' => array($sync)));
}
}
else {
@ -429,11 +448,12 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
attach_delete($this->auth->owner_id, $this->folder_hash);
$ch = channelx_by_n($this->auth->owner_id);
if ($ch) {
$sync = attach_export_data($ch, $this->folder_hash, true);
if ($sync)
Libsync::build_sync_packet($ch['channel_id'], array('file' => array($sync)));
$channel = channelx_by_n($this->auth->owner_id);
if ($channel) {
$sync = attach_export_data($channel, $this->folder_hash, true);
if ($sync) {
Libsync::build_sync_packet($channel['channel_id'], array('file' => array($sync)));
}
}
}
@ -448,7 +468,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
public function childExists($name) {
// On /cloud we show a list of available channels.
// @todo what happens if no channels are available?
$modulename = \App::$module;
$modulename = App::$module;
if ($this->red_path === '/' && $name === $modulename) {
//logger('We are at ' $modulename . ' show a channel list', LOGGER_DEBUG);
return true;
@ -456,16 +476,16 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
$x = $this->FileData($this->ext_path . '/' . $name, $this->auth, true);
//logger('FileData returns: ' . print_r($x, true), LOGGER_DATA);
if ($x)
if ($x) {
return true;
}
return false;
}
public function moveInto($targetName,$sourcePath, DAV\INode $sourceNode) {
if(! $this->auth->owner_id) {
if (! $this->auth->owner_id) {
return false;
}
@ -474,7 +494,6 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
}
return attach_move($this->auth->owner_id, $sourceNode->data->hash, $this->folder_hash);
}
@ -488,7 +507,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
logger('GetDir: ' . $this->ext_path, LOGGER_DEBUG);
$this->auth->log();
$modulename = \App::$module;
$modulename = App::$module;
$file = $this->ext_path;
@ -511,15 +530,13 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
$channel_name = $path_arr[0];
$r = q("SELECT channel_id FROM channel WHERE channel_address = '%s' AND channel_removed = 0 LIMIT 1",
dbesc($channel_name)
);
$channel = channelx_by_nick($channel_name);
if (! $r) {
if (! $channel) {
throw new DAV\Exception\NotFound('The file with name: ' . $channel_name . ' could not be found.');
}
$channel_id = $r[0]['channel_id'];
$channel_id = $channel['channel_id'];
$this->auth->owner_id = $channel_id;
$this->auth->owner_nick = $channel_name;
@ -535,10 +552,10 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
);
if ($r && intval($r[0]['is_dir'])) {
$folder = $r[0]['hash'];
if (strlen($os_path))
if (strlen($os_path)) {
$os_path .= '/';
}
$os_path .= $folder;
$path = $path . '/' . $r[0]['filename'];
}
}
@ -598,19 +615,19 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
$file = trim($file, '/');
$path_arr = explode('/', $file);
if (! $path_arr)
if (! $path_arr) {
return null;
}
$channel_name = $path_arr[0];
$r = q("SELECT channel_id FROM channel WHERE channel_address = '%s' LIMIT 1",
dbesc($channel_name)
);
$channel = channelx_by_nick($channel_name);
if (! $r)
if (! $channel) {
return null;
}
$channel_id = $r[0]['channel_id'];
$channel_id = $channel['channel_id'];
$perms = permissions_sql($channel_id);
$auth->owner_id = $channel_id;
@ -687,17 +704,19 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
);
foreach ($r as $rr) {
if(\App::$module === 'cloud' && (strpos($rr['filename'],'.') === 0) && (! get_pconfig($channel_id,'system','show_dot_files')) )
if (App::$module === 'cloud' && (strpos($rr['filename'],'.') === 0) && (! get_pconfig($channel_id,'system','show_dot_files')) ) {
continue;
}
// @FIXME I don't think we use revisions currently in attach structures.
// In case we see any in the wild provide a unique filename. This
// name may or may not be accessible
if($rr['revision'])
if ($rr['revision']) {
$rr['filename'] .= '-' . $rr['revision'];
}
//logger('filename: ' . $rr['filename'], LOGGER_DEBUG);
// logger('filename: ' . $rr['filename'], LOGGER_DEBUG);
if (intval($rr['is_dir'])) {
$ret[] = new Directory($path . '/' . $rr['filename'], $auth);
}

View file

@ -2,8 +2,12 @@
namespace Zotlabs\Storage;
use App;
use Sabre\DAV;
use Zotlabs\Lib\Libsync;
use Zotlabs\Daemon\Master;
require_once('include/photos.php');
/**
* @brief This class represents a file in DAV.
@ -117,14 +121,22 @@ class File extends DAV\Node implements DAV\IFile {
* @param resource $data
* @return void
*/
public function put($data) {
logger('put file: ' . basename($this->name), LOGGER_DEBUG);
$size = 0;
// @todo only 3 values are needed
$c = q("SELECT * FROM channel WHERE channel_id = %d AND channel_removed = 0 LIMIT 1",
intval($this->auth->owner_id)
);
if ((! $this->auth->owner_id) || (! perm_is_allowed($this->auth->owner_id, $this->auth->observer, 'write_storage'))) {
logger('permission denied for put operation');
throw new DAV\Exception\Forbidden('Permission denied.');
}
$channel = channelx_by_n($this->auth->owner_id);
if (! $channel) {
throw new DAV\Exception\Forbidden('Permission denied.');
}
$is_photo = false;
$album = '';
@ -135,22 +147,19 @@ class File extends DAV\Node implements DAV\IFile {
// and delete from a networked operating system. In this case you are only allowed to over-write the file
// if it is empty. Some DAV clients create the file and then store the contents so these would be allowed.
if(get_pconfig($this->auth->owner_id,'system','os_delete_prohibit') && \App::$module == 'dav') {
if (get_pconfig($this->auth->owner_id,'system','os_delete_prohibit') && App::$module == 'dav') {
$r = q("select filesize from attach where hash = '%s' and uid = %d limit 1",
dbesc($this->data['hash']),
intval($c[0]['channel_id'])
intval($channel['channel_id'])
);
if($r && intval($r[0]['filesize'])) {
if ($r && intval($r[0]['filesize'])) {
throw new DAV\Exception\Forbidden('Permission denied.');
}
}
$r = q("SELECT flags, folder, os_storage, os_path, display_path, filename, is_photo FROM attach WHERE hash = '%s' AND uid = %d LIMIT 1",
dbesc($this->data['hash']),
intval($c[0]['channel_id'])
intval($channel['channel_id'])
);
if ($r) {
@ -162,39 +171,51 @@ class File extends DAV\Node implements DAV\IFile {
if (intval($r[0]['os_storage'])) {
$d = q("select folder, content from attach where hash = '%s' and uid = %d limit 1",
dbesc($this->data['hash']),
intval($c[0]['channel_id'])
intval($channel['channel_id'])
);
if($d) {
if($d[0]['folder']) {
if ($d) {
if ($d[0]['folder']) {
$f1 = q("select * from attach where is_dir = 1 and hash = '%s' and uid = %d limit 1",
dbesc($d[0]['folder']),
intval($c[0]['channel_id'])
intval($channel['channel_id'])
);
if($f1) {
if ($f1) {
$album = $f1[0]['filename'];
$direct = $f1[0];
}
}
$fname = dbunescbin($d[0]['content']);
if(strpos($fname,'store/') === false)
if (strpos($fname,'store/') === false) {
$f = 'store/' . $this->auth->owner_nick . '/' . $fname ;
else
}
else {
$f = $fname;
}
if (is_resource($data)) {
$fp = fopen($f,'wb');
if ($fp) {
pipe_streams($data,$fp);
fclose($fp);
}
}
else {
file_put_contents($f, $data);
}
// @todo check return value and set $size directly
@file_put_contents($f, $data);
$size = @filesize($f);
logger('filename: ' . $f . ' size: ' . $size, LOGGER_DEBUG);
}
$gis = @getimagesize($f);
logger('getimagesize: ' . print_r($gis,true), LOGGER_DATA);
if(($gis) && ($gis[2] === IMAGETYPE_GIF || $gis[2] === IMAGETYPE_JPEG || $gis[2] === IMAGETYPE_PNG)) {
if ($gis && supported_imagetype($gis[2])) {
$is_photo = 1;
}
// If we know it's a photo, over-ride the type in case the source system could not determine what it was
if($is_photo) {
if ($is_photo) {
q("update attach set filetype = '%s' where hash = '%s' and uid = %d",
dbesc($gis['mime']),
dbesc($this->data['hash']),
@ -228,20 +249,29 @@ class File extends DAV\Node implements DAV\IFile {
intval($is_photo),
dbesc($edited),
dbesc($this->data['hash']),
intval($c[0]['channel_id'])
intval($channel['channel_id'])
);
if($is_photo) {
require_once('include/photos.php');
$args = array( 'resource_id' => $this->data['hash'], 'album' => $album, 'os_syspath' => $f, 'os_path' => $os_path, 'display_path' => $display_path, 'filename' => $filename, 'getimagesize' => $gis, 'directory' => $direct );
$p = photo_upload($c[0],\App::get_observer(),$args);
if ($is_photo) {
$args = [
'resource_id' => $this->data['hash'],
'album' => $album,
'os_syspath' => $f,
'os_path' => $os_path,
'display_path' => $display_path,
'filename' => $filename,
'getimagesize' => $gis,
'directory' => $direct
];
$p = photo_upload($channel, App::get_observer(), $args);
logger('photo_upload: ' . print_r($p,true), LOGGER_DATA);
}
// update the folder's lastmodified timestamp
$e = q("UPDATE attach SET edited = '%s' WHERE hash = '%s' AND uid = %d",
dbesc($edited),
dbesc($r[0]['folder']),
intval($c[0]['channel_id'])
intval($channel['channel_id'])
);
// @todo do we really want to remove the whole file if an update fails
@ -251,37 +281,37 @@ class File extends DAV\Node implements DAV\IFile {
$maxfilesize = get_config('system', 'maxfilesize');
if (($maxfilesize) && ($size > $maxfilesize)) {
attach_delete($c[0]['channel_id'], $this->data['hash']);
attach_delete($channel['channel_id'], $this->data['hash']);
return;
}
$limit = engr_units_to_bytes(service_class_fetch($c[0]['channel_id'], 'attach_upload_limit'));
$limit = engr_units_to_bytes(service_class_fetch($channel['channel_id'], 'attach_upload_limit'));
if ($limit !== false) {
$x = q("select sum(filesize) as total from attach where aid = %d ",
intval($c[0]['channel_account_id'])
intval($channel['channel_account_id'])
);
if (($x) && ($x[0]['total'] + $size > $limit)) {
logger('service class limit exceeded for ' . $c[0]['channel_name'] . ' total usage is ' . $x[0]['total'] . ' limit is ' . userReadableSize($limit));
attach_delete($c[0]['channel_id'], $this->data['hash']);
logger('service class limit exceeded for ' . $channel['channel_name'] . ' total usage is ' . $x[0]['total'] . ' limit is ' . userReadableSize($limit));
attach_delete($channel['channel_id'], $this->data['hash']);
return;
}
}
\Zotlabs\Daemon\Master::Summon([ 'Thumbnail' , $this->data['hash'] ]);
Master::Summon([ 'Thumbnail' , $this->data['hash'] ]);
$sync = attach_export_data($channel,$this->data['hash']);
$sync = attach_export_data($c[0],$this->data['hash']);
if($sync)
Libsync::build_sync_packet($c[0]['channel_id'],array('file' => array($sync)));
if ($sync) {
Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync)));
}
}
/**
* @brief Returns the raw data.
*
* @return string
* @return string || resource
*/
public function get() {
logger('get file ' . basename($this->name), LOGGER_DEBUG);
logger('os_path: ' . $this->os_path, LOGGER_DATA);
@ -301,10 +331,12 @@ class File extends DAV\Node implements DAV\IFile {
if (intval($r[0]['os_storage'])) {
$x = dbunescbin($r[0]['content']);
if(strpos($x,'store') === false)
if (strpos($x,'store') === false) {
$f = 'store/' . $this->auth->owner_nick . '/' . (($this->os_path) ? $this->os_path . '/' : '') . $x;
else
}
else {
$f = $x;
}
return @fopen($f, 'rb');
}
return dbunescbin($r[0]['content']);
@ -362,6 +394,7 @@ class File extends DAV\Node implements DAV\IFile {
*
* @return int last modification time in UNIX timestamp
*/
public function getLastModified() {
return datetime_convert('UTC', 'UTC', $this->data['edited'], 'U');
}
@ -393,11 +426,12 @@ class File extends DAV\Node implements DAV\IFile {
attach_delete($this->auth->owner_id, $this->data['hash']);
$ch = channelx_by_n($this->auth->owner_id);
if($ch) {
$sync = attach_export_data($ch, $this->data['hash'], true);
if($sync)
Libsync::build_sync_packet($ch['channel_id'], array('file' => array($sync)));
$channel = channelx_by_n($this->auth->owner_id);
if ($channel) {
$sync = attach_export_data($channel, $this->data['hash'], true);
if ($sync) {
Libsync::build_sync_packet($channel['channel_id'], [ 'file' => [ $sync ] ]);
}
}
}
}

View file

@ -16,7 +16,7 @@ use Zotlabs\Daemon\Master;
* @brief This file defines some global constants and includes the central App class.
*/
define ( 'STD_VERSION', '20.05.04' );
define ( 'STD_VERSION', '20.05.06' );
define ( 'ZOT_REVISION', '6.0' );
define ( 'DB_UPDATE_VERSION', 1239 );
@ -2042,9 +2042,9 @@ function dba_timer() {
*/
function get_observer_hash() {
$observer = App::get_observer();
if(is_array($observer))
if (is_array($observer)) {
return $observer['xchan_hash'];
}
return '';
}
@ -2527,3 +2527,6 @@ function get_safemode() {
return intval($_SESSION['safemode']);
}
function supported_imagetype($x) {
return in_array($x, [ IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG, IMAGETYPE_WEBP ]);
}

View file

@ -2577,8 +2577,9 @@ function attach_syspaths($channel_id,$attach_hash) {
dbesc($attach_hash),
intval($channel_id)
);
if(! $r)
if (! $r) {
break;
}
$os_path = $r[0]['hash'] . (($os_path) ? '/' . $os_path : '');
$path = $r[0]['filename'] . (($path) ? '/' . $path : '');

View file

@ -188,129 +188,131 @@ function delete_thing_photo($url, $ob_hash) {
* * \e string \b 5 => modification date
*/
function import_xchan_photo($photo, $xchan, $thing = false, $force = false) {
$modified = '';
$o = null;
$flags = (($thing) ? PHOTO_THING : PHOTO_XCHAN);
$album = (($thing) ? 'Things' : 'Contact Photos');
logger('Updating channel photo from ' . $photo . ' for ' . $xchan, LOGGER_DEBUG);
if($thing) {
$hash = photo_new_resource();
} else {
$r = q("select resource_id, edited, mimetype from photo where xchan = '%s' and photo_usage = %d and imgscale = 4 limit 1", dbesc($xchan), intval(PHOTO_XCHAN));
if($r) {
$hash = $r[0]['resource_id'];
$modified = $r[0]['edited'];
$type = $r[0]['mimetype'];
} else {
$hash = photo_new_resource();
$flags = (($thing) ? PHOTO_THING : PHOTO_XCHAN);
$album = (($thing) ? 'Things' : 'Contact Photos');
$modified = EMPTY_STR;
$o = null;
$failed = true;
$img_str = EMPTY_STR;
$hash = photo_new_resource();
if (! $thing) {
$r = q("select resource_id, edited, mimetype from photo where xchan = '%s' and photo_usage = %d and imgscale = 4 limit 1",
dbesc($xchan),
intval(PHOTO_XCHAN)
);
if ($r) {
$r = array_shift($r);
$hash = $r['resource_id'];
$modified = $r['edited'];
$type = $r['mimetype'];
}
}
$photo_failure = false;
$img_str = '';
if($photo) {
if ($photo) {
if($force || $modified == '') {
if ($modified === EMPTY_STR || $force) {
$result = z_fetch_url($photo, true);
} else {
$h = [
'headers' => [
'If-Modified-Since: ' . gmdate('D, d M Y H:i:s', strtotime($modified . 'Z')) . ' GMT'
]
];
}
else {
$h = [ 'headers' => [ 'If-Modified-Since: ' . gmdate('D, d M Y H:i:s', strtotime($modified . 'Z')) . ' GMT' ] ];
$result = z_fetch_url($photo, true, 0, $h);
}
if($result['success']) {
if ($result['success']) {
$img_str = $result['body'];
$type = guess_image_type($photo, $result['header']);
$modified = gmdate('Y-m-d H:i:s', (preg_match('/last-modified: (.+) \S+/i', $result['header'], $o) ? strtotime($o[1] . 'Z') : time()));
if(is_null($type))
$photo_failure = true;
} elseif($result['return_code'] == 304) {
if (! is_null($type)) {
$failed = false;
}
}
elseif ($result['return_code'] == 304) {
$photo = z_root() . '/photo/' . $hash . '-4';
$thumb = z_root() . '/photo/' . $hash . '-5';
$micro = z_root() . '/photo/' . $hash . '-6';
} else {
$photo_failure = true;
$failed = false;
}
} else {
$photo_failure = true;
}
if(!$photo_failure && $result['return_code'] != 304) {
if (! $failed && $result['return_code'] != 304) {
$img = photo_factory($img_str, $type);
if($img->is_valid()) {
if ($img->is_valid()) {
$width = $img->getWidth();
$height = $img->getHeight();
if($width && $height) {
if(($width / $height) > 1.2) {
if ($width && $height) {
if (($width / $height) > 1.2) {
// crop out the sides
$margin = $width - $height;
$img->cropImage(300, ($margin / 2), 0, $height, $height);
} elseif(($height / $width) > 1.2) {
}
elseif(($height / $width) > 1.2) {
// crop out the bottom
$margin = $height - $width;
$img->cropImage(300, 0, 0, $width, $width);
} else {
}
else {
$img->scaleImageSquare(300);
}
} else {
$photo_failure = true;
}
else {
$failed = true;
}
$p = [
'xchan' => $xchan,
'resource_id' => $hash,
'filename' => basename($photo),
'album' => $album,
'photo_usage' => $flags,
'imgscale' => 4,
'edited' => $modified,
'xchan' => $xchan,
'resource_id' => $hash,
'filename' => basename($photo),
'album' => $album,
'photo_usage' => $flags,
'imgscale' => 4,
'edited' => $modified,
];
$r = $img->save($p);
if($r === false)
$photo_failure = true;
if ($r === false) {
$failed = true;
}
$img->scaleImage(80);
$p['imgscale'] = 5;
$r = $img->save($p);
if($r === false)
$photo_failure = true;
if ($r === false) {
$failed = true;
}
$img->scaleImage(48);
$p['imgscale'] = 6;
$r = $img->save($p);
if($r === false)
$photo_failure = true;
if ($r === false) {
$failed = true;
}
$photo = z_root() . '/photo/' . $hash . '-4';
$thumb = z_root() . '/photo/' . $hash . '-5';
$micro = z_root() . '/photo/' . $hash . '-6';
} else {
}
else {
logger('Invalid image from ' . $photo);
$photo_failure = true;
$failed = true;
}
}
if($photo_failure) {
$default = get_default_profile_photo();
$photo = z_root() . '/' . $default;
$thumb = z_root() . '/' . get_default_profile_photo(80);
$micro = z_root() . '/' . get_default_profile_photo(48);
$type = 'image/png';
if ($failed) {
$default = get_default_profile_photo();
$photo = z_root() . '/' . $default;
$thumb = z_root() . '/' . get_default_profile_photo(80);
$micro = z_root() . '/' . get_default_profile_photo(48);
$type = 'image/png';
$modified = gmdate('Y-m-d H:i:s', filemtime($default));
}
logger('HTTP code: ' . $result['return_code'] . '; modified: ' . $modified
. '; failure: ' . ($photo_failure ? 'yes' : 'no') . '; URL: ' . $photo, LOGGER_DEBUG);
. '; failure: ' . ($failed ? 'yes' : 'no') . '; URL: ' . $photo, LOGGER_DEBUG);
return([$photo, $thumb, $micro, $type, $photo_failure, $modified]);
return([$photo, $thumb, $micro, $type, $failed, $modified]);
}
/**

View file

@ -25,7 +25,7 @@ function photo_upload($channel, $observer, $args) {
$ret = [ 'success' => false ];
$channel_id = $channel['channel_id'];
$account_id = $channel['channel_account_id'];
if (! perm_is_allowed($channel_id, $observer['xchan_hash'], 'write_storage')) {
$ret['message'] = t('Permission denied.');
return $ret;