embedded_xmp.rs (2206B)
1 // Copyright 2022 Adobe. All rights reserved. 2 // This file is licensed to you under the Apache License, 3 // Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 4 // or the MIT license (http://opensource.org/licenses/MIT), 5 // at your option. 6 7 // Unless required by applicable law or agreed to in writing, 8 // this software is distributed on an "AS IS" BASIS, WITHOUT 9 // WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or 10 // implied. See the LICENSE-MIT and LICENSE-APACHE files for the 11 // specific language governing permissions and limitations under 12 // each license. 13 14 use std::path::Path; 15 16 use tracing::error; 17 use xmp_toolkit::{OpenFileOptions, XmpError, XmpErrorType, XmpFile, XmpMeta}; 18 19 use crate::{Error, Result}; 20 21 /// Add the URI for the active manifest to the XMP packet for a file. 22 /// 23 /// This will replace any existing `dc:provenance` term 24 /// in the file's metadata, or create a new one if necessary. 25 /// 26 /// This does not check the claim at all; it is presumed 27 /// that the string that is passed is a valid signed claim. 28 pub(crate) fn add_manifest_uri_to_file<P: AsRef<Path>>(path: P, manifest_uri: &str) -> Result<()> { 29 XmpMeta::register_namespace("http://purl.org/dc/terms/", "dcterms").map_err(xmp_write_err)?; 30 31 let mut f = XmpFile::new().map_err(xmp_write_err)?; 32 33 f.open_file(path, OpenFileOptions::default().for_update()) 34 .map_err(xmp_write_err)?; 35 36 let mut m = match f.xmp() { 37 Some(m) => m, 38 None => XmpMeta::new().map_err(xmp_write_err)?, 39 }; 40 41 m.set_property( 42 "http://purl.org/dc/terms/", 43 "provenance", 44 &manifest_uri.into(), 45 ) 46 .map_err(xmp_write_err)?; 47 48 f.put_xmp(&m).map_err(xmp_write_err)?; 49 f.close(); 50 51 Ok(()) 52 } 53 54 fn xmp_write_err(err: XmpError) -> crate::Error { 55 error!("Unable to add manifest URI to file: {:?}", err); 56 match err.error_type { 57 // convert to OS permission error code so we can detect it correctly upstream 58 XmpErrorType::FilePermission => Error::IoError(std::io::Error::from_raw_os_error(13)), 59 XmpErrorType::NoFile => Error::NotFound, 60 XmpErrorType::NoFileHandler => Error::UnsupportedType, 61 _ => Error::XmpWriteError, 62 } 63 }