diff --git a/config/dbstructure.config.php b/config/dbstructure.config.php index 0be6ba402..a4728c15d 100644 --- a/config/dbstructure.config.php +++ b/config/dbstructure.config.php @@ -34,7 +34,7 @@ use Friendica\Database\DBA; if (!defined('DB_UPDATE_VERSION')) { - define('DB_UPDATE_VERSION', 1298); + define('DB_UPDATE_VERSION', 1299); } return [ @@ -99,6 +99,8 @@ return [ "allow_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed groups"], "deny_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied contact.id"], "deny_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied groups"], + "backend-class" => ["type" => "tinytext", "comment" => "Storage backend class"], + "backend-ref" => ["type" => "text", "comment" => "Storage backend data reference"], ], "indexes" => [ "PRIMARY" => ["id"], diff --git a/mod/attach.php b/mod/attach.php deleted file mode 100644 index f3192d802..000000000 --- a/mod/attach.php +++ /dev/null @@ -1,54 +0,0 @@ -argc != 2) { - notice(L10n::t('Item not available.') . EOL); - return; - } - - $item_id = intval($a->argv[1]); - - // Check for existence, which will also provide us the owner uid - - $r = DBA::selectFirst('attach', [], ['id' => $item_id]); - if (!DBA::isResult($r)) { - notice(L10n::t('Item was not found.'). EOL); - return; - } - - $sql_extra = Security::getPermissionsSQLByUserId($r['uid']); - - // Now we'll see if we can access the attachment - - $r = q("SELECT * FROM `attach` WHERE `id` = '%d' $sql_extra LIMIT 1", - DBA::escape($item_id) - ); - - if (!DBA::isResult($r)) { - notice(L10n::t('Permission denied.') . EOL); - return; - } - - // Use quotes around the filename to prevent a "multiple Content-Disposition" - // error in Chrome for filenames with commas in them - header('Content-type: ' . $r[0]['filetype']); - header('Content-length: ' . $r[0]['filesize']); - if (isset($_GET['attachment']) && $_GET['attachment'] === '0') { - header('Content-disposition: filename="' . $r[0]['filename'] . '"'); - } else { - header('Content-disposition: attachment; filename="' . $r[0]['filename'] . '"'); - } - - echo $r[0]['data']; - exit(); - // NOTREACHED -} diff --git a/src/Model/Attach.php b/src/Model/Attach.php new file mode 100644 index 000000000..13b0adb6f --- /dev/null +++ b/src/Model/Attach.php @@ -0,0 +1,152 @@ + $id]); + } + + /** + * @brief Retrive a single record given the ID + * + * @param int $id Row id of the record + * + * @return bool|array + * + * @see \Friendica\Database\DBA::select + */ + public static function getByIdWithPermission($id) + { + $r = self::selectFirst(['uid'], ['id' => $id]); + if ($r === false) { + return false; + } + + $sql_acl = Security::getPermissionsSQLByUserId($r['uid']); + + $conditions = [ + '`id` = ?' . $sql_acl, + $id + ]; + + $item = self::selectFirst([], $conditions); + + return $item; + } + + /** + * @brief Get file data for given row id. null if row id does not exist + * + * @param array $item Attachment data. Needs at least 'id', 'backend-class', 'backend-ref' + * + * @return string file data + */ + public static function getData($item) + { + if ($item['backend-class'] == '') { + // legacy data storage in 'data' column + $i = self::selectFirst(['data'], ['id' => $item['id']]); + if ($i === false) { + return null; + } + return $i['data']; + } else { + $backendClass = $item['backend-class']; + $backendRef = $item['backend-ref']; + return $backendClass::get($backendRef); + } + } +} \ No newline at end of file diff --git a/src/Module/Attach.php b/src/Module/Attach.php new file mode 100644 index 000000000..eed1275c5 --- /dev/null +++ b/src/Module/Attach.php @@ -0,0 +1,67 @@ +argc != 2) { + System::httpExit(400); // Bad Request. + } + + + $item_id = intval($a->argv[1]); + + // Check for existence + $item = MAttach::exists(['id' => $item_id]); + if ($item === false) { + System::httpExit(404, ['description' => L10n::t('Item was not found.')]); + } + + // Now we'll fetch the item, if we have enough permisson + $item = MAttach::getByIdWithPermission($item_id); + if ($item === false) { + System::httpExit(403, ['description' => L10n::t('Permission denied.')]); + } + + $data = MAttach::getData($item); + if (is_null($data)) { + Logger::log('NULL data for attachment with id ' . $item['id']); + System::httpExit(404, ['description' => L10n::t('Item was not found.')]); + } + + // Use quotes around the filename to prevent a "multiple Content-Disposition" + // error in Chrome for filenames with commas in them + header('Content-type: ' . $item['filetype']); + header('Content-length: ' . $item['filesize']); + if (isset($_GET['attachment']) && $_GET['attachment'] === '0') { + header('Content-disposition: filename="' . $item['filename'] . '"'); + } else { + header('Content-disposition: attachment; filename="' . $item['filename'] . '"'); + } + + echo $data; + exit(); + // NOTREACHED + } +} \ No newline at end of file