public function testBug325() { if (!extension_loaded('fileinfo')) { $this->markTestSkipped('The fileinfo extension is not available.'); } $this->assertEquals('text/plain', Horde_Mime_Magic::analyzeFile(__DIR__ . '/fixtures/flowed_msg.txt')); }
function getUploadedFileType($field) { /* Get any index on the field name. */ $index = Horde_Array::getArrayParts($field, $base, $keys); if ($index) { /* Index present, fetch the mime type var to check. */ $keys_path = array_merge(array($base, 'type'), $keys); $type = Horde_Array::getElement($_FILES, $keys_path); $keys_path = array_merge(array($base, 'tmp_name'), $keys); $tmp_name = Horde_Array::getElement($_FILES, $keys_path); } else { /* No index, simple set up of vars to check. */ $type = $_FILES[$field]['type']; $tmp_name = $_FILES[$field]['tmp_name']; } if (empty($type) || $type == 'application/octet-stream') { /* Type wasn't set on upload, try analising the upload. */ if (!($type = Horde_Mime_Magic::analyzeFile($tmp_name, isset($GLOBALS['conf']['mime']['magic_db']) ? $GLOBALS['conf']['mime']['magic_db'] : null))) { if ($index) { /* Get the name value. */ $keys_path = array_merge(array($base, 'name'), $keys); $name = Horde_Array::getElement($_FILES, $keys_path); /* Work out the type from the file name. */ $type = Horde_Mime_Magic::filenameToMime($name); /* Set the type. */ $keys_path = array_merge(array($base, 'type'), $keys); Horde_Array::getElement($_FILES, $keys_path, $type); } else { /* Work out the type from the file name. */ $type = Horde_Mime_Magic::filenameToMime($_FILES[$field]['name']); /* Set the type. */ $_FILES[$field]['type'] = Horde_Mime_Magic::filenameToMime($_FILES[$field]['name']); } } } return $type; }
/** * Render a MIME Part. * * @param string $mime_id The MIME ID to render. * @param integer $mode One of the RENDER_ constants. * @param array $options Additional options: * - autodetect: (boolean) Attempt to auto-detect MIME type? * - mime_part: (Horde_Mime_Part) The MIME part to render. * - type: (string) Use this MIME type instead of the MIME type * identified in the MIME part. * * @return array See Horde_Mime_Viewer_Base::render(). The following * fields may also be present in addition to the fields * defined in Horde_Mime_Viewer_Base: * - attach: (boolean) Force display of this part as an attachment. * - js: (array) A list of javascript commands to run after the content * is displayed on screen. * - name: (string) Contains the MIME name information. * - wrap: (string) If present, indicates that this part, and all child * parts, will be wrapped in a DIV with the given class name. */ public function renderMIMEPart($mime_id, $mode, array $options = array()) { $this->_buildMessage(); $mime_part = empty($options['mime_part']) ? $this->getMimePart($mime_id) : $options['mime_part']; if (!$mime_part) { return array($mime_id => null); } if (!empty($options['autodetect']) && ($tempfile = Horde::getTempFile()) && ($fp = fopen($tempfile, 'w')) && !is_null($contents = $mime_part->getContents(array('stream' => true)))) { rewind($contents); while (!feof($contents)) { fwrite($fp, fread($contents, 65536)); } fclose($fp); $options['type'] = Horde_Mime_Magic::analyzeFile($tempfile, empty($GLOBALS['conf']['mime']['magic_db']) ? null : $GLOBALS['conf']['mime']['magic_db']); } $type = empty($options['type']) ? null : $options['type']; $viewer = $GLOBALS['injector']->getInstance('IMP_Factory_MimeViewer')->create($mime_part, array('contents' => $this, 'type' => $type)); switch ($mode) { case self::RENDER_INLINE: case self::RENDER_INLINE_AUTO: case self::RENDER_INLINE_DISP_NO: $textmode = 'inline'; $limit = $viewer->getConfigParam('limit_inline_size'); if ($limit && $mime_part->getBytes() > $limit) { $data = ''; $status = new IMP_Mime_Status($mime_part, array(_("This message part cannot be viewed because it is too large."), $this->linkView($mime_part, 'download_attach', _("Click to download the data.")))); $status->icon('alerts/warning.png', _("Warning")); if (method_exists($viewer, 'overLimitText')) { $data = $viewer->overLimitText(); $status->addText(_("The initial portion of this text part is displayed below.")); } return array($mime_id => array('data' => $data, 'name' => '', 'status' => $status, 'type' => 'text/html; charset=' . 'UTF-8')); } break; case self::RENDER_INFO: $textmode = 'info'; break; case self::RENDER_RAW: $textmode = 'raw'; break; case self::RENDER_RAW_FALLBACK: $textmode = $viewer->canRender('raw') ? 'raw' : 'full'; break; case self::RENDER_FULL: default: $textmode = 'full'; break; } $ret = $viewer->render($textmode); if (empty($ret)) { return $mode == self::RENDER_INLINE_AUTO ? $this->renderMIMEPart($mime_id, self::RENDER_INFO, $options) : array(); } if (!empty($ret[$mime_id]) && !isset($ret[$mime_id]['name'])) { $ret[$mime_id]['name'] = $mime_part->getName(true); } /* Don't show empty parts. */ if ($textmode == 'inline' && !is_null($ret[$mime_id]['data']) && !strlen($ret[$mime_id]['data']) && !isset($ret[$mime_id]['status'])) { $ret[$mime_id] = null; } return $ret; }
/** * Checks for a file uploaded via the pluploader. If one is found, handle * it, send the server json response and exit. */ protected function _handleFileUpload() { if ($filename = Horde_Util::getFormData('name')) { if (isset($_SERVER["HTTP_CONTENT_TYPE"])) { $type = $_SERVER["HTTP_CONTENT_TYPE"]; } elseif (isset($_SERVER["CONTENT_TYPE"])) { $type = $_SERVER["CONTENT_TYPE"]; } if (empty($type) || $type == 'application/octet-stream') { $temp = Horde_Util::getTempFile('', true); $out = fopen($temp, 'w+'); if ($out) { // Read binary input stream and append it to temp file $in = fopen("php://input", "rb"); if ($in) { stream_copy_to_stream($in, $out); rewind($out); fclose($in); } else { fclose($out); header('Content-Type: application/json'); echo '{ "status" : "500", "file": "' . $temp . '", error" : { "message": "Failed to open input stream." } }'; exit; } } else { header('Content-Type: application/json'); echo '{ "status" : "500", "file": "' . $temp . '", error" : { "message": "Failed to open output stream." } }'; exit; } // // Don't know type. Try to deduce it. if (!($type = Horde_Mime_Magic::analyzeFile($temp, isset($GLOBALS['conf']['mime']['magic_db']) ? $GLOBALS['conf']['mime']['magic_db'] : null))) { $type = Horde_Mime_Magic::filenameToMime($filename); } } elseif (strpos($type, "multipart") !== false) { // Handle mulitpart uploads $temp = Horde_Util::getTempFile('', true); $out = fopen($temp, 'w+'); if ($out) { $in = fopen($_FILES['file']['tmp_name'], 'rb'); if ($in) { stream_copy_to_stream($in, $out); rewind($out); fclose($in); } else { fclose($out); header('Content-Type: application/json'); echo '{ "status" : "500", "file": "' . $temp . '", error" : { "message": "Failed to open input stream." } }'; exit; } } else { header('Content-Type: application/json'); echo '{ "status" : "500", "file": "' . $temp . '", error" : { "message": "Failed to open output stream." } }'; exit; } } // Figure out what to do with the file if (in_array($type, array('x-extension/zip', 'application/x-compressed', 'application/x-zip-compressed', 'application/zip')) || Horde_Mime_Magic::filenameToMime($temp) == 'application/zip') { // ZIP file try { $image_ids = $this->_handleZip($temp); } catch (Ansel_Exception $e) { $notification->push(sprintf(_("There was an error processing the uploaded archive: %s"), $e->getMessage()), 'horde.error'); } } else { // Try and make sure the image is in a recognizeable format. if (getimagesize($temp) === false) { header('Content-Type: application/json'); echo '{ "status" : "400", "error" : { "message": "Not a valid, supported image file." }, "id" : "id" }'; exit; } // Add the image to the gallery $image_data = array('image_filename' => $filename, 'image_type' => $type, 'data' => stream_get_contents($out)); fclose($out); try { $image_ids = array($this->_gallery->addImage($image_data)); } catch (Ansel_Exception $e) { header('Content-Type: application/json'); echo '{ "status" : "400", "error" : { "message": "Not a valid, supported image file." }, "id" : "id" }'; exit; } unset($data); } // Try to auto generate some thumbnails. $qtask = new Ansel_Queue_ProcessThumbs($image_ids); $queue = $GLOBALS['injector']->getInstance('Horde_Queue_Storage'); $queue->add($qtask); header('Content-Type: application/json'); echo '{ "status" : "200", "error" : {} }'; exit; } }
/** * Read an image from the filesystem. * * @param string $file The filename of the image. * @param array $override Overwrite the file array with these values. * * @return array The image data of the file as an array * @throws Horde_Exception_NotFound */ public static function getImageFromFile($file, $override = array()) { if (!file_exists($file)) { throw new Horde_Exception_NotFound(sprintf(_("The file \"%s\" doesn't exist."), $file)); } global $conf; // Get the mime type of the file (and make sure it's an image). $mime_type = Horde_Mime_Magic::analyzeFile($file, isset($conf['mime']['magic_db']) ? $conf['mime']['magic_db'] : null); if (strpos($mime_type, 'image') === false) { throw new Horde_Exception_NotFound(sprintf(_("Can't get unknown file type \"%s\"."), $file)); } $image = array('image_filename' => basename($file), 'image_caption' => '', 'image_type' => $mime_type, 'data' => file_get_contents($file)); // Override the array e.g., if we're changing filename to something else. if (count($override)) { $image = array_merge($image, $override); } return $image; }
/** * Adds an attachment to the outgoing compose message. * * @param string $atc_file Temporary file containing attachment contents. * @param integer $bytes Size of data, in bytes. * @param string $filename Filename of data. * @param string $type MIME type of data. * * @return IMP_Compose_Attachment Attachment object. * @throws IMP_Compose_Exception */ protected function _addAttachment($atc_file, $bytes, $filename, $type) { global $conf, $injector; $atc = new Horde_Mime_Part(); $atc->setBytes($bytes); /* Try to determine the MIME type from 1) the extension and * then 2) analysis of the file (if available). */ if (strlen($filename)) { $atc->setName($filename); if ($type == 'application/octet-stream') { $type = Horde_Mime_Magic::filenameToMIME($filename, false); } } $atc->setType($type); if ($atc->getType() == 'application/octet-stream' || $atc->getPrimaryType() == 'text') { $analyze = Horde_Mime_Magic::analyzeFile($atc_file, empty($conf['mime']['magic_db']) ? null : $conf['mime']['magic_db'], array('nostrip' => true)); $atc->setCharset('UTF-8'); if ($analyze) { $ctype = new Horde_Mime_Headers_ContentParam('Content-Type', $analyze); $atc->setType($ctype->value); if (isset($ctype->params['charset'])) { $atc->setCharset($ctype->params['charset']); } } } else { $atc->setHeaderCharset('UTF-8'); } $atc_ob = new IMP_Compose_Attachment($this, $atc, $atc_file); /* Check for attachment size limitations. */ $size_limit = null; if ($atc_ob->linked) { if (!empty($conf['compose']['link_attach_size_limit'])) { $linked = true; $size_limit = 'link_attach_size_limit'; } } elseif (!empty($conf['compose']['attach_size_limit'])) { $linked = false; $size_limit = 'attach_size_limit'; } if (!is_null($size_limit)) { $total_size = $conf['compose'][$size_limit] - $bytes; foreach ($this as $val) { if ($val->linked == $linked) { $total_size -= $val->getPart()->getBytes(); } } if ($total_size < 0) { throw new IMP_Compose_Exception(strlen($filename) ? sprintf(_("Attached file \"%s\" exceeds the attachment size limits. File NOT attached."), $filename) : _("Attached file exceeds the attachment size limits. File NOT attached.")); } } try { $injector->getInstance('Horde_Core_Hooks')->callHook('compose_attachment', 'imp', array($atc_ob)); } catch (Horde_Exception_HookNotSet $e) { } $this->_atc[$atc_ob->id] = $atc_ob; $this->changed = 'changed'; return $atc_ob; }
/** * @requires extension fileinfo */ public function testBug325() { $this->assertEquals('text/plain', Horde_Mime_Magic::analyzeFile(__DIR__ . '/fixtures/flowed_msg.txt')); }