Page MenuHomePhabricator

D12818.id30808.diff
No OneTemporary

D12818.id30808.diff

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -33,7 +33,7 @@
'rsrc/css/aphront/typeahead-browse.css' => 'd8581d2c',
'rsrc/css/aphront/typeahead.css' => '0e403212',
'rsrc/css/application/almanac/almanac.css' => 'dbb9b3af',
- 'rsrc/css/application/auth/auth.css' => '1e655982',
+ 'rsrc/css/application/auth/auth.css' => 'fee03832',
'rsrc/css/application/base/main-menu-view.css' => '663e3810',
'rsrc/css/application/base/notification-menu.css' => '3c9d8aa1',
'rsrc/css/application/base/phabricator-application-launch-view.css' => '16ca323f',
@@ -281,10 +281,6 @@
'rsrc/image/icon/fatcow/source/mobile.png' => 'f1321264',
'rsrc/image/icon/fatcow/source/tablet.png' => '49396799',
'rsrc/image/icon/fatcow/source/web.png' => '136ccb5d',
- 'rsrc/image/icon/fatcow/thumbnails/default280x210.png' => '43e8926a',
- 'rsrc/image/icon/fatcow/thumbnails/image280x210.png' => '91ae054a',
- 'rsrc/image/icon/fatcow/thumbnails/pdf280x210.png' => '1c585653',
- 'rsrc/image/icon/fatcow/thumbnails/zip280x210.png' => 'dfda5b8e',
'rsrc/image/icon/lightbox/close-2.png' => 'cc40e7c8',
'rsrc/image/icon/lightbox/close-hover-2.png' => 'fb5d6d9e',
'rsrc/image/icon/lightbox/left-arrow-2.png' => '8426133b',
@@ -495,7 +491,7 @@
'aphront-tooltip-css' => '7672b60f',
'aphront-two-column-view-css' => '16ab3ad2',
'aphront-typeahead-control-css' => '0e403212',
- 'auth-css' => '1e655982',
+ 'auth-css' => 'fee03832',
'changeset-view-manager' => '58562350',
'conduit-api-css' => '7bc725c4',
'config-options-css' => '7fedf08b',
diff --git a/src/applications/auth/view/PhabricatorAuthAccountView.php b/src/applications/auth/view/PhabricatorAuthAccountView.php
--- a/src/applications/auth/view/PhabricatorAuthAccountView.php
+++ b/src/applications/auth/view/PhabricatorAuthAccountView.php
@@ -89,13 +89,17 @@
$account_uri);
}
- $image_uri = $account->getProfileImageFile()->getProfileThumbURI();
+ $image_file = $account->getProfileImageFile();
+ $xform = PhabricatorFileTransform::getTransformByKey(
+ PhabricatorFileThumbnailTransform::TRANSFORM_PROFILE);
+ $image_uri = $image_file->getURIForTransform($xform);
+ list($x, $y) = $xform->getTransformedDimensions($image_file);
return phutil_tag(
'div',
array(
'class' => 'auth-account-view',
- 'style' => 'background-image: url('.$image_uri.')',
+ 'style' => 'background-image: url('.$image_uri.');',
),
$content);
}
diff --git a/src/applications/files/PhabricatorImageTransformer.php b/src/applications/files/PhabricatorImageTransformer.php
--- a/src/applications/files/PhabricatorImageTransformer.php
+++ b/src/applications/files/PhabricatorImageTransformer.php
@@ -20,21 +20,6 @@
));
}
- public function executeThumbTransform(
- PhabricatorFile $file,
- $x,
- $y) {
-
- $image = $this->crudelyScaleTo($file, $x, $y);
-
- return PhabricatorFile::newFromFileData(
- $image,
- array(
- 'name' => 'thumb-'.$file->getName(),
- 'canCDN' => true,
- ));
- }
-
public function executeProfileTransform(
PhabricatorFile $file,
$x,
@@ -123,21 +108,6 @@
return self::saveImageDataInAnyFormat($dst, $file->getMimeType());
}
-
- /**
- * Very crudely scale an image up or down to an exact size.
- */
- private function crudelyScaleTo(PhabricatorFile $file, $dx, $dy) {
- $scaled = $this->applyScaleWithImagemagick($file, $dx, $dy);
-
- if ($scaled != null) {
- return $scaled;
- }
-
- $dst = $this->applyScaleTo($file, $dx, $dy);
- return self::saveImageDataInAnyFormat($dst, $file->getMimeType());
- }
-
private function getBlankDestinationFile($dx, $dy) {
$dst = imagecreatetruecolor($dx, $dy);
imagesavealpha($dst, true);
diff --git a/src/applications/files/controller/PhabricatorFileTransformController.php b/src/applications/files/controller/PhabricatorFileTransformController.php
--- a/src/applications/files/controller/PhabricatorFileTransformController.php
+++ b/src/applications/files/controller/PhabricatorFileTransformController.php
@@ -44,50 +44,33 @@
}
}
- $type = $file->getMimeType();
-
- if (!$file->isViewableInBrowser() || !$file->isTransformableImage()) {
- return $this->buildDefaultTransformation($file, $transform);
+ $xforms = PhabricatorFileTransform::getAllTransforms();
+ if (!isset($xforms[$transform])) {
+ return new Aphront404Response();
}
+ $xform = $xforms[$transform];
+
// We're essentially just building a cache here and don't need CSRF
// protection.
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
$xformed_file = null;
-
- $xforms = PhabricatorFileTransform::getAllTransforms();
- if (isset($xforms[$transform])) {
- $xform = $xforms[$transform];
- if ($xform->canApplyTransform($file)) {
- try {
- $xformed_file = $xforms[$transform]->applyTransform($file);
- } catch (Exception $ex) {
- // In normal transform mode, we ignore failures and generate a
- // default transform below. If we're explicitly regenerating the
- // thumbnail, rethrow the exception.
- if ($is_regenerate) {
- throw $ex;
- }
+ if ($xform->canApplyTransform($file)) {
+ try {
+ $xformed_file = $xforms[$transform]->applyTransform($file);
+ } catch (Exception $ex) {
+ // In normal transform mode, we ignore failures and generate a
+ // default transform below. If we're explicitly regenerating the
+ // thumbnail, rethrow the exception.
+ if ($is_regenerate) {
+ throw $ex;
}
}
-
- if (!$xformed_file) {
- $xformed_file = $xform->getDefaultTransform($file);
- }
}
if (!$xformed_file) {
- switch ($transform) {
- case 'thumb-profile':
- $xformed_file = $this->executeThumbTransform($file, 50, 50);
- break;
- case 'thumb-280x210':
- $xformed_file = $this->executeThumbTransform($file, 280, 210);
- break;
- default:
- return new Aphront400Response();
- }
+ $xformed_file = $xform->getDefaultTransform($file);
}
if (!$xformed_file) {
@@ -103,40 +86,6 @@
return $this->buildTransformedFileResponse($xform);
}
- private function buildDefaultTransformation(
- PhabricatorFile $file,
- $transform) {
- 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 ($transform) {
- case 'thumb-280x210':
- $suffix = '280x210';
- 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);
- }
-
private function buildTransformedFileResponse(
PhabricatorTransformedFile $xform) {
@@ -154,11 +103,6 @@
return $file->getRedirectResponse();
}
- private function executeThumbTransform(PhabricatorFile $file, $x, $y) {
- $xformer = new PhabricatorImageTransformer();
- return $xformer->executeThumbTransform($file, $x, $y);
- }
-
private function destroyTransform(PhabricatorTransformedFile $xform) {
$file = id(new PhabricatorFileQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
diff --git a/src/applications/files/storage/PhabricatorFile.php b/src/applications/files/storage/PhabricatorFile.php
--- a/src/applications/files/storage/PhabricatorFile.php
+++ b/src/applications/files/storage/PhabricatorFile.php
@@ -784,14 +784,6 @@
return PhabricatorEnv::getCDNURI($path);
}
- public function getProfileThumbURI() {
- return $this->getTransformedURI('thumb-profile');
- }
-
- public function getThumb280x210URI() {
- return $this->getTransformedURI('thumb-280x210');
- }
-
public function isViewableInBrowser() {
return ($this->getViewableMimeType() !== null);
}
diff --git a/src/applications/files/transform/PhabricatorFileImageTransform.php b/src/applications/files/transform/PhabricatorFileImageTransform.php
--- a/src/applications/files/transform/PhabricatorFileImageTransform.php
+++ b/src/applications/files/transform/PhabricatorFileImageTransform.php
@@ -42,13 +42,20 @@
$dst_w, $dst_h,
$src_x, $src_y,
$src_w, $src_h,
- $use_w, $use_h) {
+ $use_w, $use_h,
+ $scale_up) {
+
+ // Figure out the effective destination width, height, and offsets.
+ $cpy_w = min($dst_w, $use_w);
+ $cpy_h = min($dst_h, $use_h);
+
+ // If we aren't scaling up, and are copying a very small source image,
+ // we're just going to center it in the destination image.
+ if (!$scale_up) {
+ $cpy_w = min($cpy_w, $src_w);
+ $cpy_h = min($cpy_h, $src_h);
+ }
- // Figure out the effective destination width, height, and offsets. We
- // never want to scale images up, so if we're copying a very small source
- // image we're just going to center it in the destination image.
- $cpy_w = min($dst_w, $src_w, $use_w);
- $cpy_h = min($dst_h, $src_h, $use_h);
$off_x = ($dst_w - $cpy_w) / 2;
$off_y = ($dst_h - $cpy_h) / 2;
@@ -58,11 +65,18 @@
$argv[] = '-shave';
$argv[] = $src_x.'x'.$src_y;
$argv[] = '-resize';
- $argv[] = $dst_w.'x'.$dst_h.'>';
+
+ if ($scale_up) {
+ $argv[] = $dst_w.'x'.$dst_h;
+ } else {
+ $argv[] = $dst_w.'x'.$dst_h.'>';
+ }
+
$argv[] = '-bordercolor';
$argv[] = 'rgba(255, 255, 255, 0)';
$argv[] = '-border';
$argv[] = $off_x.'x'.$off_y;
+
return $this->applyImagemagick($argv);
}
@@ -117,7 +131,13 @@
* @param string Raw file data.
*/
protected function newFileFromData($data) {
- $name = $this->getTransformKey().'-'.$this->file->getName();
+ if ($this->file) {
+ $name = $this->file->getName();
+ } else {
+ $name = 'default.png';
+ }
+
+ $name = $this->getTransformKey().'-'.$name;
return PhabricatorFile::newFromFileData(
$data,
diff --git a/src/applications/files/transform/PhabricatorFileThumbnailTransform.php b/src/applications/files/transform/PhabricatorFileThumbnailTransform.php
--- a/src/applications/files/transform/PhabricatorFileThumbnailTransform.php
+++ b/src/applications/files/transform/PhabricatorFileThumbnailTransform.php
@@ -12,6 +12,7 @@
private $key;
private $dstX;
private $dstY;
+ private $scaleUp;
public function setName($name) {
$this->name = $name;
@@ -29,6 +30,11 @@
return $this;
}
+ public function setScaleUp($scale) {
+ $this->scaleUp = $scale;
+ return $this;
+ }
+
public function getTransformName() {
return $this->name;
}
@@ -42,7 +48,8 @@
id(new PhabricatorFileThumbnailTransform())
->setName(pht("Profile (100px \xC3\x97 100px)"))
->setKey(self::TRANSFORM_PROFILE)
- ->setDimensions(100, 100),
+ ->setDimensions(100, 100)
+ ->setScaleUp(true),
id(new PhabricatorFileThumbnailTransform())
->setName(pht("Pinboard (280px \xC3\x97 210px)"))
->setKey(self::TRANSFORM_PINBOARD)
@@ -86,7 +93,8 @@
$copy_x,
$copy_y,
$use_x,
- $use_y);
+ $use_y,
+ $this->scaleUp);
}
@@ -144,22 +152,35 @@
$copy_x = $src_x;
$copy_y = $src_y;
} else {
+ $scale_up = $this->scaleUp;
+
// Otherwise, both dimensions are fixed. Figure out how much we'd have to
// scale the image down along each dimension to get the entire thing to
// fit.
- $scale_x = min(($dst_x / $src_x), 1);
- $scale_y = min(($dst_y / $src_y), 1);
+ $scale_x = ($dst_x / $src_x);
+ $scale_y = ($dst_y / $src_y);
+
+ if (!$scale_up) {
+ $scale_x = min($scale_x, 1);
+ $scale_y = min($scale_y, 1);
+ }
if ($scale_x > $scale_y) {
// This image is relatively tall and narrow. We're going to crop off the
// top and bottom.
- $copy_x = $src_x;
- $copy_y = min($src_y, $dst_y / $scale_x);
+ $scale = $scale_x;
} else {
// This image is relatively short and wide. We're going to crop off the
// left and right.
- $copy_x = min($src_x, $dst_x / $scale_y);
- $copy_y = $src_y;
+ $scale = $scale_y;
+ }
+
+ $copy_x = $dst_x / $scale_x;
+ $copy_y = $dst_y / $scale_x;
+
+ if (!$scale_up) {
+ $copy_x = min($src_x, $copy_x);
+ $copy_y = min($src_y, $copy_y);
}
// In this mode, we always use the entire destination image. We may
diff --git a/src/applications/macro/query/PhabricatorMacroSearchEngine.php b/src/applications/macro/query/PhabricatorMacroSearchEngine.php
--- a/src/applications/macro/query/PhabricatorMacroSearchEngine.php
+++ b/src/applications/macro/query/PhabricatorMacroSearchEngine.php
@@ -179,14 +179,18 @@
assert_instances_of($macros, 'PhabricatorFileImageMacro');
$viewer = $this->requireViewer();
+ $xform = PhabricatorFileTransform::getTransformByKey(
+ PhabricatorFileThumbnailTransform::TRANSFORM_PINBOARD);
+
$pinboard = new PHUIPinboardView();
foreach ($macros as $macro) {
$file = $macro->getFile();
$item = new PHUIPinboardItemView();
if ($file) {
- $item->setImageURI($file->getThumb280x210URI());
- $item->setImageSize(280, 210);
+ $item->setImageURI($file->getURIForTransform($xform));
+ list($x, $y) = $xform->getTransformedDimensions($file);
+ $item->setImageSize($x, $y);
}
if ($macro->getDateCreated()) {
diff --git a/src/applications/pholio/query/PholioMockSearchEngine.php b/src/applications/pholio/query/PholioMockSearchEngine.php
--- a/src/applications/pholio/query/PholioMockSearchEngine.php
+++ b/src/applications/pholio/query/PholioMockSearchEngine.php
@@ -141,15 +141,22 @@
$viewer = $this->requireViewer();
+ $xform = PhabricatorFileTransform::getTransformByKey(
+ PhabricatorFileThumbnailTransform::TRANSFORM_PINBOARD);
+
$board = new PHUIPinboardView();
foreach ($mocks as $mock) {
+ $image = $mock->getCoverFile();
+ $image_uri = $image->getURIForTransform($xform);
+ list($x, $y) = $xform->getTransformedDimensions($image);
+
$header = 'M'.$mock->getID().' '.$mock->getName();
$item = id(new PHUIPinboardItemView())
->setHeader($header)
->setURI('/M'.$mock->getID())
- ->setImageURI($mock->getCoverFile()->getThumb280x210URI())
- ->setImageSize(280, 210)
+ ->setImageURI($image_uri)
+ ->setImageSize($x, $y)
->setDisabled($mock->isClosed())
->addIconCount('fa-picture-o', count($mock->getImages()))
->addIconCount('fa-trophy', $mock->getTokenCount());
diff --git a/src/applications/pholio/view/PholioMockEmbedView.php b/src/applications/pholio/view/PholioMockEmbedView.php
--- a/src/applications/pholio/view/PholioMockEmbedView.php
+++ b/src/applications/pholio/view/PholioMockEmbedView.php
@@ -28,25 +28,29 @@
$this->mock->getImages(), array_flip($this->images));
}
+ $xform = PhabricatorFileTransform::getTransformByKey(
+ PhabricatorFileThumbnailTransform::TRANSFORM_PINBOARD);
+
if ($images_to_show) {
- foreach ($images_to_show as $image) {
- $thumbfile = $image->getFile();
- $thumbnail = $thumbfile->getThumb280x210URI();
- }
+ $image = head($images_to_show);
+ $thumbfile = $image->getFile();
$header = 'M'.$mock->getID().' '.$mock->getName().
' (#'.$image->getID().')';
$uri = '/M'.$this->mock->getID().'/'.$image->getID().'/';
} else {
- $thumbnail = $mock->getCoverFile()->getThumb280x210URI();
+ $thumbfile = $mock->getCoverFile();
$header = 'M'.$mock->getID().' '.$mock->getName();
$uri = '/M'.$this->mock->getID();
}
+ $thumbnail = $thumbfile->getURIForTransform($xform);
+ list($x, $y) = $xform->getTransformedDimensions($thumbfile);
+
$item = id(new PHUIPinboardItemView())
->setHeader($header)
->setURI($uri)
->setImageURI($thumbnail)
- ->setImageSize(280, 210)
+ ->setImageSize($x, $y)
->setDisabled($mock->isClosed())
->addIconCount('fa-picture-o', count($mock->getImages()))
->addIconCount('fa-trophy', $mock->getTokenCount());
diff --git a/src/applications/pholio/view/PholioMockImagesView.php b/src/applications/pholio/view/PholioMockImagesView.php
--- a/src/applications/pholio/view/PholioMockImagesView.php
+++ b/src/applications/pholio/view/PholioMockImagesView.php
@@ -68,8 +68,11 @@
// TODO: We could maybe do a better job with tailoring this, which is the
// image shown on the review stage.
- $nonimage_uri = celerity_get_resource_uri(
- 'rsrc/image/icon/fatcow/thumbnails/default.p100.png');
+ $default_name = 'image-100x100.png';
+ $builtins = PhabricatorFile::loadBuiltins(
+ $this->getUser(),
+ array($default_name));
+ $default = $builtins[$default_name];
$engine = id(new PhabricatorMarkupEngine())
->setViewer($this->getUser());
@@ -97,7 +100,7 @@
'fullURI' => $file->getBestURI(),
'stageURI' => ($file->isViewableImage()
? $file->getBestURI()
- : $nonimage_uri),
+ : $default->getBestURI()),
'pageURI' => $this->getImagePageURI($image, $mock),
'downloadURI' => $file->getDownloadURI(),
'historyURI' => $history_uri,
diff --git a/src/applications/pholio/view/PholioUploadedImageView.php b/src/applications/pholio/view/PholioUploadedImageView.php
--- a/src/applications/pholio/view/PholioUploadedImageView.php
+++ b/src/applications/pholio/view/PholioUploadedImageView.php
@@ -38,11 +38,15 @@
->setSigil('image-description')
->setLabel(pht('Description'));
+ $xform = PhabricatorFileTransform::getTransformByKey(
+ PhabricatorFileThumbnailTransform::TRANSFORM_PINBOARD);
+ $thumbnail_uri = $file->getURIForTransform($xform);
+
$thumb_frame = phutil_tag(
'div',
array(
'class' => 'pholio-thumb-frame',
- 'style' => 'background-image: url('.$file->getThumb280x210URI().');',
+ 'style' => 'background-image: url('.$thumbnail_uri.');',
));
$handle = javelin_tag(
diff --git a/webroot/rsrc/css/application/auth/auth.css b/webroot/rsrc/css/application/auth/auth.css
--- a/webroot/rsrc/css/application/auth/auth.css
+++ b/webroot/rsrc/css/application/auth/auth.css
@@ -28,6 +28,7 @@
border: 1px solid {$lightblueborder};
background-repeat: no-repeat;
background-position: 4px 4px;
+ background-size: 50px 50px;
padding: 4px 4px 4px 62px;
min-height: 50px;
border-radius: 2px;
diff --git a/webroot/rsrc/image/icon/fatcow/thumbnails/default280x210.png b/webroot/rsrc/image/icon/fatcow/thumbnails/default280x210.png
deleted file mode 100644
index 7288c81954ec6a5e5916cdbbe6c93c2eb660390e..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 2123
zc%17D@N?(olHy`uVBq!ia0y~yV3Yu|FLAH|$%$R}UjZq}64!{5;QX|b^2DN42FH~A
zq*MjZ+{E<Mpwz^a%EFVWHVh2RDw!b>B@w<pR>}FfdWj%4dKI|^3?N`*Ur~^loSj;t
zkd&I9nP;o?e)oPQh0GLNrEpVU1K$GY)Qn7zs-o23D!-8As_bOT6eW8*1)B;hpaHq5
zC5Z|ZxjA{oRu#5NU~{d2Y>=?Nk^)#sNw%#L#8DBx0SeCfMX3s=dd9lR28M<TW@dVZ
zCZ=X)hB^vH28KrZ20&z{YiMF+YG!3*t^fr}K--E^(yW49+@N*=dA3R!B_#z``ugSN
z<$C4Ddih1^`i7R4mLM~XjC6r2bc-wVN)jt{^NN*WCb*;)Cl_TFlw{`TDS-HiN%^HE
zwn|DcFXR@$jm;~D1`{yA^eYkz^bPe4^pO<$`r=obn+sQ6ToRO;hF^7YNM%8)eo$(0
zerZuMFyhjbL7EG!oQqNuOY)0C^7C_Gp%{>nUy@&(kzb(T9Bihb;hUJ8nFkWk1ncni
zwerj>E=kNwPW5!LRRW6WWoD*WIh#8<nHiayxH>yI8XCG9TUa<bJ3AT}7`hl6IGdW8
z!1TK0Czs}?=9R$orXcj1;?xUD3=rL^MVV!(DQ-pixe8!UTV>*QixF<OK=h{Ic8f7i
zz4}1M=%Yn7ObD2MKumbT1#;j?KQ#}S-iv?<d-DU9?+gqqdp%toLn>~)x$B!B5-M}x
zVez{?H#k{dIx(?`Z4!*#Sj_lFHN&g&=IX-Sh?7mNit9>ViYMeJ>#7{<tz*48t3ff5
z+3=H^F3YPkPv`73-fHCgVoAB!6FdLn%OcCRpL}^%|G#m5Z)zl4L!^cdqk=)h0R|2p
z@+k%;W{N4GQ4~{P2jwr?rkb%%BDwni)cN7_zCC{VwQlCWrE`ACtW|2ulZdJQa8~{K
z<>~+PN@s7<(cO07g2P^!>BqzU-o8-TfA?2);=`k#__OcN+dE<3o9Hl>ww!gdVw`sT
zJHA(7^~z^k?@v*m<oIh(K}mf_{6C3P@6Wd`J@2P8PkZ|Gd9~_Be~#B0@ZMML-R`=!
zM788n+48-;i+A1q!KHQR?C;eNuT;NZazZBlP3_h_Q~c921trW%f;4Wel$sk>^VV=r
zY+#N`*83RqJ3D?`%(2_$pCTZkw)N7rj9bY$`>y-BoBy%vI`iqdx>$LvkR;2pkH`Ao
zZ@H8*NnUW)vlV^;%iabF^1ZFpmbrJ?`}WeU9|CXb#r}Tu<k6p}Q>Q+t+voQA^zvN-
zms}>jf6#k-M{eJxiiV$GeoPe5|0iO$&+z~A1cN<~%lE#hnX~WJ(#M^mViL3VxN2>a
zpOG^muj2W|%LQK#ZG5<K>c0dF`Lmoo2QGX$aO5RZ@RHm2qHE>e*;U%ji8EuHadF=3
z!-qdVejC1J7nAd2^%+S!-p*XdR`_V={&`!w4;WM`Zb{O8?3S6}m~bPjJH$W1A)(@{
zlg6sIezJ{*hZPKbd<>YH4+N~gIB!|#nRj<Mc+@1i8x9yO=3dybl~*RH^?-rlK@J|K
z!#R2_VS%=u>)NU-7rzx_I-GV_X2yd+6_z%u-mDL==hySb$A`2#&T2VVR}hdXAW^%L
z=l<i=FHOf~eGN4AYS$OJB>bq)I3`~@hm)o4>}2<U8s&E7PdJx-;jsqtrDw`auj5_c
zx{m4dD>k0Sg%hn7Z_l*&{I7B5oZmB5fx(g;ZoOvT->>?+uYbNBeeG*n;KpCKJ%8T$
zAMq&d{PBB@YYy)JBk_Hi|NCXhb!@+9)+E~c9DiHVYrE+dlk;b$%O{<Etacgy64bx6
zaoW0#rK@!f7`A?Dzs}Ie$in83KmjEnK{>_3Mll6;P=)edkpu=6rK8?jdp8Gws&`LU
KKbLh*2~7Ze$@y0R
diff --git a/webroot/rsrc/image/icon/fatcow/thumbnails/image280x210.png b/webroot/rsrc/image/icon/fatcow/thumbnails/image280x210.png
deleted file mode 100644
index efdf733f8eeb118cb36403c6cb9a741d0ded879f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 2600
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
diff --git a/webroot/rsrc/image/icon/fatcow/thumbnails/pdf280x210.png b/webroot/rsrc/image/icon/fatcow/thumbnails/pdf280x210.png
deleted file mode 100644
index 8036981aca18575e4fed1ebfa343188e5fed852c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 2824
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
diff --git a/webroot/rsrc/image/icon/fatcow/thumbnails/zip280x210.png b/webroot/rsrc/image/icon/fatcow/thumbnails/zip280x210.png
deleted file mode 100644
index 8db127b282c1ea95127548ba0022eabd8475315a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 2511
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

File Metadata

Mime Type
text/plain
Expires
Wed, Mar 19, 2:10 AM (5 d, 14 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7312669
Default Alt Text
D12818.id30808.diff (29 KB)

Event Timeline