X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=actions%2Fapimediaupload.php;h=38b3a6f4feae569363fbc9d0d67b3e11d86b505f;hb=09412ac813f4c14cd7969efcc8d9a8c103d34cc6;hp=ec316edc8d78b1c50d5573db9a10bad8ac9707d0;hpb=e89908f26140c217e01b2f8f755712f38f3935f3;p=quix0rs-gnu-social.git diff --git a/actions/apimediaupload.php b/actions/apimediaupload.php index ec316edc8d..38b3a6f4fe 100644 --- a/actions/apimediaupload.php +++ b/actions/apimediaupload.php @@ -26,16 +26,11 @@ * @link http://status.net/ */ -if (!defined('STATUSNET')) { - exit(1); -} - -require_once INSTALLDIR . '/lib/apiauth.php'; -require_once INSTALLDIR . '/lib/mediafile.php'; +if (!defined('GNUSOCIAL')) { exit(1); } /** * Upload an image via the API. Returns a shortened URL for the image - * to the user. + * to the user. Apparently modelled after a former Twitpic API. * * @category API * @package StatusNet @@ -43,32 +38,27 @@ require_once INSTALLDIR . '/lib/mediafile.php'; * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ */ - class ApiMediaUploadAction extends ApiAuthAction { - /** - * Handle the request - * - * Grab the file from the 'media' param, then store, and shorten - * - * @todo Upload throttle! - * - * @param array $args $_REQUEST data (unused) - * - * @return void - */ + protected $needPost = true; - function handle($args) + protected function prepare(array $args=array()) { - parent::handle($args); - - if ($_SERVER['REQUEST_METHOD'] != 'POST') { - $this->clientError( - _('This method requires a POST.'), - 400, $this->format - ); - return; + parent::prepare($args); + + // fallback to xml for older clients etc + if (empty($this->format)) { + $this->format = 'xml'; } + if (!in_array($this->format, ['json', 'xml'])) { + throw new ClientException('This API call does not support the format '._ve($this->format)); + } + return true; + } + + protected function handle() + { + parent::handle(); // Workaround for PHP returning empty $_POST and $_FILES when POST // length > post_max_size in php.ini @@ -77,65 +67,129 @@ class ApiMediaUploadAction extends ApiAuthAction && empty($_POST) && ($_SERVER['CONTENT_LENGTH'] > 0) ) { - $msg = _('The server was unable to handle that much POST ' . - 'data (%s bytes) due to its current configuration.'); - - $this->clientError(sprintf($msg, $_SERVER['CONTENT_LENGTH'])); - return; + // TRANS: Client error displayed when the number of bytes in a POST request exceeds a limit. + // TRANS: %s is the number of bytes of the CONTENT_LENGTH. + $msg = _m('The server was unable to handle that much POST data (%s byte) due to its current configuration.', + 'The server was unable to handle that much POST data (%s bytes) due to its current configuration.', + intval($_SERVER['CONTENT_LENGTH'])); + throw new ClientException(sprintf($msg, $_SERVER['CONTENT_LENGTH'])); } - $upload = null; - try { - $upload = MediaFile::fromUpload('media', $this->auth_user); - } catch (ClientException $ce) { - $this->clientError($ce->getMessage()); - return; - } - - if (isset($upload)) { - $this->showResponse($upload); - } else { - $this->clientError('Upload failed.'); - return; + $upload = MediaFile::fromUpload('media', $this->scoped); + } catch (NoUploadedMediaException $e) { + common_debug('No media file was uploaded to the _FILES array'); + $fh = tmpfile(); + if ($this->arg('media')) { + common_debug('Found media parameter which we hope contains a media file!'); + fwrite($fh, $this->arg('media')); + } elseif ($this->arg('media_data')) { + common_debug('Found media_data parameter which we hope contains a base64-encoded media file!'); + fwrite($fh, base64_decode($this->arg('media_data'))); + } else { + common_debug('No media|media_data POST parameter was supplied'); + fclose($fh); + throw $e; + } + common_debug('MediaFile importing the uploaded file with fromFilehandle'); + $upload = MediaFile::fromFilehandle($fh, $this->scoped); } + + common_debug('MediaFile completed and saved us fileRecord with id=='._ve($upload->fileRecord->id)); + // Thumbnails will be generated/cached on demand when accessed (such as with /attachment/:id/thumbnail) + $this->showResponse($upload); } /** * Show a Twitpic-like response with the ID of the media file * and a (hopefully) shortened URL for it. * - * @param File $upload the uploaded file + * @param MediaFile $upload the uploaded file * * @return void */ - function showResponse($upload) + protected function showResponse(MediaFile $upload) { - $this->initDocument(); - $this->elementStart('rsp', array('stat' => 'ok')); + $this->initDocument($this->format); + switch ($this->format) { + case 'json': + return $this->showResponseJson($upload); + case 'xml': + return $this->showResponseXml($upload); + default: + throw new ClientException('This API call does not support the format '._ve($this->format)); + } + $this->endDocument($this->format); + } + + protected function showResponseJson(MediaFile $upload) + { + $enc = $upload->fileRecord->getEnclosure(); + + // note that we use media_id instead of mediaid which XML users might've gotten used to (nowadays we service media_id in both!) + $output = [ + 'media_id' => $upload->fileRecord->id, + 'media_id_string' => (string)$upload->fileRecord->id, + 'media_url' => $upload->shortUrl(), + 'size' => $upload->fileRecord->size, + ]; + if (common_get_mime_media($enc->mimetype) === 'image') { + $output['image'] = [ + 'w' => $enc->width, + 'h' => $enc->height, + 'image_type' => $enc->mimetype, + ]; + } + print json_encode($output); + } + + protected function showResponseXml(MediaFile $upload) + { + $this->elementStart('rsp', array('stat' => 'ok', 'xmlns:atom'=>Activity::ATOM)); $this->element('mediaid', null, $upload->fileRecord->id); $this->element('mediaurl', null, $upload->shortUrl()); + $this->element('media_url', null, $upload->shortUrl()); + $this->element('size', null, $upload->fileRecord->size); + + $enclosure = $upload->fileRecord->getEnclosure(); + $this->element('atom:link', array('rel' => 'enclosure', + 'href' => $enclosure->url, + 'type' => $enclosure->mimetype)); + + // Twitter specific metadata expected in response since Twitter's Media upload API v1.1 (even though Twitter doesn't use XML) + $this->element('media_id', null, $upload->fileRecord->id); + $this->element('media_id_string', null, (string)$upload->fileRecord->id); + if (common_get_mime_media($enclosure->mimetype) === 'image') { + $this->element('image', ['w'=>$enclosure->width, 'h'=>$enclosure->height, 'image_type'=>$enclosure->mimetype]); + } $this->elementEnd('rsp'); - $this->endDocument(); } /** * Overrided clientError to show a more Twitpic-like error * * @param String $msg an error message - * */ - function clientError($msg) + function clientError($msg, $code=400, $format=null) { - $this->initDocument(); - $this->elementStart('rsp', array('stat' => 'fail')); - - // @todo add in error code - $errAttr = array('msg' => $msg); - - $this->element('err', $errAttr, null); - $this->elementEnd('rsp'); - $this->endDocument(); + $this->initDocument($this->format); + switch ($this->format) { + case 'json': + $error = ['errors' => array()]; + $error['errors'][] = ['message'=>$msg, 'code'=>131]; + print json_encode($error); + break; + case 'xml': + $this->elementStart('rsp', array('stat' => 'fail')); + + // @todo add in error code + $errAttr = array('msg' => $msg); + + $this->element('err', $errAttr, null); + $this->elementEnd('rsp'); + break; + } + $this->endDocument($this->format); + exit; } - }