- Untuk mengubah konten teks dalam PDF tanpa alat PDF komersial, Anda perlu mengekstrak stream yang terkompresi, menelusuri encoding per font, lalu mengganti teks asli dan teks pengganti dengan cara yang sama
- Banyak PDF menyimpan teks dokumen sebenarnya bukan sebagai plaintext, melainkan sebagai stream terkompresi dan string yang tampak seperti heksadesimal;
qpdf --qdf --object-streams=disable dapat mengekstraknya ke bentuk yang lebih mendekati bisa diedit
- Blok teks terdiri dari perintah PDF seperti
BT, Tf, Td, Tj, ET, dan nilai seperti <002a004800570003003600480057> Tj belum tentu merupakan code point Unicode sederhana
- Jika PDF menyertakan pemetaan ToUnicode per font, Anda bisa memakai
pdffonts untuk memeriksa apakah emb dan uni bernilai yes, lalu mengikuti referensi seperti /ToUnicode 19 0 R untuk menemukan tabel encoding
- Karena kompleksitas standar PDF, metode ini sulit digeneralisasi ke semua file, tetapi pada PDF tertentu Anda dapat menemukan encoding teks asli dan mengganti teks dengan find-and-replace
Mengekstrak Stream Teks PDF yang Terkompresi
- Jika PDF dibuka dengan editor teks, sebagian strukturnya dapat terbaca, tetapi teks dokumen sebenarnya mungkin tidak terlihat
- Banyak PDF menyimpan data teks dalam bentuk terkompresi
- Anda dapat mengekstrak stream teks terkompresi dengan
qpdf untuk memeriksanya
- Di Mac tersedia formula homebrew
- Di distribusi Linux, alat terkait juga tersedia
qpdf --qdf --object-streams=disable in.pdf out.pdf
- Setelah diedit, stream dapat dikompresi kembali
qpdf out-edited.pdf out-recompressed.pdf
- Perintah kompresi ulang menghasilkan error, tetapi PDF hasilnya tetap dapat dibaca di Preview
Mencari Teks di Dalam Perintah PDF
- Setelah diekstrak pun, teks masih berada di dalam blok perintah PDF
- Blok teks dasar memiliki bentuk seperti berikut
BT
/Font_0 12 Tf
288 720 Td
<002a004800570003003600480057> Tj
ET
- Berdasarkan PDF Reference, blok ini menjalankan operasi berikut secara berurutan
- Memulai objek teks
- Mengatur font dan ukuran yang akan digunakan
- Menentukan posisi awal pada halaman
- Menggambar glyph string di posisi tersebut
- Mengakhiri objek teks
Mengapa Teks Tidak Langsung Terbaca
- Nilai seperti
<002a004800570003003600480057> terlihat seperti string heksadesimal, tetapi belum tentu merupakan daftar code point Unicode sederhana
- PDF memiliki banyak cara untuk menentukan encoding, dan dapat menyertakan encoding kustom di dalam file
- Encoding semacam ini pada umumnya dapat dipetakan ke code point Unicode
- Prosedur ini mengasumsikan PDF yang sedang dikerjakan menyertakan encoding tertanam
- Cara menangani kasus lain tidak dibahas
Memeriksa Font dan Pemetaan Unicode
- Encoding teks PDF terkait dengan font tertentu
pdffonts menampilkan informasi tentang font dan encoding di dalam PDF
$ pdffonts sample.pdf
name type emb sub uni prob object ID
------------------------------------ ----------------- --- --- --- ---- ---------
CLDQZB+TrebuchetMS,Bold CID TrueType yes yes yes 9 0
YQBAIZ+TrebuchetMS CID TrueType yes yes yes 10 0
- Field yang perlu diperiksa di sini adalah sebagai berikut
emb: berarti font tertanam di dalam PDF
uni: berarti ada pemetaan Unicode
- Jika kedua nilainya
yes, ada kemungkinan Anda dapat menemukan pemetaan yang diperlukan
- Identifier font seperti
/Font_0 dalam contoh dapat berkorespondensi dengan nama font pada output pdffonts, bergantung pada kasusnya
- Pada kasus tersebut,
/Font_0 menunjuk ke CLDQZB+TrebuchetMS,Bold
Menelusuri Tabel Pemetaan ToUnicode
- Setelah menemukan nama lengkap font yang digunakan pada teks, cari nama tersebut di dalam PDF
- Di lokasi tertentu, Anda dapat menemukan referensi seperti berikut
/ToUnicode 19 0 R
- Nilai ini menunjuk ke ID objek tabel encoding
- Setelah itu, dengan mencari
19 0 obj, tabel tersebut dapat ditemukan
Mengganti Teks Menggunakan Tabel Encoding
- Bagian inti tabel pemetaan dapat berbentuk seperti berikut
38 beginbfrange^M
<0036><0036><0053>^M
<0057><0057><0074>^M
<0044><0044><0061>^M
<0048><0048><0065>^M
<0050><0050><006D>^M
...
- Contoh ini memetakan rentang titik encoding kustom ke titik Unicode
- Di sini rentangnya hanya satu karakter
0036 dipetakan ke titik Unicode 0053
- Jika format tabelnya berbeda, Anda dapat merujuk ke tutorial file pemetaan ToUnicode
- Untuk konversi otomatis, tabel diubah menjadi dictionary dengan Python dan fungsi encoding/decoding sederhana ditulis
- Alur penggantian akhirnya adalah sebagai berikut
- Periksa nilai encoding kustom dari teks lama yang ingin diganti
- Encoding teks pengganti dengan cara yang sama ke encoding kustom
- Ganti nilai lama di PDF dengan find-and-replace
1 komentar
Opini Hacker News
Spesifikasi PDF cukup kasar. Trivia favorit saya belakangan ini adalah bahwa saat merender elemen yang saling tumpang tindih, PDF mendukung semua mode blend layer Photoshop
Favorit kedua saya: konten yang ditambahkan di belakang bisa mengubah konten sebelumnya, jadi semua versi berbeda yang direpresentasikan dalam satu berkas harus diperiksa secara forensik
Ini juga contoh yang menunjukkan kehampaan DRM. Di spesifikasi ada enkripsi berbasis kata sandi, bisa ada kata sandi “owner” dan “user” yang terpisah, serta bit field seperti “dilarang mencetak” dan “dilarang menyalin teks”. Namun agar dokumen bisa dibaca, pada akhirnya ia harus didekripsi, jadi jika Anda membuka PDF terenkripsi dengan kata sandi “user” di alat yang tidak patuh, lalu menyimpannya sebagai versi yang tidak terenkripsi, Anda mendapatkan salinan ekuivalen yang bisa diedit
[1] Bagian “More than just transparency” dari https://blog.adobe.com/en/publish/2022/01/31/20-years-of-tra...
[2] https://blog.didierstevens.com/2008/05/07/solving-a-little-p...
[3] Halaman 61 dari https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandard...
[4] Misalnya skrip yang memakai pustaka pypdf
Salah satu tutorial cracking terkenal saat itu menghapus DRM dari reader resmi dengan menambal fungsi yang memeriksa izin
Topik ini muncul secara berkala; kebanyakan orang menganggap PDF sebagai format biner yang sulit ditembus, padahal sebenarnya tidak demikian
PDF adalah graf objek dengan berbagai tipe, dan tipenya sendiri dijelaskan dengan baik dalam spesifikasi resmi. Saya punya selera menyiksa diri untuk membacanya demi hiburan
Yang selalu saya sarankan adalah, seperti penulis, mengonversi PDF menjadi versi tanpa data terkompresi. Alat favorit saya adalah mutool, dan Anda bisa memakai
mutool clean -d in.pdf out.pdf. Setelah itu, jika Anda mengubek-ubeknya, Anda akan terkejut karena lebih banyak bagian yang bisa diikuti daripada yang didugaArtikel itu melewatkan tahap melihat objek halaman dan memeriksa resource. Di sanalah nama font yang dipakai dalam content stream dihubungkan dengan sub-objek sebenarnya
Bagian penting lain yang terlewat adalah bahwa sebagian besar font dimasukkan ke dalam PDF sebagai subset. Hanya glif yang diperlukan yang dipertahankan di font. Re-encoding biasanya tampaknya terjadi di sini, dan ToUnicode dipertahankan agar penyalinan teks atau pencarian PDF bisa dilakukan. Itu hal yang bagus bagi pengguna, dan menurut pengalaman saya umumnya ada serta cukup benar
Sejak awal, filosofi desain untuk membuat format read-only itu sendiri sudah keliru. Bukankah fungsi pertama yang akan diminta orang sudah jelas?
Saya penasaran apakah ada wawasan lain tentang cara menanganinya dengan baik secara native tanpa penyedia cloud. Terutama saat menangani tabel
Bisa dilakukan seperti ini:
Konversi ke PostScript
a.psdenganpdf2ps a.pdfEdit PostScript langsung dengan
vim a.psKonversi kembali ke PDF dengan
ps2pdf a.psPDF kompleks yang berisi JavaScript bawaan atau animasi kadang tidak berfungsi dengan benar setelah proses bolak-balik ini. Meski begitu, untuk dokumen biasa, cara ini bekerja cukup baik. Menghapus watermark serta mengubah kata dan angka mudah dilakukan, sedangkan mengubah spasi/jarak lebih sulit. Tentu saja, Anda perlu sedikit banyak memahami PostScript
Walaupun output-nya sudah benar, kami tetap perlu menyusun ulang halaman, menerapkan barcode untuk pemrosesan mesin surat dan penyortiran pos, serta membuat laporan. Biasanya kami mengeruk teks dari halaman dengan Perl dan alat lain untuk mendapatkan alamat, dan PS umumnya jauh lebih mudah daripada PDF, tetapi ada juga kasus yang sangat rapuh, misalnya ketika PDF “aman” tidak memiliki pemetaan glyph yang benar
Dalam kasus terburuk, pelanggan mengirim PDF dokumen tunggal, dan ketika digabungkan, font subset pada output membengkak drastis hingga memenuhi memori printer dan membuatnya mati. Saat saya berhenti dari pekerjaan itu pun, rasanya belum ada alat berguna untuk menyatukan dan menggabungkan font subset yang berasal dari font sumber yang sama. Seharusnya itu mungkin dan akan sangat berguna, tetapi saya tidak punya waktu atau pengetahuan untuk menyelidikinya
Sejujurnya, tampaknya satu-satunya pihak yang diuntungkan oleh kompleksitas PDF hanyalah pembuat malware
Sepertinya ada poin penting yang terlewat. Di akhir PDF ada tabel yang menyimpan offset byte berbagai objek di dalam file, yaitu tabel referensi silang
Jika isi file diubah, biasanya offset-offset ini berubah dan file menjadi rusak. Tulisan itu tampaknya hanya peduli pada mengganti satu angka dengan angka lain, sehingga posisinya mungkin tidak berubah
Namun secara umum, jika Anda menambah, menghapus, atau mengubah sesuatu di tengah file, tabel xref harus dihitung ulang, sehingga memakai library jauh lebih mudah daripada mengedit teks secara langsung
qpdf tampaknya merekonstruksi struktur PDF asli dan mencoba mempertahankan nomor objek apa adanya, tetapi offset dihitung ulang sepenuhnya
Kalau para pembuatnya suatu hari bercerita, saya ingin membaca mengapa formatnya menjadi seperti itu. Rasanya awalnya dimaksudkan sebagai format teks sepenuhnya, lalu belakangan mereka menilai biner lebih efisien. Namun keharusan membuat panjang entri tabel xref tetap juga agak aneh jika dikaitkan dengan asumsi itu
mutool cleanuntuk memperbaikinya. Karena dapat diturunkan sepenuhnya dari kontennya, ini amanSelama panjangnya dipertahankan, biner bisa diubah sesuka hati
Ada sebuah perangkat lunak yang dulu saya pakai yang melakukan autentikasi ke server, tetapi semua pemrosesan berlangsung di sisi klien. Klien mengeksekusi SQL langsung ke server, dan server hanya memeriksa apakah klien ini melampaui jumlah lisensi yang dibeli
Saya bisa menjalankannya di disassembler untuk menemukan bagian pemeriksaan, mengubah bagian itu langsung menjadi JMP, lalu mengisi ruang tersisa dengan NOP
Sepertinya ada langkah penting yang terlewat saat memakai mode
--qdfmilik qpdf. Setelah selesai mengedit, file perlu dilewatkan ke utilitas fix-pdf untuk menghitung ulang semua offset objek dan membangun ulang tabel referensi silang di akhir file. Pengecualiannya adalah jika Anda hanya mengganti di tempat tanpa menambah atau menghapus byteTiga fakta menarik teratas tentang PDF adalah sebagai berikut
[0] Contoh: https://lab6.com/2
Jika ingin terus mempelajari perjalanan PDF ini lebih lanjut, Anda bisa membaca dokumen pembedahan file yang baru-baru ini saya susun:
https://pdfsyntax.dev/introduction_pdf_syntax.html
Hal yang sering dilewatkan orang tentang PDF adalah bahwa dalam beberapa hal PDF lebih dekat ke format gambar daripada dokumen Word. Dalam penyuntingan dokumen, dokumen Word, PDF, dan gambar itu seperti proyek DAW, MIDI, dan MP3 dalam musik; mirip juga dengan kode sumber Java, bytecode JVM, dan bahasa mesin x86 murni dalam perangkat lunak
Tujuan utama file PDF adalah memberi tahu secara sepenuhnya jelas apa yang harus ditampilkan atau dicetak, dengan jumlah byte yang jauh lebih sedikit daripada gambar sebenarnya. Dengan memanfaatkan fakta bahwa pembuat dokumen mengetahui pola struktur dokumen, jika direpresentasikan dengan benar, hasilnya bisa terkompresi jauh lebih baik daripada algoritme kompresi gambar nyata. Misalnya, jika bisa mengakses font yang sebenarnya, lebih baik mengatakan “letakkan karakter-karakter ini di koordinat ini dengan jarak ini” daripada memasukkan setiap kemunculan huruf sebagai bagian dari gambar dan berharap algoritme kompresi mengurangi pengulangan dengan sendirinya. Karakter mana yang termasuk ke kata mana, bahkan codepoint Unicode mana yang sesuai dengan glyph font mana, pada dasarnya tidak penting jika tujuannya hanya menyampaikan citra dokumen secara efisien
Untuk dokumen yang dapat diedit, bukan hanya tampilan, tetapi struktur makna kontennya menjadi jauh lebih penting. Penting apakah jeda tertentu dalam teks adalah beberapa spasi, kolom berikutnya dalam tabel, atau tata letak halaman yang aneh karena gambar. Penting juga apakah teks di bagian bawah setiap halaman dimasukkan berkali-kali oleh penulis, atau dimasukkan sekali lalu ditetapkan sebagai footer. Jika menambahkan paragraf baru harus mengubah tata letak halaman, penting untuk mengetahui bahwa paragraf terakhir di halaman ini adalah catatan kaki sehingga tidak boleh berpindah ke halaman berikutnya. Yang penting adalah judul bagian yang berpindah ke halaman lain harus membuat daftar isi diperbarui otomatis, bukan sekadar teks yang diketik manual oleh penulis
Dari sudut pandang printer atau layar, semua itu tidak ada relevansinya. Mereka cukup mencetak atau menampilkan sesuai instruksi. Dalam PDF, catatan kaki, judul bagian, footer, dan daftar isi tidak perlu bersifat khusus; bisa saja hanya teks berformat tanpa makna. Karena itu, jika PDF digunakan untuk tujuan selain menampilkan atau mencetak, hasilnya tidak bisa 100% akurat. Tentu ada upaya untuk menambal kekurangan ini, dan program pembuat PDF bebas memasukkan metadata yang diinginkan, tetapi itu tidak wajib
Ini mungkin bukan model mental yang dimaksudkan oleh para pembuat PDF, tetapi sudut pandang ini berguna untuk memahami mengapa PDF berbentuk seperti itu
Jika dicetak dengan printer PostScript, tampilannya persis sama, dan dengan font Type 1 kadang bahkan lebih baik
Orang yang ingin melakukan ini melewatkan inti dari PDF. PDF adalah format deskripsi halaman, jadi ia hanya merepresentasikan jejak tampilan di atas halaman, bukan struktur dokumen
Jangan mencoba mengedit PDF; editlah dokumen asli yang menghasilkan PDF itu
Entah bagaimana, mengirim dokumen yang memang dibuat untuk diedit menjadi dianggap “tidak profesional”, dan akhirnya kita berada dalam situasi seperti ini
Opsional, tetapi disarankan demi aksesibilitas. Contohnya PDF/UA. Lihat bab 14.7–14.8 di [1]
[1] https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandard...
Teks PDF tidak bisa langsung diubah. Karena penata huruf tidak akan melihat perubahan itu. Alat markup Acrobat memang tidak buruk-buruk amat, tetapi belum setara dengan masa memakai kertas dan pensil merah. Kecuali jika memakai alat “pencil” Acrobat. Saya berharap bagian ini diperbaiki
Dua puluh tahun lalu saya bekerja di sebuah surat kabar sebagai penanggung jawab pelat cetak. Kami punya dua “printer” pelat Kodak seharga jutaan dolar, meskipun istilah printer kurang tepat. Kalau ingatan saya benar, emulsi pada pelat terkena sinar ultraviolet lalu larut dalam bak kimia
Peralatan Kodak itu sering gagal, dan atasan saya biasa membuka langsung file PostScript atau EPS untuk memperbaiki header atau bagian rusak yang dikirim perangkat lunak tata letak. Setelah itu semuanya berjalan lagi. Sebagai catatan, mesin cetak offset web raksasa buatan Jerman kami menjalankan Linux
Nama atasan saya sepertinya Bill. Dia orang baik yang pernah membawa saya, saat berusia 17 tahun, ke konser Sigur Ros. Jadi sudah ada dua cerita yang tidak ada hubungannya dengan PDF
Tulisan yang bagus. Selama kira-kira 5 tahun terakhir membuat DocSpring [1], saya banyak membaca spesifikasi PDF, tetapi rasanya masih baru menggores permukaannya. qpdf adalah alat yang luar biasa, dan alat lain yang saya sukai adalah RUPS [2], yang memungkinkan kita menggali struktur PDF secara mendalam
[1] https://docspring.com
[2] https://github.com/itext/i7j-rups