public function upload(stored_file $photo, array $meta = []) {

        $args = [
            'title' => isset($meta['title']) ? $meta['title'] : null,
            'description' => isset($meta['description']) ? $meta['description'] : null,
            'tags' => isset($meta['tags']) ? $meta['tags'] : null,
            'is_public' => isset($meta['is_public']) ? $meta['is_public'] : 0,
            'is_friend' => isset($meta['is_friend']) ? $meta['is_friend'] : 0,
            'is_family' => isset($meta['is_family']) ? $meta['is_family'] : 0,
            'safety_level' => isset($meta['safety_level']) ? $meta['safety_level'] : 1,
            'content_type' => isset($meta['content_type']) ? $meta['content_type'] : 1,
            'hidden' => isset($meta['hidden']) ? $meta['hidden'] : 2,
        ];

        $this->sign_secret = $this->consumer_secret.'&'.$this->access_token_secret;
        $params = $this->prepare_oauth_parameters(self::UPLOAD_ROOT, ['oauth_token' => $this->access_token] + $args, 'POST');

        $params['photo'] = $photo;

        $response = $this->http->post(self::UPLOAD_ROOT, $params);

        if ($response) {
            $xml = simplexml_load_string($response);

            if ((string)$xml['stat'] === 'ok') {
                return (int)$xml->photoid;

            } else if ((string)$xml['stat'] === 'fail' && (int)$xml->err['code'] == 98) {
                // Authentication failure.
                return false;

            } else {
                throw new moodle_exception('flickr_upload_failed', 'core_error', '',
                    ['code' => (int)$xml->err['code'], 'message' => (string)$xml->err['msg']]);
            }

        } else {
            throw new moodle_exception('flickr_upload_error', 'core_error', '', null, $response);
        }
    }