Example #1
0
 /**
  * HTTP REPORT method implementation
  *
  * Although the REPORT method is not part of the standard WebDAV spec (it's from rfc3253)
  * It's used in a lot of extensions, so it made sense to implement it into the core.
  *
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return bool
  */
 function httpReport(RequestInterface $request, ResponseInterface $response)
 {
     $path = $request->getPath();
     $result = $this->server->xml->parse($request->getBody(), $request->getUrl(), $rootElementName);
     if ($this->server->emit('report', [$rootElementName, $result, $path])) {
         // If emit returned true, it means the report was not supported
         throw new Exception\ReportNotSupported();
     }
     // Sending back false will interupt the event chain and tell the server
     // we've handled this method.
     return false;
 }
Example #2
0
 /**
  * Turns a RequestInterface object into an array with settings that can be
  * fed to curl_setopt
  *
  * @param RequestInterface $request
  * @return array
  */
 protected function createCurlSettingsArray(RequestInterface $request)
 {
     $settings = $this->curlSettings;
     switch ($request->getMethod()) {
         case 'HEAD':
             $settings[CURLOPT_NOBODY] = true;
             $settings[CURLOPT_CUSTOMREQUEST] = 'HEAD';
             $settings[CURLOPT_POSTFIELDS] = '';
             $settings[CURLOPT_PUT] = false;
             break;
         case 'GET':
             $settings[CURLOPT_CUSTOMREQUEST] = 'GET';
             $settings[CURLOPT_POSTFIELDS] = '';
             $settings[CURLOPT_PUT] = false;
             break;
         default:
             $body = $request->getBody();
             if (is_resource($body)) {
                 // This needs to be set to PUT, regardless of the actual
                 // method used. Without it, INFILE will be ignored for some
                 // reason.
                 $settings[CURLOPT_PUT] = true;
                 $settings[CURLOPT_INFILE] = $request->getBody();
             } else {
                 // For security we cast this to a string. If somehow an array could
                 // be passed here, it would be possible for an attacker to use @ to
                 // post local files.
                 $settings[CURLOPT_POSTFIELDS] = (string) $body;
             }
             $settings[CURLOPT_CUSTOMREQUEST] = $request->getMethod();
             break;
     }
     $nHeaders = [];
     foreach ($request->getHeaders() as $key => $values) {
         foreach ($values as $value) {
             $nHeaders[] = $key . ': ' . $value;
         }
     }
     $settings[CURLOPT_HTTPHEADER] = $nHeaders;
     $settings[CURLOPT_URL] = $request->getUrl();
     // FIXME: CURLOPT_PROTOCOLS is currently unsupported by HHVM
     if (defined('CURLOPT_PROTOCOLS')) {
         $settings[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
     }
     // FIXME: CURLOPT_REDIR_PROTOCOLS is currently unsupported by HHVM
     if (defined('CURLOPT_REDIR_PROTOCOLS')) {
         $settings[CURLOPT_REDIR_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
     }
     return $settings;
 }
Example #3
0
 /**
  * This method handles POST requests to the schedule-outbox.
  *
  * Currently, two types of requests are support:
  *   * FREEBUSY requests from RFC 6638
  *   * Simple iTIP messages from draft-desruisseaux-caldav-sched-04
  *
  * The latter is from an expired early draft of the CalDAV scheduling
  * extensions, but iCal depends on a feature from that spec, so we
  * implement it.
  *
  * @param IOutbox $outboxNode
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return void
  */
 function outboxRequest(IOutbox $outboxNode, RequestInterface $request, ResponseInterface $response)
 {
     $outboxPath = $request->getPath();
     // Parsing the request body
     try {
         $vObject = VObject\Reader::read($request->getBody());
     } catch (VObject\ParseException $e) {
         throw new BadRequest('The request body must be a valid iCalendar object. Parse error: ' . $e->getMessage());
     }
     // The incoming iCalendar object must have a METHOD property, and a
     // component. The combination of both determines what type of request
     // this is.
     $componentType = null;
     foreach ($vObject->getComponents() as $component) {
         if ($component->name !== 'VTIMEZONE') {
             $componentType = $component->name;
             break;
         }
     }
     if (is_null($componentType)) {
         throw new BadRequest('We expected at least one VTODO, VJOURNAL, VFREEBUSY or VEVENT component');
     }
     // Validating the METHOD
     $method = strtoupper((string) $vObject->METHOD);
     if (!$method) {
         throw new BadRequest('A METHOD property must be specified in iTIP messages');
     }
     // So we support one type of request:
     //
     // REQUEST with a VFREEBUSY component
     $acl = $this->server->getPlugin('acl');
     if ($componentType === 'VFREEBUSY' && $method === 'REQUEST') {
         $acl && $acl->checkPrivileges($outboxPath, '{' . self::NS_CALDAV . '}schedule-query-freebusy');
         $this->handleFreeBusyRequest($outboxNode, $vObject, $request, $response);
     } else {
         throw new NotImplemented('We only support VFREEBUSY (REQUEST) on this endpoint');
     }
 }
Example #4
0
 /**
  * We intercept this to handle POST requests on shared resources
  *
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return null|bool
  */
 function httpPost(RequestInterface $request, ResponseInterface $response)
 {
     $path = $request->getPath();
     $contentType = $request->getHeader('Content-Type');
     // We're only interested in the davsharing content type.
     if (strpos($contentType, 'application/davsharing+xml') === false) {
         return;
     }
     $message = $this->server->xml->parse($request->getBody(), $request->getUrl(), $documentType);
     switch ($documentType) {
         case '{DAV:}share-resource':
             $this->shareResource($path, $message->sharees);
             $response->setStatus(200);
             // Adding this because sending a response body may cause issues,
             // and I wanted some type of indicator the response was handled.
             $response->setHeader('X-Sabre-Status', 'everything-went-well');
             // Breaking the event chain
             return false;
         default:
             throw new BadRequest('Unexpected document type: ' . $documentType . ' for this Content-Type');
     }
 }