public function s3_store($doc, $docinfo, $trust_sha1 = false)
 {
     global $Opt;
     if (!isset($doc->content) && !$this->load_content($doc)) {
         return false;
     }
     if (!$trust_sha1 && Filer::binary_sha1($doc) !== sha1($doc->content, true)) {
         error_log("S3 upload cancelled: data claims checksum " . Filer::text_sha1($doc) . ", has checksum " . sha1($doc->content));
         return false;
     }
     $s3 = self::s3_document();
     $dtype = isset($doc->documentType) ? $doc->documentType : $this->dtype;
     $meta = array("conf" => $Opt["dbName"], "pid" => (int) $docinfo->paperId, "dtype" => (int) $dtype);
     if (get($doc, "filter")) {
         $meta["filtertype"] = (int) $doc->filter;
         if (get($doc, "original_sha1")) {
             $meta["original_sha1"] = $doc->original_sha1;
         }
     }
     $filename = self::s3_filename($doc);
     $s3->save($filename, $doc->content, $doc->mimetype, array("hotcrp" => json_encode($meta)));
     if ($s3->status != 200) {
         error_log("S3 error: POST {$filename}: {$s3->status} {$s3->status_text} " . json_encode($s3->response_headers));
     }
     return $s3->status == 200;
 }