/**
  * @NoAdminRequired
  * @NoCSRFRequired
  */
 public function getAddressBook()
 {
     $params = $this->request->urlParams;
     $addressBook = $this->app->getAddressBook($params['backend'], $params['addressBookId']);
     $lastModified = $addressBook->lastModified();
     $etag = null;
     $response = new JSONResponse();
     if (!is_null($lastModified)) {
         //$response->addHeader('Cache-Control', 'private, must-revalidate');
         $response->setLastModified(\DateTime::createFromFormat('U', $lastModified) ?: null);
         $etag = md5($lastModified);
         $response->setETag($etag);
     }
     //$response->debug('comparing: "' . $etag . '" to ' . $this->request->getHeader('If-None-Match'));
     if (!is_null($etag) && $this->request->getHeader('If-None-Match') === '"' . $etag . '"') {
         return $response->setStatus(Http::STATUS_NOT_MODIFIED);
     } else {
         $contacts = array();
         foreach ($addressBook->getChildren() as $i => $contact) {
             $result = JSONSerializer::serializeContact($contact);
             if ($result !== null) {
                 $contacts[] = $result;
             }
         }
         return $response->setData(array('contacts' => $contacts));
     }
 }
 /**
  * @NoAdminRequired
  * @NoCSRFRequired
  */
 public function backendStatus()
 {
     $response = new JSONResponse();
     $params = $this->request->urlParams;
     $backend = $params['backend'];
     $enabled = \OCP\Config::getAppValue('contacts', 'backend_' . $backend, "false");
     return $response->setData($enabled);
 }
 /**
  * Get a photo from the oC and crops it with the suplied geometry.
  * @NoAdminRequired
  * @NoCSRFRequired
  */
 public function cropPhoto()
 {
     $params = $this->request->urlParams;
     $x = isset($this->request->post['x']) && $this->request->post['x'] ? $this->request->post['x'] : 0;
     $y = isset($this->request->post['y']) && $this->request->post['y'] ? $this->request->post['y'] : 0;
     $w = isset($this->request->post['w']) && $this->request->post['w'] ? $this->request->post['w'] : -1;
     $h = isset($this->request->post['h']) && $this->request->post['h'] ? $this->request->post['h'] : -1;
     $tmpkey = $params['key'];
     $maxSize = isset($this->request->post['maxSize']) ? $this->request->post['maxSize'] : 200;
     $app = new App($this->api->getUserId());
     $addressBook = $app->getAddressBook($params['backend'], $params['addressBookId']);
     $contact = $addressBook->getChild($params['contactId']);
     $response = new JSONResponse();
     if (!$contact) {
         return $response->bailOut(App::$l10n->t('Couldn\'t find contact.'));
     }
     $data = $this->server->getCache()->get($tmpkey);
     if (!$data) {
         return $response->bailOut(App::$l10n->t('Image has been removed from cache'));
     }
     $image = new \OCP\Image();
     if (!$image->loadFromData($data)) {
         return $response->bailOut(App::$l10n->t('Error creating temporary image'));
     }
     $w = $w !== -1 ? $w : $image->width();
     $h = $h !== -1 ? $h : $image->height();
     if (!$image->crop($x, $y, $w, $h)) {
         return $response->bailOut(App::$l10n->t('Error cropping image'));
     }
     if ($image->width() < $maxSize || $image->height() < $maxSize) {
         if (!$image->resize(200)) {
             return $response->bailOut(App::$l10n->t('Error resizing image'));
         }
     }
     // For vCard 3.0 the type must be e.g. JPEG or PNG
     // For version 4.0 the full mimetype should be used.
     // https://tools.ietf.org/html/rfc2426#section-3.1.4
     if (strval($contact->VERSION) === '4.0') {
         $type = $image->mimeType();
     } else {
         $type = explode('/', $image->mimeType());
         $type = strtoupper(array_pop($type));
     }
     if (isset($contact->PHOTO)) {
         $property = $contact->PHOTO;
         if (!$property) {
             $this->server->getCache()->remove($tmpkey);
             return $response->bailOut(App::$l10n->t('Error getting PHOTO property.'));
         }
         $property->setValue(strval($image));
         $property->parameters = array();
         $property->parameters[] = new \Sabre\VObject\Parameter('ENCODING', 'b');
         $property->parameters[] = new \Sabre\VObject\Parameter('TYPE', $image->mimeType());
         $contact->PHOTO = $property;
     } else {
         $contact->add('PHOTO', strval($image), array('ENCODING' => 'b', 'TYPE' => $type));
         // TODO: Fix this hack
         $contact->setSaved(false);
     }
     if (!$contact->save()) {
         return $response->bailOut(App::$l10n->t('Error saving contact.'));
     }
     $thumbnail = Properties::cacheThumbnail($params['backend'], $params['addressBookId'], $params['contactId'], $image);
     $response->setData(array('status' => 'success', 'data' => array('id' => $params['contactId'], 'thumbnail' => $thumbnail)));
     $this->server->getCache()->remove($tmpkey);
     return $response;
 }
 /**
  * @NoAdminRequired
  * @NoCSRFRequired
  */
 public function getContacts()
 {
     $params = $this->request->urlParams;
     $addressBook = $this->app->getAddressBook($params['backend'], $params['addressBookId']);
     $lastModified = $addressBook->lastModified();
     $etag = null;
     $response = new JSONResponse();
     if (!is_null($lastModified)) {
         //$response->addHeader('Cache-Control', 'private, must-revalidate');
         $response->setLastModified(\DateTime::createFromFormat('U', $lastModified) ?: null);
         $etag = md5($lastModified);
         $response->setETag($etag);
     }
     if (!is_null($etag) && $this->request->getHeader('If-None-Match') === '"' . $etag . '"') {
         return $response->setStatus(Http::STATUS_NOT_MODIFIED);
     } else {
         switch ($this->request->method) {
             case 'OPTIONS':
                 $options = array('GET', 'HEAD', 'OPTIONS');
                 if ($addressBook->hasPermission(\OCP\PERMISSION_DELETE) && $addressBook->getBackend()->hasAddressBookMethodFor(\OCP\PERMISSION_DELETE)) {
                     $options[] = 'DELETE';
                 }
                 if ($addressBook->hasPermission(\OCP\PERMISSION_UPDATE) && $addressBook->getBackend()->hasAddressBookMethodFor(\OCP\PERMISSION_UPDATE)) {
                     $options[] = 'POST';
                 }
                 $response->addHeader('Allow', implode(',', $options));
                 return $response;
             case 'HEAD':
                 return $response;
             case 'GET':
                 $contacts = array();
                 foreach ($addressBook->getChildren() as $i => $contact) {
                     $result = JSONSerializer::serializeContact($contact);
                     if ($result !== null) {
                         $contacts[] = $result;
                     }
                 }
                 return $response->setData(array('contacts' => $contacts));
         }
     }
 }
 /**
  * @NoAdminRequired
  */
 public function patch()
 {
     $params = $this->request->urlParams;
     $patch = $this->request->patch;
     $response = new JSONResponse();
     $name = $patch['name'];
     $value = $patch['value'];
     $checksum = isset($patch['checksum']) ? $patch['checksum'] : null;
     $parameters = isset($patch['parameters']) ? $patch['parameters'] : null;
     $addressBook = $this->app->getAddressBook($params['backend'], $params['addressBookId']);
     $contact = $addressBook->getChild($params['contactId']);
     if (!$contact) {
         return $response->setStatus(Http::STATUS_NOT_FOUND)->bailOut(App::$l10n->t('Couldn\'t find contact.'));
     }
     if (!$name) {
         return $response->setStatus(Http::STATUS_PRECONDITION_FAILED)->bailOut(App::$l10n->t('Property name is not set.'));
     }
     if (!$checksum && in_array($name, Properties::$multi_properties)) {
         return $response->setStatus(Http::STATUS_PRECONDITION_FAILED)->bailOut(App::$l10n->t('Property checksum is not set.'));
     }
     if (is_array($value)) {
         // NOTE: Important, otherwise the compound value will be
         // set in the order the fields appear in the form!
         ksort($value);
     }
     $result = array('contactId' => $params['contactId']);
     if ($checksum && in_array($name, Properties::$multi_properties)) {
         try {
             if (is_null($value)) {
                 $contact->unsetPropertyByChecksum($checksum);
             } else {
                 $checksum = $contact->setPropertyByChecksum($checksum, $name, $value, $parameters);
                 $result['checksum'] = $checksum;
             }
         } catch (Exception $e) {
             return $response->setStatus(Http::STATUS_PRECONDITION_FAILED)->bailOut(App::$l10n->t('Information about vCard is incorrect. Please reload the page.'));
         }
     } elseif (!in_array($name, Properties::$multi_properties)) {
         if (is_null($value)) {
             unset($contact->{$name});
         } else {
             if (!$contact->setPropertyByName($name, $value, $parameters)) {
                 return $response->setStatus(Http::STATUS_INTERNAL_SERVER_ERROR)->bailOut(App::$l10n->t('Error updating contact'));
             }
         }
     }
     if (!$contact->save()) {
         return $response->bailOut(App::$l10n->t('Error saving contact to backend'));
     }
     $result['lastmodified'] = $contact->lastModified();
     return $response->setData($result);
 }
 /**
  * Saves the photo from ownCloud FS to oC cache
  * @return JSONResponse with data.tmp set to the key in the cache.
  *
  * @NoAdminRequired
  * @NoCSRFRequired
  */
 public function cacheFileSystemPhoto()
 {
     $params = $this->request->urlParams;
     $response = new JSONResponse();
     if (!isset($this->request->get['path'])) {
         $response->bailOut(App::$l10n->t('No photo path was submitted.'));
     }
     $localpath = \OC\Files\Filesystem::getLocalFile($this->request->get['path']);
     $tmpkey = 'contact-photo-' . $params['contactId'];
     if (!file_exists($localpath)) {
         return $response->bailOut(App::$l10n->t('File doesn\'t exist:') . $localpath);
     }
     $image = new \OCP\Image();
     if (!$image) {
         return $response->bailOut(App::$l10n->t('Error loading image.'));
     }
     if (!$image->loadFromFile($localpath)) {
         return $response->bailOut(App::$l10n->t('Error loading image.'));
     }
     if ($image->width() > 400 || $image->height() > 400) {
         $image->resize(400);
         // Prettier resizing than with browser and saves bandwidth.
     }
     if (!$image->fixOrientation()) {
         // No fatal error so we don't bail out.
         $response->debug('Couldn\'t save correct image orientation: ' . $localpath);
     }
     if (!$this->server->getCache()->set($tmpkey, $image->data(), 600)) {
         return $response->bailOut('Couldn\'t save temporary image: ' . $tmpkey);
     }
     return $response->setData(array('tmp' => $tmpkey, 'metadata' => array('contactId' => $params['contactId'], 'addressBookId' => $params['addressBookId'], 'backend' => $params['backend'])));
 }
 /**
  * Get a photo from the oC and crops it with the suplied geometry.
  * @NoAdminRequired
  * @NoCSRFRequired
  */
 public function cropPhoto()
 {
     $params = $this->request->urlParams;
     $x = $this->params('x', 0);
     $y = $this->params('y', 0);
     $w = $this->params('w', -1);
     $h = $this->params('h', -1);
     $tmpkey = $params['key'];
     $addressBook = $this->app->getAddressBook($params['backend'], $params['addressBookId']);
     $contact = $addressBook->getChild($params['contactId']);
     $response = new JSONResponse();
     $tmpPhoto = new TemporaryPhoto($this->cache, $tmpkey);
     $image = $tmpPhoto->getPhoto();
     if (!$image || !$image->valid()) {
         return $response->bailOut(App::$l10n->t('Error loading image from cache'));
     }
     $w = $w !== -1 ? $w : $image->width();
     $h = $h !== -1 ? $h : $image->height();
     $image->crop($x, $y, $w, $h);
     if (!$contact->setPhoto($image)) {
         $tmpPhoto->remove($tmpkey);
         return $response->bailOut(App::$l10n->t('Error getting PHOTO property.'));
     }
     if (!$contact->save()) {
         return $response->bailOut(App::$l10n->t('Error saving contact.'));
     }
     $thumbnail = Properties::cacheThumbnail($params['backend'], $params['addressBookId'], $params['contactId'], $image, $contact);
     $response->setData(array('status' => 'success', 'data' => array('id' => $params['contactId'], 'thumbnail' => $thumbnail)));
     $tmpPhoto->remove($tmpkey);
     return $response;
 }