Page MenuHomePhorge

Extension: how to use PhabricatorFile::newFromFileData()
Closed, ResolvedPublic

Asked by mturdus on Jun 11 2023, 10:05.
Tags
Referenced Files
None
Tokens
"Yellow Medal" token, awarded by 20after4."Mountain of Wealth" token, awarded by valerio.bozzolan.

Details

I'm trying to write an extension which can create file objects (e.g. F123).

I have the following code:

extensions/example/src/application/Example.php
<?php
final class Example extends PhabricatorApplication {
	public function getName() {
		return pht('My Example');
	}
	public function getBaseURI() {
		return '/example/';
	}
	public function getIcon() {
		return 'fa-star';
	}
	public function getShortDescription() {
		return pht('Example extension');
	}
	public function getTitleGlyph() {
		return '\xE2\x98\x85';
	}
	public function getApplicationGroup() {
		return self::GROUP_UTILITIES;
	}
	public function getRoutes() {
		return array(
			'/example/' => array(
				'.*' => 'exampleController'
			)
		);
	}
}
extensions/example/src/controller/ExampleController.php
<?php
final class ExampleController extends PhabricatorController {
  public function handleRequest(AphrontRequest $request) {
    $request = $this->getRequest();
    $viewer = $request->getViewer();
    $user = $request->getUser();
    $viewer_spaces = PhabricatorSpacesNamespaceQuery::getViewerSpaces($user);

    $base64_data = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==');

    // Set the options for the new file
    $options = array(
      'name' => 'my_image.png',
      'viewPolicy' => PhabricatorPolicies::POLICY_USER,
      'mime-type' => 'image/png',
    );

    // Create the new file object
    $file = PhabricatorFile::newFromFileData($base64_data, $options);

    $response = new AphrontFileResponse();
    $response->setCacheDurationInSeconds(60*60*24*30);
    $response->setContent($base64_data);
    $response->setMimeType('image/png');
    return $response;
  }
}

I would have expected that the newFromFileData call in the controller would create a file object, but I'm getting the following crash:

[Sun Jun 11 11:19:55.205192 2023] [php:notice] [::1:45810] [2023-06-11 09:19:55] EXCEPTION: (RuntimeException) strncmp(): Passing null to parameter #1 ($string1) of type string is deprecated at [<arcanist>/src/error/PhutilErrorHandler.php:261]
[Sun Jun 11 11:19:55.205432 2023] [php:notice] [::1:45810] arcanist(head=master, ref.master=b325304b6e52), diagramsnet(), example(), phorge(head=master, ref.master=7b57ba2b982f, custom=1)
[Sun Jun 11 11:19:55.205438 2023] [php:notice] [::1:45810]   #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer) called at [<arcanist>/src/error/PhutilErrorHandler.php:261]
[Sun Jun 11 11:19:55.205441 2023] [php:notice] [::1:45810]   #1 <#2> strncmp(NULL, string, integer) called at [<phorge>/src/applications/auth/engine/PhabricatorAuthCSRFEngine.php:50]
[Sun Jun 11 11:19:55.205443 2023] [php:notice] [::1:45810]   #2 <#2> PhabricatorAuthCSRFEngine::isValidToken(NULL) called at [<phorge>/src/applications/people/storage/PhabricatorUser.php:985]
[Sun Jun 11 11:19:55.205445 2023] [php:notice] [::1:45810]   #3 <#2> PhabricatorUser::validateCSRFToken(NULL) called at [<phorge>/src/aphront/AphrontRequest.php:348]
[Sun Jun 11 11:19:55.205447 2023] [php:notice] [::1:45810]   #4 <#2> AphrontRequest::validateCSRF() called at [<phorge>/src/aphront/writeguard/AphrontWriteGuard.php:167]
[Sun Jun 11 11:19:55.205449 2023] [php:notice] [::1:45810]   #5 <#2> AphrontWriteGuard::willWrite() called at [<phorge>/src/infrastructure/storage/connection/mysql/AphrontBaseMySQLDatabaseConnection.php:305]
[Sun Jun 11 11:19:55.205451 2023] [php:notice] [::1:45810]   #6 <#2> AphrontBaseMySQLDatabaseConnection::checkWrite(string) called at [<phorge>/src/infrastructure/storage/connection/mysql/AphrontBaseMySQLDatabaseConnection.php:193]
[Sun Jun 11 11:19:55.205462 2023] [php:notice] [::1:45810]   #7 <#2> AphrontBaseMySQLDatabaseConnection::executeQuery(PhutilQueryString) called at [<phorge>/src/infrastructure/storage/xsprintf/queryfx.php:8]
[Sun Jun 11 11:19:55.205465 2023] [php:notice] [::1:45810]   #8 <#2> queryfx(AphrontMySQLiDatabaseConnection, string, PhutilQueryString, PhabricatorFileStorageBlob, array, array) called at [<phorge>/src/infrastructure/storage/connection/AphrontDatabaseConnection.php:58]
[Sun Jun 11 11:19:55.205467 2023] [php:notice] [::1:45810]   #9 <#2> AphrontDatabaseConnection::query(string, PhutilQueryString, PhabricatorFileStorageBlob, array, array) called at [<phorge>/src/infrastructure/storage/lisk/LiskDAO.php:1117]
[Sun Jun 11 11:19:55.205469 2023] [php:notice] [::1:45810]   #10 <#2> LiskDAO::insertRecordIntoDatabase(string) called at [<phorge>/src/infrastructure/storage/lisk/LiskDAO.php:954]
[Sun Jun 11 11:19:55.205471 2023] [php:notice] [::1:45810]   #11 <#2> LiskDAO::insert() called at [<phorge>/src/infrastructure/storage/lisk/LiskDAO.php:923]
[Sun Jun 11 11:19:55.205473 2023] [php:notice] [::1:45810]   #12 <#2> LiskDAO::save() called at [<phorge>/src/applications/files/engine/PhabricatorMySQLFileStorageEngine.php:55]
[Sun Jun 11 11:19:55.205475 2023] [php:notice] [::1:45810]   #13 <#2> PhabricatorMySQLFileStorageEngine::writeFile(string, array) called at [<phorge>/src/applications/files/storage/PhabricatorFile.php:553]
[Sun Jun 11 11:19:55.205478 2023] [php:notice] [::1:45810]   #14 <#2> PhabricatorFile::writeToEngine(PhabricatorMySQLFileStorageEngine, string, array) called at [<phorge>/src/applications/files/storage/PhabricatorFile.php:380]
[Sun Jun 11 11:19:55.205480 2023] [php:notice] [::1:45810]   #15 phlog(RuntimeException) called at [<phorge>/src/applications/files/storage/PhabricatorFile.php:395]
[Sun Jun 11 11:19:55.205482 2023] [php:notice] [::1:45810]   #16 PhabricatorFile::buildFromFileData(string, array) called at [<phorge>/src/applications/files/storage/PhabricatorFile.php:449]
[Sun Jun 11 11:19:55.205484 2023] [php:notice] [::1:45810]   #17 PhabricatorFile::newFromFileData(string, array) called at [<phorge>/src/extensions/example/src/controller/ExampleController.php:18]
[Sun Jun 11 11:19:55.205486 2023] [php:notice] [::1:45810]   #18 ExampleController::handleRequest(AphrontRequest) called at [<phorge>/src/aphront/configuration/AphrontApplicationConfiguration.php:284]
[Sun Jun 11 11:19:55.205488 2023] [php:notice] [::1:45810]   #19 AphrontApplicationConfiguration::processRequest(AphrontRequest, PhutilDeferredLog, AphrontPHPHTTPSink, MultimeterControl) called at [<phorge>/src/aphront/configuration/AphrontApplicationConfiguration.php:203]
[Sun Jun 11 11:19:55.205490 2023] [php:notice] [::1:45810]   #20 AphrontApplicationConfiguration::runHTTPRequest(AphrontPHPHTTPSink) called at [<phorge>/webroot/index.php:35]

It seems that I need to generate or renew some kind of a CSRF token before I can execute newFromFileData.
But when I look at the first lines of the handleRequest method from PhabricatorFileDropUploadController, there is no such CSRF code and the copy/paste of an image in a remarkup editor just works:

phorge/src/applications/files/controller/PhabricatorFileDropUploadController.php
public function handleRequest(AphrontRequest $request) {
  $viewer = $request->getViewer();

  // NOTE: Throws if valid CSRF token is not present in the request.
  $request->validateCSRF();

I already looked for extensions on github but I can't find anything.

How can I create file objects in an extension?

New Answer

Answer

This question has been marked as closed, but you can still leave a new answer.