Details
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?