public static function checkUploadForErrors($syncProcessID) { Zotero_DB::beginTransaction(); if (Z_Core::probability(30)) { $sql = "UPDATE syncUploadQueue SET started=NULL, errorCheck=0 WHERE started IS NOT NULL AND errorCheck=1 AND\n\t\t\t\t\t\tstarted < (NOW() - INTERVAL 15 MINUTE) AND finished IS NULL"; Zotero_DB::query($sql); } // Get a queued process that hasn't been error-checked and is large enough to warrant it $sql = "SELECT * FROM syncUploadQueue WHERE started IS NULL AND errorCheck=0\n\t\t\t\tAND dataLength>=" . self::$minErrorCheckSize . " ORDER BY added LIMIT 1 FOR UPDATE"; $row = Zotero_DB::rowQuery($sql); // No pending processes if (!$row) { Zotero_DB::commit(); return 0; } $sql = "UPDATE syncUploadQueue SET started=NOW(), errorCheck=1 WHERE syncUploadQueueID=?"; Zotero_DB::query($sql, array($row['syncUploadQueueID'])); // We track error processes as upload processes that just get reset back to // started=NULL on completion (but with errorCheck=2) self::addUploadProcess($row['userID'], null, $row['syncUploadQueueID'], $syncProcessID); Zotero_DB::commit(); try { $doc = new DOMDocument(); $doc->loadXML($row['xmldata']); // Get long tags $value = Zotero_Tags::getLongDataValueFromXML($doc); if ($value) { throw new Exception("Tag '" . $value . "' too long", Z_ERROR_TAG_TOO_LONG); } // Get long collection names $value = Zotero_Collections::getLongDataValueFromXML($doc); if ($value) { throw new Exception("Collection '" . $value . "' too long", Z_ERROR_COLLECTION_TOO_LONG); } // Get long creator names $node = Zotero_Creators::getLongDataValueFromXML($doc); // returns DOMNode rather than value if ($node) { if ($node->nodeName == 'firstName') { throw new Exception("=First name '" . mb_substr($node->nodeValue, 0, 50) . "…' too long"); } if ($node->nodeName == 'lastName') { throw new Exception("=Last name '" . mb_substr($node->nodeValue, 0, 50) . "…' too long"); } if ($node->nodeName == 'name') { throw new Exception("=Name '" . mb_substr($node->nodeValue, 0, 50) . "…' too long"); } } $node = Zotero_Items::getLongDataValueFromXML($doc); // returns DOMNode rather than value if ($node) { $fieldName = $node->getAttribute('name'); $fieldName = Zotero_ItemFields::getLocalizedString(null, $fieldName); if ($fieldName) { $start = "'{$fieldName}' field"; } else { $start = "Field"; } throw new Exception("={$start} value '" . mb_substr($node->nodeValue, 0, 50) . "...' too long"); } } catch (Exception $e) { //Z_Core::logError($e); Zotero_DB::beginTransaction(); $sql = "UPDATE syncUploadQueue SET syncProcessID=NULL, finished=?,\n\t\t\t\t\t\terrorCode=?, errorMessage=? WHERE syncUploadQueueID=?"; Zotero_DB::query($sql, array(Zotero_DB::getTransactionTimestamp(), $e->getCode(), serialize($e), $row['syncUploadQueueID'])); $sql = "DELETE FROM syncUploadQueueLocks WHERE syncUploadQueueID=?"; Zotero_DB::query($sql, $row['syncUploadQueueID']); self::removeUploadProcess($syncProcessID); Zotero_DB::commit(); return -2; } Zotero_DB::beginTransaction(); $sql = "UPDATE syncUploadQueue SET syncProcessID=NULL, started=NULL, errorCheck=2 WHERE syncUploadQueueID=?"; Zotero_DB::query($sql, $row['syncUploadQueueID']); self::removeUploadProcess($syncProcessID); Zotero_DB::commit(); return 1; }
public static function checkUploadForErrors($syncProcessID) { Zotero_DB::beginTransaction(); if (Z_Core::probability(30)) { $sql = "UPDATE syncUploadQueue SET started=NULL, errorCheck=0 WHERE started IS NOT NULL AND errorCheck=1 AND\n\t\t\t\t\t\tstarted < (NOW() - INTERVAL 15 MINUTE) AND finished IS NULL"; Zotero_DB::query($sql); } // Get a queued process that hasn't been error-checked and is large enough to warrant it $sql = "SELECT * FROM syncUploadQueue WHERE started IS NULL AND errorCheck=0\n\t\t\t\tAND dataLength>=" . self::$minErrorCheckSize . " ORDER BY added LIMIT 1 FOR UPDATE"; $row = Zotero_DB::rowQuery($sql); // No pending processes if (!$row) { Zotero_DB::commit(); return 0; } $sql = "UPDATE syncUploadQueue SET started=NOW(), errorCheck=1 WHERE syncUploadQueueID=?"; Zotero_DB::query($sql, array($row['syncUploadQueueID'])); // We track error processes as upload processes that just get reset back to // started=NULL on completion (but with errorCheck=2) self::addUploadProcess($row['userID'], null, $row['syncUploadQueueID'], $syncProcessID); Zotero_DB::commit(); try { $doc = new DOMDocument(); $doc->loadXML($row['xmldata'], LIBXML_COMPACT | LIBXML_PARSEHUGE); // Get long tags $value = Zotero_Tags::getLongDataValueFromXML($doc); if ($value) { throw new Exception("Tag '" . $value . "' too long", Z_ERROR_TAG_TOO_LONG); } // Get long collection names $value = Zotero_Collections::getLongDataValueFromXML($doc); if ($value) { throw new Exception("Collection '" . $value . "' too long", Z_ERROR_COLLECTION_TOO_LONG); } // Get long creator names $node = Zotero_Creators::getLongDataValueFromXML($doc); // returns DOMNode rather than value if ($node) { $name = mb_substr($node->nodeValue, 0, 50); throw new Exception("=The name ‘{$name}…’ is too long to sync.\n\n" . "Search for the item with this name and shorten it. " . "Note that the item may be in the trash or in a group library.\n\n" . "If you receive this message repeatedly for items saved from a " . "particular site, you can report this issue in the Zotero Forums.", Z_ERROR_CREATOR_TOO_LONG); } // Get long item data fields $node = Zotero_Items::getLongDataValueFromXML($doc); // returns DOMNode rather than value if ($node) { $libraryID = $node->parentNode->getAttribute('libraryID'); $key = $node->parentNode->getAttribute('key'); if ($libraryID) { $key = $libraryID . "/" . $key; } $fieldName = $node->getAttribute('name'); $fieldName = Zotero_ItemFields::getLocalizedString(null, $fieldName); if ($fieldName) { $start = "{$fieldName} field"; } else { $start = "Field"; } throw new Exception("={$start} value '" . mb_substr($node->nodeValue, 0, 75) . "...' too long for item '{$key}'", Z_ERROR_FIELD_TOO_LONG); } } catch (Exception $e) { //Z_Core::logError($e); Zotero_DB::beginTransaction(); $sql = "UPDATE syncUploadQueue SET syncProcessID=NULL, finished=?,\n\t\t\t\t\t\terrorCode=?, errorMessage=? WHERE syncUploadQueueID=?"; Zotero_DB::query($sql, array(Zotero_DB::getTransactionTimestamp(), $e->getCode(), serialize($e), $row['syncUploadQueueID'])); $sql = "DELETE FROM syncUploadQueueLocks WHERE syncUploadQueueID=?"; Zotero_DB::query($sql, $row['syncUploadQueueID']); self::removeUploadProcess($syncProcessID); Zotero_DB::commit(); return -2; } Zotero_DB::beginTransaction(); $sql = "UPDATE syncUploadQueue SET syncProcessID=NULL, started=NULL, errorCheck=2 WHERE syncUploadQueueID=?"; Zotero_DB::query($sql, $row['syncUploadQueueID']); self::removeUploadProcess($syncProcessID); Zotero_DB::commit(); return 1; }
public function testGetLongDataValueFromXML() { $longStr = str_pad("", 65534, "-") . "\nFoobar"; $xml = <<<EOD \t\t\t<data> \t\t\t\t<items> \t\t\t\t\t<item libraryID="1" key="BBBBBBBB" itemType="attachment" dateAdded="2010-01-08 10:31:09" dateModified="2010-01-08 10:31:17" sourceItem="VN9DPHBB" linkMode="0" mimeType="application/pdf" storageModTime="1262946676" storageHash="41125f70cc25117b0da961bd7108938 9"> \t\t\t\t\t\t<field name="title">Test_Filename.pdf</field> \t\t\t\t\t</item> \t\t\t\t\t<item libraryID="1" key="AAAAAAAA" itemType="journalArticle" dateAdded="2010-01-08 10:29:36" dateModified="2010-01-08 10:29:36"> \t\t\t\t\t\t<field name="title">Foo</field> \t\t\t\t\t\t<field name="abstractNote">{$longStr}</field> \t\t\t\t\t\t<creator libraryID="1" key="AAAAAAAA" creatorType="author" index="0"> \t\t\t\t\t\t\t<creator libraryID="1" key="AAAAAAAA" dateAdded="2010-01-08 10:29:36" dateModified="2010-01-08 10:29:36"> \t\t\t\t\t\t\t\t<firstName>Irrelevant</firstName> \t\t\t\t\t\t\t\t<lastName>Creator</lastName> \t\t\t\t\t\t\t</creator> \t\t\t\t\t\t</creator> \t\t\t\t\t</item> \t\t\t\t</items> \t\t\t</data> EOD; $doc = new DOMDocument(); $doc->loadXML($xml); $node = Zotero_Items::getLongDataValueFromXML($doc); $this->assertEquals("abstractNote", $node->getAttribute('name')); $this->assertEquals($longStr, $node->nodeValue); }