Metadata: การสร้างแพ็กเก็ต XMP และการอ่านแบบสตรีม
ภาพรวมโดยย่อ
หัวข้อที่มีชื่อว่า “ภาพรวมโดยย่อ”โมดูล Metadata เป็นเลเยอร์ Extensible Metadata Platform (XMP) ของเอนจิน ใช้สร้างแพ็กเก็ต XMP ที่ไฟล์ Portable Document Format (PDF) บรรจุไว้ในรูปของสตรีมเมตาดาตา อ่านแพ็กเก็ตที่มีอยู่ได้โดยไม่ต้องโหลดเอกสารทั้งฉบับเข้าหน่วยความจำ และปล่อยส่วนขยาย XMP สำหรับร่องรอยการตรวจสอบของเอนจิน
การติดตั้ง
หัวข้อที่มีชื่อว่า “การติดตั้ง”composer require nextpdf/core:^3ภาพรวมเชิงแนวคิด
หัวข้อที่มีชื่อว่า “ภาพรวมเชิงแนวคิด”PDF จัดเก็บเมตาดาตาระดับเอกสารในรูปของแพ็กเก็ต XMP ภายในสตรีมเมตาดาตาที่ผูกกับ document catalog ตามที่อธิบายไว้ใน ISO 32000-2 §14.3 โมดูลนี้รับผิดชอบทั้งการสร้างและการอ่านแพ็กเก็ตดังกล่าว พื้นผิวการใช้งานตั้งใจออกแบบให้เล็กและมุ่งเน้น ประกอบด้วยสามคลาสภายใต้ NextPDF\Metadata\Xmp
XmpMetadataBuilder เป็นตัวสร้างแพ็กเก็ต ตัวสร้างจะซีเรียลไลซ์ชุดพร็อพเพอร์ตีให้เป็นเอกสาร XMP ที่มีโครงสร้างถูกต้อง โดยห่อไว้ด้วย processing instructions <?xpacket?> มาตรฐาน ตัวสร้างใช้ค่า globally unique identifier (GUID) ของแพ็กเก็ตในรูปแบบ canonical และ byte-order mark ที่ข้อกำหนด XMP กำหนดไว้ตายตัว เอาต์พุตคือสตริงไบต์ที่ Writer ฝังไว้ในรูปของสตรีมเมตาดาตา ซึ่งเป็นการแทน XMP ภายใน PDF ตามที่อธิบายไว้ใน §14.3
XmpStreamReader เป็นตัวอ่านแพ็กเก็ต ตัวอ่านนี้สร้างมาเพื่อรับมือกับอินพุตที่เป็นอันตราย แหล่งข้อมูลจะถูกสตรีมเป็นชังก์ขนาด 64 KB ลงในไฟล์ชั่วคราวที่มีขีดจำกัดก่อนการแจง ตัวอ่านบังคับใช้ขีดจำกัดจำนวนไบต์โดยรวมระหว่างการเขียนนั้น entity loader ของ libxml จะถูกตั้งค่าเป็น null ระหว่างการแจง แล้วคืนค่ากลับหลังจากนั้น การมี DOCTYPE จะทำให้ถูกปฏิเสธทันที iterateProperties() คืนค่าเป็น generator ที่ส่ง tuple (namespaceUri, localName, textContent) สำหรับ leaf element แต่ละรายการ โดยไม่สร้างทรีทั้งหมดในหน่วยความจำ ในแต่ละช่วงเวลา มีเพียง element ปัจจุบันและ text node ของ element นั้นเท่านั้นที่คงอยู่ในตัวแจง แพ็กเก็ตที่มีขนาดเกินจะทำให้เกิด PacketTooLargeException ส่วน Extensible Markup Language (XML) ที่ผิดรูปแบบ การมี DOCTYPE หรืออินพุตที่ไม่ใช่ UTF-8 จะทำให้เกิด InvalidConfigException
XmpAuditFieldEmitter เป็นส่วนขยายเฉพาะของเอนจิน ตัวปล่อยนี้จะเรนเดอร์ AuditReport ลงในฟิลด์ XMP แบบกำหนดเองภายใต้ namespace nextpdfAudit เพื่อให้การตรวจสอบความสอดคล้องของเอกสารเดินทางไปพร้อมกับไฟล์ในรูปของ XMP ที่เป็นไปตามมาตรฐาน แทนที่จะอยู่ในรูปของ sidecar AuditReport ที่ตัวปล่อยเรนเดอร์ไม่ได้ถูกสร้างขึ้นโดยตัวปล่อยเอง ผู้เรียกจะเปิดใช้งานการเสริมข้อมูลด้วยการรันการเรนเดอร์ภายใต้ CssRenderingMode::Audit พร้อมกับ auditCollector ที่ผู้เรียกจัดเตรียมและกำหนดค่าผ่าน Config(auditCollector: ...) ตัวเก็บข้อมูลถูกขับเคลื่อนโดยผู้เรียก ผู้เรียกเป็นผู้ป้อนข้อมูลให้ และตัวปล่อยจะเรนเดอร์สิ่งที่ตัวเก็บข้อมูลรวบรวมไว้ ตัวปล่อยนี้ใหม่กว่าพื้นผิว XMP หลัก (@since 5.4.0) ตัวสร้างและตัวอ่านคือ @since 2.0.0
พื้นผิว API
หัวข้อที่มีชื่อว่า “พื้นผิว API”| คลาส | สมาชิกหลัก | บทบาท |
|---|---|---|
XmpMetadataBuilder | build(): string, XPACKET_GUID, XPACKET_BOM | ซีเรียลไลซ์ชุดพร็อพเพอร์ตีให้เป็นแพ็กเก็ต XMP (@since 2.0.0) |
XmpStreamReader | iterateProperties(mixed $source, int $byteCap = DEFAULT_BYTE_CAP): \Generator, DEFAULT_BYTE_CAP | ตัวอ่าน XMP ที่มีขีดจำกัด ทำงานแบบสตรีม และปฏิเสธ DOCTYPE (@since 2.0.0) |
PacketTooLargeException | extends NextPdfException | เกิดขึ้นเมื่อแพ็กเก็ต XMP เกินขีดจำกัดจำนวนไบต์ (@since 2.0.0) |
XmpAuditFieldEmitter | render(?AuditReport $report): string, NAMESPACE_URI | เรนเดอร์ร่องรอยการตรวจสอบในรูปของฟิลด์ XMP แบบกำหนดเอง (@since 5.4.0) |
รัน composer docs:generate-api-php -- --module=Metadata เพื่อสร้างตาราง PHPDoc ฉบับสมบูรณ์
ตัวอย่างโค้ด — เริ่มต้นใช้งานอย่างรวดเร็ว
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — เริ่มต้นใช้งานอย่างรวดเร็ว”สตรีมพร็อพเพอร์ตีออกจากแพ็กเก็ต XMP ที่มีอยู่ภายใต้ขีดจำกัดจำนวนไบต์ที่ระบุไว้อย่างชัดเจน
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Metadata\Xmp\XmpStreamReader;
$reader = new XmpStreamReader();
foreach ($reader->iterateProperties(file_get_contents('/srv/in/xmp.xml'), byteCap: 1_048_576) as [$ns, $name, $value]) { printf("%s:%s = %s\n", $ns, $name, $value);}ตัวอย่างโค้ด — ระดับใช้งานจริง
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — ระดับใช้งานจริง”อ่านแพ็กเก็ตอย่างระมัดระวัง และแมปข้อผิดพลาดของโมดูลที่มีชนิดไปยังผลลัพธ์ระดับแอปพลิเคชัน แทนที่จะปล่อยให้ข้อผิดพลาดดิบจากตัวแจงหลุดออกไป
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Exception\InvalidConfigException;use NextPDF\Metadata\Xmp\PacketTooLargeException;use NextPDF\Metadata\Xmp\XmpStreamReader;use Psr\Log\LoggerInterface;
final readonly class XmpIngestService{ public function __construct( private XmpStreamReader $reader, private LoggerInterface $logger, ) {}
/** * @param resource|string $source A stream resource or XMP byte string. * * @return array<string, string> Flattened "ns:name" => value map. */ public function ingest(mixed $source): array { $properties = [];
try { // Cap untrusted XMP at 4 MB regardless of the 1 GiB default. foreach ($this->reader->iterateProperties($source, byteCap: 4_194_304) as [$ns, $name, $value]) { $properties["{$ns}:{$name}"] = $value; } } catch (PacketTooLargeException $e) { $this->logger->warning('XMP packet exceeded ingest cap; rejected.', ['error' => $e->getMessage()]);
return []; } catch (InvalidConfigException $e) { $this->logger->warning('XMP packet malformed or unsafe; rejected.', ['error' => $e->getMessage()]);
return []; }
return $properties; }}กรณีขอบและข้อควรระวัง
หัวข้อที่มีชื่อว่า “กรณีขอบและข้อควรระวัง”XmpStreamReaderปฏิเสธ DOCTYPE ใดก็ตามทันที นี่คือการป้องกัน XML External Entity (XXE) ไม่ใช่กลไกตรวจสอบความถูกต้อง แพ็กเก็ตที่จำเป็นต้องมี DOCTYPE จะไม่ได้รับการยอมรับ ให้ทำความสะอาดแพ็กเก็ตตั้งแต่ต้นทาง- ขีดจำกัดจำนวนไบต์มีค่าเริ่มต้นที่ 1 GiB (
DEFAULT_BYTE_CAP) ค่าเริ่มต้นนี้เป็นเพดานสูงสุด ไม่ใช่ค่าที่แนะนำให้ใช้ ส่งค่าbyteCapที่เข้มงวดสำหรับอินพุตที่ไม่น่าเชื่อถือ iterateProperties()เป็น generator ที่ใช้งานได้เพียงครั้งเดียว การวนซ้ำครั้งที่สองจะไม่เล่นซ้ำ- ตัวอ่านตั้งค่า entity loader ของ libxml เป็น null ระหว่างการแจง แล้วคืนค่ากลับ อย่ารันพร้อมกับการแจงอื่นที่อิงกับ libxml ในรีเควสต์เดียวกัน หากการแจงนั้นพึ่งพา entity loader
XmpAuditFieldEmitter::render(null)ถูกต้องและให้ผลเป็นการเรนเดอร์ว่าง ค่าAuditReportที่เป็น null หมายถึง “no audit” ไม่ใช่ข้อผิดพลาด
ประสิทธิภาพ
หัวข้อที่มีชื่อว่า “ประสิทธิภาพ”ตัวสร้างทำงานแบบเชิงเส้นตามจำนวนพร็อพเพอร์ตี การใช้หน่วยความจำของตัวอ่านถูกกำหนดโดยช่วงข้อความเดี่ยวที่ยาวที่สุด ไม่ใช่ขนาดของเอกสาร เนื่องจากมีเพียง element ปัจจุบันเท่านั้นที่คงอยู่ในตัวแจง แพ็กเก็ตขนาดใหญ่จะถูกสตรีมแทนการโหลดเข้าหน่วยความจำ โหลดงานอ้างอิงเริ่มต้นอยู่ภายในงบประมาณ 1500 ms wall / 64 MB peak โปรไฟล์ความสามารถในการทำซ้ำคือ structural แพ็กเก็ต XMP บันทึก timestamp ของการแก้ไข การสร้างสองครั้งจากเมตาดาตาเชิงตรรกะเดียวกันจะแตกต่างกันในฟิลด์เหล่านั้น แต่โครงสร้างของทั้งสองจะเหมือนกันทุกประการ
หมายเหตุด้านความปลอดภัย
หัวข้อที่มีชื่อว่า “หมายเหตุด้านความปลอดภัย”XmpStreamReader แจง XML ที่ไม่น่าเชื่อถือ และได้รับการเสริมความแข็งแกร่งอย่างเหมาะสม การแบ่งชังก์แบบสตรีมพร้อมขีดจำกัดจำนวนไบต์ที่บังคับใช้ช่วยจำกัดการโจมตีปฏิเสธการให้บริการแบบขยายหน่วยความจำ การปฏิเสธ DOCTYPE ช่วยปิดช่องโหว่ XXE LIBXML_NONET ปิดกั้นการแปลงค่า entity ผ่านเครือข่าย อินพุตที่ไม่ใช่ UTF-8 จะถูกปฏิเสธ ถึงกระนั้น ก็ควรตั้งค่า byteCap ที่เหมาะสมกับการดีพลอยสำหรับแพ็กเก็ตที่มาจากแหล่งภายนอก แทนที่จะพึ่งพาค่าเริ่มต้นระดับกิกะไบต์ ปฏิบัติต่อค่าพร็อพเพอร์ตี XMP เหมือนสตริงที่ไม่น่าเชื่อถือเมื่อค่าเหล่านั้นกลับเข้าสู่แอปพลิเคชัน ดูแบบจำลองภัยคุกคามของเอนจินได้ที่ /modules/core/security/
ความสอดคล้องตามมาตรฐาน
หัวข้อที่มีชื่อว่า “ความสอดคล้องตามมาตรฐาน”แพ็กเก็ตที่ XmpMetadataBuilder สร้างขึ้นคือการแทนสตรีมเมตาดาตา XMP ภายใน PDF ตามที่กำหนดไว้ใน ISO 32000-2 §14.3 () รูปแบบการซีเรียลไลซ์ XMP เองถูกกำกับโดยข้อกำหนด XMP (ISO 16684-1) ซึ่งไม่ได้อยู่ในคลังการอ้างอิงที่ตรวจสอบได้ ข้อกำหนดนั้นถูกอ้างอิงด้วยหมายเลข ไม่ได้ถูกปักหมุดเป็นชังก์ สิ่งเหล่านี้คือข้อเท็จจริงเชิงการนำไปปฏิบัติที่สร้างขึ้นโดย src/Metadata/Xmp/ และถูกทดสอบโดย tests/Unit/Metadata/Xmp/ ความสอดคล้องของเมตาดาตาแบบครบวงจรสำหรับโปรไฟล์ (PDF/A, PDF/UA) ได้รับการตรวจสอบโดย oracle และชุดทดสอบ golden ตามที่อธิบายไว้ใน /modules/core/conformance/
ดูเพิ่มเติม
หัวข้อที่มีชื่อว่า “ดูเพิ่มเติม”- โมดูล Document — ทรี DPart ที่จับคู่กับ Document Part Metadata (DPM)
- โมดูล Audit — สร้าง
AuditReportที่ตัวปล่อยเรนเดอร์ - โมดูล Writer — ฝังแพ็กเก็ตในรูปของสตรีมเมตาดาตา
- ภาพรวมความสอดคล้องตามมาตรฐาน
- แบบจำลองความปลอดภัยของเอนจิน