diff --git a/api/BusinessLogic/Attachments/AttachmentRetriever.php b/api/BusinessLogic/Attachments/AttachmentRetriever.php index eb5b57c5..2c276c61 100644 --- a/api/BusinessLogic/Attachments/AttachmentRetriever.php +++ b/api/BusinessLogic/Attachments/AttachmentRetriever.php @@ -30,6 +30,20 @@ class AttachmentRetriever { $this->userToTicketChecker = $userToTicketChecker; } + //-- TODO Test + function getAttachmentContentsForTrackingId($trackingId, $attachmentId, $userContext, $heskSettings) { + $ticket = $this->ticketGateway->getTicketByTrackingId($trackingId, $heskSettings); + + if ($ticket === null) { + throw new ApiFriendlyException("Ticket {$trackingId} not found!", "Ticket Not Found", 404); + } + + $attachment = $this->attachmentGateway->getAttachmentById($attachmentId, $heskSettings); + + return array('meta' => $attachment, + 'contents' => $this->fileReader->readFromFile($attachment->savedName, $heskSettings['attach_dir'])); + } + function getAttachmentContentsForTicket($ticketId, $attachmentId, $userContext, $heskSettings) { $ticket = $this->ticketGateway->getTicketById($ticketId, $heskSettings); diff --git a/api/Controllers/Attachments/PublicAttachmentController.php b/api/Controllers/Attachments/PublicAttachmentController.php new file mode 100644 index 00000000..c5e9077c --- /dev/null +++ b/api/Controllers/Attachments/PublicAttachmentController.php @@ -0,0 +1,39 @@ +get[AttachmentRetriever::class]; + + $attachment = $attachmentRetriever->getAttachmentContentsForTrackingId($trackingId, $attachmentId, $userContext, $hesk_settings); + + /* @var $metadata Attachment */ + $metadata = $attachment['meta']; + + // Send the file as an attachment to prevent malicious code from executing + header("Pragma: "); # To fix a bug in IE when running https + header("Cache-Control: "); # To fix a bug in IE when running https + header('Content-Description: File Transfer'); + header('Content-Type: application/octet-stream'); + header('Content-Length: ' . $metadata->fileSize); + header('Content-Disposition: attachment; filename=' . $metadata->displayName); + print $attachment['contents']; + } + + private static function verifyAttachmentsAreEnabled($heskSettings) { + if (!$heskSettings['attachments']['use']) { + throw new ApiFriendlyException('Attachments are disabled on this server', 'Attachments Disabled', 404); + } + } +} diff --git a/api/index.php b/api/index.php index 4b0e6e6e..77b28904 100644 --- a/api/index.php +++ b/api/index.php @@ -20,6 +20,9 @@ function before() { if ($internalUse === 'true') { buildUserContextFromSession(); + } elseif (preg_match('/\/v1\/tickets\/.+\/attachments\/\d+/', $_SERVER['PATH_INFO'])) { + //-- TODO Clean this up + return; } else { assertApiIsEnabled(); $token = \BusinessLogic\Helpers::getHeader('X-AUTH-TOKEN'); @@ -168,13 +171,14 @@ Link::before('before'); Link::all(array( // Categories - '/v1/categories' => \Controllers\Categories\CategoryController::class . '::printAllCategories', + '/v1/categories' => [\Controllers\Categories\CategoryController::class . '::printAllCategories'], '/v1/categories/{i}' => \Controllers\Categories\CategoryController::class, // Tickets '/v1/tickets' => \Controllers\Tickets\CustomerTicketController::class, // Tickets - Staff '/v1/staff/tickets/{i}' => \Controllers\Tickets\StaffTicketController::class, // Attachments + '/v1/tickets/{a}/attachments/{i}' => \Controllers\Attachments\PublicAttachmentController::class . '::getRaw', '/v1/staff/tickets/{i}/attachments' => \Controllers\Attachments\StaffTicketAttachmentsController::class, '/v1/staff/tickets/{i}/attachments/{i}' => \Controllers\Attachments\StaffTicketAttachmentsController::class, // Statuses diff --git a/inc/common.inc.php b/inc/common.inc.php index d2eadaca..94f487dc 100644 --- a/inc/common.inc.php +++ b/inc/common.inc.php @@ -262,13 +262,13 @@ function hesk_load_database_functions() function hesk_load_api_database_functions() { - require(__DIR__ . '/../api/core/json_error.php'); + require(__DIR__ . '/../api/Core/json_error.php'); // Preferrably use the MySQLi functions if (function_exists('mysqli_connect')) { - require(__DIR__ . '/../api/core/database_mysqli.inc.php'); + require(__DIR__ . '/../api/Core/database_mysqli.inc.php'); } // Default to MySQL else { - require(__DIR__ . '/../api/core/database.inc.php'); + require(__DIR__ . '/../api/Core/database.inc.php'); } } // END hesk_load_database_functions()