2011-01-23 03:33:00 +01:00
|
|
|
<?php
|
|
|
|
|
Move ALL files to serve from the alternate file domain, not just files without
"Content-Disposition: attachment"
Summary:
We currently serve some files off the primary domain (with "Content-Disposition:
attachment" + a CSRF check) and some files off the alternate domain (without
either).
This is not sufficient, because some UAs (like the iPad) ignore
"Content-Disposition: attachment". So there's an attack that goes like this:
- Alice uploads xss.html
- Alice says to Bob "hey download this file on your iPad"
- Bob clicks "Download" on Phabricator on his iPad, gets XSS'd.
NOTE: This removes the CSRF check for downloading files. The check is nice to
have but only raises the barrier to entry slightly. Between iPad / sniffing /
flash bytecode attacks, single-domain installs are simply insecure. We could
restore the check at some point in conjunction with a derived authentication
cookie (i.e., a mini-session-token which is only useful for downloading files),
but that's a lot of complexity to drop all at once.
(Because files are now authenticated only by knowing the PHID and secret key,
this also fixes the "no profile pictures in public feed while logged out"
issue.)
Test Plan: Viewed, info'd, and downloaded files
Reviewers: btrahan, arice, alok
Reviewed By: arice
CC: aran, epriestley
Maniphest Tasks: T843
Differential Revision: https://secure.phabricator.com/D1608
2012-02-14 23:52:27 +01:00
|
|
|
final class PhabricatorFileInfoController extends PhabricatorFileController {
|
2011-01-23 03:33:00 +01:00
|
|
|
|
|
|
|
private $phid;
|
|
|
|
|
|
|
|
public function willProcessRequest(array $data) {
|
|
|
|
$this->phid = $data['phid'];
|
|
|
|
}
|
|
|
|
|
|
|
|
public function processRequest() {
|
Use phabricator_ time functions in more places
Summary:
Replace some more date() calls with locale-aware calls.
Also, at least on my system, the DateTimeZone / DateTime stuff didn't actually
work and always rendered in UTC. Fixed that.
Test Plan:
Viewed daemon console, differential revisions, files, and maniphest timestamps
in multiple timezones.
Reviewed By: toulouse
Reviewers: toulouse, fratrik, jungejason, aran, tuomaspelkonen
CC: aran, toulouse
Differential Revision: 530
2011-06-26 18:22:52 +02:00
|
|
|
$request = $this->getRequest();
|
|
|
|
$user = $request->getUser();
|
|
|
|
|
2012-12-17 01:33:24 +01:00
|
|
|
$file = id(new PhabricatorFileQuery())
|
|
|
|
->setViewer($user)
|
|
|
|
->withPHIDs(array($this->phid))
|
|
|
|
->executeOne();
|
|
|
|
|
2011-01-23 03:33:00 +01:00
|
|
|
if (!$file) {
|
|
|
|
return new Aphront404Response();
|
|
|
|
}
|
2011-02-22 18:22:57 +01:00
|
|
|
|
2012-12-17 01:33:24 +01:00
|
|
|
$phid = $file->getPHID();
|
2013-09-05 22:11:02 +02:00
|
|
|
$xactions = id(new PhabricatorFileTransactionQuery())
|
|
|
|
->setViewer($user)
|
|
|
|
->withObjectPHIDs(array($phid))
|
|
|
|
->execute();
|
|
|
|
|
2013-10-01 17:43:34 +02:00
|
|
|
$handle_phids = array_merge(
|
|
|
|
array($file->getAuthorPHID()),
|
|
|
|
$file->getObjectPHIDs());
|
|
|
|
|
|
|
|
$this->loadHandles($handle_phids);
|
2013-09-17 18:12:37 +02:00
|
|
|
$header = id(new PHUIHeaderView())
|
2013-12-30 20:27:02 +01:00
|
|
|
->setUser($user)
|
|
|
|
->setPolicyObject($file)
|
2012-12-17 01:33:24 +01:00
|
|
|
->setHeader($file->getName());
|
|
|
|
|
2013-02-20 22:33:47 +01:00
|
|
|
$ttl = $file->getTTL();
|
|
|
|
if ($ttl !== null) {
|
|
|
|
$ttl_tag = id(new PhabricatorTagView())
|
|
|
|
->setType(PhabricatorTagView::TYPE_OBJECT)
|
|
|
|
->setName(pht("Temporary"));
|
|
|
|
$header->addTag($ttl_tag);
|
|
|
|
}
|
|
|
|
|
2012-12-17 01:33:24 +01:00
|
|
|
$actions = $this->buildActionView($file);
|
2013-09-05 22:11:02 +02:00
|
|
|
$timeline = $this->buildTransactionView($file, $xactions);
|
2013-04-10 22:08:36 +02:00
|
|
|
$crumbs = $this->buildApplicationCrumbs();
|
|
|
|
$crumbs->setActionList($actions);
|
2013-12-19 02:47:34 +01:00
|
|
|
$crumbs->addTextCrumb(
|
|
|
|
'F'.$file->getID(),
|
|
|
|
$this->getApplicationURI("/info/{$phid}/"));
|
2013-04-10 22:08:36 +02:00
|
|
|
|
2013-09-29 00:55:38 +02:00
|
|
|
$object_box = id(new PHUIObjectBoxView())
|
2013-10-11 16:53:56 +02:00
|
|
|
->setHeader($header);
|
|
|
|
|
2013-10-19 21:08:06 +02:00
|
|
|
$this->buildPropertyViews($object_box, $file, $actions);
|
2013-09-29 00:55:38 +02:00
|
|
|
|
2012-12-17 01:33:24 +01:00
|
|
|
return $this->buildApplicationPage(
|
|
|
|
array(
|
|
|
|
$crumbs,
|
2013-09-29 00:55:38 +02:00
|
|
|
$object_box,
|
2013-09-05 22:11:02 +02:00
|
|
|
$timeline
|
2012-12-17 01:33:24 +01:00
|
|
|
),
|
|
|
|
array(
|
|
|
|
'title' => $file->getName(),
|
|
|
|
'device' => true,
|
2013-09-05 22:11:02 +02:00
|
|
|
'pageObjects' => array($file->getPHID()),
|
2012-12-17 01:33:24 +01:00
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2013-09-05 22:11:02 +02:00
|
|
|
private function buildTransactionView(
|
|
|
|
PhabricatorFile $file,
|
|
|
|
array $xactions) {
|
|
|
|
|
|
|
|
$user = $this->getRequest()->getUser();
|
|
|
|
$engine = id(new PhabricatorMarkupEngine())
|
|
|
|
->setViewer($user);
|
|
|
|
foreach ($xactions as $xaction) {
|
|
|
|
if ($xaction->getComment()) {
|
|
|
|
$engine->addObject(
|
|
|
|
$xaction->getComment(),
|
|
|
|
PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$engine->process();
|
|
|
|
|
|
|
|
$timeline = id(new PhabricatorApplicationTransactionView())
|
|
|
|
->setUser($user)
|
|
|
|
->setObjectPHID($file->getPHID())
|
|
|
|
->setTransactions($xactions)
|
|
|
|
->setMarkupEngine($engine);
|
|
|
|
|
|
|
|
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
|
|
|
|
|
2013-11-22 01:09:04 +01:00
|
|
|
$add_comment_header = $is_serious
|
|
|
|
? pht('Add Comment')
|
|
|
|
: pht('Question File Integrity');
|
2013-09-05 22:11:02 +02:00
|
|
|
|
|
|
|
$submit_button_name = $is_serious
|
|
|
|
? pht('Add Comment')
|
|
|
|
: pht('Debate the Bits');
|
|
|
|
|
|
|
|
$draft = PhabricatorDraft::newFromUserAndKey($user, $file->getPHID());
|
|
|
|
|
|
|
|
$add_comment_form = id(new PhabricatorApplicationTransactionCommentView())
|
|
|
|
->setUser($user)
|
|
|
|
->setObjectPHID($file->getPHID())
|
|
|
|
->setDraft($draft)
|
2013-11-22 01:09:04 +01:00
|
|
|
->setHeaderText($add_comment_header)
|
2013-09-05 22:11:02 +02:00
|
|
|
->setAction($this->getApplicationURI('/comment/'.$file->getID().'/'))
|
|
|
|
->setSubmitButtonName($submit_button_name);
|
|
|
|
|
|
|
|
return array(
|
|
|
|
$timeline,
|
2013-11-22 01:09:04 +01:00
|
|
|
$add_comment_form);
|
2013-09-05 22:11:02 +02:00
|
|
|
}
|
|
|
|
|
2012-12-17 01:33:24 +01:00
|
|
|
private function buildActionView(PhabricatorFile $file) {
|
|
|
|
$request = $this->getRequest();
|
|
|
|
$user = $request->getUser();
|
2011-07-08 06:17:00 +02:00
|
|
|
|
2012-12-17 01:33:24 +01:00
|
|
|
$id = $file->getID();
|
2011-02-22 18:22:57 +01:00
|
|
|
|
2012-12-17 01:33:24 +01:00
|
|
|
$view = id(new PhabricatorActionListView())
|
|
|
|
->setUser($user)
|
2013-07-12 20:39:47 +02:00
|
|
|
->setObjectURI($this->getRequest()->getRequestURI())
|
2012-12-17 01:33:24 +01:00
|
|
|
->setObject($file);
|
2012-01-16 22:26:44 +01:00
|
|
|
|
2011-02-22 18:19:14 +01:00
|
|
|
if ($file->isViewableInBrowser()) {
|
2012-12-17 01:33:24 +01:00
|
|
|
$view->addAction(
|
|
|
|
id(new PhabricatorActionView())
|
|
|
|
->setName(pht('View File'))
|
|
|
|
->setIcon('preview')
|
|
|
|
->setHref($file->getViewURI()));
|
2011-02-22 18:19:14 +01:00
|
|
|
} else {
|
2012-12-17 01:33:24 +01:00
|
|
|
$view->addAction(
|
|
|
|
id(new PhabricatorActionView())
|
|
|
|
->setUser($user)
|
|
|
|
->setRenderAsForm(true)
|
2013-01-29 03:12:09 +01:00
|
|
|
->setDownload(true)
|
2012-12-17 01:33:24 +01:00
|
|
|
->setName(pht('Download File'))
|
|
|
|
->setIcon('download')
|
|
|
|
->setHref($file->getViewURI()));
|
2012-01-16 22:26:44 +01:00
|
|
|
}
|
|
|
|
|
2012-12-17 01:33:24 +01:00
|
|
|
$view->addAction(
|
|
|
|
id(new PhabricatorActionView())
|
|
|
|
->setName(pht('Delete File'))
|
|
|
|
->setIcon('delete')
|
|
|
|
->setHref($this->getApplicationURI("/delete/{$id}/"))
|
|
|
|
->setWorkflow(true));
|
|
|
|
|
|
|
|
return $view;
|
|
|
|
}
|
|
|
|
|
2013-10-19 21:08:06 +02:00
|
|
|
private function buildPropertyViews(
|
|
|
|
PHUIObjectBoxView $box,
|
2013-10-11 16:53:56 +02:00
|
|
|
PhabricatorFile $file,
|
|
|
|
PhabricatorActionListView $actions) {
|
2012-12-17 01:33:24 +01:00
|
|
|
$request = $this->getRequest();
|
|
|
|
$user = $request->getUser();
|
|
|
|
|
2013-10-19 21:08:06 +02:00
|
|
|
|
2013-10-11 16:53:56 +02:00
|
|
|
$properties = id(new PHUIPropertyListView());
|
|
|
|
$properties->setActionList($actions);
|
2013-10-19 21:08:06 +02:00
|
|
|
$box->addPropertyList($properties, pht('Details'));
|
2012-12-17 01:33:24 +01:00
|
|
|
|
|
|
|
if ($file->getAuthorPHID()) {
|
2013-10-11 16:53:56 +02:00
|
|
|
$properties->addProperty(
|
2012-12-17 01:33:24 +01:00
|
|
|
pht('Author'),
|
|
|
|
$this->getHandle($file->getAuthorPHID())->renderLink());
|
2011-02-22 18:19:14 +01:00
|
|
|
}
|
2011-07-30 01:01:59 +02:00
|
|
|
|
2013-10-11 16:53:56 +02:00
|
|
|
$properties->addProperty(
|
2012-12-17 01:33:24 +01:00
|
|
|
pht('Created'),
|
|
|
|
phabricator_datetime($file->getDateCreated(), $user));
|
|
|
|
|
2013-10-19 21:08:06 +02:00
|
|
|
|
|
|
|
$finfo = id(new PHUIPropertyListView());
|
|
|
|
$box->addPropertyList($finfo, pht('File Info'));
|
|
|
|
|
|
|
|
$finfo->addProperty(
|
2012-12-17 01:33:24 +01:00
|
|
|
pht('Size'),
|
|
|
|
phabricator_format_bytes($file->getByteSize()));
|
|
|
|
|
2013-10-19 21:08:06 +02:00
|
|
|
$finfo->addProperty(
|
2012-12-17 01:33:24 +01:00
|
|
|
pht('Mime Type'),
|
2013-01-29 20:01:47 +01:00
|
|
|
$file->getMimeType());
|
2012-12-17 01:33:24 +01:00
|
|
|
|
2013-10-19 21:08:06 +02:00
|
|
|
$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)));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$storage_properties = new PHUIPropertyListView();
|
|
|
|
$box->addPropertyList($storage_properties, pht('Storage'));
|
|
|
|
|
|
|
|
$storage_properties->addProperty(
|
2012-12-17 01:33:24 +01:00
|
|
|
pht('Engine'),
|
2013-01-29 20:01:47 +01:00
|
|
|
$file->getStorageEngine());
|
2012-12-17 01:33:24 +01:00
|
|
|
|
2013-10-19 21:08:06 +02:00
|
|
|
$storage_properties->addProperty(
|
2012-12-17 01:33:24 +01:00
|
|
|
pht('Format'),
|
2013-01-29 20:01:47 +01:00
|
|
|
$file->getStorageFormat());
|
2012-12-17 01:33:24 +01:00
|
|
|
|
2013-10-19 21:08:06 +02:00
|
|
|
$storage_properties->addProperty(
|
2012-12-17 01:33:24 +01:00
|
|
|
pht('Handle'),
|
2013-01-29 20:01:47 +01:00
|
|
|
$file->getStorageHandle());
|
2012-12-17 01:33:24 +01:00
|
|
|
|
2013-01-07 18:43:35 +01:00
|
|
|
|
2013-10-01 17:43:34 +02:00
|
|
|
$phids = $file->getObjectPHIDs();
|
|
|
|
if ($phids) {
|
2013-10-11 16:53:56 +02:00
|
|
|
$attached = new PHUIPropertyListView();
|
2013-10-19 21:08:06 +02:00
|
|
|
$box->addPropertyList($attached, pht('Attached'));
|
|
|
|
|
2013-10-11 16:53:56 +02:00
|
|
|
$attached->addProperty(
|
2013-10-01 17:43:34 +02:00
|
|
|
pht('Attached To'),
|
|
|
|
$this->renderHandlesForPHIDs($phids));
|
|
|
|
}
|
|
|
|
|
2012-12-17 01:33:24 +01:00
|
|
|
|
2013-10-19 21:08:06 +02:00
|
|
|
if ($file->isViewableImage()) {
|
2013-01-18 03:39:02 +01:00
|
|
|
$image = phutil_tag(
|
2012-12-17 01:33:24 +01:00
|
|
|
'img',
|
2012-01-16 15:54:08 +01:00
|
|
|
array(
|
2012-12-17 01:33:24 +01:00
|
|
|
'src' => $file->getViewURI(),
|
2013-10-11 16:53:56 +02:00
|
|
|
'class' => 'phui-property-list-image',
|
2012-01-16 15:54:08 +01:00
|
|
|
));
|
|
|
|
|
2013-01-18 09:32:58 +01:00
|
|
|
$linked_image = phutil_tag(
|
2012-12-17 01:33:24 +01:00
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => $file->getViewURI(),
|
|
|
|
),
|
|
|
|
$image);
|
|
|
|
|
2013-10-11 16:53:56 +02:00
|
|
|
$media = id(new PHUIPropertyListView())
|
|
|
|
->addImageContent($linked_image);
|
2013-10-19 21:08:06 +02:00
|
|
|
|
|
|
|
$box->addPropertyList($media);
|
2013-09-27 19:51:25 +02:00
|
|
|
} else if ($file->isAudio()) {
|
|
|
|
$audio = phutil_tag(
|
|
|
|
'audio',
|
|
|
|
array(
|
|
|
|
'controls' => 'controls',
|
2013-10-11 16:53:56 +02:00
|
|
|
'class' => 'phui-property-list-audio',
|
2013-09-27 19:51:25 +02:00
|
|
|
),
|
|
|
|
phutil_tag(
|
|
|
|
'source',
|
|
|
|
array(
|
|
|
|
'src' => $file->getViewURI(),
|
|
|
|
'type' => $file->getMimeType(),
|
|
|
|
)));
|
2013-10-11 16:53:56 +02:00
|
|
|
$media = id(new PHUIPropertyListView())
|
|
|
|
->addImageContent($audio);
|
2011-05-22 23:40:51 +02:00
|
|
|
|
2013-10-19 21:08:06 +02:00
|
|
|
$box->addPropertyList($media);
|
|
|
|
}
|
2011-01-23 03:33:00 +01:00
|
|
|
}
|
2012-12-17 01:33:24 +01:00
|
|
|
|
2011-01-23 03:33:00 +01:00
|
|
|
}
|