Delphi'de gerçek PDF karartma (redaction), alttaki baytların üzerine boyamak değil, onları silmek anlamına gelir. losLab PDF Library bu ayrımı iki API ile çizer: RedactRegion sayfa içerik akışını düzenleyerek kaldırılan metin, vektör ve resimlerin fiziksel olarak yok olmasını sağlar; SanitizeDocument ise karartılan bilgilerin gizlendiği meta verileri, betikleri ve eylemleri temizler. İki yarımdan birini yanlış yaparsanız, ekranda sansürlenmiş görünen ancak metni kopyalayan veya Belge Özellikleri'ni açan herkese sırrı geri veren bir dosya göndermiş olursunuz
Bu hata modu kamuoyunun malumudur. Gazeteler, mahkemeler ve devlet kurumları, bir adın veya numaranın üzerine siyah bir dikdörtgen yerleştirilmiş PDF'ler yayınlamışlar, ancak bir okuyucu alttaki metni seçip kopyalamış ve karartıldığı varsayılan dizeyi açıkça görebileceği bir yere yapıştırmıştır. Dikdörtgen sadece bir çizimdi. Metin ise boyanın bir katman altında, içerik akışında tamamen sağlam ve seçilebilir bir şekilde duruyordu. TPDFlib sınıfı aracılığıyla sunulan Delphi ve C++Builder PDF motoru losLab PDF Library, bu ayrımı karartmanın sonradan akla gelen bir düşünce değil, asıl amacı olarak görür
PDF metninin üzerine siyah bir kutu çizmek neden gerçek karartma değildir?
losLab PDF Library, bir filigran, görsel karartma veya onay damgası gibi kapatmanın gerçekten istediğiniz şey olduğu durumlar için MaskRect yöntemini sunar. MaskRect(Page, Left, Top, Width, Height, Red, Green, Blue) yöntemi, sayfa içerik akışına bir dikdörtgen ekler og bunu re yol oluşturma operatörü ve ardından f doldurma operatörü ile boyar (ISO 32000-1 §8.5). Sayfada zaten mevcut olan her bayt — kapattığınız adın glifleri, vektör çizgileri, gömülü resim — aynı akışta bir önceki talimat olarak tam olarak bulunduğu yerde kalır. Uyumlu bir görüntüleyici siyah kutuyu en son çizer, böylece görsel olarak o kazanır. Kapatma, alttaki hiçbir şeyi değiştirmez
Herkes orijinal içeriği üç yolla geri alabilir: opak kutunun içinden metni doğrudan seçip kopyalayarak, sayfa üzerinde bir metin ayıklayıcı çalıştırarak veya içerik akışından kapatan dikdörtgeni silerek. MaskRect kendi adıyla bu konuda dürüsttür — maskeler, kaldırmaz. Sonuç, üzerindeki etiketi kaldırarak hala okuyabileceğiniz bir kelimenin üzerindeki yapışkan bir çıkartma gibidir
RedactRegion talimat düzeyinde içeriği nasıl siler
RedactRegion(Page, Left, Top, Width, Height, Options) boyanın bir katman altında çalışır. losLab PDF Library, sayfanın her içerik katmanını bir TPDFContentProgram olarak ayrıştırır, talimat listesini bir CTM izleme analizörü (içerik modelinde FindInstructionsInRect) ile tarar ve boyalı alanı dikdörtgeninizle kesişen her metin gösteren, yol boyayan ve resim çizen Do operatörünü işaretler. Bu talimatlar TPDFContentProgram.Delete ile kaldırılır ve düzenlenen katman WritePageContentLayer ile geri yazılır. Baytlar bir kapağın arkasına kaymaz — akıştan ayrılırlar. Daha sonra çalıştırılan bir metin ayıklayıcı hiçbir şey bulamaz, çünkü bulunacak hiçbir şey yoktur
İki uygulama ayrıntısını kendi mantığınıza dahil etmenizde fayda vardır. RedactRegion, geçerli başlangıç noktası ve birimlerindeki bir sol üst dikdörtgeni kabul eder ve bunu dahili olarak içerik akışının kullandığı sol alt kullanıcı alanına dönüştürür; böylece bölgeyi sayfada gördüğünüz şekilde belirlersiniz. Bir dikdörtgen birkaç talimatı kapsadığında, RedactRegion bunları azalan dizin sırasına göre siler; çünkü talimat 7'den önce talimat 4'ü kaldırmak sonraki her dizini kaydırır ve aralığı bozar. Options = 0 geçildiğinde losLab PDF Library temizlenen bölgeye görsel bir işaret olarak düz siyah bir kutu da basar — ancak bu işaret kozmetiktir, gerçek içerik zaten gittikten sonra uygulanır
Pratikte dikdörtgeni nadiren sabit kodlarsınız. Sayfada hassas dizeyi arar ve onun sınırlayıcı kutusunu okursunuz — Delphi'de metin ve sayfa öğelerinin yerini belirleme makalesinde ele alınan sayfa arama ve öğe listeleme ile aynıdır — ardından bu dikdörtgeni RedactRegion'a iletirsiniz:
var
PDF: TPDFlib;
begin
PDF := TPDFlib.Create;
try
if PDF.LoadFromFile('contract.pdf', '') = 1 then
begin
// Delete everything painted inside a 220 x 14 pt box on page 1.
// Coordinates are top-left, in the current origin and units.
PDF.RedactRegion(1, 90, 705, 220, 14, 0); // Options=0 stamps a black marker
PDF.SaveToFile('contract-redacted.pdf');
end;
finally
PDF.Free;
end;
end;
Karartılmış bilgiler bir PDF'te hala nerede gizlenir?
Görünür katmanda duran karartma geride bir iz bırakır, çünkü bir PDF bilgileri okuyucunun asla bakmadığı yerlerde saklar. losLab PDF Library bu sızıntıları adlandırılmaya değer kanallara ayırır. Belge Bilgi Sözlüğü ve XMP meta veri akışı rutin olarak, gövdeden kaldırdığınız kişinin veya davanın adını veren bir Yazar, Üretici veya Anahtar Kelimeler dizesi taşır. Belge düzeyindeki JavaScript ve katalog OpenAction açılışta yürütülebilir ve gittiğini düşündüğünüz verilere ulaşabilir. Her açıklama isteğe bağlı bir /A eylemi taşır ve açıklamanın kendisi — bir yapışkan not, eski bir form alanı, bir bağlantı — metnin kendi kopyasıyla doğrudan karartılmış alanın üzerinde yer alabilir. Bunların hiçbirine şifreleme dokunmaz; düz metin XMP paketi içeren şifrelenmiş bir dosya başlığını herhangi bir dizinleyiciye sızdırır; bu, kendi başına şifreleme ve izinleri denetleme makalesinde incelenmeye değer bir boşluktur. Savunulabilir bir temizleme, sadece baktığınız sayfayı değil, bu gizlenme yerlerinin her birini ziyaret etmelidir
SanitizeDocument ile belgeyi temizleme
losLab PDF Library bu sızıntı yelpazesine, bir bit maskesiyle seçilen bağımsız temizleme kümelerini çalıştıran ve uyguladığı temizleme sayısını döndüren bir düzenleme çağrısı olan SanitizeDocument(Flags) ile yanıt verir. Bayraklar birleştirilebilir. SANITIZE_JAVASCRIPT belge düzeyindeki her JavaScript paketini ve tüm OpenAction betiklerini kaldırır. SANITIZE_ACTIONS, yeni TPDFAnnots.RemoveAnnotAction aracılığıyla her açıklamadan /A eylem sözlüğünü çıkarır ve katalog OpenAction'ı temizler. SANITIZE_METADATA hem Belge Bilgi Sözlüğü'ndeki (ISO 32000-1 §14.3.3) hem de XMP meta veri akışındaki (§14.3.2) Yazar, Konu, Anahtar Kelimeler, Oluşturucu ve Üretici bilgilerini boşaltır. SANITIZE_ANNOTATIONS belge genelindeki her açıklamayı siler ve SANITIZE_OPEN_ACTION katalog /OpenAction girdisini kaldırır. SANITIZE_ALL, bu beşinin bit düzeyinde birleşimidir
Bu şeritlerin içindeki dizin kuralları, elle yazılmış bir döngüyü sessizce bozan türden şeylerdir; bu da SanitizeDocument'ın tek bir çağrı olarak var olmesinin önemli bir nedenidir. GlobalJavaScriptPackageName 0 tabanlıdır ve RemoveGlobalJavaScript ilerledikçe listeyi küçültür, bu nedenle JavaScript şeridi her zaman paket dizini 0'ı okur ve sayı sıfıra ulaşana kadar kaldırır. DeleteAnnotation ise buna karşılık 1 tabanlıdır. AnnotationCount o sırada seçili olan sayfaya göre rapor verir, bu nedenle açıklama şeritleri saymadan önce sırayla her sayfayı seçer. losLab PDF Library bu sınırları dahili olarak doğru yönetir, böylece beş farklı yineleme kuralını yeniden üretmek yerine tek bir bayrak kümesi geçirir ve bir sayım değerini geri okursunuz
var
Applied: Integer;
begin
// Strip metadata, scripts, and actions but keep the annotations:
Applied := PDF.SanitizeDocument(SANITIZE_METADATA or SANITIZE_JAVASCRIPT or
SANITIZE_ACTIONS or SANITIZE_OPEN_ACTION);
// Or clear every hidden channel, annotations included:
Applied := PDF.SanitizeDocument(SANITIZE_ALL);
end;
Eksiksiz karartma ve temizleme iş akışı
İkisini bir araya getirdiğinizde tam prosedür kısadır. losLab PDF Library sayfa sayfa RedactRegion ile görünür içeriği kaldırır, ardından dosya yazılmadan önce SanitizeDocument(SANITIZE_ALL) ile her gizli kanalı temizler. Karartma neredeyse her zaman kontrolünüz dışından gelen belgelerde çalıştığından, bunları korumalı bir yoldan yüklemek mantıklıdır — güvenilmeyen PDF'leri güvenle ayrıştırma makalesinde açıklanan savunma pozisyonuyla aynıdır — böylece bozuk bir girdi karartma aşamasının ortasında çökmek yerine temiz bir şekilde başarısız olur
var
PDF: TPDFlib;
Applied: Integer;
begin
PDF := TPDFlib.Create;
try
if PDF.LoadFromFile('incoming.pdf', '') = 1 then
begin
PDF.RedactRegion(1, 90, 705, 220, 14, 0); // delete the sensitive line
Applied := PDF.SanitizeDocument(SANITIZE_ALL); // clear metadata, JS, actions, annots
PDF.SaveToFile('published.pdf');
end;
finally
PDF.Free;
end;
end;
İçerik akışı karartmasının durduğu yer
RedactRegion içerik akışı üzerinde çalışır; bu da tam olarak dijital doğan metinlerin yaşadığı ve taranmış metinlerin yaşamadığı yerdir. Bir sayfa taranmış bir resim olduğunda, kelimeler metin operatörleri değil, bir resim XObject'inin içindeki piksellerdir ve losLab PDF Library bir adı bir piksel görüntüsünün ortasından bir glifi sildiği gibi söküp alamaz. Resim işleme yaklaşımı kasıtlı olarak muhafazakardır: yerleşimi dikdörtgenle kesişen her resim tamamen kaldırılır, bu nedenle taranmış bir sayfadaki bir karartma kutusu resmin bir parçası yerine tüm taramayı beraberinde götürür. Bir resim içindeki bir bölgeyi karartmak, içerik akışı silme işleminden farklı bir işlem olan piksel düzeyinde pikselleştirmek, boyamak ve yeniden gömmek anlamına gelir. Aynı dikkat, taranmış bir sayfa üzerindeki bir OCR metin katmanı için de geçerlidir: RedactRegion görebildiği metin operatörlerini kaldırır, ancak resim XObject'i de kutuyla kesişmedikçe alttaki resim dokunulmadan kalır
İki ince nokta sonuçların dürüst kalmasını sağlar. Kesişim testi, her metin serisinin genişliğini exact glif metriklerini ölçmek yerine karakter sayısından ve yazı tipi boyutundan kabaca tahmin eder, bu nedenle orantılı bir yazı tipiyle yazılmış çok kısa bir kelime sıkıca çizilmiş bir dikdörtgeni atlatabilir — kutuya küçük bir pay verin. Silme işlemi ayrıca talimat düzeyindedir: RedactRegion metin gösteren operatörleri tamamen kaldırır, bu nedenle bir serinin yalnızca bir kısmını kesen bir dikdörtgen, aynı operatörü paylaşan bitişik karakterleri de götürebilir. İki sınır da mekanizmaya güvenmemek için bir neden değildir, sadece dikdörtgeni dikkatlice sınırlandırmak ve sonucu kontrol etmek için bir nedendir
Her karartma iş akışını kapatan disiplin güven değil, doğrulamadır. Bölgeyi karartın, belgeyi temizleyin, yeni bir dosyaya kaydedin, yeniden açın ve hem kaldırdığınız metni hem de temizlediğiniz meta verileri geri almaya çalışın; her ikisi de boş döndüğünde karartma başarılı olmuş demektir. Burada gösterilen RedactRegion and SanitizeDocument API'leri, tam içerik modeli ve temizleme referansıyla birlikte Delphi ve C++Builder için losLab PDF Library ile birlikte gelir