private function getAttachment()
 {
     // FIXME: Do we really need to mess with memory limits here? We're only reading ~80KB at a time...
     @ini_set('memory_limit', '128M');
     if (!$this->isRequiredIDValid('id', $_GET)) {
         CommonErrors::fatal(COMMONERROR_BADINDEX, $this, 'No attachment ID specified.');
     }
     $attachmentID = $_GET['id'];
     $attachments = new Attachments(-1);
     $rs = $attachments->get($attachmentID, false);
     if (empty($rs) || md5($rs['directoryName']) != $_GET['directoryNameHash']) {
         CommonErrors::fatal(COMMONERROR_BADFIELDS, $this, 'Invalid id / directory / filename, or you do not have permission to access this attachment.');
     }
     $directoryName = $rs['directoryName'];
     $fileName = $rs['storedFilename'];
     $filePath = sprintf('attachments/%s/%s', $directoryName, $fileName);
     /* Check for the existence of the backup.  If it is gone, send the user to a page informing them to press back and generate the backup again. */
     if ($rs['contentType'] == 'catsbackup' && !file_exists($filePath)) {
         CommonErrors::fatal(COMMONERROR_FILENOTFOUND, $this, 'The specified backup file no longer exists. Please go back and regenerate the backup before downloading. We are sorry for the inconvenience.');
     }
     // FIXME: Stream file rather than redirect? (depends on download preparer working).
     if (!eval(Hooks::get('ATTACHMENT_RETRIEVAL'))) {
         return;
     }
     /* Determine MIME content type of the file. */
     $contentType = Attachments::fileMimeType($fileName);
     /* Open the file and verify that it is readable. */
     $fp = @fopen($filePath, 'r');
     if ($fp === false) {
         CommonErrors::fatal(COMMONERROR_BADFIELDS, $this, 'This attachment is momentarily offline, please try again later. The support staff has been notified.');
     }
     /* Set headers for sending the file. */
     header('Content-Disposition: inline; filename="' . $fileName . '"');
     //Disposition attachment was default, but forces download.
     header('Content-Type: ' . $contentType);
     header('Content-Length: ' . filesize($filePath));
     header('Pragma: no-cache');
     header('Expires: 0');
     /* Read the file in ATTACHMENT_BLOCK_SIZE-sized chunks from disk and
      * output to the browser.
      */
     while (!feof($fp)) {
         print fread($fp, self::ATTACHMENT_BLOCK_SIZE);
     }
     fclose($fp);
     /* Exit to prevent output after the attachment. */
     exit;
 }