示例#1
0
 /**
  * Handle uploaded data, overwriting existing data
  */
 public function upload()
 {
     $this->sessionCheck();
     // Another session is either queued or writing — upload data won't be valid,
     // so client should wait and return to /updated with 'upload' flag
     Zotero_DB::beginTransaction();
     if (Zotero_Sync::userIsReadLocked($this->userID) || Zotero_Sync::userIsWriteLocked($this->userID)) {
         Zotero_DB::commit();
         $locked = $this->responseXML->addChild('locked');
         $locked['wait'] = $this->getWaitTime($this->sessionID);
         $this->end();
     }
     Zotero_DB::commit();
     $this->clearWaitTime($this->sessionID);
     if (empty($_REQUEST['updateKey'])) {
         $this->error(400, 'INVALID_UPLOAD_DATA', 'Update key not provided');
     }
     if ($_REQUEST['updateKey'] != Zotero_Users::getUpdateKey($this->userID)) {
         $this->e409("Server data has changed since last retrieval");
     }
     // TODO: change to POST
     if (empty($_REQUEST['data'])) {
         $this->error(400, 'MISSING_UPLOAD_DATA', 'Uploaded data not provided');
     }
     $xmldata =& $_REQUEST['data'];
     try {
         $doc = new DOMDocument();
         $doc->loadXML($xmldata, LIBXML_PARSEHUGE);
         // For huge uploads, make sure notes aren't bigger than SimpleXML can parse
         if (strlen($xmldata) > 7000000) {
             $xpath = new DOMXPath($doc);
             $results = $xpath->query('/data/items/item/note[string-length(text()) > ' . Zotero_Notes::$MAX_NOTE_LENGTH . ']');
             if ($results->length) {
                 $noteElem = $results->item(0);
                 $text = $noteElem->textContent;
                 $libraryID = $noteElem->parentNode->getAttribute('libraryID');
                 $key = $noteElem->parentNode->getAttribute('key');
                 // UTF-8   (0xC2 0xA0) isn't trimmed by default
                 $whitespace = chr(0x20) . chr(0x9) . chr(0xa) . chr(0xd) . chr(0x0) . chr(0xb) . chr(0xc2) . chr(0xa0);
                 $excerpt = iconv("UTF-8", "UTF-8//IGNORE", Zotero_Notes::noteToTitle(trim($text), true));
                 $excerpt = trim($excerpt, $whitespace);
                 // If tag-stripped version is empty, just return raw HTML
                 if ($excerpt == '') {
                     $excerpt = iconv("UTF-8", "UTF-8//IGNORE", preg_replace('/\\s+/', ' ', mb_substr(trim($text), 0, Zotero_Notes::$MAX_TITLE_LENGTH)));
                     $excerpt = html_entity_decode($excerpt);
                     $excerpt = trim($excerpt, $whitespace);
                 }
                 $msg = "=Note '" . $excerpt . "...' too long";
                 if ($key) {
                     $msg .= " for item '" . $libraryID . "/" . $key . "'";
                 }
                 throw new Exception($msg, Z_ERROR_NOTE_TOO_LONG);
             }
         }
     } catch (Exception $e) {
         $this->handleUploadError($e, $xmldata);
     }
     function relaxNGErrorHandler($errno, $errstr)
     {
         //Z_Core::logError($errstr);
     }
     set_error_handler('relaxNGErrorHandler');
     set_time_limit(60);
     if (!$doc->relaxNGValidate(Z_ENV_MODEL_PATH . 'relax-ng/upload.rng')) {
         $id = substr(md5(uniqid(rand(), true)), 0, 10);
         $str = date("D M j G:i:s T Y") . "\n";
         $str .= "IP address: " . $_SERVER['REMOTE_ADDR'] . "\n";
         if (isset($_SERVER['HTTP_X_ZOTERO_VERSION'])) {
             $str .= "Version: " . $_SERVER['HTTP_X_ZOTERO_VERSION'] . "\n";
         }
         $str .= "Error: RELAX NG validation failed\n\n";
         $str .= $xmldata;
         if (!file_put_contents(Z_CONFIG::$SYNC_ERROR_PATH . $id, $str)) {
             error_log("Unable to save error report to " . Z_CONFIG::$SYNC_ERROR_PATH . $id);
         }
         $this->error(500, 'INVALID_UPLOAD_DATA', "Uploaded data not well-formed (Report ID: {$id})");
     }
     restore_error_handler();
     try {
         $xml = simplexml_import_dom($doc);
         $queue = true;
         if (Z_ENV_TESTING_SITE && !empty($_GET['noqueue'])) {
             $queue = false;
         }
         if ($queue) {
             $affectedLibraries = Zotero_Sync::parseAffectedLibraries($xmldata);
             // Relations-only uploads don't have affected libraries
             if (!$affectedLibraries) {
                 $affectedLibraries = array(Zotero_Users::getLibraryIDFromUserID($this->userID));
             }
             Zotero_Sync::queueUpload($this->userID, $this->sessionID, $xmldata, $affectedLibraries);
             try {
                 Zotero_Processors::notifyProcessors('upload');
                 Zotero_Processors::notifyProcessors('error');
                 usleep(750000);
             } catch (Exception $e) {
                 Z_Core::logError($e);
             }
             // Give processor a chance to finish while we're still here
             $this->uploadstatus();
         } else {
             set_time_limit(210);
             $timestamp = Zotero_Sync::processUpload($this->userID, $xml);
             $this->responseXML['timestamp'] = $timestamp;
             $this->responseXML->addChild('uploaded');
             $this->end();
         }
     } catch (Exception $e) {
         $this->handleUploadError($e, $xmldata);
     }
 }
 /**
  * Handle uploaded data, overwriting existing data
  */
 public function upload()
 {
     $this->sessionCheck();
     // Another session is either queued or writing — upload data won't be valid,
     // so client should wait and return to /updated with 'upload' flag
     Zotero_DB::beginTransaction();
     if (Zotero_Sync::userIsReadLocked($this->userID) || Zotero_Sync::userIsWriteLocked($this->userID)) {
         Zotero_DB::commit();
         $locked = $this->responseXML->addChild('locked');
         $locked['wait'] = $this->getWaitTime($this->sessionID);
         $this->end();
     }
     Zotero_DB::commit();
     $this->clearWaitTime($this->sessionID);
     if (empty($_REQUEST['updateKey'])) {
         $this->error(400, 'INVALID_UPLOAD_DATA', 'Update key not provided');
     }
     if ($_REQUEST['updateKey'] != Zotero_Users::getUpdateKey($this->userID)) {
         $this->e409("Server data has changed since last retrieval");
     }
     // TODO: change to POST
     if (empty($_REQUEST['data'])) {
         $this->error(400, 'MISSING_UPLOAD_DATA', 'Uploaded data not provided');
     }
     $xmldata =& $_REQUEST['data'];
     $doc = new DOMDocument();
     $doc->loadXML($xmldata);
     function relaxNGErrorHandler($errno, $errstr)
     {
         //Z_Core::logError($errstr);
     }
     set_error_handler('relaxNGErrorHandler');
     set_time_limit(60);
     if (!$doc->relaxNGValidate(Z_ENV_MODEL_PATH . 'relax-ng/upload.rng')) {
         $id = substr(md5(uniqid(rand(), true)), 0, 10);
         $str = date("D M j G:i:s T Y") . "\n";
         $str .= "IP address: " . $_SERVER['REMOTE_ADDR'] . "\n";
         if (isset($_SERVER['HTTP_X_ZOTERO_VERSION'])) {
             $str .= "Version: " . $_SERVER['HTTP_X_ZOTERO_VERSION'] . "\n";
         }
         $str .= "Error: RELAX NG validation failed\n\n";
         $str .= $xmldata;
         file_put_contents(Z_CONFIG::$SYNC_ERROR_PATH . $id, $str);
         $this->error(500, 'INVALID_UPLOAD_DATA', "Uploaded data not well-formed (Report ID: {$id})");
     }
     restore_error_handler();
     try {
         $xml = simplexml_import_dom($doc);
         $queue = true;
         if (Z_ENV_TESTING_SITE && !empty($_GET['noqueue'])) {
             $queue = false;
         }
         if ($queue) {
             $affectedLibraries = Zotero_Sync::parseAffectedLibraries($xmldata);
             // Relations-only uploads don't have affected libraries
             if (!$affectedLibraries) {
                 $affectedLibraries = array(Zotero_Users::getLibraryIDFromUserID($this->userID));
             }
             Zotero_Sync::queueUpload($this->userID, $this->sessionID, $xmldata, $affectedLibraries);
             try {
                 Zotero_Processors::notifyProcessors('upload');
                 Zotero_Processors::notifyProcessors('error');
                 usleep(750000);
             } catch (Exception $e) {
                 Z_Core::logError($e);
             }
             // Give processor a chance to finish while we're still here
             $this->uploadstatus();
         } else {
             set_time_limit(210);
             $timestamp = Zotero_Sync::processUpload($this->userID, $xml);
             $this->responseXML['timestamp'] = $timestamp;
             $this->responseXML->addChild('uploaded');
             Zotero_Processors::notifyProcessors('index');
             $this->end();
         }
     } catch (Exception $e) {
         $this->handleUploadError($e, $xmldata);
     }
 }