shell bypass 403
<?php namespace Srmklive\Dropbox; trait UploadContent { /** * The file should be uploaded in chunks if it size exceeds the 150 MB threshold * or if the resource size could not be determined (eg. a popen() stream). * * @param string|resource $contents * * @return bool */ protected function shouldUploadChunk($contents) { $size = is_string($contents) ? strlen($contents) : fstat($contents)['size']; return ($this->isPipe($contents) || ($size === null)) ? true : ($size > $this->maxChunkSize); } /** * Check if the contents is a pipe stream (not seekable, no size defined). * * @param string|resource $contents * * @return bool */ protected function isPipe($contents) { return is_resource($contents) ? (fstat($contents)['mode'] & 010000) != 0 : false; } /** * Upload file split in chunks. This allows uploading large files, since * Dropbox API v2 limits the content size to 150MB. * * The chunk size will affect directly the memory usage, so be careful. * Large chunks tends to speed up the upload, while smaller optimizes memory usage. * * @param string $path * @param string|resource $contents * @param string $mode * @param int $chunkSize * * @throws \Exception * * @return array */ public function uploadChunk($path, $contents, $mode = 'add', $chunkSize = null) { $chunkSize = empty($chunkSize) ? static::MAX_CHUNK_SIZE : $chunkSize; $stream = $contents; // This method relies on resources, so we need to convert strings to resource if (is_string($contents)) { $stream = fopen('php://memory', 'r+'); fwrite($stream, $contents); rewind($stream); } $data = self::readChunk($stream, $chunkSize); $cursor = null; while (!((strlen($data) < $chunkSize) || feof($stream))) { // Start upload session on first iteration, then just append on subsequent iterations $cursor = isset($cursor) ? $this->appendContentToUploadSession($data, $cursor) : $this->startUploadSession($data); $data = self::readChunk($stream, $chunkSize); } // If there's no cursor here, our stream is small enough to a single request if (!isset($cursor)) { $cursor = $this->startUploadSession($data); $data = ''; } return $this->finishUploadSession($data, $cursor, $path, $mode); } /** * Upload sessions allow you to upload a single file in one or more requests, * for example where the size of the file is greater than 150 MB. * This call starts a new upload session with the given data. * * @link https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-start * * @param string $contents * @param bool $close * * @return \Srmklive\Dropbox\DropboxUploadCounter */ public function startUploadSession($contents, $close = false) { $this->setupRequest( compact('close') ); $this->apiEndpoint = 'files/upload_session/start'; $this->content = $contents; $response = json_decode( $this->doDropboxApiContentRequest()->getBody(), true ); return new DropboxUploadCounter($response['session_id'], strlen($contents)); } /** * Append more data to an upload session. * When the parameter close is set, this call will close the session. * A single request should not upload more than 150 MB. * * @link https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-append_v2 * * @param string $contents * @param DropboxUploadCounter $cursor * @param bool $close * * @return \Srmklive\Dropbox\DropboxUploadCounter */ public function appendContentToUploadSession($contents, DropboxUploadCounter $cursor, $close = false) { $this->setupRequest(compact('cursor', 'close')); $this->apiEndpoint = 'files/upload_session/append_v2'; $this->content = $contents; $this->doDropboxApiContentRequest()->getBody(); $cursor->offset += strlen($contents); return $cursor; } /** * Finish an upload session and save the uploaded data to the given file path. * A single request should not upload more than 150 MB. * * @link https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-finish * * @param string $contents * @param \Srmklive\Dropbox\DropboxUploadCounter $cursor * @param string $path * @param string|array $mode * @param bool $autorename * @param bool $mute * * @return array */ public function finishUploadSession($contents, DropboxUploadCounter $cursor, $path, $mode = 'add', $autorename = false, $mute = false) { $arguments = compact('cursor'); $arguments['commit'] = compact('path', 'mode', 'autorename', 'mute'); $this->setupRequest($arguments); $this->apiEndpoint = 'files/upload_session/finish'; $this->content = $contents; $response = $this->doDropboxApiContentRequest(); $metadata = json_decode($response->getBody(), true); $metadata['.tag'] = 'file'; return $metadata; } /** * Sometimes fread() returns less than the request number of bytes (for example, when reading * from network streams). This function repeatedly calls fread until the requested number of * bytes have been read or we've reached EOF. * * @param resource $stream * @param int $chunkSize * * @throws \Exception * * @return string */ protected static function readChunk($stream, $chunkSize) { $chunk = ''; while (!feof($stream) && $chunkSize > 0) { $part = fread($stream, $chunkSize); if ($part === false) { throw new \Exception('Error reading from $stream.'); } $chunk .= $part; $chunkSize -= strlen($part); } return $chunk; } }