Ejemplo n.º 1
0
 protected function end()
 {
     if ($this->profile) {
         Zotero_DB::profileEnd($this->objectLibraryID, true);
     }
     switch ($this->responseCode) {
         case 200:
             // Output a Content-Type header for the given format
             //
             // Note that this overrides any Content-Type set elsewhere. To force a content
             // type elsewhere, clear $this->queryParams['format'] when calling header()
             // manually.
             //
             // TODO: Check headers_list so that clearing the format parameter manually isn't
             // necessary? Performance?
             if (isset($this->queryParams['format'])) {
                 Zotero_API::outputContentType($this->queryParams['format']);
             }
             break;
         case 301:
         case 302:
         case 303:
             // Handled in $this->redirect()
             break;
         case 401:
             header('WWW-Authenticate: Basic realm="Zotero API"');
             header('HTTP/1.1 401 Unauthorized');
             break;
             // PHP completes these automatically
         // PHP completes these automatically
         case 201:
         case 204:
         case 300:
         case 304:
         case 400:
         case 403:
         case 404:
         case 405:
         case 409:
         case 412:
         case 413:
         case 422:
         case 500:
         case 501:
         case 503:
             header("HTTP/1.1 " . $this->responseCode);
             break;
         case 428:
             header("HTTP/1.1 428 Precondition Required");
             break;
         case 429:
             header("HTTP/1.1 429 Too Many Requests");
             break;
         default:
             throw new Exception("Unsupported response code " . $this->responseCode);
     }
     if (isset($this->libraryVersion)) {
         if ($this->apiVersion >= 2) {
             header("Last-Modified-Version: " . $this->libraryVersion);
         }
         // Send notification if library has changed
         if ($this->isWriteMethod()) {
             if ($this->libraryVersion > Zotero_Libraries::getOriginalVersion($this->objectLibraryID)) {
                 Zotero_Notifier::trigger('modify', 'library', $this->objectLibraryID);
             }
         }
     }
     if ($this->responseXML instanceof SimpleXMLElement) {
         if (!$this->responseCode) {
             $updated = (string) $this->responseXML->updated;
             if ($updated) {
                 $updated = strtotime($updated);
                 $ifModifiedSince = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] : false;
                 $ifModifiedSince = strtotime($ifModifiedSince);
                 if ($ifModifiedSince >= $updated) {
                     header('HTTP/1.1 304 Not Modified');
                     exit;
                 }
                 $lastModified = substr(date('r', $updated), 0, -5) . "GMT";
                 header("Last-Modified: {$lastModified}");
             }
         }
         $xmlstr = $this->responseXML->asXML();
         // TEMP: Strip control characters
         $xmlstr = Zotero_Utilities::cleanString($xmlstr, true);
         $doc = new DOMDocument('1.0');
         $doc->loadXML($xmlstr);
         $doc->formatOutput = true;
         echo $doc->saveXML();
     }
     $this->logRequestTime();
     self::addHeaders();
     echo ob_get_clean();
     exit;
 }
Ejemplo n.º 2
0
 /**
  * @param object $object Zotero object (Zotero_Item, Zotero_Collection, Zotero_Search, Zotero_Setting)
  * @param object $json JSON object to check
  * @param array $requestParams
  * @param int $requireVersion If 0, don't require; if 1, require if there's
  *                            an object key property in the JSON; if 2,
  *                            always require
  */
 public static function checkJSONObjectVersion($object, $json, $requestParams, $requireVersion)
 {
     $objectType = Zotero_Utilities::getObjectTypeFromObject($object);
     if (!in_array($objectType, array('item', 'collection', 'search', 'setting'))) {
         throw new Exception("Invalid object type");
     }
     $oldKeyProp = $objectType . "Key";
     $oldVersionProp = $objectType == 'setting' ? 'version' : $objectType . "Version";
     $newKeyProp = 'key';
     $newVersionProp = 'version';
     if ($requestParams['v'] >= 3) {
         $keyProp = $newKeyProp;
         $versionProp = $newVersionProp;
         // Disallow old properties
         if (isset($json->{$oldKeyProp})) {
             throw new Exception("'{$oldKeyProp}' property is now '" . $newKeyProp . "'", Z_ERROR_INVALID_INPUT);
         } else {
             if (isset($json->{$oldVersionProp}) && $oldVersionProp != $newVersionProp) {
                 throw new Exception("'{$oldVersionProp}' property is now '" . $newVersionProp . "'", Z_ERROR_INVALID_INPUT);
             }
         }
     } else {
         $keyProp = $oldKeyProp;
         $versionProp = $oldVersionProp;
         // Disallow new properties
         if (isset($json->{$newKeyProp})) {
             throw new Exception("Invalid property '{$newKeyProp}'", Z_ERROR_INVALID_INPUT);
         } else {
             if (isset($json->{$newVersionProp}) && $oldVersionProp != $newVersionProp) {
                 throw new Exception("Invalid property '{$newVersionProp}'", Z_ERROR_INVALID_INPUT);
             }
         }
     }
     if (isset($json->{$versionProp})) {
         if ($requestParams['v'] < 2) {
             throw new Exception("Invalid property '{$versionProp}'", Z_ERROR_INVALID_INPUT);
         }
         if (!is_numeric($json->{$versionProp})) {
             throw new Exception("'{$versionProp}' must be an integer", Z_ERROR_INVALID_INPUT);
         }
         if (!isset($json->{$keyProp}) && $objectType != 'setting' && !$object->key) {
             throw new Exception("'{$versionProp}' is valid only if {$objectType} key is provided", Z_ERROR_INVALID_INPUT);
         }
         $originalVersion = Zotero_Libraries::getOriginalVersion($object->libraryID);
         $updatedVersion = Zotero_Libraries::getUpdatedVersion($object->libraryID);
         // Make sure the object hasn't been modified since the specified version
         if ($object->version > $json->{$versionProp}) {
             // Unless it was modified in this request
             if ($updatedVersion != $originalVersion && $object->version == $updatedVersion) {
                 return;
             }
             throw new HTTPException(ucwords($objectType) . " has been modified since specified version " . "(expected {$json->{$versionProp}}, found {$object->version})", 412);
         } else {
             if ($json->{$versionProp} > 0 && !$object->version) {
                 throw new HTTPException(ucwords($objectType) . " doesn't exist (expected version {$json->{$versionProp}}; use 0 instead)", 404);
             }
         }
     } else {
         if ($requireVersion == 1 && isset($json->{$keyProp})) {
             if ($objectType == 'setting') {
                 throw new HTTPException("Either If-Unmodified-Since-Version or " . "'{$versionProp}' property must be provided", 428);
             } else {
                 throw new HTTPException("Either If-Unmodified-Since-Version or " . "'{$versionProp}' property must be provided for " . "'{$keyProp}'-based writes", 428);
             }
         } else {
             if ($requireVersion == 2) {
                 throw new HTTPException("Either If-Unmodified-Since-Version or " . "'{$versionProp}' property must be provided for " . "single-{$objectType} writes", 428);
             }
         }
     }
 }
Ejemplo n.º 3
0
 public function settings()
 {
     if ($this->apiVersion < 2) {
         $this->e404();
     }
     // Check for general library access
     if (!$this->permissions->canAccess($this->objectLibraryID)) {
         $this->e403();
     }
     if ($this->isWriteMethod()) {
         Zotero_DB::beginTransaction();
         // Check for library write access
         if (!$this->permissions->canWrite($this->objectLibraryID)) {
             $this->e403("Write access denied");
         }
         // Make sure library hasn't been modified
         if (!$this->singleObject) {
             $libraryTimestampChecked = $this->checkLibraryIfUnmodifiedSinceVersion();
         }
         Zotero_Libraries::updateVersionAndTimestamp($this->objectLibraryID);
     }
     // Single setting
     if ($this->singleObject) {
         $this->allowMethods(array('GET', 'PUT', 'DELETE'));
         $setting = Zotero_Settings::getByLibraryAndKey($this->objectLibraryID, $this->objectKey);
         if (!$setting) {
             if ($this->method == 'PUT') {
                 $setting = new Zotero_Setting();
                 $setting->libraryID = $this->objectLibraryID;
                 $setting->name = $this->objectKey;
             } else {
                 $this->e404("Setting not found");
             }
         }
         if ($this->isWriteMethod()) {
             if ($this->method == 'PUT') {
                 $json = $this->jsonDecode($this->body);
                 $objectVersionValidated = $this->checkSingleObjectWriteVersion('setting', $setting, $json);
             }
             $this->libraryVersion = Zotero_Libraries::getUpdatedVersion($this->objectLibraryID);
             // Update setting
             if ($this->method == 'PUT') {
                 $changed = Zotero_Settings::updateFromJSON($setting, $json, $this->queryParams, $this->userID, $objectVersionValidated ? 0 : 2);
                 // If not updated, return the original library version
                 if (!$changed) {
                     $this->libraryVersion = Zotero_Libraries::getOriginalVersion($this->objectLibraryID);
                     Zotero_DB::rollback();
                     $this->e204();
                 }
             } else {
                 if ($this->method == 'DELETE') {
                     Zotero_Settings::delete($this->objectLibraryID, $this->objectKey);
                 } else {
                     throw new Exception("Unexpected method {$this->method}");
                 }
             }
             Zotero_DB::commit();
             $this->e204();
         } else {
             $this->libraryVersion = $setting->version;
             $json = $setting->toJSON(true, $this->queryParams);
             echo Zotero_Utilities::formatJSON($json);
         }
     } else {
         $this->allowMethods(array('GET', 'POST'));
         $this->libraryVersion = Zotero_Libraries::getUpdatedVersion($this->objectLibraryID);
         // Create a setting
         if ($this->method == 'POST') {
             $obj = $this->jsonDecode($this->body);
             $changed = Zotero_Settings::updateMultipleFromJSON($obj, $this->queryParams, $this->objectLibraryID, $this->userID, $this->permissions, $libraryTimestampChecked ? 0 : 1, null);
             // If not updated, return the original library version
             if (!$changed) {
                 $this->libraryVersion = Zotero_Libraries::getOriginalVersion($this->objectLibraryID);
             }
             Zotero_DB::commit();
             $this->e204();
         } else {
             $settings = Zotero_Settings::search($this->objectLibraryID, $this->queryParams);
             $json = new stdClass();
             foreach ($settings as $setting) {
                 $json->{$setting->name} = $setting->toJSON(true, $this->queryParams);
             }
             echo Zotero_Utilities::formatJSON($json);
         }
     }
     $this->end();
 }