public DirectoryList ReadJpegSegments(IEnumerable <JpegSegment> segments) { // Ensure collection materialised (avoiding multiple lazy enumeration) segments = segments.ToList(); var directories = segments .Where(IsXmpSegment) .Select(segment => Extract(segment.Bytes, JpegSegmentPreambleBytes.Length, segment.Bytes.Length - JpegSegmentPreambleBytes.Length)) .Cast <Directory>() .ToList(); var extensionGroups = segments.Where(IsExtendedXmpSegment).GroupBy(GetExtendedDataGuid); foreach (var extensionGroup in extensionGroups) { var buffer = new MemoryStream(); foreach (var segment in extensionGroup) { var N = JpegSegmentPreambleExtensionBytes.Length + 32 + 4 + 4; buffer.Write(segment.Bytes, N, segment.Bytes.Length - N); } buffer.Position = 0; var directory = new XmpDirectory(); var xmpMeta = XmpMetaFactory.Parse(buffer); directory.SetXmpMeta(xmpMeta); directories.Add(directory); } return(directories); }
/** * Adds information about the PDF/A conformance level to the XMP metadata. * * @param conformanceLevel * @throws IOException */ private void AddRdfDescription(PdfAConformanceLevel conformanceLevel) { switch (conformanceLevel) { case PdfAConformanceLevel.PDF_A_1A: xmpMeta.SetProperty(XmpConst.NS_PDFA_ID, PdfAProperties.PART, "1"); xmpMeta.SetProperty(XmpConst.NS_PDFA_ID, PdfAProperties.CONFORMANCE, "A"); break; case PdfAConformanceLevel.PDF_A_1B: xmpMeta.SetProperty(XmpConst.NS_PDFA_ID, PdfAProperties.PART, "1"); xmpMeta.SetProperty(XmpConst.NS_PDFA_ID, PdfAProperties.CONFORMANCE, "B"); break; case PdfAConformanceLevel.PDF_A_2A: xmpMeta.SetProperty(XmpConst.NS_PDFA_ID, PdfAProperties.PART, "2"); xmpMeta.SetProperty(XmpConst.NS_PDFA_ID, PdfAProperties.CONFORMANCE, "A"); break; case PdfAConformanceLevel.PDF_A_2B: xmpMeta.SetProperty(XmpConst.NS_PDFA_ID, PdfAProperties.PART, "2"); xmpMeta.SetProperty(XmpConst.NS_PDFA_ID, PdfAProperties.CONFORMANCE, "B"); break; case PdfAConformanceLevel.PDF_A_2U: xmpMeta.SetProperty(XmpConst.NS_PDFA_ID, PdfAProperties.PART, "2"); xmpMeta.SetProperty(XmpConst.NS_PDFA_ID, PdfAProperties.CONFORMANCE, "U"); break; case PdfAConformanceLevel.PDF_A_3A: xmpMeta.SetProperty(XmpConst.NS_PDFA_ID, PdfAProperties.PART, "3"); xmpMeta.SetProperty(XmpConst.NS_PDFA_ID, PdfAProperties.CONFORMANCE, "A"); break; case PdfAConformanceLevel.PDF_A_3B: xmpMeta.SetProperty(XmpConst.NS_PDFA_ID, PdfAProperties.PART, "3"); xmpMeta.SetProperty(XmpConst.NS_PDFA_ID, PdfAProperties.CONFORMANCE, "B"); break; case PdfAConformanceLevel.PDF_A_3U: xmpMeta.SetProperty(XmpConst.NS_PDFA_ID, PdfAProperties.PART, "3"); xmpMeta.SetProperty(XmpConst.NS_PDFA_ID, PdfAProperties.CONFORMANCE, "U"); break; case PdfAConformanceLevel.ZUGFeRD: xmpMeta.SetProperty(XmpConst.NS_PDFA_ID, PdfAProperties.PART, "3"); xmpMeta.SetProperty(XmpConst.NS_PDFA_ID, PdfAProperties.CONFORMANCE, "B"); IXmpMeta taggedExtensionMeta = XmpMetaFactory.ParseFromString(zugferdExtension); XmpUtils.AppendProperties(taggedExtensionMeta, xmpMeta, true, false); break; default: break; } if (writer.IsTagged()) { IXmpMeta taggedExtensionMeta = XmpMetaFactory.ParseFromString(pdfUaExtension); XmpUtils.AppendProperties(taggedExtensionMeta, xmpMeta, true, false); } }
public void copyDateCreatedToDateTimeOriginal() { IXmpMeta xmpMeta; using (var fileStream = File.OpenRead(XmpFile.FullName)) { xmpMeta = XmpMetaFactory.Parse(fileStream); if (xmpMeta.DoesPropertyExist("http://ns.adobe.com/photoshop/1.0/", "photoshop:DateCreated")) { IXmpDateTime xmpMetaCreateDate = xmpMeta.GetPropertyDate("http://ns.adobe.com/photoshop/1.0/", "photoshop:DateCreated"); List <FileInfo> correspondingImageFiles = this.getCorrespondingImageFile(); foreach (FileInfo correspondingImageFile in correspondingImageFiles) { DateTime?DateTimeOriginal = this.getDateTimeOriginal(correspondingImageFile); if (DateTimeOriginal == null) { ExifToolWrapper exifTool = new ExifToolWrapper(); ExifToolResponse jsonExifToolOutput = exifTool.execute(string.Concat("-m -S -overwrite_original \"-DateTimeOriginal=", xmpMetaCreateDate.ToIso8601String(), "\""), correspondingImageFile); } else { Program.MainLogger.Information($"DateTimeOriginal TAG in file {correspondingImageFile} already set to {DateTimeOriginal}"); } } } else { Program.MainLogger.Information($"Cant't find 'photoshop:DateCreated' property in namespace 'http://ns.adobe.com/photoshop/1.0/'"); } } }
/** * Test simple constructors and parsing, setting the instance ID * @throws XmpException Forwards exceptions */ private static void CoverCreatingXmp() { writeMajorLabel("Test simple constructors and parsing, setting the instance ID"); var meta1 = XmpMetaFactory.Create(); printXmpMeta(meta1, "Empty XMP object"); var meta2 = XmpMetaFactory.Create(); meta2.SetObjectName("New object name"); printXmpMeta(meta2, "XMP object with name"); var meta3 = XmpMetaFactory.ParseFromString(TestData.RDF_COVERAGE); printXmpMeta(meta3, "Construct and parse from buffer"); meta3.SetProperty(XmpConstants.NsXmpMm, "InstanceID", "meta2:Original"); printXmpMeta(meta3, "Add instance ID"); XmpMeta meta4 = (XmpMeta)meta3.Clone(); meta4.SetProperty(XmpConstants.NsXmpMm, "InstanceID", "meta2:Clone"); printXmpMeta(meta3, "Clone and add instance ID"); }
public void BillionLaughs_DoctypeDisabled() { var testdata = @"<?xml version=""1.0""?> <!DOCTYPE lolz [ <!ENTITY lol ""lol""> <!ENTITY lol2 ""&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;""> <!ENTITY lol3 ""&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;""> <!ENTITY lol4 ""&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;""> <!ENTITY lol5 ""&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;""> <!ENTITY lol6 ""&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;""> <!ENTITY lol7 ""&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;""> <!ENTITY lol8 ""&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;""> <!ENTITY lol9 ""&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;""> ]> <lolz>&lol9;</lolz>"; XmpException e = null; try { // doctype not allowed by default XmpMetaFactory.ParseFromString(testdata); } catch (XmpException ex) { e = ex; } Assert.NotNull(e); Assert.True(e.InnerException.Message.StartsWith("For security reasons DTD is prohibited")); }
public void BillionLaughs_DoctypeEnabled() { var testdata = @"<?xml version=""1.0""?> <!DOCTYPE lolz [ <!ENTITY lol ""lol""> <!ENTITY lol2 ""&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;""> <!ENTITY lol3 ""&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;""> <!ENTITY lol4 ""&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;""> <!ENTITY lol5 ""&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;""> <!ENTITY lol6 ""&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;""> <!ENTITY lol7 ""&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;""> <!ENTITY lol8 ""&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;""> <!ENTITY lol9 ""&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;""> ]> <lolz>&lol9;</lolz>"; var options = new Options.ParseOptions(); // enable doctype options.DisallowDoctype = false; XmpException e = null; try { XmpMetaFactory.ParseFromString(testdata, options); } catch (XmpException ex) { e = ex; } Assert.NotNull(e); Assert.True(e.InnerException.Message.StartsWith("The input document has exceeded a limit set by MaxCharactersFromEntities")); }
public void XXE_DoctypeDisabled() { string testdata = @"<!DOCTYPE doc [<!ENTITY win SYSTEM ""c:\windows\win.ini"">]><doc></doc>"; // doctype not allowed by default Assert.Throws <XmpException>(() => XmpMetaFactory.ParseFromString(testdata)); }
/** * Parse and serialize methods. * @throws XmpException Forwards exceptions */ private static void CoverParsing() { writeMajorLabel("Test parsing with multiple buffers and various options"); var meta = XmpMetaFactory.ParseFromString(TestData.SIMPLE_RDF); printXmpMeta(meta, "Parse from String"); meta = XmpMetaFactory.ParseFromString(TestData.SIMPLE_RDF, new ParseOptions { RequireXmpMeta = true }); printXmpMeta(meta, "Parse and require xmpmeta element, which is missing"); meta = XmpMetaFactory.ParseFromString(TestData.NAMESPACE_RDF); printXmpMeta(meta, "Parse RDF with multiple nested namespaces"); meta = XmpMetaFactory.ParseFromString(TestData.XMPMETA_RDF, new ParseOptions { RequireXmpMeta = true }); printXmpMeta(meta, "Parse and require xmpmeta element, which is present"); meta = XmpMetaFactory.ParseFromString(TestData.INCONSISTENT_RDF); printXmpMeta(meta, "Parse and reconcile inconsistent aliases"); try { XmpMetaFactory.ParseFromString(TestData.INCONSISTENT_RDF, new ParseOptions { StrictAliasing = true }); } catch (XmpException e) { log.WriteLine("Parse and do not reconcile inconsistent aliases - threw XmpException #{0} : {1}", e.GetErrorCode(), e.Message); } }
public FileIndexItem GetDataFromString(string xmpDataAsString, FileIndexItem databaseItem = null) { // Does not require appSettings if (databaseItem == null) { databaseItem = new FileIndexItem(); } try { var xmp = XmpMetaFactory.ParseFromString(xmpDataAsString); // ContentNameSpace is for example : Namespace=http://... databaseItem = GetDataContentNameSpaceTypes(xmp, databaseItem); // NullNameSpace is for example : string.Empty databaseItem = GetDataNullNameSpaceTypes(xmp, databaseItem); } catch (XmpException e) { Console.WriteLine($"XmpException {databaseItem.FilePath} >>\n{e}\n <<XmpException"); databaseItem.Tags = "XmpException"; databaseItem.ColorClass = ColorClassParser.Color.None; } return(databaseItem); }
/** * Test CR and LF in values. * @throws XmpException Forwards exceptions */ private static void CoverLinefeedValues() { writeMajorLabel("Test CR and LF in values"); string valueWithCR = "ASCII \r CR"; string valueWithLF = "ASCII \n LF"; string valueWithCRLF = "ASCII \r\n CRLF"; var meta = XmpMetaFactory.ParseFromString(TestData.NEWLINE_RDF); meta.SetProperty(TestData.NS2, "HasCR", valueWithCR); meta.SetProperty(TestData.NS2, "HasLF", valueWithLF); meta.SetProperty(TestData.NS2, "HasCRLF", valueWithCRLF); string result = XmpMetaFactory.SerializeToString(meta, new SerializeOptions { OmitPacketWrapper = true }); log.WriteLine(result); var hasCR = meta.GetPropertyString(TestData.NS1, "HasCR"); var hasCR2 = meta.GetPropertyString(TestData.NS2, "HasCR"); var hasLF = meta.GetPropertyString(TestData.NS1, "HasLF"); var hasLF2 = meta.GetPropertyString(TestData.NS2, "HasLF"); var hasCRLF = meta.GetPropertyString(TestData.NS1, "HasCRLF"); var hasCRLF2 = meta.GetPropertyString(TestData.NS2, "HasCRLF"); if (hasCR == valueWithCR && hasCR2 == valueWithCR && hasLF == valueWithLF && hasLF2 == valueWithLF && hasCRLF == valueWithCRLF && hasCRLF2 == valueWithCRLF) { log.WriteLine(); log.WriteLine("\n## HasCR and HasLF and HasCRLF correctly retrieved\n"); } }
/// <summary> /// Some image editing apps such as Lightroom, On1, etc., do not persist the keyword metadata /// in the images by default. This can mean you keyword-tag them, but those keywords are only /// stored in the sidecars. Damselfly only scans keyword metadata from the EXIF image data /// itself. /// So to rectify this, we can either read the sidecar files for those keywords, and optionally /// write the missing keywords to the Exif Metadata as we index them. /// </summary> /// <param name="img"></param> /// <param name="keywords"></param> private void ProcessSideCarKeywords(Image img, string[] keywords) { var sideCarTags = new List <string>(); var sidecarSearch = Path.ChangeExtension(img.FileName, "*"); DirectoryInfo dir = new DirectoryInfo(img.Folder.Path); var files = dir.GetFiles(sidecarSearch); var on1Sidecar = files.FirstOrDefault(x => x.Extension.Equals(".on1", StringComparison.OrdinalIgnoreCase)); if (on1Sidecar != null) { var on1MetaData = On1Sidecar.LoadMetadata(on1Sidecar); if (on1MetaData != null) { var missingKeywords = on1MetaData.Keywords .Except(keywords, StringComparer.OrdinalIgnoreCase) .ToList(); if (missingKeywords.Any()) { Logging.LogVerbose($"Image {img.FileName} is missing {missingKeywords.Count} keywords present in the On1 Sidecar."); sideCarTags = sideCarTags.Union(missingKeywords, StringComparer.OrdinalIgnoreCase).ToList(); } } } var xmpSidecar = files.FirstOrDefault(x => x.Extension.Equals(".xmp", StringComparison.OrdinalIgnoreCase)); if (xmpSidecar != null) { using var stream = File.OpenRead(xmpSidecar.FullName); IXmpMeta xmp = XmpMetaFactory.Parse(stream); var xmpKeywords = xmp.Properties.FirstOrDefault(x => x.Path == "pdf:Keywords"); if (xmpKeywords != null) { var missingKeywords = xmpKeywords.Value .Split(",") .Select(x => x.Trim()) .Except(keywords) .ToList(); if (missingKeywords.Any()) { Logging.LogVerbose($"Image {img.FileName} is missing {missingKeywords.Count} keywords present in the XMP Sidecar."); sideCarTags = sideCarTags.Union(missingKeywords, StringComparer.OrdinalIgnoreCase).ToList(); } } } if (sideCarTags.Any()) { // Now, submit the tags; note they won't get created immediately, but in batch. Logging.Log($"Applying {sideCarTags.Count} keywords from sidecar files to image {img.FileName}"); _ = MetaDataService.Instance.UpdateTagsAsync(new[] { img }, sideCarTags, null); } }
/** * XPath composition utilities using the <code>XmpPathFactory</code>. * @throws XmpException Forwards exceptions */ private static void CoverPathCreation() { writeMajorLabel("XPath composition utilities"); var meta = XmpMetaFactory.Create(); meta.AppendArrayItem(TestData.NS1, "ArrayProp", new PropertyOptions { IsArray = true }, "Item 1", null); string path = XmpPathFactory.ComposeArrayItemPath("ArrayProp", 2); log.WriteLine("composeArrayItemPath ArrayProp[2] = " + path); meta.SetProperty(TestData.NS1, path, "new ns1:ArrayProp[2] value"); path = "StructProperty"; path += XmpPathFactory.ComposeStructFieldPath(TestData.NS2, "Field3"); log.WriteLine("composeStructFieldPath StructProperty/ns2:Field3 = " + path); meta.SetProperty(TestData.NS1, path, "new ns1:StructProp/ns2:Field3 value"); path = "QualProp"; path += XmpPathFactory.ComposeQualifierPath(TestData.NS2, "Qual"); log.WriteLine("composeStructFieldPath QualProp/?ns2:Qual = " + path); meta.SetProperty(TestData.NS1, path, "new ns1:QualProp/?ns2:Qual value"); meta.SetLocalizedText(TestData.NS1, "AltTextProp", null, "en-US", "initival value"); path = "AltTextProp"; path += XmpPathFactory.ComposeQualifierPath(XmpConstants.NsXml, "lang"); log.WriteLine("composeQualifierPath ns1:AltTextProp/?xml:lang = " + path); meta.SetProperty(TestData.NS1, path, "new ns1:AltTextProp/?xml:lang value"); printXmpMeta(meta, "Modified simple RDF"); }
public XmpDirectory Extract([NotNull] byte[] xmpBytes, int offset, int length) { if (offset < 0) { throw new ArgumentOutOfRangeException(nameof(offset), "Must be zero or greater."); } if (length < 0) { throw new ArgumentOutOfRangeException(nameof(length), "Must be zero or greater."); } if (xmpBytes.Length < offset + length) { throw new ArgumentException("Extends beyond length of byte array.", nameof(length)); } // Trim any trailing null bytes // https://github.com/drewnoakes/metadata-extractor-dotnet/issues/154 while (xmpBytes[offset + length - 1] == 0) { length--; } var directory = new XmpDirectory(); try { var xmpMeta = XmpMetaFactory.ParseFromBuffer(xmpBytes, offset, length); directory.SetXmpMeta(xmpMeta); } catch (XmpException e) { directory.AddError("Error processing XMP data: " + e.Message); } return(directory); }
/** * Literal value set/get methods * @throws XmpException */ private static void CoverLiteralProperties() { writeMajorLabel("Test SetProperty... and getProperty... methods " + "(set/get with literal values)"); var meta = XmpMetaFactory.ParseFromString(TestData.DATETIME_RDF); var dateValue = XmpDateTimeFactory.Create(2000, 1, 2, 3, 4, 5, 0); meta.SetPropertyBoolean(TestData.NS1, "Bool0", false); meta.SetPropertyBoolean(TestData.NS1, "Bool1", true); meta.SetPropertyInteger(TestData.NS1, "Int", 42); meta.SetPropertyDouble(TestData.NS1, "Double", 4.2); meta.SetPropertyDate(TestData.NS1, "Date10", dateValue); /* * TODO reinstate this code * * int offset = (/* hour #1# 06 * 3600 * 1000 + /* minute #1# 07 * 60 * 1000) * /* sign #1# 1; * dateValue.SetTimeZone(new SimpleTimeZone(offset, "test")); * meta.SetPropertyDate (NS1, "Date11", dateValue); * offset *= -1; * dateValue.SetTimeZone(new SimpleTimeZone(offset, "test")); * meta.SetPropertyDate (NS1, "Date12", dateValue); * dateValue.SetNanosecond(9); * meta.SetPropertyDate (NS1, "Date13", dateValue); */ printXmpMeta(meta, "A few basic binary Set... calls"); log.WriteLine(); bool b = meta.GetPropertyBoolean(TestData.NS1, "Bool0"); log.WriteLine("getPropertyBoolean ns1:Bool0 = " + b); b = meta.GetPropertyBoolean(TestData.NS1, "Bool1"); log.WriteLine("getPropertyBoolean ns1:Bool1 = " + b); int integer = meta.GetPropertyInteger(TestData.NS1, "Int"); log.WriteLine("getPropertyBoolean ns1:Int = " + integer); double d = meta.GetPropertyDouble(TestData.NS1, "Double"); log.WriteLine("getPropertyBoolean ns1:Int = " + d); log.WriteLine(); for (int i = 1; i <= 13; i++) { var dateName = "Date" + i; var dt = meta.GetPropertyDate(TestData.NS1, dateName); log.WriteLine("getPropertyDate (" + i + ") = " + dt); meta.SetPropertyDate(TestData.NS2, dateName, dateValue); } printXmpMeta(meta, "Get and re-set the dates in NS2"); }
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding encoding) { var xmp = XmpMetaFactory.SerializeToString(context.Object as IXmpMeta, new SerializeOptions()); using (var writer = context.WriterFactory(context.HttpContext.Response.Body, encoding)) { return(writer.WriteAsync(xmp)); } }
private static IReadOnlyList <XmpDirectory> ReadJpegSegments(IEnumerable <JpegSegment> segments) { // This is a modified version of XmpReader.ReadJpegSegments // The original version specifically tests the buffer against the classic XMP preamble and discards everything else. // Here we also test against the extended XMP preamble and regroup all the extended segments into a single buffer. // Note that we do not import any of the usual tags as in ProcessXmpTags(). Users of the class have to go // through XmpMeta methods. var directories = new List <XmpDirectory>(); byte[] extendedData = null; int maxPreambleLength = Math.Max(XmpJpegPreamble.Length, XmpJpegExtendedPreamble.Length); try { foreach (var segment in segments) { string extractedPreamble = Encoding.UTF8.GetString(segment.Bytes, 0, maxPreambleLength); if (extractedPreamble.StartsWith(XmpJpegPreamble)) { ParseNormalXmpSegment(directories, segment.Bytes); } else if (extractedPreamble.StartsWith(XmpJpegExtendedPreamble)) { ParseExtendedXmpSegment(ref extendedData, segment.Bytes); } } } catch (JpegProcessingException) { return(directories); } if (extendedData == null) { return(directories); } // We have collected extended XMP data, let's parse the reconstructed buffer. XmpDirectory directory = new XmpDirectory(); try { var xmpMeta = XmpMetaFactory.ParseFromBuffer(extendedData); directory.SetXmpMeta(xmpMeta); } catch (XmpException e) { directory.AddError("Error processing XMP data: " + e.Message); } directories.Add(directory); return(directories); }
private void WriteXmpMetaData(string imageFilePath, MasterImage masterImage, bool alwaysWriteMetadata, bool preview) { bool writeMetadata = false; IXmpMeta xmp = XmpMetaFactory.Create(); if ((!String.IsNullOrEmpty(masterImage.Caption) && !IsEquivalent(masterImage.Caption, imageFilePath)) || alwaysWriteMetadata) { xmp.AppendArrayItem(XmpConstants.NsDC, "dc:title", new PropertyOptions { IsArrayAlternate = true }, masterImage.Caption, null); writeMetadata = true; } if (!String.IsNullOrEmpty(masterImage.Comment)) { xmp.AppendArrayItem(XmpConstants.NsDC, "dc:description", new PropertyOptions { IsArrayAlternate = true }, masterImage.Comment, null); writeMetadata = true; } if (masterImage.Rating != null && (int)masterImage.Rating > 0) { xmp.SetProperty(XmpConstants.NsXmp, "xmp:Rating", ((int)masterImage.Rating).ToString()); writeMetadata = true; } // TODO: Handle faces. if (writeMetadata) { string metaFilePath = Path.ChangeExtension(imageFilePath, ".xmp"); if (File.Exists(metaFilePath)) { Console.Error.WriteLine("ERROR: XMP meta file already exists, skipping '" + metaFilePath + "'."); } else if (!preview) { Directory.CreateDirectory(Path.GetDirectoryName(metaFilePath)); using (var stream = File.OpenWrite(metaFilePath)) { XmpMetaFactory.Serialize(xmp, stream, new SerializeOptions { OmitPacketWrapper = true }); } numMetadataFilesCreated++; } } }
private void GenerateEAttachmentDocument(PdfAWriter writer, XmpWriter xmpWriter, EAttactment attachment) { // Use default intent if output intent of this instance was not set if (attachment.outputIntents == null) { //byte[] iccProfile = File.ReadAllBytes("/Resources/sRGB Color Space Profile.icm"); byte[] iccProfile = Properties.Resources.sRGB_Color_Space_Profile; ICC_Profile icc = ICC_Profile.GetInstance(iccProfile); writer.SetOutputIntents("sRGB IEC61966-2.1", "", "http://www.color.org", "sRGB IEC61966-2.1", icc); } else { OutputIntents outputIntents = attachment.outputIntents; byte[] iccProfileByteArray = File.ReadAllBytes(outputIntents.colorProfilePath); ICC_Profile icc = ICC_Profile.GetInstance(iccProfileByteArray); writer.SetOutputIntents(outputIntents.outputConditionIdentifier, outputIntents.outputCondition, outputIntents.registryName, outputIntents.info, icc); } //============= Create Exchange ECertificate ================= // 1 add ContentInformation.xml to document PdfArray attachmentArray = new PdfArray(); writer.ExtraCatalog.Put(new PdfName("AF"), attachmentArray); PdfFileSpecification contentSpec = this.EmbeddedAttachment(attachment.contentInformationXMLPath, attachment.attachmentName, attachment.attachmentMIME, new PdfName(attachment.attachmentType), writer, attachment.attachmentDescription); attachmentArray.Add(contentSpec.Reference); foreach (var item in attachment.fileAttachments) { contentSpec = this.EmbeddedAttachment(item.attachmentPath, item.attachmentName, item.attachmentMIME, new PdfName(item.attachmentType), writer, item.attachmentDescription); attachmentArray.Add(contentSpec.Reference); } // 2 add Electronic Document XMP Metadata ElectronicDocumentSchema ed = ElectronicDocumentSchema.generateED(attachment.attachmentName, attachment.documentVersion, attachment.documentID, attachment.documentOID); xmpWriter.AddRdfDescription(ed); string pdfaSchema = Properties.Resources.EDocument_PDFAExtensionSchema; // convert string to stream byte[] byteArray = Encoding.UTF8.GetBytes(pdfaSchema); //byte[] byteArray = Encoding.ASCII.GetBytes(contents); MemoryStream stream = new MemoryStream(byteArray); IXmpMeta edPDFAextension = XmpMetaFactory.Parse(stream); IXmpMeta originalXMP = xmpWriter.XmpMeta; XmpUtils.AppendProperties(edPDFAextension, originalXMP, true, true); }
/** * Flushes and closes the XmpWriter. * @throws IOException */ virtual public void Close() { if (outputStream == null) { return; } try { XmpMetaFactory.Serialize(xmpMeta, outputStream, serializeOptions); outputStream = null; } catch (XmpException xmpExc) { throw new IOException(xmpExc.Message); } }
/// <summary> /// Performs the XMP data extraction. /// <para /> /// The extraction is done with Adobe's XMPCore library. /// </summary> public XmpDirectory Extract([NotNull] byte[] xmpBytes) { var directory = new XmpDirectory(); try { var xmpMeta = XmpMetaFactory.ParseFromBuffer(xmpBytes); ProcessXmpTags(directory, xmpMeta); } catch (XmpException e) { directory.AddError("Error processing XMP data: " + e.Message); } return(directory); }
public XmpDirectory Extract([NotNull] byte[] xmpBytes, int offset, int length) { var directory = new XmpDirectory(); try { var xmpMeta = XmpMetaFactory.ParseFromBuffer(xmpBytes, offset, length); directory.SetXmpMeta(xmpMeta); } catch (XmpException e) { directory.AddError("Error processing XMP data: " + e.Message); } return(directory); }
internal static IXmpMeta Get(ImageDetails details) { var xmp = XmpMetaFactory.Create(); var idNs = "https://id.parliament.uk/"; var schemaNs = $"{idNs}schema/"; XmpMetaFactory.SchemaRegistry.RegisterNamespace(idNs, "id"); XmpMetaFactory.SchemaRegistry.RegisterNamespace(schemaNs, "schema"); xmp.SetProperty(XmpConstants.NsIptccore, "CiAdrCity", "London"); xmp.SetProperty(XmpConstants.NsIptccore, "CiAdrCtry", "UK"); xmp.SetProperty(XmpConstants.NsIptccore, "CiAdrRegion", "London"); xmp.SetProperty(XmpConstants.NsIptccore, "CiEmailWork", "*****@*****.**"); xmp.SetProperty(XmpConstants.NsIptccore, "CiTelWork", "+447740424810"); xmp.SetProperty(XmpConstants.NsIptccore, "CiUrlWork", "http://www.mcandrewphoto.co.uk"); xmp.SetProperty(XmpConstants.NsPhotoshop, "Source", "Chris McAndrew / UK Parliament"); xmp.SetProperty(XmpConstants.NsPhotoshop, "Credit", "Chris McAndrew / UK Parliament (Attribution 3.0 Unported (CC BY 3.0))"); xmp.SetPropertyDate(XmpConstants.NsPhotoshop, "DateCreated", XmpDateTimeFactory.Create(2017, 6, 17, 11, 30, 41, 0)); xmp.SetProperty(XmpConstants.NsDC, "rights", "Attribution 3.0 Unported (CC BY 3.0)"); xmp.SetProperty(XmpConstants.NsDC, "title", $"{details.GivenName} {details.FamilyName}"); xmp.SetProperty(XmpConstants.NsDC, "description", $"{details.GivenName} {details.FamilyName} - UK Parliament official portraits 2017"); xmp.SetProperty(XmpConstants.NsDC, "creator", "Chris McAndrew / UK Parliament"); // <rdf:Description rdf:about="http://id.parliament.uk/IMAGE1" /> xmp.SetObjectName($"{idNs}{details.Id}"); // id:IMAGE1 a schema:Image xmp.SetProperty(XmpConstants.NsRdf, "type", $"{schemaNs}Image", new PropertyOptions { IsUri = true }); // id:IMAGE1 schema:parlHasSubject id:PERSON1 xmp.SetProperty(schemaNs, "imageHasSubject", details.MemberUri, new PropertyOptions { IsUri = true }); // id:PERSON1 a schema:Person xmp.SetQualifier(schemaNs, "imageHasSubject", XmpConstants.NsRdf, "type", $"{schemaNs}Person", new PropertyOptions { IsUri = true }); return(xmp); }
virtual public void AddRdfDescription(XmpSchema s) { try { String str = "<rdf:RDF xmlns:rdf=\"" + XmpConst.NS_RDF + "\">" + "<rdf:Description rdf:about=\"" + xmpMeta.ObjectName + "\" " + s.Xmlns + ">" + s.ToString() + "</rdf:Description></rdf:RDF>\n"; IXmpMeta extMeta = XmpMetaFactory.ParseFromString(str); XmpUtils.AppendProperties(extMeta, xmpMeta, true, true); } catch (XmpException xmpExc) { throw new IOException(xmpExc.Message); } }
private static void HandleFile(FileInfo file) { // Console.WriteLine("{0}", file.Name); IXmpMeta xmp; String curFile = file.FullName.ToString(); // using (var stream = File.OpenRead(file.DirectoryName + "/" + file.Name)) using (var stream = File.OpenRead(curFile)) xmp = XmpMetaFactory.Parse(stream); Boolean success = false; foreach (var property in xmp.Properties) { success = false; //Console.WriteLine($"Path={property.Path} Namespace={property.Namespace} Value={property.Value}"); // Console.WriteLine($"Path={property.Path} Value={property.Value}"); // if (property.Path == "crs:Look/crs:Name"|| property.Path == "crs:Name[1]") if (property.Path == "crs:Name[1]") { string newfilename = property.Value.Trim().Replace('/', '-') + ".xmp"; if (string.Compare(newfilename, file.Name.ToString(), CultureInfo.CurrentCulture, CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreCase) == 0) // if (newfilename != file.Name) { break; } else { file.CopyTo(file.DirectoryName + "/" + file.Name + "_old", true); file.CopyTo(file.DirectoryName + "/" + newfilename, true); Console.WriteLine(property.Value); success = true; break; } } } if (success == true) { file.Delete(); } }
public void AddRdfDescription(String xmlns, String content) { try { String str = "<rdf:RDF xmlns:rdf=\"" + XmpConst.NS_RDF + "\">" + "<rdf:Description rdf:about=\"" + xmpMeta.ObjectName + "\" " + xmlns + ">" + content + "</rdf:Description></rdf:RDF>\n"; byte[] bytes = Encoding.Convert(Encoding.UTF8, Encoding.ASCII, Encoding.UTF8.GetBytes(str)); IXmpMeta extMeta = XmpMetaFactory.ParseFromString(str); XmpUtils.AppendProperties(extMeta, xmpMeta, true, true); } catch (XmpException xmpExc) { throw new IOException(xmpExc.Message); } }
public XmpDirectory Extract([NotNull] byte[] xmpBytes, int offset, int length) { if (offset < 0) { throw new ArgumentOutOfRangeException(nameof(offset), "Must be zero or greater."); } if (length < 0) { throw new ArgumentOutOfRangeException(nameof(length), "Must be zero or greater."); } if (xmpBytes.Length < offset + length) { throw new ArgumentException("Extends beyond length of byte array.", nameof(length)); } // Trim any trailing null bytes // https://github.com/drewnoakes/metadata-extractor-dotnet/issues/154 while (xmpBytes[offset + length - 1] == 0) { length--; } var directory = new XmpDirectory(); try { // Limit photoshop:DocumentAncestors node as it can reach over 100000 items and make parsing extremely slow. // This is not a typical value but it may happen https://forums.adobe.com/thread/2081839 var parseOptions = new ParseOptions(); parseOptions.SetXMPNodesToLimit(new Dictionary <string, int>() { { "photoshop:DocumentAncestors", 1000 } }); var xmpMeta = XmpMetaFactory.ParseFromBuffer(xmpBytes, offset, length, parseOptions); directory.SetXmpMeta(xmpMeta); } catch (XmpException e) { directory.AddError("Error processing XMP data: " + e.Message); } return(directory); }
private static void ParseNormalXmpSegment(List <XmpDirectory> directories, byte[] segmentBytes) { byte[] xmpBytes = new byte[segmentBytes.Length - XmpJpegPreamble.Length]; Array.Copy(segmentBytes, XmpJpegPreamble.Length, xmpBytes, 0, xmpBytes.Length); XmpDirectory directory = new XmpDirectory(); try { var xmpMeta = XmpMetaFactory.ParseFromBuffer(xmpBytes); directory.SetXmpMeta(xmpMeta); } catch (XmpException e) { directory.AddError("Error processing XMP data: " + e.Message); } directories.Add(directory); }
/// <summary> /// Given a sidecar object, parses the files (ON1 or XMP) and pulls out /// the list of keywords in the sidecar file. /// </summary> /// <param name="sidecar"></param> /// <returns></returns> public static IList <string> GetKeywords(this ImageSideCar sidecar) { var sideCarTags = new List <string>(); // If there's an On1 sidecar, read it try { if (sidecar.Type == SidecarUtils.SidecarType.ON1) { var on1MetaData = On1Sidecar.LoadMetadata(sidecar.Filename); if (on1MetaData != null && on1MetaData.Keywords != null && on1MetaData.Keywords.Any()) { sideCarTags = on1MetaData.Keywords .Select(x => x.Trim()) .ToList(); } } // If there's an XMP sidecar if (sidecar.Type == SidecarUtils.SidecarType.XMP) { using var stream = File.OpenRead(sidecar.Filename.FullName); IXmpMeta xmp = XmpMetaFactory.Parse(stream); var xmpKeywords = xmp.Properties.FirstOrDefault(x => x.Path == "pdf:Keywords"); if (xmpKeywords != null) { sideCarTags = xmpKeywords.Value.Split(",") .Select(x => x.Trim()) .ToList(); } } } catch (Exception ex) { Logging.LogError($"Exception processing {sidecar.Type} sidecar: {sidecar.Filename.FullName}: {ex.Message}"); } return(sideCarTags); }
public void XXE_DoctypeEnabled() { string testdata = @"<!DOCTYPE doc [<!ENTITY win SYSTEM ""c:\windows\win.ini"">]><doc></doc>"; var options = new Options.ParseOptions(); // enable doctype options.DisallowDoctype = false; Exception e = null; try { XmpMetaFactory.ParseFromString(testdata, options); } catch (Exception ex) { e = ex; } Assert.Null(e); }
/** * Creates an XmpWriter. * @param os * @param utfEncoding * @param extraSpace * @throws IOException */ public XmpWriter(Stream os, String utfEncoding, int extraSpace) { outputStream = os; serializeOptions = new SerializeOptions(); if (UTF16BE.Equals(utfEncoding) || UTF16.Equals(utfEncoding)) { serializeOptions.EncodeUtf16Be = true; } else if (UTF16LE.Equals(utfEncoding)) { serializeOptions.EncodeUtf16Le = true; } serializeOptions.Padding = extraSpace; xmpMeta = XmpMetaFactory.Create(); xmpMeta.ObjectName = XmpConst.TAG_XMPMETA; xmpMeta.ObjectName = ""; try { xmpMeta.SetProperty(XmpConst.NS_DC, DublinCoreProperties.FORMAT, "application/pdf"); xmpMeta.SetProperty(XmpConst.NS_PDF, PdfProperties.PRODUCER, Version.GetInstance().GetVersion); } catch (XmpException) {} }