private function buildDefaultTransformation(PhabricatorFile $file)
 {
     static $regexps = array('@application/zip@' => 'zip', '@image/@' => 'image', '@application/pdf@' => 'pdf', '@.*@' => 'default');
     $type = $file->getMimeType();
     $prefix = 'default';
     foreach ($regexps as $regexp => $implied_prefix) {
         if (preg_match($regexp, $type)) {
             $prefix = $implied_prefix;
             break;
         }
     }
     switch ($this->transform) {
         case 'thumb-280x210':
             $suffix = '280x210';
             break;
         case 'thumb-160x120':
             $suffix = '160x120';
             break;
         case 'thumb-60x45':
             $suffix = '60x45';
             break;
         case 'preview-100':
             $suffix = '.p100';
             break;
         default:
             throw new Exception('Unsupported transformation type!');
     }
     $path = celerity_get_resource_uri("rsrc/image/icon/fatcow/thumbnails/{$prefix}{$suffix}.png");
     return id(new AphrontRedirectResponse())->setURI($path);
 }
 /**
  * Very crudely scale an image up or down to an exact size.
  */
 private function crudelyScaleTo(PhabricatorFile $file, $dx, $dy)
 {
     $data = $file->loadFileData();
     $src = imagecreatefromstring($data);
     $dst = $this->applyScaleTo($src, $dx, $dy);
     return $this->saveImageDataInAnyFormat($dst, $file->getMimeType());
 }
 private function applyMemeToFile(PhabricatorFile $file, $upper_text, $lower_text)
 {
     $data = $file->loadFileData();
     $img_type = $file->getMimeType();
     $imagemagick = PhabricatorEnv::getEnvConfig('files.enable-imagemagick');
     if ($img_type != 'image/gif' || $imagemagick == false) {
         return $this->applyMemeTo($data, $upper_text, $lower_text, $img_type);
     }
     $data = $file->loadFileData();
     $input = new TempFile();
     Filesystem::writeFile($input, $data);
     list($out) = execx('convert %s info:', $input);
     $split = phutil_split_lines($out);
     if (count($split) > 1) {
         return $this->applyMemeWithImagemagick($input, $upper_text, $lower_text, count($split), $img_type);
     } else {
         return $this->applyMemeTo($data, $upper_text, $lower_text, $img_type);
     }
 }
 private function generatePreview(PhabricatorFile $file, $size)
 {
     $data = $file->loadFileData();
     $src = imagecreatefromstring($data);
     $x = imagesx($src);
     $y = imagesy($src);
     $scale = min($size / $x, $size / $y, 1);
     $dx = max($size / 4, $scale * $x);
     $dy = max($size / 4, $scale * $y);
     $dst = imagecreatetruecolor($dx, $dy);
     imagesavealpha($dst, true);
     imagefill($dst, 0, 0, imagecolorallocatealpha($dst, 255, 255, 255, 127));
     $sdx = $scale * $x;
     $sdy = $scale * $y;
     imagecopyresampled($dst, $src, ($dx - $sdx) / 2, ($dy - $sdy) / 2, 0, 0, $sdx, $sdy, $x, $y);
     return $this->saveImageDataInAnyFormat($dst, $file->getMimeType());
 }
 private function renderAudioFile(PhabricatorFile $file, PhabricatorObjectHandle $handle, array $options)
 {
     if (idx($options, 'autoplay')) {
         $preload = 'auto';
         $autoplay = 'autoplay';
     } else {
         $preload = 'none';
         $autoplay = null;
     }
     return $this->newTag('audio', array('controls' => 'controls', 'preload' => $preload, 'autoplay' => $autoplay, 'loop' => idx($options, 'loop') ? 'loop' : null), $this->newTag('source', array('src' => $file->getBestURI(), 'type' => $file->getMimeType())));
 }
 private function buildPropertyViews(PHUIObjectBoxView $box, PhabricatorFile $file)
 {
     $request = $this->getRequest();
     $viewer = $request->getUser();
     $tab_group = id(new PHUITabGroupView());
     $box->addTabGroup($tab_group);
     $properties = id(new PHUIPropertyListView());
     $tab_group->addTab(id(new PHUITabView())->setName(pht('Details'))->setKey('details')->appendChild($properties));
     if ($file->getAuthorPHID()) {
         $properties->addProperty(pht('Author'), $viewer->renderHandle($file->getAuthorPHID()));
     }
     $properties->addProperty(pht('Created'), phabricator_datetime($file->getDateCreated(), $viewer));
     $finfo = id(new PHUIPropertyListView());
     $tab_group->addTab(id(new PHUITabView())->setName(pht('File Info'))->setKey('info')->appendChild($finfo));
     $finfo->addProperty(pht('Size'), phutil_format_bytes($file->getByteSize()));
     $finfo->addProperty(pht('Mime Type'), $file->getMimeType());
     $width = $file->getImageWidth();
     if ($width) {
         $finfo->addProperty(pht('Width'), pht('%s px', new PhutilNumber($width)));
     }
     $height = $file->getImageHeight();
     if ($height) {
         $finfo->addProperty(pht('Height'), pht('%s px', new PhutilNumber($height)));
     }
     $is_image = $file->isViewableImage();
     if ($is_image) {
         $image_string = pht('Yes');
         $cache_string = $file->getCanCDN() ? pht('Yes') : pht('No');
     } else {
         $image_string = pht('No');
         $cache_string = pht('Not Applicable');
     }
     $types = array();
     if ($file->isViewableImage()) {
         $types[] = pht('Image');
     }
     if ($file->isVideo()) {
         $types[] = pht('Video');
     }
     if ($file->isAudio()) {
         $types[] = pht('Audio');
     }
     if ($file->getCanCDN()) {
         $types[] = pht('Can CDN');
     }
     $builtin = $file->getBuiltinName();
     if ($builtin !== null) {
         $types[] = pht('Builtin ("%s")', $builtin);
     }
     if ($file->getIsProfileImage()) {
         $types[] = pht('Profile');
     }
     if ($types) {
         $types = implode(', ', $types);
         $finfo->addProperty(pht('Attributes'), $types);
     }
     $storage_properties = new PHUIPropertyListView();
     $tab_group->addTab(id(new PHUITabView())->setName(pht('Storage'))->setKey('storage')->appendChild($storage_properties));
     $storage_properties->addProperty(pht('Engine'), $file->getStorageEngine());
     $engine = $this->loadStorageEngine($file);
     if ($engine && $engine->isChunkEngine()) {
         $format_name = pht('Chunks');
     } else {
         $format_key = $file->getStorageFormat();
         $format = PhabricatorFileStorageFormat::getFormat($format_key);
         if ($format) {
             $format_name = $format->getStorageFormatName();
         } else {
             $format_name = pht('Unknown ("%s")', $format_key);
         }
     }
     $storage_properties->addProperty(pht('Format'), $format_name);
     $storage_properties->addProperty(pht('Handle'), $file->getStorageHandle());
     $phids = $file->getObjectPHIDs();
     if ($phids) {
         $attached = new PHUIPropertyListView();
         $tab_group->addTab(id(new PHUITabView())->setName(pht('Attached'))->setKey('attached')->appendChild($attached));
         $attached->addProperty(pht('Attached To'), $viewer->renderHandleList($phids));
     }
     if ($file->isViewableImage()) {
         $image = phutil_tag('img', array('src' => $file->getViewURI(), 'class' => 'phui-property-list-image'));
         $linked_image = phutil_tag('a', array('href' => $file->getViewURI()), $image);
         $media = id(new PHUIPropertyListView())->addImageContent($linked_image);
         $box->addPropertyList($media);
     } else {
         if ($file->isVideo()) {
             $video = phutil_tag('video', array('controls' => 'controls', 'class' => 'phui-property-list-video'), phutil_tag('source', array('src' => $file->getViewURI(), 'type' => $file->getMimeType())));
             $media = id(new PHUIPropertyListView())->addImageContent($video);
             $box->addPropertyList($media);
         } else {
             if ($file->isAudio()) {
                 $audio = phutil_tag('audio', array('controls' => 'controls', 'class' => 'phui-property-list-audio'), phutil_tag('source', array('src' => $file->getViewURI(), 'type' => $file->getMimeType())));
                 $media = id(new PHUIPropertyListView())->addImageContent($audio);
                 $box->addPropertyList($media);
             }
         }
     }
     $engine = $this->loadStorageEngine($file);
     if ($engine) {
         if ($engine->isChunkEngine()) {
             $chunkinfo = new PHUIPropertyListView();
             $tab_group->addTab(id(new PHUITabView())->setName(pht('Chunks'))->setKey('chunks')->appendChild($chunkinfo));
             $chunks = id(new PhabricatorFileChunkQuery())->setViewer($viewer)->withChunkHandles(array($file->getStorageHandle()))->execute();
             $chunks = msort($chunks, 'getByteStart');
             $rows = array();
             $completed = array();
             foreach ($chunks as $chunk) {
                 $is_complete = $chunk->getDataFilePHID();
                 $rows[] = array($chunk->getByteStart(), $chunk->getByteEnd(), $is_complete ? pht('Yes') : pht('No'));
                 if ($is_complete) {
                     $completed[] = $chunk;
                 }
             }
             $table = id(new AphrontTableView($rows))->setHeaders(array(pht('Offset'), pht('End'), pht('Complete')))->setColumnClasses(array('', '', 'wide'));
             $chunkinfo->addProperty(pht('Total Chunks'), count($chunks));
             $chunkinfo->addProperty(pht('Completed Chunks'), count($completed));
             $chunkinfo->addRawContent($table);
         }
     }
 }
Esempio n. 7
0
 /**
  * Apply the specified ZIP archive onto the fragment, removing
  * and creating fragments as needed.
  */
 public function updateFromZIP(PhabricatorUser $viewer, PhabricatorFile $file)
 {
     if ($file->getMimeType() !== 'application/zip') {
         throw new Exception(pht("File must have mimetype '%s'.", 'application/zip'));
     }
     // First apply the ZIP as normal.
     $this->updateFromFile($viewer, $file);
     // Ensure we have ZIP support.
     $zip = null;
     try {
         $zip = new ZipArchive();
     } catch (Exception $e) {
         // The server doesn't have php5-zip, so we can't do recursive updates.
         return;
     }
     $temp = new TempFile();
     Filesystem::writeFile($temp, $file->loadFileData());
     if (!$zip->open($temp)) {
         throw new Exception(pht('Unable to open ZIP.'));
     }
     // Get all of the paths and their data from the ZIP.
     $mappings = array();
     for ($i = 0; $i < $zip->numFiles; $i++) {
         $path = trim($zip->getNameIndex($i), '/');
         $stream = $zip->getStream($path);
         $data = null;
         // If the stream is false, then it is a directory entry. We leave
         // $data set to null for directories so we know not to create a
         // version entry for them.
         if ($stream !== false) {
             $data = stream_get_contents($stream);
             fclose($stream);
         }
         $mappings[$path] = $data;
     }
     // We need to detect any directories that are in the ZIP folder that
     // aren't explicitly noted in the ZIP. This can happen if the file
     // entries in the ZIP look like:
     //
     //  * something/blah.png
     //  * something/other.png
     //  * test.png
     //
     // Where there is no explicit "something/" entry.
     foreach ($mappings as $path_key => $data) {
         if ($data === null) {
             continue;
         }
         $directory = dirname($path_key);
         while ($directory !== '.') {
             if (!array_key_exists($directory, $mappings)) {
                 $mappings[$directory] = null;
             }
             if (dirname($directory) === $directory) {
                 // dirname() will not reduce this directory any further; to
                 // prevent infinite loop we just break out here.
                 break;
             }
             $directory = dirname($directory);
         }
     }
     // Adjust the paths relative to this fragment so we can look existing
     // fragments up in the DB.
     $base_path = $this->getPath();
     $paths = array();
     foreach ($mappings as $p => $data) {
         $paths[] = $base_path . '/' . $p;
     }
     // FIXME: What happens when a child exists, but the current user
     // can't see it. We're going to create a new child with the exact
     // same path and then bad things will happen.
     $children = id(new PhragmentFragmentQuery())->setViewer($viewer)->needLatestVersion(true)->withLeadingPath($this->getPath() . '/')->execute();
     $children = mpull($children, null, 'getPath');
     // Iterate over the existing fragments.
     foreach ($children as $full_path => $child) {
         $path = substr($full_path, strlen($base_path) + 1);
         if (array_key_exists($path, $mappings)) {
             if ($child->isDirectory() && $mappings[$path] === null) {
                 // Don't create a version entry for a directory
                 // (unless it's been converted into a file).
                 continue;
             }
             // The file is being updated.
             $file = PhabricatorFile::newFromFileData($mappings[$path], array('name' => basename($path)));
             $child->updateFromFile($viewer, $file);
         } else {
             // The file is being deleted.
             $child->deleteFile($viewer);
         }
     }
     // Iterate over the mappings to find new files.
     foreach ($mappings as $path => $data) {
         if (!array_key_exists($base_path . '/' . $path, $children)) {
             // The file is being created. If the data is null,
             // then this is explicitly a directory being created.
             $file = null;
             if ($mappings[$path] !== null) {
                 $file = PhabricatorFile::newFromFileData($mappings[$path], array('name' => basename($path)));
             }
             self::createFromFile($viewer, $file, $base_path . '/' . $path, $this->getViewPolicy(), $this->getEditPolicy());
         }
     }
 }
 private function renderMediaFile($tag, PhabricatorFile $file, PhabricatorObjectHandle $handle, array $options)
 {
     $is_video = $tag == 'video';
     if (idx($options, 'autoplay')) {
         $preload = 'auto';
         $autoplay = 'autoplay';
     } else {
         // If we don't preload video, the user can't see the first frame and
         // has no clue what they're looking at, so always preload.
         if ($is_video) {
             $preload = 'auto';
         } else {
             $preload = 'none';
         }
         $autoplay = null;
     }
     return $this->newTag($tag, array('controls' => 'controls', 'preload' => $preload, 'autoplay' => $autoplay, 'loop' => idx($options, 'loop') ? 'loop' : null, 'alt' => $options['alt'], 'class' => 'phabricator-media'), $this->newTag('source', array('src' => $file->getBestURI(), 'type' => $file->getMimeType())));
 }
 private function applyScaleWithImagemagick(PhabricatorFile $file, $dx, $dy)
 {
     $img_type = $file->getMimeType();
     $imagemagick = PhabricatorEnv::getEnvConfig('files.enable-imagemagick');
     if ($img_type != 'image/gif' || $imagemagick == false) {
         return null;
     }
     $data = $file->loadFileData();
     $src = imagecreatefromstring($data);
     $x = imagesx($src);
     $y = imagesy($src);
     if (self::isEnormousGIF($x, $y)) {
         return null;
     }
     $scale = min($dx / $x, $dy / $y, 1);
     $sdx = $scale * $x;
     $sdy = $scale * $y;
     $input = new TempFile();
     Filesystem::writeFile($input, $data);
     $resized = new TempFile();
     $future = new ExecFuture('convert %s -coalesce -resize %sX%s%s %s', $input, $sdx, $sdy, '!', $resized);
     // Don't spend more than 10 seconds resizing; just fail if it takes longer
     // than that.
     $future->setTimeout(10)->resolvex();
     return Filesystem::readFile($resized);
 }
 private function buildPropertyViews(PHUIObjectBoxView $box, PhabricatorFile $file, PhabricatorActionListView $actions)
 {
     $request = $this->getRequest();
     $viewer = $request->getUser();
     $properties = id(new PHUIPropertyListView());
     $properties->setActionList($actions);
     $box->addPropertyList($properties, pht('Details'));
     if ($file->getAuthorPHID()) {
         $properties->addProperty(pht('Author'), $viewer->renderHandle($file->getAuthorPHID()));
     }
     $properties->addProperty(pht('Created'), phabricator_datetime($file->getDateCreated(), $viewer));
     $finfo = id(new PHUIPropertyListView());
     $box->addPropertyList($finfo, pht('File Info'));
     $finfo->addProperty(pht('Size'), phutil_format_bytes($file->getByteSize()));
     $finfo->addProperty(pht('Mime Type'), $file->getMimeType());
     $width = $file->getImageWidth();
     if ($width) {
         $finfo->addProperty(pht('Width'), pht('%s px', new PhutilNumber($width)));
     }
     $height = $file->getImageHeight();
     if ($height) {
         $finfo->addProperty(pht('Height'), pht('%s px', new PhutilNumber($height)));
     }
     $is_image = $file->isViewableImage();
     if ($is_image) {
         $image_string = pht('Yes');
         $cache_string = $file->getCanCDN() ? pht('Yes') : pht('No');
     } else {
         $image_string = pht('No');
         $cache_string = pht('Not Applicable');
     }
     $finfo->addProperty(pht('Viewable Image'), $image_string);
     $finfo->addProperty(pht('Cacheable'), $cache_string);
     $builtin = $file->getBuiltinName();
     if ($builtin === null) {
         $builtin_string = pht('No');
     } else {
         $builtin_string = $builtin;
     }
     $finfo->addProperty(pht('Builtin'), $builtin_string);
     $is_profile = $file->getIsProfileImage() ? pht('Yes') : pht('No');
     $finfo->addProperty(pht('Profile'), $is_profile);
     $storage_properties = new PHUIPropertyListView();
     $box->addPropertyList($storage_properties, pht('Storage'));
     $storage_properties->addProperty(pht('Engine'), $file->getStorageEngine());
     $storage_properties->addProperty(pht('Format'), $file->getStorageFormat());
     $storage_properties->addProperty(pht('Handle'), $file->getStorageHandle());
     $phids = $file->getObjectPHIDs();
     if ($phids) {
         $attached = new PHUIPropertyListView();
         $box->addPropertyList($attached, pht('Attached'));
         $attached->addProperty(pht('Attached To'), $viewer->renderHandleList($phids));
     }
     if ($file->isViewableImage()) {
         $image = phutil_tag('img', array('src' => $file->getViewURI(), 'class' => 'phui-property-list-image'));
         $linked_image = phutil_tag('a', array('href' => $file->getViewURI()), $image);
         $media = id(new PHUIPropertyListView())->addImageContent($linked_image);
         $box->addPropertyList($media);
     } else {
         if ($file->isAudio()) {
             $audio = phutil_tag('audio', array('controls' => 'controls', 'class' => 'phui-property-list-audio'), phutil_tag('source', array('src' => $file->getViewURI(), 'type' => $file->getMimeType())));
             $media = id(new PHUIPropertyListView())->addImageContent($audio);
             $box->addPropertyList($media);
         }
     }
     $engine = null;
     try {
         $engine = $file->instantiateStorageEngine();
     } catch (Exception $ex) {
         // Don't bother raising this anywhere for now.
     }
     if ($engine) {
         if ($engine->isChunkEngine()) {
             $chunkinfo = new PHUIPropertyListView();
             $box->addPropertyList($chunkinfo, pht('Chunks'));
             $chunks = id(new PhabricatorFileChunkQuery())->setViewer($viewer)->withChunkHandles(array($file->getStorageHandle()))->execute();
             $chunks = msort($chunks, 'getByteStart');
             $rows = array();
             $completed = array();
             foreach ($chunks as $chunk) {
                 $is_complete = $chunk->getDataFilePHID();
                 $rows[] = array($chunk->getByteStart(), $chunk->getByteEnd(), $is_complete ? pht('Yes') : pht('No'));
                 if ($is_complete) {
                     $completed[] = $chunk;
                 }
             }
             $table = id(new AphrontTableView($rows))->setHeaders(array(pht('Offset'), pht('End'), pht('Complete')))->setColumnClasses(array('', '', 'wide'));
             $chunkinfo->addProperty(pht('Total Chunks'), count($chunks));
             $chunkinfo->addProperty(pht('Completed Chunks'), count($completed));
             $chunkinfo->addRawContent($table);
         }
     }
 }
 private function buildPropertyViews(PHUIObjectBoxView $box, PhabricatorFile $file, PhabricatorActionListView $actions)
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $properties = id(new PHUIPropertyListView());
     $properties->setActionList($actions);
     $box->addPropertyList($properties, pht('Details'));
     if ($file->getAuthorPHID()) {
         $properties->addProperty(pht('Author'), $this->getHandle($file->getAuthorPHID())->renderLink());
     }
     $properties->addProperty(pht('Created'), phabricator_datetime($file->getDateCreated(), $user));
     $finfo = id(new PHUIPropertyListView());
     $box->addPropertyList($finfo, pht('File Info'));
     $finfo->addProperty(pht('Size'), phutil_format_bytes($file->getByteSize()));
     $finfo->addProperty(pht('Mime Type'), $file->getMimeType());
     $width = $file->getImageWidth();
     if ($width) {
         $finfo->addProperty(pht('Width'), pht('%s px', new PhutilNumber($width)));
     }
     $height = $file->getImageHeight();
     if ($height) {
         $finfo->addProperty(pht('Height'), pht('%s px', new PhutilNumber($height)));
     }
     $is_image = $file->isViewableImage();
     if ($is_image) {
         $image_string = pht('Yes');
         $cache_string = $file->getCanCDN() ? pht('Yes') : pht('No');
     } else {
         $image_string = pht('No');
         $cache_string = pht('Not Applicable');
     }
     $finfo->addProperty(pht('Viewable Image'), $image_string);
     $finfo->addProperty(pht('Cacheable'), $cache_string);
     $storage_properties = new PHUIPropertyListView();
     $box->addPropertyList($storage_properties, pht('Storage'));
     $storage_properties->addProperty(pht('Engine'), $file->getStorageEngine());
     $storage_properties->addProperty(pht('Format'), $file->getStorageFormat());
     $storage_properties->addProperty(pht('Handle'), $file->getStorageHandle());
     $phids = $file->getObjectPHIDs();
     if ($phids) {
         $attached = new PHUIPropertyListView();
         $box->addPropertyList($attached, pht('Attached'));
         $attached->addProperty(pht('Attached To'), $this->renderHandlesForPHIDs($phids));
     }
     if ($file->isViewableImage()) {
         $image = phutil_tag('img', array('src' => $file->getViewURI(), 'class' => 'phui-property-list-image'));
         $linked_image = phutil_tag('a', array('href' => $file->getViewURI()), $image);
         $media = id(new PHUIPropertyListView())->addImageContent($linked_image);
         $box->addPropertyList($media);
     } else {
         if ($file->isAudio()) {
             $audio = phutil_tag('audio', array('controls' => 'controls', 'class' => 'phui-property-list-audio'), phutil_tag('source', array('src' => $file->getViewURI(), 'type' => $file->getMimeType())));
             $media = id(new PHUIPropertyListView())->addImageContent($audio);
             $box->addPropertyList($media);
         }
     }
 }