diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/AccessList.php | 148 | ||||
-rw-r--r-- | include/DReport.php | 55 | ||||
-rw-r--r-- | include/RedDAV/RedBasicAuth.php | 212 | ||||
-rw-r--r-- | include/RedDAV/RedBrowser.php | 372 | ||||
-rw-r--r-- | include/RedDAV/RedDirectory.php | 536 | ||||
-rw-r--r-- | include/RedDAV/RedFile.php | 322 | ||||
-rw-r--r-- | include/account.php | 4 | ||||
-rw-r--r-- | include/api.php | 10 | ||||
-rw-r--r-- | include/datetime.php | 49 | ||||
-rw-r--r-- | include/enotify.php | 2 | ||||
-rw-r--r-- | include/event.php | 2 | ||||
-rw-r--r-- | include/features.php | 2 | ||||
-rw-r--r-- | include/identity.php | 4 | ||||
-rwxr-xr-x | include/items.php | 13 | ||||
-rw-r--r-- | include/language.php | 2 | ||||
-rw-r--r-- | include/menu.php | 4 | ||||
-rw-r--r-- | include/network.php | 14 | ||||
-rwxr-xr-x | include/oembed.php | 2 | ||||
-rw-r--r-- | include/permissions.php | 8 | ||||
-rw-r--r-- | include/photos.php | 2 | ||||
-rwxr-xr-x | include/plugin.php | 11 | ||||
-rw-r--r-- | include/reddav.php | 22 | ||||
-rw-r--r-- | include/text.php | 60 | ||||
-rw-r--r-- | include/zot.php | 15 |
24 files changed, 153 insertions, 1718 deletions
diff --git a/include/AccessList.php b/include/AccessList.php deleted file mode 100644 index 43f1de111..000000000 --- a/include/AccessList.php +++ /dev/null @@ -1,148 +0,0 @@ -<?php - - -class AccessList { - - private $allow_cid; - private $allow_gid; - private $deny_cid; - private $deny_gid; - - /* indicates if we are using the default constructor values or values that have been set explicitly. */ - - private $explicit; - - function __construct($channel) { - - if($channel) { - $this->allow_cid = $channel['channel_allow_cid']; - $this->allow_gid = $channel['channel_allow_gid']; - $this->deny_cid = $channel['channel_deny_cid']; - $this->deny_gid = $channel['channel_deny_gid']; - } - else { - $this->allow_cid = ''; - $this->allow_gid = ''; - $this->deny_cid = ''; - $this->deny_gid = ''; - } - - $this->explicit = false; - } - - function get_explicit() { - return $this->explicit; - } - - /** - * Set AccessList from strings such as those in already - * existing stored data items - */ - - function set($arr,$explicit = true) { - $this->allow_cid = $arr['allow_cid']; - $this->allow_gid = $arr['allow_gid']; - $this->deny_cid = $arr['deny_cid']; - $this->deny_gid = $arr['deny_gid']; - - $this->explicit = $explicit; - } - - /** - * return an array consisting of the current - * access list components where the elements - * are directly storable. - */ - - function get() { - return array( - 'allow_cid' => $this->allow_cid, - 'allow_gid' => $this->allow_gid, - 'deny_cid' => $this->deny_cid, - 'deny_gid' => $this->deny_gid, - ); - } - - /** - * Set AccessList from arrays, such as those provided by - * acl_selector(). For convenience, a string (or non-array) input is - * assumed to be a comma-separated list and auto-converted into an array. - */ - - function set_from_array($arr,$explicit = true) { - $this->allow_cid = perms2str((is_array($arr['contact_allow'])) - ? $arr['contact_allow'] : explode(',',$arr['contact_allow'])); - $this->allow_gid = perms2str((is_array($arr['group_allow'])) - ? $arr['group_allow'] : explode(',',$arr['group_allow'])); - $this->deny_cid = perms2str((is_array($arr['contact_deny'])) - ? $arr['contact_deny'] : explode(',',$arr['contact_deny'])); - $this->deny_gid = perms2str((is_array($arr['group_deny'])) - ? $arr['group_deny'] : explode(',',$arr['group_deny'])); - - $this->explicit = $explicit; - } - - function is_private() { - return (($this->allow_cid || $this->allow_gid || $this->deny_cid || $this->deny_gid) ? true : false); - } - -} - -/** - * @brief Used to wrap ACL elements in angle brackets for storage. - * - * @param[in,out] array &$item - */ -function sanitise_acl(&$item) { - if (strlen($item)) - $item = '<' . notags(trim($item)) . '>'; - else - unset($item); -} - -/** - * @brief Convert an ACL array to a storable string. - * - * @param array $p - * @return array - */ -function perms2str($p) { - $ret = ''; - - if (is_array($p)) - $tmp = $p; - else - $tmp = explode(',', $p); - - if (is_array($tmp)) { - array_walk($tmp, 'sanitise_acl'); - $ret = implode('', $tmp); - } - - return $ret; -} - - -/** - * @brief Turn user/group ACLs stored as angle bracketed text into arrays. - * - * turn string array of angle-bracketed elements into string array - * e.g. "<123xyz><246qyo><sxo33e>" => array(123xyz,246qyo,sxo33e); - * - * @param string $s - * @return array - */ -function expand_acl($s) { - $ret = array(); - - if(strlen($s)) { - $t = str_replace('<','',$s); - $a = explode('>',$t); - foreach($a as $aa) { - if($aa) - $ret[] = $aa; - } - } - - return $ret; -} diff --git a/include/DReport.php b/include/DReport.php deleted file mode 100644 index ef86c8cbc..000000000 --- a/include/DReport.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php - - -class DReport { - - private $location; - private $sender; - private $recipient; - private $message_id; - private $status; - private $date; - - function __construct($location,$sender,$recipient,$message_id,$status = 'deliver') { - $this->location = $location; - $this->sender = $sender; - $this->recipient = $recipient; - $this->message_id = $message_id; - $this->status = $status; - $this->date = datetime_convert(); - } - - function update($status) { - $this->status = $status; - $this->date = datetime_convert(); - } - - function addto_recipient($name) { - $this->recipient = $this->recipient . ' ' . $name; - } - - function addto_update($status) { - $this->status = $this->status . ' ' . $status; - } - - - function set($arr) { - $this->location = $arr['location']; - $this->sender = $arr['sender']; - $this->recipient = $arr['recipient']; - $this->message_id = $arr['message_id']; - $this->status = $arr['status']; - $this->date = $arr['date']; - } - - function get() { - return array( - 'location' => $this->location, - 'sender' => $this->sender, - 'recipient' => $this->recipient, - 'message_id' => $this->message_id, - 'status' => $this->status, - 'date' => $this->date - ); - } -} diff --git a/include/RedDAV/RedBasicAuth.php b/include/RedDAV/RedBasicAuth.php deleted file mode 100644 index 19dd9a5f0..000000000 --- a/include/RedDAV/RedBasicAuth.php +++ /dev/null @@ -1,212 +0,0 @@ -<?php - -namespace RedMatrix\RedDAV; - -use Sabre\DAV; - -/** - * @brief Authentication backend class for RedDAV. - * - * This class also contains some data which is not necessary for authentication - * like timezone settings. - * - * @extends Sabre\DAV\Auth\Backend\AbstractBasic - * - * @link http://github.com/friendica/red - * @license http://opensource.org/licenses/mit-license.php The MIT License (MIT) - */ -class RedBasicAuth extends DAV\Auth\Backend\AbstractBasic { - - /** - * @brief This variable holds the currently logged-in channel_address. - * - * It is used for building path in filestorage/. - * - * @var string|null - */ - protected $channel_name = null; - /** - * channel_id of the current channel of the logged-in account. - * - * @var int - */ - public $channel_id = 0; - /** - * channel_hash of the current channel of the logged-in account. - * - * @var string - */ - public $channel_hash = ''; - /** - * Set in mod/cloud.php to observer_hash. - * - * @var string - */ - public $observer = ''; - /** - * - * @see RedBrowser::set_writeable() - * @var \Sabre\DAV\Browser\Plugin - */ - public $browser; - /** - * channel_id of the current visited path. Set in RedDirectory::getDir(). - * - * @var int - */ - public $owner_id = 0; - /** - * channel_name of the current visited path. Set in RedDirectory::getDir(). - * - * Used for creating the path in cloud/ - * - * @var string - */ - public $owner_nick = ''; - /** - * Timezone from the visiting channel's channel_timezone. - * - * Used in @ref RedBrowser - * - * @var string - */ - protected $timezone = ''; - - - /** - * @brief Validates a username and password. - * - * Guest access is granted with the password "+++". - * - * @see \Sabre\DAV\Auth\Backend\AbstractBasic::validateUserPass - * @param string $username - * @param string $password - * @return bool - */ - protected function validateUserPass($username, $password) { - if (trim($password) === '+++') { - logger('guest: ' . $username); - return true; - } - - require_once('include/auth.php'); - $record = account_verify_password($username, $password); - if ($record && $record['account_default_channel']) { - $r = q("SELECT * FROM channel WHERE channel_account_id = %d AND channel_id = %d LIMIT 1", - intval($record['account_id']), - intval($record['account_default_channel']) - ); - if ($r) { - return $this->setAuthenticated($r[0]); - } - } - $r = q("SELECT * FROM channel WHERE channel_address = '%s' LIMIT 1", - dbesc($username) - ); - if ($r) { - $x = q("SELECT account_flags, account_salt, account_password FROM account WHERE account_id = %d LIMIT 1", - intval($r[0]['channel_account_id']) - ); - if ($x) { - // @fixme this foreach should not be needed? - foreach ($x as $record) { - if (($record['account_flags'] == ACCOUNT_OK) || ($record['account_flags'] == ACCOUNT_UNVERIFIED) - && (hash('whirlpool', $record['account_salt'] . $password) === $record['account_password'])) { - logger('password verified for ' . $username); - return $this->setAuthenticated($r[0]); - } - } - } - } - - $error = 'password failed for ' . $username; - logger($error); - log_failed_login($error); - - return false; - } - - /** - * @brief Sets variables and session parameters after successfull authentication. - * - * @param array $r - * Array with the values for the authenticated channel. - * @return bool - */ - protected function setAuthenticated($r) { - $this->channel_name = $r['channel_address']; - $this->channel_id = $r['channel_id']; - $this->channel_hash = $this->observer = $r['channel_hash']; - $_SESSION['uid'] = $r['channel_id']; - $_SESSION['account_id'] = $r['channel_account_id']; - $_SESSION['authenticated'] = true; - return true; - } - - /** - * Sets the channel_name from the currently logged-in channel. - * - * @param string $name - * The channel's name - */ - public function setCurrentUser($name) { - $this->channel_name = $name; - } - /** - * Returns information about the currently logged-in channel. - * - * If nobody is currently logged in, this method should return null. - * - * @see \Sabre\DAV\Auth\Backend\AbstractBasic::getCurrentUser - * @return string|null - */ - public function getCurrentUser() { - return $this->channel_name; - } - - /** - * @brief Sets the timezone from the channel in RedBasicAuth. - * - * Set in mod/cloud.php if the channel has a timezone set. - * - * @param string $timezone - * The channel's timezone. - * @return void - */ - public function setTimezone($timezone) { - $this->timezone = $timezone; - } - /** - * @brief Returns the timezone. - * - * @return string - * Return the channel's timezone. - */ - public function getTimezone() { - return $this->timezone; - } - - /** - * @brief Set browser plugin for SabreDAV. - * - * @see RedBrowser::set_writeable() - * @param \Sabre\DAV\Browser\Plugin $browser - */ - public function setBrowserPlugin($browser) { - $this->browser = $browser; - } - - /** - * @brief Prints out all RedBasicAuth variables to logger(). - * - * @return void - */ - public function log() { - logger('channel_name ' . $this->channel_name, LOGGER_DATA); - logger('channel_id ' . $this->channel_id, LOGGER_DATA); - logger('channel_hash ' . $this->channel_hash, LOGGER_DATA); - logger('observer ' . $this->observer, LOGGER_DATA); - logger('owner_id ' . $this->owner_id, LOGGER_DATA); - logger('owner_nick ' . $this->owner_nick, LOGGER_DATA); - } -}
\ No newline at end of file diff --git a/include/RedDAV/RedBrowser.php b/include/RedDAV/RedBrowser.php deleted file mode 100644 index 1aa5f435e..000000000 --- a/include/RedDAV/RedBrowser.php +++ /dev/null @@ -1,372 +0,0 @@ -<?php - -namespace RedMatrix\RedDAV; - -use Sabre\DAV; - -/** - * @brief Provides a DAV frontend for the webbrowser. - * - * RedBrowser is a SabreDAV server-plugin to provide a view to the DAV storage - * for the webbrowser. - * - * @extends \Sabre\DAV\Browser\Plugin - * - * @link http://github.com/friendica/red - * @license http://opensource.org/licenses/mit-license.php The MIT License (MIT) - */ -class RedBrowser extends DAV\Browser\Plugin { - - /** - * @see set_writeable() - * @see \Sabre\DAV\Auth\Backend\BackendInterface - * @var RedBasicAuth - */ - private $auth; - - /** - * @brief Constructor for RedBrowser class. - * - * $enablePost will be activated through set_writeable() in a later stage. - * At the moment the write_storage permission is only valid for the whole - * folder. No file specific permissions yet. - * @todo disable enablePost by default and only activate if permissions - * grant edit rights. - * - * Disable assets with $enableAssets = false. Should get some thumbnail views - * anyway. - * - * @param RedBasicAuth &$auth - */ - public function __construct(&$auth) { - $this->auth = $auth; - parent::__construct(true, false); - } - - /** - * The DAV browser is instantiated after the auth module and directory classes - * but before we know the current directory and who the owner and observer - * are. So we add a pointer to the browser into the auth module and vice versa. - * Then when we've figured out what directory is actually being accessed, we - * call the following function to decide whether or not to show web elements - * which include writeable objects. - * - * @fixme It only disable/enable the visible parts. Not the POST handler - * which handels the actual requests when uploading files or creating folders. - * - * @todo Maybe this whole way of doing this can be solved with some - * $server->subscribeEvent(). - */ - public function set_writeable() { - if (! $this->auth->owner_id) { - $this->enablePost = false; - } - - if (! perm_is_allowed($this->auth->owner_id, get_observer_hash(), 'write_storage')) { - $this->enablePost = false; - } else { - $this->enablePost = true; - } - } - - /** - * @brief Creates the directory listing for the given path. - * - * @param string $path which should be displayed - */ - public function generateDirectoryIndex($path) { - // (owner_id = channel_id) is visitor owner of this directory? - $is_owner = ((local_channel() && $this->auth->owner_id == local_channel()) ? true : false); - - if ($this->auth->getTimezone()) - date_default_timezone_set($this->auth->getTimezone()); - - require_once('include/conversation.php'); - require_once('include/text.php'); - if ($this->auth->owner_nick) { - $html = profile_tabs(get_app(), (($is_owner) ? true : false), $this->auth->owner_nick); - } - - $files = $this->server->getPropertiesForPath($path, array( - '{DAV:}displayname', - '{DAV:}resourcetype', - '{DAV:}getcontenttype', - '{DAV:}getcontentlength', - '{DAV:}getlastmodified', - ), 1); - - - $parent = $this->server->tree->getNodeForPath($path); - - $parentpath = array(); - // only show parent if not leaving /cloud/; TODO how to improve this? - if ($path && $path != "cloud") { - list($parentUri) = DAV\URLUtil::splitPath($path); - $fullPath = DAV\URLUtil::encodePath($this->server->getBaseUri() . $parentUri); - - $parentpath['icon'] = $this->enableAssets ? '<a href="' . $fullPath . '"><img src="' . $this->getAssetUrl('icons/parent' . $this->iconExtension) . '" width="24" alt="' . t('parent') . '"></a>' : ''; - $parentpath['path'] = $fullPath; - } - - $f = array(); - foreach ($files as $file) { - $ft = array(); - $type = null; - - // This is the current directory, we can skip it - if (rtrim($file['href'],'/') == $path) continue; - - list(, $name) = DAV\URLUtil::splitPath($file['href']); - - if (isset($file[200]['{DAV:}resourcetype'])) { - $type = $file[200]['{DAV:}resourcetype']->getValue(); - - // resourcetype can have multiple values - if (!is_array($type)) $type = array($type); - - foreach ($type as $k=>$v) { - // Some name mapping is preferred - switch ($v) { - case '{DAV:}collection' : - $type[$k] = t('Collection'); - break; - case '{DAV:}principal' : - $type[$k] = t('Principal'); - break; - case '{urn:ietf:params:xml:ns:carddav}addressbook' : - $type[$k] = t('Addressbook'); - break; - case '{urn:ietf:params:xml:ns:caldav}calendar' : - $type[$k] = t('Calendar'); - break; - case '{urn:ietf:params:xml:ns:caldav}schedule-inbox' : - $type[$k] = t('Schedule Inbox'); - break; - case '{urn:ietf:params:xml:ns:caldav}schedule-outbox' : - $type[$k] = t('Schedule Outbox'); - break; - case '{http://calendarserver.org/ns/}calendar-proxy-read' : - $type[$k] = 'Proxy-Read'; - break; - case '{http://calendarserver.org/ns/}calendar-proxy-write' : - $type[$k] = 'Proxy-Write'; - break; - } - } - $type = implode(', ', $type); - } - - // If no resourcetype was found, we attempt to use - // the contenttype property - if (!$type && isset($file[200]['{DAV:}getcontenttype'])) { - $type = $file[200]['{DAV:}getcontenttype']; - } - if (!$type) $type = t('Unknown'); - - $size = isset($file[200]['{DAV:}getcontentlength']) ? (int)$file[200]['{DAV:}getcontentlength'] : ''; - $lastmodified = ((isset($file[200]['{DAV:}getlastmodified'])) ? $file[200]['{DAV:}getlastmodified']->getTime()->format('Y-m-d H:i:s') : ''); - - $fullPath = DAV\URLUtil::encodePath('/' . trim($this->server->getBaseUri() . ($path ? $path . '/' : '') . $name, '/')); - - - $displayName = isset($file[200]['{DAV:}displayname']) ? $file[200]['{DAV:}displayname'] : $name; - - $displayName = $this->escapeHTML($displayName); - $type = $this->escapeHTML($type); - - $icon = ''; - - if ($this->enableAssets) { - $node = $this->server->tree->getNodeForPath(($path ? $path . '/' : '') . $name); - foreach (array_reverse($this->iconMap) as $class=>$iconName) { - if ($node instanceof $class) { - $icon = '<a href="' . $fullPath . '"><img src="' . $this->getAssetUrl($iconName . $this->iconExtension) . '" alt="" width="24"></a>'; - break; - } - } - } - - $parentHash = ''; - $owner = $this->auth->owner_id; - $splitPath = explode('/', $fullPath); - if (count($splitPath) > 3) { - for ($i = 3; $i < count($splitPath); $i++) { - $attachName = urldecode($splitPath[$i]); - $attachHash = $this->findAttachHash($owner, $parentHash, $attachName); - $parentHash = $attachHash; - } - } - - $attachIcon = ""; // "<a href=\"attach/".$attachHash."\" title=\"".$displayName."\"><i class=\"icon-download\"></i></a>"; - - // put the array for this file together - $ft['attachId'] = $this->findAttachIdByHash($attachHash); - $ft['fileStorageUrl'] = substr($fullPath, 0, strpos($fullPath, "cloud/")) . "filestorage/" . $this->auth->getCurrentUser(); - $ft['icon'] = $icon; - $ft['attachIcon'] = (($size) ? $attachIcon : ''); - // @todo Should this be an item value, not a global one? - $ft['is_owner'] = $is_owner; - $ft['fullPath'] = $fullPath; - $ft['displayName'] = $displayName; - $ft['type'] = $type; - $ft['size'] = $size; - $ft['sizeFormatted'] = userReadableSize($size); - $ft['lastmodified'] = (($lastmodified) ? datetime_convert('UTC', date_default_timezone_get(), $lastmodified) : ''); - $ft['iconFromType'] = getIconFromType($type); - - $f[] = $ft; - } - - $output = ''; - if ($this->enablePost) { - $this->server->broadcastEvent('onHTMLActionsPanel', array($parent, &$output)); - } - - $html .= replace_macros(get_markup_template('cloud.tpl'), array( - '$header' => t('Files') . ": " . $this->escapeHTML($path) . "/", - '$total' => t('Total'), - '$actionspanel' => $output, - '$shared' => t('Shared'), - '$create' => t('Create'), - '$upload' => t('Upload'), - '$is_owner' => $is_owner, - '$parentpath' => $parentpath, - '$entries' => $f, - '$name' => t('Name'), - '$type' => t('Type'), - '$size' => t('Size'), - '$lastmod' => t('Last Modified'), - '$parent' => t('parent'), - '$edit' => t('Edit'), - '$delete' => t('Delete'), - '$nick' => $this->auth->getCurrentUser() - )); - - $a = get_app(); - $a->page['content'] = $html; - load_pdl($a); - - $theme_info_file = "view/theme/" . current_theme() . "/php/theme.php"; - if (file_exists($theme_info_file)){ - require_once($theme_info_file); - if (function_exists(str_replace('-', '_', current_theme()) . '_init')) { - $func = str_replace('-', '_', current_theme()) . '_init'; - $func($a); - } - } - construct_page($a); - } - - /** - * @brief Creates a form to add new folders and upload files. - * - * @param \Sabre\DAV\INode $node - * @param string &$output - */ - public function htmlActionsPanel(DAV\INode $node, &$output) { - if (! $node instanceof DAV\ICollection) - return; - - // We also know fairly certain that if an object is a non-extended - // SimpleCollection, we won't need to show the panel either. - if (get_class($node) === 'Sabre\\DAV\\SimpleCollection') - return; - - // Storage and quota for the account (all channels of the owner of this directory)! - $limit = service_class_fetch($owner, 'attach_upload_limit'); - $r = q("SELECT SUM(filesize) AS total FROM attach WHERE aid = %d", - intval($this->auth->channel_account_id) - ); - $used = $r[0]['total']; - if ($used) { - $quotaDesc = t('You are using %1$s of your available file storage.'); - $quotaDesc = sprintf($quotaDesc, - userReadableSize($used)); - } - if ($limit && $used) { - $quotaDesc = t('You are using %1$s of %2$s available file storage. (%3$s%)'); - $quotaDesc = sprintf($quotaDesc, - userReadableSize($used), - userReadableSize($limit), - round($used / $limit, 1) * 100); - } - - // prepare quota for template - $quota = array(); - $quota['used'] = $used; - $quota['limit'] = $limit; - $quota['desc'] = $quotaDesc; - $quota['warning'] = ((($limit) && ((round($used / $limit, 1) * 100) >= 90)) ? t('WARNING:') : ''); // 10485760 bytes = 100MB - - $output .= replace_macros(get_markup_template('cloud_actionspanel.tpl'), array( - '$folder_header' => t('Create new folder'), - '$folder_submit' => t('Create'), - '$upload_header' => t('Upload file'), - '$upload_submit' => t('Upload'), - '$quota' => $quota - )); - } - - /** - * This method takes a path/name of an asset and turns it into url - * suiteable for http access. - * - * @param string $assetName - * @return string - */ - protected function getAssetUrl($assetName) { - return z_root() . '/cloud/?sabreAction=asset&assetName=' . urlencode($assetName); - } - - /** - * @brief Return the hash of an attachment. - * - * Given the owner, the parent folder and and attach name get the attachment - * hash. - * - * @param int $owner - * The owner_id - * @param string $hash - * The parent's folder hash - * @param string $attachName - * The name of the attachment - * @return string - */ - - protected function findAttachHash($owner, $parentHash, $attachName) { - $r = q("SELECT hash FROM attach WHERE uid = %d AND folder = '%s' AND filename = '%s' ORDER BY edited DESC LIMIT 1", - intval($owner), - dbesc($parentHash), - dbesc($attachName) - ); - $hash = ""; - if ($r) { - foreach ($r as $rr) { - $hash = $rr['hash']; - } - } - return $hash; - } - - /** - * @brief Returns an attachment's id for a given hash. - * - * This id is used to access the attachment in filestorage/ - * - * @param string $attachHash - * The hash of an attachment - * @return string - */ - protected function findAttachIdByHash($attachHash) { - $r = q("SELECT id FROM attach WHERE hash = '%s' ORDER BY edited DESC LIMIT 1", - dbesc($attachHash) - ); - $id = ""; - if ($r) { - foreach ($r as $rr) { - $id = $rr['id']; - } - } - return $id; - } -} diff --git a/include/RedDAV/RedDirectory.php b/include/RedDAV/RedDirectory.php deleted file mode 100644 index 8d8af5bd3..000000000 --- a/include/RedDAV/RedDirectory.php +++ /dev/null @@ -1,536 +0,0 @@ -<?php - -namespace RedMatrix\RedDAV; - -use Sabre\DAV; - -/** - * @brief RedDirectory class. - * - * A class that represents a directory. - * - * @extends \Sabre\DAV\Node - * @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 RedDirectory extends DAV\Node implements DAV\ICollection, DAV\IQuota { - - /** - * @brief The path inside /cloud - * - * @var string - */ - private $red_path; - private $folder_hash; - /** - * @brief The full path as seen in the browser. - * /cloud + $red_path - * @todo I think this is not used anywhere, we always strip '/cloud' and only use it in debug - * @var string - */ - private $ext_path; - private $root_dir = ''; - private $auth; - /** - * @brief The real path on the filesystem. - * The actual path in store/ with the hashed names. - * - * @var string - */ - private $os_path = ''; - - /** - * @brief Sets up the directory node, expects a full path. - * - * @param string $ext_path a full path - * @param RedBasicAuth &$auth_plugin - */ - public function __construct($ext_path, &$auth_plugin) { -// $ext_path = urldecode($ext_path); - logger('directory ' . $ext_path, LOGGER_DATA); - $this->ext_path = $ext_path; - // remove "/cloud" from the beginning of the path - $modulename = get_app()->module; - $this->red_path = ((strpos($ext_path, '/' . $modulename) === 0) ? substr($ext_path, strlen($modulename) + 1) : $ext_path); - if (! $this->red_path) { - $this->red_path = '/'; - } - $this->auth = $auth_plugin; - $this->folder_hash = ''; - $this->getDir(); - - if ($this->auth->browser) { - $this->auth->browser->set_writeable(); - } - } - - private function log() { - logger('ext_path ' . $this->ext_path, LOGGER_DATA); - logger('os_path ' . $this->os_path, LOGGER_DATA); - logger('red_path ' . $this->red_path, LOGGER_DATA); - } - - /** - * @brief Returns an array with all the child nodes. - * - * @throw \Sabre\DAV\Exception\Forbidden - * @return array \Sabre\DAV\INode[] - */ - public function getChildren() { - logger('children for ' . $this->ext_path, LOGGER_DATA); - $this->log(); - - if (get_config('system', 'block_public') && (! $this->auth->channel_id) && (! $this->auth->observer)) { - throw new DAV\Exception\Forbidden('Permission denied.'); - } - - if (($this->auth->owner_id) && (! perm_is_allowed($this->auth->owner_id, $this->auth->observer, 'view_storage'))) { - throw new DAV\Exception\Forbidden('Permission denied.'); - } - - $contents = RedCollectionData($this->red_path, $this->auth); - return $contents; - } - - /** - * @brief Returns a child by name. - * - * - * @throw \Sabre\DAV\Exception\Forbidden - * @throw \Sabre\DAV\Exception\NotFound - * @param string $name - */ - public function getChild($name) { - logger($name, LOGGER_DATA); - - if (get_config('system', 'block_public') && (! $this->auth->channel_id) && (! $this->auth->observer)) { - throw new DAV\Exception\Forbidden('Permission denied.'); - } - - if (($this->auth->owner_id) && (! perm_is_allowed($this->auth->owner_id, $this->auth->observer, 'view_storage'))) { - throw new DAV\Exception\Forbidden('Permission denied.'); - } - - $modulename = get_app()->module; - if ($this->red_path === '/' && $name === $modulename) { - return new RedDirectory('/' . $modulename, $this->auth); - } - - $x = RedFileData($this->ext_path . '/' . $name, $this->auth); - if ($x) { - return $x; - } - - throw new DAV\Exception\NotFound('The file with name: ' . $name . ' could not be found.'); - } - - /** - * @brief Returns the name of the directory. - * - * @return string - */ - public function getName() { - //logger(basename($this->red_path), LOGGER_DATA); - return (basename($this->red_path)); - } - - /** - * @brief Renames the directory. - * - * @todo handle duplicate directory name - * - * @throw \Sabre\DAV\Exception\Forbidden - * @param string $name The new name of the directory. - * @return void - */ - public function setName($name) { - logger('old name ' . basename($this->red_path) . ' -> ' . $name, LOGGER_DATA); - - if ((! $name) || (! $this->auth->owner_id)) { - logger('permission denied ' . $name); - throw new DAV\Exception\Forbidden('Permission denied.'); - } - - if (! perm_is_allowed($this->auth->owner_id, $this->auth->observer, 'write_storage')) { - logger('permission denied '. $name); - throw new DAV\Exception\Forbidden('Permission denied.'); - } - - list($parent_path, ) = DAV\URLUtil::splitPath($this->red_path); - $new_path = $parent_path . '/' . $name; - - $r = q("UPDATE attach SET filename = '%s' WHERE hash = '%s' AND uid = %d", - dbesc($name), - dbesc($this->folder_hash), - intval($this->auth->owner_id) - ); - - $this->red_path = $new_path; - } - - /** - * @brief Creates a new file in the directory. - * - * Data will either be supplied as a stream resource, or in certain cases - * as a string. Keep in mind that you may have to support either. - * - * After successful creation of the file, you may choose to return the ETag - * of the new file here. - * - * @throw \Sabre\DAV\Exception\Forbidden - * @param string $name Name of the file - * @param resource|string $data Initial payload - * @return null|string ETag - */ - public function createFile($name, $data = null) { - logger($name, LOGGER_DEBUG); - - if (! $this->auth->owner_id) { - logger('permission denied ' . $name); - throw new DAV\Exception\Forbidden('Permission denied.'); - } - - if (! perm_is_allowed($this->auth->owner_id, $this->auth->observer, 'write_storage')) { - logger('permission denied ' . $name); - throw new DAV\Exception\Forbidden('Permission denied.'); - } - - $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) - ); - - if (! $c) { - logger('no channel'); - throw new DAV\Exception\Forbidden('Permission denied.'); - } - - $filesize = 0; - $hash = random_string(); - - $f = 'store/' . $this->auth->owner_nick . '/' . (($this->os_path) ? $this->os_path . '/' : '') . $hash; - - $direct = null; - - 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']) - ); - if($r) - $direct = $r[0]; - } - - 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']; - } - 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']; - } - - $r = q("INSERT INTO attach ( aid, uid, hash, creator, filename, folder, os_storage, filetype, filesize, revision, is_photo, data, created, edited, 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' ) ", - intval($c[0]['channel_account_id']), - intval($c[0]['channel_id']), - dbesc($hash), - dbesc($this->auth->observer), - dbesc($name), - dbesc($this->folder_hash), - intval(1), - dbesc($mimetype), - intval($filesize), - intval(0), - intval($is_photo), - dbesc($f), - dbesc(datetime_convert()), - dbesc(datetime_convert()), - dbesc($allow_cid), - dbesc($allow_gid), - dbesc($deny_cid), - dbesc($deny_gid) - ); - - - - // returns the number of bytes that were written to the file, or FALSE on failure - $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); - return; - } - - // returns now - $edited = datetime_convert(); - - - - $is_photo = 0; - $x = @getimagesize($f); - logger('getimagesize: ' . print_r($x,true), LOGGER_DATA); - if(($x) && ($x[2] === IMAGETYPE_GIF || $x[2] === IMAGETYPE_JPEG || $x[2] === IMAGETYPE_PNG)) { - $is_photo = 1; - } - - - // updates entry with filesize and timestamp - $d = q("UPDATE attach SET filesize = '%s', is_photo = %d, edited = '%s' WHERE hash = '%s' AND uid = %d", - dbesc($size), - intval($is_photo), - dbesc($edited), - dbesc($hash), - intval($c[0]['channel_id']) - ); - - // update the 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']) - ); - - $maxfilesize = get_config('system', 'maxfilesize'); - if (($maxfilesize) && ($size > $maxfilesize)) { - attach_delete($c[0]['channel_id'], $hash); - return; - } - - // check against service class quota - $limit = service_class_fetch($c[0]['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']) - ); - 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 ' . $limit); - attach_delete($c[0]['channel_id'], $hash); - return; - } - } - - if($is_photo) { - $album = ''; - if($this->folder_hash) { - $f1 = q("select filename from attach WHERE hash = '%s' AND uid = %d", - dbesc($this->folder_hash), - intval($c[0]['channel_id']) - ); - if($f1) - $album = $f1[0]['filename']; - } - - require_once('include/photos.php'); - $args = array( 'resource_id' => $hash, 'album' => $album, 'os_path' => $f, 'filename' => $name, 'getimagesize' => $x, 'directory' => $direct); - $p = photo_upload($c[0],get_app()->get_observer(),$args); - } - - } - - /** - * @brief Creates a new subdirectory. - * - * @param string $name the directory to create - * @return void - */ - public function createDirectory($name) { - logger($name, LOGGER_DEBUG); - - if ((! $this->auth->owner_id) || (! perm_is_allowed($this->auth->owner_id, $this->auth->observer, 'write_storage'))) { - 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) - ); - - if ($r) { - $result = attach_mkdir($r[0], $this->auth->observer, array('filename' => $name, 'folder' => $this->folder_hash)); - if (! $result['success']) { - logger('error ' . print_r($result, true), LOGGER_DEBUG); - } - } - } - - /** - * @brief delete directory - */ - - public function delete() { - logger('delete file ' . basename($this->red_path), LOGGER_DEBUG); - - if ((! $this->auth->owner_id) || (! perm_is_allowed($this->auth->owner_id, $this->auth->observer, 'write_storage'))) { - throw new DAV\Exception\Forbidden('Permission denied.'); - } - - if ($this->auth->owner_id !== $this->auth->channel_id) { - if (($this->auth->observer !== $this->data['creator']) || intval($this->data['is_dir'])) { - throw new DAV\Exception\Forbidden('Permission denied.'); - } - } - - attach_delete($this->auth->owner_id, $this->folder_hash); - } - - - /** - * @brief Checks if a child exists. - * - * @param string $name - * The name to check if it exists. - * @return boolean - */ - public function childExists($name) { - // On /cloud we show a list of available channels. - // @todo what happens if no channels are available? - $modulename = get_app()->module; - if ($this->red_path === '/' && $name === $modulename) { - //logger('We are at ' $modulename . ' show a channel list', LOGGER_DEBUG); - return true; - } - - $x = RedFileData($this->ext_path . '/' . $name, $this->auth, true); - //logger('RedFileData returns: ' . print_r($x, true), LOGGER_DATA); - if ($x) - return true; - - return false; - } - - /** - * @todo add description of what this function does. - * - * @throw \Sabre\DAV\Exception\NotFound - * @return void - */ - function getDir() { - - logger('GetDir: ' . $this->ext_path, LOGGER_DEBUG); - $this->auth->log(); - $modulename = get_app()->module; - - $file = $this->ext_path; - - $x = strpos($file, '/' . $modulename); - if ($x === 0) { - $file = substr($file, strlen($modulename) + 1); - } - - if ((! $file) || ($file === '/')) { - return; - } - - $file = trim($file, '/'); - $path_arr = explode('/', $file); - - if (! $path_arr) - return; - - logger('paths: ' . print_r($path_arr, true), LOGGER_DATA); - - $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) - ); - - if (! $r) { - throw new DAV\Exception\NotFound('The file with name: ' . $channel_name . ' could not be found.'); - } - - $channel_id = $r[0]['channel_id']; - $this->auth->owner_id = $channel_id; - $this->auth->owner_nick = $channel_name; - - $path = '/' . $channel_name; - $folder = ''; - $os_path = ''; - - for ($x = 1; $x < count($path_arr); $x++) { - $r = q("select id, hash, filename, flags, is_dir from attach where folder = '%s' and filename = '%s' and uid = %d and is_dir != 0", - dbesc($folder), - dbesc($path_arr[$x]), - intval($channel_id) - ); - if ($r && intval($r[0]['is_dir'])) { - $folder = $r[0]['hash']; - if (strlen($os_path)) - $os_path .= '/'; - $os_path .= $folder; - - $path = $path . '/' . $r[0]['filename']; - } - } - $this->folder_hash = $folder; - $this->os_path = $os_path; - } - - /** - * @brief Returns the last modification time for the directory, as a UNIX - * timestamp. - * - * It looks for the last edited file in the folder. If it is an empty folder - * it returns the lastmodified time of the folder itself, to prevent zero - * timestamps. - * - * @return int last modification time in UNIX timestamp - */ - public function getLastModified() { - $r = q("SELECT edited FROM attach WHERE folder = '%s' AND uid = %d ORDER BY edited DESC LIMIT 1", - dbesc($this->folder_hash), - intval($this->auth->owner_id) - ); - if (! $r) { - $r = q("SELECT edited FROM attach WHERE hash = '%s' AND uid = %d LIMIT 1", - dbesc($this->folder_hash), - intval($this->auth->owner_id) - ); - if (! $r) - return ''; - } - return datetime_convert('UTC', 'UTC', $r[0]['edited'], 'U'); - } - - /** - * @brief Return quota usage. - * - * @fixme Should guests relly see the used/free values from filesystem of the - * complete store directory? - * - * @return array with used and free values in bytes. - */ - public function getQuotaInfo() { - // values from the filesystem of the complete <i>store/</i> directory - $limit = disk_total_space('store'); - $free = disk_free_space('store'); - - if ($this->auth->owner_id) { - $c = q("select * from channel where channel_id = %d and channel_removed = 0 limit 1", - intval($this->auth->owner_id) - ); - - $ulimit = service_class_fetch($c[0]['channel_id'], 'attach_upload_limit'); - $limit = (($ulimit) ? $ulimit : $limit); - - $x = q("select sum(filesize) as total from attach where aid = %d", - intval($c[0]['channel_account_id']) - ); - $free = (($x) ? $limit - $x[0]['total'] : 0); - } - - return array( - $limit - $free, - $free - ); - } -}
\ No newline at end of file diff --git a/include/RedDAV/RedFile.php b/include/RedDAV/RedFile.php deleted file mode 100644 index 3283a6e88..000000000 --- a/include/RedDAV/RedFile.php +++ /dev/null @@ -1,322 +0,0 @@ -<?php - -namespace RedMatrix\RedDAV; - -use Sabre\DAV; - -/** - * @brief This class represents a file in DAV. - * - * It provides all functions to work with files in Red's cloud through DAV protocol. - * - * @extends \Sabre\DAV\Node - * @implements \Sabre\DAV\IFile - * - * @link http://github.com/friendica/red - * @license http://opensource.org/licenses/mit-license.php The MIT License (MIT) - */ -class RedFile extends DAV\Node implements DAV\IFile { - - /** - * The file from attach table. - * - * @var array - * data - * flags - * filename (string) - * filetype (string) - */ - private $data; - /** - * @see \Sabre\DAV\Auth\Backend\BackendInterface - * @var \RedMatrix\RedDAV\RedBasicAuth - */ - private $auth; - /** - * @var string - */ - private $name; - - /** - * Sets up the node, expects a full path name. - * - * @param string $name - * @param array $data from attach table - * @param &$auth - */ - public function __construct($name, $data, &$auth) { - $this->name = $name; - $this->data = $data; - $this->auth = $auth; - - logger(print_r($this->data, true), LOGGER_DATA); - } - - /** - * @brief Returns the name of the file. - * - * @return string - */ - public function getName() { - //logger(basename($this->name), LOGGER_DATA); - return basename($this->name); - } - - /** - * @brief Renames the file. - * - * @throw Sabre\DAV\Exception\Forbidden - * @param string $name The new name of the file. - * @return void - */ - public function setName($newName) { - logger('old name ' . basename($this->name) . ' -> ' . $newName, LOGGER_DATA); - - if ((! $newName) || (! $this->auth->owner_id) || (! perm_is_allowed($this->auth->owner_id, $this->auth->observer, 'write_storage'))) { - logger('permission denied '. $newName); - throw new DAV\Exception\Forbidden('Permission denied.'); - } - - $newName = str_replace('/', '%2F', $newName); - - $r = q("UPDATE attach SET filename = '%s' WHERE hash = '%s' AND id = %d", - dbesc($newName), - dbesc($this->data['hash']), - intval($this->data['id']) - ); - } - - /** - * @brief Updates the data of the file. - * - * @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) - ); - - $is_photo = false; - $album = ''; - - $r = q("SELECT flags, folder, os_storage, filename, is_photo FROM attach WHERE hash = '%s' AND uid = %d LIMIT 1", - dbesc($this->data['hash']), - intval($c[0]['channel_id']) - ); - if ($r) { - if (intval($r[0]['os_storage'])) { - $d = q("select folder, data from attach where hash = '%s' and uid = %d limit 1", - dbesc($this->data['hash']), - intval($c[0]['channel_id']) - ); - 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']) - ); - if($f1) { - $album = $f1[0]['filename']; - $direct = $f1[0]; - } - } - $fname = dbunescbin($d[0]['data']); - if(strpos($fname,'store') === false) - $f = 'store/' . $this->auth->owner_nick . '/' . $fname ; - else - $f = $fname; - - // @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)) { - $is_photo = 1; - } - } - else { - // this shouldn't happen any more - $r = q("UPDATE attach SET data = '%s' WHERE hash = '%s' AND uid = %d", - dbescbin(stream_get_contents($data)), - dbesc($this->data['hash']), - intval($this->data['uid']) - ); - $r = q("SELECT length(data) AS fsize FROM attach WHERE hash = '%s' AND uid = %d LIMIT 1", - dbesc($this->data['hash']), - intval($this->data['uid']) - ); - if ($r) { - $size = $r[0]['fsize']; - } - } - } - - // returns now() - $edited = datetime_convert(); - - $d = q("UPDATE attach SET filesize = '%s', is_photo = %d, edited = '%s' WHERE hash = '%s' AND uid = %d", - dbesc($size), - intval($is_photo), - dbesc($edited), - dbesc($this->data['hash']), - intval($c[0]['channel_id']) - ); - - if($is_photo) { - require_once('include/photos.php'); - $args = array( 'resource_id' => $this->data['hash'], 'album' => $album, 'os_path' => $f, 'filename' => $r[0]['filename'], 'getimagesize' => $gis, 'directory' => $direct ); - $p = photo_upload($c[0],get_app()->get_observer(),$args); - } - - // 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']) - ); - - // @todo do we really want to remove the whole file if an update fails - // because of maxfilesize or quota? - // There is an Exception "InsufficientStorage" or "PaymentRequired" for - // our service class from SabreDAV we could use. - - $maxfilesize = get_config('system', 'maxfilesize'); - if (($maxfilesize) && ($size > $maxfilesize)) { - attach_delete($c[0]['channel_id'], $this->data['hash']); - return; - } - - $limit = service_class_fetch($c[0]['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']) - ); - 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 ' . $limit); - attach_delete($c[0]['channel_id'], $this->data['hash']); - return; - } - } - } - - /** - * @brief Returns the raw data. - * - * @return string - */ - public function get() { - logger('get file ' . basename($this->name), LOGGER_DEBUG); - logger('os_path: ' . $this->os_path, LOGGER_DATA); - - $r = q("SELECT data, flags, os_storage, filename, filetype FROM attach WHERE hash = '%s' AND uid = %d LIMIT 1", - dbesc($this->data['hash']), - intval($this->data['uid']) - ); - if ($r) { - // @todo this should be a global definition - $unsafe_types = array('text/html', 'text/css', 'application/javascript'); - - if (in_array($r[0]['filetype'], $unsafe_types)) { - header('Content-disposition: attachment; filename="' . $r[0]['filename'] . '"'); - header('Content-type: text/plain'); - } - - if (intval($r[0]['os_storage'])) { - $x = dbunescbin($r[0]['data']); - if(strpos($x,'store') === false) - $f = 'store/' . $this->auth->owner_nick . '/' . (($this->os_path) ? $this->os_path . '/' : '') . $x; - else - $f = $x; - return fopen($f, 'rb'); - } - return dbunescbin($r[0]['data']); - } - } - - /** - * @brief Returns the ETag for a file. - * - * An ETag is a unique identifier representing the current version of the file. - * If the file changes, the ETag MUST change. - * The ETag is an arbitrary string, but MUST be surrounded by double-quotes. - * - * Return null if the ETag can not effectively be determined. - * - * @return null|string - */ - public function getETag() { - $ret = null; - if ($this->data['hash']) { - $ret = '"' . $this->data['hash'] . '"'; - } - return $ret; - } - - /** - * @brief Returns the mime-type for a file. - * - * If null is returned, we'll assume application/octet-stream - * - * @return mixed - */ - public function getContentType() { - // @todo this should be a global definition. - $unsafe_types = array('text/html', 'text/css', 'application/javascript'); - if (in_array($this->data['filetype'], $unsafe_types)) { - return 'text/plain'; - } - return $this->data['filetype']; - } - - /** - * @brief Returns the size of the node, in bytes. - * - * @return int - * filesize in bytes - */ - public function getSize() { - return $this->data['filesize']; - } - - /** - * @brief Returns the last modification time for the file, as a unix - * timestamp. - * - * @return int last modification time in UNIX timestamp - */ - public function getLastModified() { - return datetime_convert('UTC', 'UTC', $this->data['edited'], 'U'); - } - - /** - * @brief Delete the file. - * - * This method checks the permissions and then calls attach_delete() function - * to actually remove the file. - * - * @throw \Sabre\DAV\Exception\Forbidden - */ - public function delete() { - logger('delete file ' . basename($this->name), LOGGER_DEBUG); - - if ((! $this->auth->owner_id) || (! perm_is_allowed($this->auth->owner_id, $this->auth->observer, 'write_storage'))) { - throw new DAV\Exception\Forbidden('Permission denied.'); - } - - if ($this->auth->owner_id !== $this->auth->channel_id) { - if (($this->auth->observer !== $this->data['creator']) || intval($this->data['is_dir'])) { - throw new DAV\Exception\Forbidden('Permission denied.'); - } - } - - attach_delete($this->auth->owner_id, $this->data['hash']); - } -} diff --git a/include/account.php b/include/account.php index dae0f4895..4c828003e 100644 --- a/include/account.php +++ b/include/account.php @@ -407,7 +407,7 @@ function account_allow($hash) { pop_lang(); - if(get_config('system','auto_channel_create')) + if(get_config('system','auto_channel_create') || UNO) auto_channel_create($register[0]['uid']); if ($res) { @@ -500,7 +500,7 @@ function account_approve($hash) { ); - if(get_config('system','auto_channel_create')) + if(get_config('system','auto_channel_create') || UNO) auto_channel_create($register[0]['uid']); info( t('Account verified. Please login.') . EOL ); diff --git a/include/api.php b/include/api.php index ef41a4912..e78e6cc37 100644 --- a/include/api.php +++ b/include/api.php @@ -2106,10 +2106,10 @@ require_once('include/api_auth.php'); 'private' => $private, 'textlimit' => $textlimit, 'sslserver' => $sslserver, 'ssl' => $ssl, 'shorturllength' => '30', 'hubzilla' => array( - 'PLATFORM_NAME' => get_platform_name(), - 'RED_VERSION' => get_project_version(), + 'PLATFORM_NAME' => Zotlabs\Project\System::get_platform_name(), + 'RED_VERSION' => Zotlabs\Project\System::get_project_version(), 'ZOT_REVISION' => ZOT_REVISION, - 'DB_UPDATE_VERSION' => get_update_version() + 'DB_UPDATE_VERSION' => Zotlabs\Project\System::get_update_version() ) )); @@ -2142,12 +2142,12 @@ require_once('include/api_auth.php'); if($type === 'xml') { header("Content-type: application/xml"); - echo '<?xml version="1.0" encoding="UTF-8"?>' . "\r\n" . '<version>' . get_project_version() . '</version>' . "\r\n"; + echo '<?xml version="1.0" encoding="UTF-8"?>' . "\r\n" . '<version>' . Zotlabs\Project\System::get_project_version() . '</version>' . "\r\n"; killme(); } elseif($type === 'json') { header("Content-type: application/json"); - echo '"' . get_project_version() . '"'; + echo '"' . Zotlabs\Project\System::get_project_version() . '"'; killme(); } } diff --git a/include/datetime.php b/include/datetime.php index 1d10e7ad7..bfd806f32 100644 --- a/include/datetime.php +++ b/include/datetime.php @@ -269,15 +269,16 @@ function relative_date($posted_date, $format = null) { return t('less than a second ago'); } - $a = array( 12 * 30 * 24 * 60 * 60 => array( t('year'), t('years')), - 30 * 24 * 60 * 60 => array( t('month'), t('months')), - 7 * 24 * 60 * 60 => array( t('week'), t('weeks')), - 24 * 60 * 60 => array( t('day'), t('days')), - 60 * 60 => array( t('hour'), t('hours')), - 60 => array( t('minute'), t('minutes')), - 1 => array( t('second'), t('seconds')) + $a = array( 12 * 30 * 24 * 60 * 60 => 'y', + 30 * 24 * 60 * 60 => 'm', + 7 * 24 * 60 * 60 => 'w', + 24 * 60 * 60 => 'd', + 60 * 60 => 'h', + 60 => 'i', + 1 => 's' ); + foreach ($a as $secs => $str) { $d = $etime / $secs; if ($d >= 1) { @@ -285,11 +286,43 @@ function relative_date($posted_date, $format = null) { if (! $format) $format = t('%1$d %2$s ago', 'e.g. 22 hours ago, 1 minute ago'); - return sprintf($format, $r, (($r == 1) ? $str[0] : $str[1])); + return sprintf($format, $r, plural_dates($str,$r)); } } } +function plural_dates($k,$n) { + + switch($k) { + case 'y': + return tt('year','years',$n,'relative_date'); + break; + case 'm': + return tt('month','months',$n,'relative_date'); + break; + case 'w': + return tt('week','weeks',$n,'relative_date'); + break; + case 'd': + return tt('day','days',$n,'relative_date'); + break; + case 'h': + return tt('hour','hours',$n,'relative_date'); + break; + case 'i': + return tt('minute','minutes',$n,'relative_date'); + break; + case 's': + return tt('second','seconds',$n,'relative_date'); + break; + default: + return; + } +} + + + + /** * @brief Returns timezone correct age in years. * diff --git a/include/enotify.php b/include/enotify.php index c4c49c8ff..e182377c0 100644 --- a/include/enotify.php +++ b/include/enotify.php @@ -529,7 +529,7 @@ function notification($params) { $tpl = get_markup_template('email_notify_html.tpl'); $email_html_body = replace_macros($tpl,array( '$banner' => $datarray['banner'], - '$notify_icon' => get_notify_icon(), + '$notify_icon' => Zotlabs\Project\System::get_notify_icon(), '$product' => $datarray['product'], '$preamble' => $datarray['preamble'], '$sitename' => $datarray['sitename'], diff --git a/include/event.php b/include/event.php index 51988acac..73033a1c3 100644 --- a/include/event.php +++ b/include/event.php @@ -67,7 +67,7 @@ function ical_wrapper($ev) { $o .= "BEGIN:VCALENDAR"; $o .= "\r\nVERSION:2.0"; $o .= "\r\nMETHOD:PUBLISH"; - $o .= "\r\nPRODID:-//" . get_config('system','sitename') . "//" . get_platform_name() . "//" . strtoupper(get_app()->language). "\r\n"; + $o .= "\r\nPRODID:-//" . get_config('system','sitename') . "//" . Zotlabs\Project\System::get_platform_name() . "//" . strtoupper(get_app()->language). "\r\n"; if(array_key_exists('start', $ev)) $o .= format_event_ical($ev); else { diff --git a/include/features.php b/include/features.php index d8b0be7d5..9c925bc35 100644 --- a/include/features.php +++ b/include/features.php @@ -25,7 +25,7 @@ function feature_enabled($uid,$feature) { } function get_feature_default($feature) { - $f = get_features(); + $f = get_features(false); foreach($f as $cat) { foreach($cat as $feat) { if(is_array($feat) && $feat[0] === $feature) diff --git a/include/identity.php b/include/identity.php index 51744f7bf..a389a613e 100644 --- a/include/identity.php +++ b/include/identity.php @@ -484,7 +484,7 @@ function identity_basic_export($channel_id, $items = false) { // use constants here as otherwise we will have no idea if we can import from a site // with a non-standard platform and version. - $ret['compatibility'] = array('project' => PLATFORM_NAME, 'version' => RED_VERSION, 'database' => DB_UPDATE_VERSION, 'server_role' => get_server_role()); + $ret['compatibility'] = array('project' => PLATFORM_NAME, 'version' => RED_VERSION, 'database' => DB_UPDATE_VERSION, 'server_role' => Zotlabs\Project\System::get_server_role()); $r = q("select * from channel where channel_id = %d limit 1", intval($channel_id) @@ -1847,4 +1847,4 @@ function get_zcard($channel,$observer_hash = '',$args = array()) { return $o; -}
\ No newline at end of file +} diff --git a/include/items.php b/include/items.php index f5eccfccd..363563278 100755 --- a/include/items.php +++ b/include/items.php @@ -610,8 +610,8 @@ function get_feed_for($channel, $observer_hash, $params) { $atom = ''; $atom .= replace_macros($feed_template, array( - '$version' => xmlify(get_project_version()), - '$red' => xmlify(get_platform_name()), + '$version' => xmlify(Zotlabs\Project\System::get_project_version()), + '$red' => xmlify(Zotlabs\Project\System::get_platform_name()), '$feed_id' => xmlify($channel['xchan_url']), '$feed_title' => xmlify($channel['channel_name']), '$feed_updated' => xmlify(datetime_convert('UTC', 'UTC', 'now' , ATOM_TIME)) , @@ -2887,13 +2887,13 @@ function store_diaspora_comment_sig($datarray, $channel, $parent_item, $post_id, $signed_text = $datarray['mid'] . ';' . $parent_item['mid'] . ';' . $signed_body . ';' . $diaspora_handle; - /** @FIXME $uprvkey is undefined, do we still need this if-statement? */ - if( $uprvkey !== false ) + + if( $channel && $channel['channel_prvkey'] ) $authorsig = base64_encode(rsa_sign($signed_text, $channel['channel_prvkey'], 'sha256')); else $authorsig = ''; - $x = array('signer' => $diaspora_handle, 'body' => $signed_body, 'signed_text' => $signed_text, 'signature' => base64_encode($authorsig)); + $x = array('signer' => $diaspora_handle, 'body' => $signed_body, 'signed_text' => $signed_text, 'signature' => $authorsig); $y = json_encode($x); @@ -2902,6 +2902,7 @@ function store_diaspora_comment_sig($datarray, $channel, $parent_item, $post_id, intval($post_id) ); + if(! $r) logger('store_diaspora_comment_sig: DB write failed'); @@ -5440,7 +5441,7 @@ function send_profile_photo_activity($channel,$photo,$profile) { $arr['body'] = sprintf($t,$channel['channel_name'],$ptext) . "\n\n" . $ltext; - $acl = new AccessList($channel); + $acl = new Zotlabs\Access\AccessList($channel); $x = $acl->get(); $arr['allow_cid'] = $x['allow_cid']; diff --git a/include/language.php b/include/language.php index c843db85e..121816ae6 100644 --- a/include/language.php +++ b/include/language.php @@ -189,7 +189,7 @@ function t($s, $ctx = '') { function translate_projectname($s) { - return str_replace(array('$projectname','$Projectname'),array(get_platform_name(),ucfirst(get_platform_name())),$s); + return str_replace(array('$projectname','$Projectname'),array(Zotlabs\Project\System::get_platform_name(),ucfirst(Zotlabs\Project\System::get_platform_name())),$s); } diff --git a/include/menu.php b/include/menu.php index 075372515..d90cefddb 100644 --- a/include/menu.php +++ b/include/menu.php @@ -299,7 +299,7 @@ function menu_add_item($menu_id, $uid, $arr) { $channel = get_app()->get_channel(); } - $acl = new AccessList($channel); + $acl = new Zotlabs\Access\AccessList($channel); $acl->set_from_array($arr); $p = $acl->get(); @@ -340,7 +340,7 @@ function menu_edit_item($menu_id, $uid, $arr) { $channel = get_app()->get_channel(); } - $acl = new AccessList($channel); + $acl = new Zotlabs\Access\AccessList($channel); $acl->set_from_array($arr); $p = $acl->get(); diff --git a/include/network.php b/include/network.php index 7a9bca94a..ecaf4e05f 100644 --- a/include/network.php +++ b/include/network.php @@ -294,8 +294,8 @@ function z_post_url_json($url, $params, $redirects = 0, $opts = array()) { } -function json_return_and_die($x) { - header("content-type: application/json"); +function json_return_and_die($x, $content_type = 'application/json') { + header("Content-type: $content_type"); echo json_encode($x); killme(); } @@ -1620,7 +1620,7 @@ function format_and_send_email($sender,$xchan,$item) { $tpl = get_markup_template('email_notify_html.tpl'); $email_html_body = replace_macros($tpl,array( '$banner' => $banner, - '$notify_icon' => get_notify_icon(), + '$notify_icon' => Zotlabs\Project\System::get_notify_icon(), '$product' => $product, '$preamble' => '', '$sitename' => $sitename, @@ -1768,8 +1768,8 @@ function get_site_info() { $site_info = get_config('system','info'); $site_name = get_config('system','sitename'); if(! get_config('system','hidden_version_siteinfo')) { - $version = get_project_version(); - $tag = get_std_version(); + $version = Zotlabs\Project\System::get_project_version(); + $tag = Zotlabs\Project\System::get_std_version(); if(@is_dir('.git') && function_exists('shell_exec')) { $commit = trim( @shell_exec('git log -1 --format="%h"')); @@ -1805,7 +1805,7 @@ function get_site_info() { $data = Array( 'version' => $version, 'version_tag' => $tag, - 'server_role' => get_server_role(), + 'server_role' => Zotlabs\Project\System::get_server_role(), 'commit' => $commit, 'url' => z_root(), 'plugins' => $visible_plugins, @@ -1819,7 +1819,7 @@ function get_site_info() { 'locked_features' => $locked_features, 'admin' => $admin, 'site_name' => (($site_name) ? $site_name : ''), - 'platform' => get_platform_name(), + 'platform' => Zotlabs\Project\System::get_platform_name(), 'dbdriver' => $db->getdriver(), 'lastpoll' => get_config('system','lastpoll'), 'info' => (($site_info) ? $site_info : ''), diff --git a/include/oembed.php b/include/oembed.php index cac0154f6..fb7a30e65 100755 --- a/include/oembed.php +++ b/include/oembed.php @@ -232,7 +232,7 @@ function oembed_format_object($j){ // add link to source if not present in "rich" type if ( $j->type!='rich' || !strpos($j->html,$embedurl) ){ $embedlink = (isset($j->title))?$j->title:$embedurl; - $ret .= '<br /><span class="bookmark-identifier">#^</span>' . "<a href='$embedurl' rel='oembed'>$embedlink</a>"; + $ret .= '<br />' . "<a href='$embedurl' rel='oembed'>$embedlink</a>"; $ret .= "<br />"; if (isset($j->author_name)) $ret.=" by ".$j->author_name; if (isset($j->provider_name)) $ret.=" on ".$j->provider_name; diff --git a/include/permissions.php b/include/permissions.php index 8c36f9744..e4cd9ddda 100644 --- a/include/permissions.php +++ b/include/permissions.php @@ -864,10 +864,10 @@ function get_role_perms($role) { */ function get_roles() { $roles = array( - t('Social Networking') => array('social' => t('Mostly Public'), 'social_restricted' => t('Restricted'), 'social_private' => t('Private')), - t('Community Forum') => array('forum' => t('Mostly Public'), 'forum_restricted' => t('Restricted'), 'forum_private' => t('Private')), - t('Feed Republish') => array('feed' => t('Mostly Public'), 'feed_restricted' => t('Restricted')), - t('Special Purpose') => array('soapbox' => t('Celebrity/Soapbox'), 'repository' => t('Group Repository')), + t('Social Networking') => array('social' => t('Social - Mostly Public'), 'social_restricted' => t('Social - Restricted'), 'social_private' => t('Social - Private')), + t('Community Forum') => array('forum' => t('Forum - Mostly Public'), 'forum_restricted' => t('Forum - Restricted'), 'forum_private' => t('Forum - Private')), + t('Feed Republish') => array('feed' => t('Feed - Mostly Public'), 'feed_restricted' => t('Feed - Restricted')), + t('Special Purpose') => array('soapbox' => t('Special - Celebrity/Soapbox'), 'repository' => t('Special - Group Repository')), t('Other') => array('custom' => t('Custom/Expert Mode')) ); diff --git a/include/photos.php b/include/photos.php index 93511d2c0..1a57ce76f 100644 --- a/include/photos.php +++ b/include/photos.php @@ -48,7 +48,7 @@ function photo_upload($channel, $observer, $args) { // all other settings. 'allow_cid' being passed from an external source takes priority over channel settings. // ...messy... needs re-factoring once the photos/files integration stabilises - $acl = new AccessList($channel); + $acl = new Zotlabs\Access\AccessList($channel); if(array_key_exists('directory',$args) && $args['directory']) $acl->set($args['directory']); if(array_key_exists('allow_cid',$args)) diff --git a/include/plugin.php b/include/plugin.php index da4568ad7..5afded542 100755 --- a/include/plugin.php +++ b/include/plugin.php @@ -653,17 +653,6 @@ function get_markup_template($s, $root = '') { return $template; } -// return the standardised version. Since we can't easily compare -// before the STD_VERSION definition was applied, we have to treat -// all prior release versions the same. You can dig through them -// with other means (such as RED_VERSION) if necessary. - -function get_std_version() { - if(defined('STD_VERSION')) - return STD_VERSION; - return '0.0.0'; -} - function folder_exists($folder) { diff --git a/include/reddav.php b/include/reddav.php index c592597a9..a0bd1b1fc 100644 --- a/include/reddav.php +++ b/include/reddav.php @@ -19,13 +19,13 @@ */ use Sabre\DAV; -use RedMatrix\RedDAV; +use Zotlabs\Storage; require_once('vendor/autoload.php'); require_once('include/attach.php'); -require_once('include/RedDAV/RedFile.php'); -require_once('include/RedDAV/RedDirectory.php'); -require_once('include/RedDAV/RedBasicAuth.php'); +//require_once('Zotlabs/Storage/File.php'); +//require_once('Zotlabs/Storage/Directory.php'); +//require_once('Zotlabs/Storage/BasicAuth.php'); /** * @brief Returns an array with viewable channels. @@ -51,7 +51,7 @@ function RedChannelList(&$auth) { if (perm_is_allowed($rr['channel_id'], $auth->observer, 'view_storage')) { logger('found channel: /cloud/' . $rr['channel_address'], LOGGER_DATA); // @todo can't we drop '/cloud'? It gets stripped off anyway in RedDirectory - $ret[] = new RedDAV\RedDirectory('/cloud/' . $rr['channel_address'], $auth); + $ret[] = new Zotlabs\Storage\Directory('/cloud/' . $rr['channel_address'], $auth); } } } @@ -167,9 +167,9 @@ function RedCollectionData($file, &$auth) { foreach ($r as $rr) { //logger('filename: ' . $rr['filename'], LOGGER_DEBUG); if (intval($rr['is_dir'])) { - $ret[] = new RedDAV\RedDirectory($path . '/' . $rr['filename'], $auth); + $ret[] = new Zotlabs\Storage\Directory($path . '/' . $rr['filename'], $auth); } else { - $ret[] = new RedDAV\RedFile($path . '/' . $rr['filename'], $rr, $auth); + $ret[] = new Zotlabs\Storage\File($path . '/' . $rr['filename'], $rr, $auth); } } @@ -204,7 +204,7 @@ function RedFileData($file, &$auth, $test = false) { if ((! $file) || ($file === '/')) { - return new RedDAV\RedDirectory('/', $auth); + return new Zotlabs\Storage\Directory('/', $auth); } $file = trim($file, '/'); @@ -274,7 +274,7 @@ function RedFileData($file, &$auth, $test = false) { if ($test) return true; // final component was a directory. - return new RedDAV\RedDirectory($file, $auth); + return new Zotlabs\Storage\Directory($file, $auth); } if ($errors) { @@ -293,9 +293,9 @@ function RedFileData($file, &$auth, $test = false) { return true; if (intval($r[0]['is_dir'])) { - return new RedDAV\RedDirectory($path . '/' . $r[0]['filename'], $auth); + return new Zotlabs\Storage\Directory($path . '/' . $r[0]['filename'], $auth); } else { - return new RedDAV\RedFile($path . '/' . $r[0]['filename'], $r[0], $auth); + return new Zotlabs\Storage\File($path . '/' . $r[0]['filename'], $r[0], $auth); } } return false; diff --git a/include/text.php b/include/text.php index f6fa1c304..6b074d390 100644 --- a/include/text.php +++ b/include/text.php @@ -2728,3 +2728,63 @@ function item_url_replace($channel,&$item,$old,$new) { // @fixme item['plink'] and item['llink'] } + + +/** + * @brief Used to wrap ACL elements in angle brackets for storage. + * + * @param[in,out] array &$item + */ +function sanitise_acl(&$item) { + if (strlen($item)) + $item = '<' . notags(trim($item)) . '>'; + else + unset($item); +} + +/** + * @brief Convert an ACL array to a storable string. + * + * @param array $p + * @return array + */ +function perms2str($p) { + $ret = ''; + + if (is_array($p)) + $tmp = $p; + else + $tmp = explode(',', $p); + + if (is_array($tmp)) { + array_walk($tmp, 'sanitise_acl'); + $ret = implode('', $tmp); + } + + return $ret; +} + + +/** + * @brief Turn user/group ACLs stored as angle bracketed text into arrays. + * + * turn string array of angle-bracketed elements into string array + * e.g. "<123xyz><246qyo><sxo33e>" => array(123xyz,246qyo,sxo33e); + * + * @param string $s + * @return array + */ +function expand_acl($s) { + $ret = array(); + + if(strlen($s)) { + $t = str_replace('<','',$s); + $a = explode('>',$t); + foreach($a as $aa) { + if($aa) + $ret[] = $aa; + } + } + + return $ret; +} diff --git a/include/zot.php b/include/zot.php index e9335769e..de841f956 100644 --- a/include/zot.php +++ b/include/zot.php @@ -11,7 +11,6 @@ require_once('include/crypto.php'); require_once('include/items.php'); require_once('include/hubloc.php'); -require_once('include/DReport.php'); require_once('include/queue_fn.php'); @@ -1589,7 +1588,7 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ foreach($deliveries as $d) { $local_public = $public; - $DR = new DReport(z_root(),$sender['hash'],$d['hash'],$arr['mid']); + $DR = new Zotlabs\Zot\DReport(z_root(),$sender['hash'],$d['hash'],$arr['mid']); $r = q("select * from channel where channel_hash = '%s' limit 1", dbesc($d['hash']) @@ -2068,7 +2067,7 @@ function process_mail_delivery($sender, $arr, $deliveries) { foreach($deliveries as $d) { - $DR = new DReport(z_root(),$sender['hash'],$d['hash'],$arr['mid']); + $DR = new Zotlabs\Zot\DReport(z_root(),$sender['hash'],$d['hash'],$arr['mid']); $r = q("select * from channel where channel_hash = '%s' limit 1", dbesc($d['hash']) @@ -3410,14 +3409,12 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { // we should probably do this for all items, but usually we only send one. - require_once('include/DReport.php'); - if(array_key_exists('item',$arr) && is_array($arr['item'][0])) { - $DR = new DReport(z_root(),$d['hash'],$d['hash'],$arr['item'][0]['message_id'],'channel sync processed'); + $DR = new Zotlabs\Zot\DReport(z_root(),$d['hash'],$d['hash'],$arr['item'][0]['message_id'],'channel sync processed'); $DR->addto_recipient($channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>'); } else - $DR = new DReport(z_root(),$d['hash'],$d['hash'],'sync packet','channel sync delivered'); + $DR = new Zotlabs\Zot\DReport(z_root(),$d['hash'],$d['hash'],'sync packet','channel sync delivered'); $result[] = $DR->get(); @@ -3835,7 +3832,7 @@ function zotinfo($arr) { $ret['site']['channels'] = channel_total(); - $ret['site']['version'] = get_platform_name() . ' ' . RED_VERSION . '[' . DB_UPDATE_VERSION . ']'; + $ret['site']['version'] = Zotlabs\Project\System::get_platform_name() . ' ' . RED_VERSION . '[' . DB_UPDATE_VERSION . ']'; $ret['site']['admin'] = get_config('system','admin_email'); @@ -3855,7 +3852,7 @@ function zotinfo($arr) { $ret['site']['sellpage'] = get_config('system','sellpage'); $ret['site']['location'] = get_config('system','site_location'); $ret['site']['realm'] = get_directory_realm(); - $ret['site']['project'] = get_platform_name(); + $ret['site']['project'] = Zotlabs\Project\System::get_platform_name(); } |