- बिना किसी commercial PDF tool के PDF की text content बदलनी हो, तो compressed stream को unpack करना होगा, font-specific encoding को समझना होगा, और original text व replacement phrase को उसी तरीके से बदलना होगा
- कई PDF असली document text को plain text की तरह नहीं बल्कि compressed stream और hex string जैसी दिखने वाली string के रूप में स्टोर करते हैं, और
qpdf --qdf --object-streams=disable से इन्हें editing के लिए अपेक्षाकृत खुला रूप दिया जा सकता है
- text block
BT, Tf, Td, Tj, ET जैसे PDF commands से बनते हैं, और <002a004800570003003600480057> Tj जैसा मान साधारण Unicode codepoint नहीं भी हो सकता है
- अगर PDF में font-specific ToUnicode mapping शामिल है, तो
pdffonts से emb और uni के yes होने की जाँच की जा सकती है, और /ToUnicode 19 0 R जैसे reference को follow करके encoding table खोजी जा सकती है
- PDF standard की जटिलता के कारण यह तरीका हर file पर सामान्य रूप से लागू नहीं होता, लेकिन कुछ खास PDF में original encoding ढूँढकर find-and-replace से text बदला जा सकता है
compressed PDF text stream को unpack करना
- PDF को text editor में खोलने पर कुछ structure पढ़ा जा सकता है, लेकिन असली document text दिखाई नहीं भी दे सकता है
- कई PDF text data को compressed form में स्टोर करते हैं
qpdf से compressed text stream को unpack करके देखा जा सकता है
- Mac पर homebrew formula उपलब्ध है
- Linux distributions में भी संबंधित tool उपयोग किए जा सकते हैं
qpdf --qdf --object-streams=disable in.pdf out.pdf
- edit करने के बाद stream को फिर से compress किया जा सकता है
qpdf out-edited.pdf out-recompressed.pdf
- recompress command ने error दिया, लेकिन बनी हुई PDF Preview में पढ़ी जा सकती थी
PDF commands के भीतर text ढूँढना
- unpack करने के बाद भी text PDF command block के भीतर ही रहता है
- एक basic text block कुछ ऐसा दिखता है
BT
/Font_0 12 Tf
288 720 Td
<002a004800570003003600480057> Tj
ET
- PDF Reference के अनुसार यह block क्रम से ये काम करता है
- text object शुरू करता है
- उपयोग होने वाला font और size सेट करता है
- page पर शुरुआती position तय करता है
- उस position पर string के glyph draw करता है
- text object समाप्त करता है
text सीधे पढ़ा क्यों नहीं जाता
<002a004800570003003600480057> जैसा मान hex string जैसा दिखता है, लेकिन यह साधारण Unicode codepoint list नहीं भी हो सकता है
- PDF में encoding बताने के कई तरीके होते हैं, और file के भीतर custom encoding भी शामिल हो सकती है
- ऐसी encoding अधिकतर Unicode codepoint से map की जा सकती है
- यह प्रक्रिया इस मान्यता पर आधारित है कि जिस PDF पर काम हो रहा है उसमें embedded encoding शामिल है
- दूसरे मामलों को कैसे संभालना है, यह यहाँ शामिल नहीं है
font और Unicode mapping की जाँच
- PDF का text encoding किसी खास font से जुड़ा होता है
pdffonts PDF के भीतर के fonts और encoding-संबंधित जानकारी दिखाता है
$ 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 ये हैं
emb: इसका मतलब font PDF में embedded है
uni: इसका मतलब Unicode mapping मौजूद है
- अगर दोनों मान
yes हैं, तो ज़रूरी mapping मिलने की संभावना है
/Font_0 जैसा font identifier कुछ मामलों में pdffonts output के font name से मेल खा सकता है
- इस उदाहरण में
/Font_0 CLDQZB+TrebuchetMS,Bold को संकेत कर रहा था
ToUnicode mapping table तक पहुँचना
- text में इस्तेमाल हुए font का पूरा नाम मिलने के बाद PDF के भीतर उसी नाम को search किया जाता है
- किसी खास जगह पर नीचे जैसा reference मिल सकता है
/ToUnicode 19 0 R
- यह मान encoding table object ID की ओर इशारा करता है
- फिर
19 0 obj खोजने पर संबंधित table मिल सकती थी
encoding table का उपयोग करके text replace करना
- mapping table का मुख्य हिस्सा कुछ ऐसा हो सकता है
38 beginbfrange^M
<0036><0036><0053>^M
<0057><0057><0074>^M
<0044><0044><0061>^M
<0048><0048><0065>^M
<0050><0050><006D>^M
...
- यह उदाहरण custom encoding point की range को Unicode point से map करता है
- यहाँ range एक-एक character की है
0036 Unicode point 0053 से map होता है
- अगर table format अलग हो, तो ToUnicode mapping file tutorial देखा जा सकता है
- automatic conversion के लिए Python से table को dictionary में बदला गया और सरल encoding/decoding functions लिखे गए
- अंतिम replacement flow इस प्रकार है
- जिस existing text को बदलना है उसका custom encoding value पता करें
- replacement text को उसी तरीके से custom encoding में encode करें
- PDF में find-and-replace करके पुराने value को बदल दें
1 टिप्पणियां
Hacker News राय
PDF specification काफी खुरदरा है। इन दिनों मेरी पसंदीदा trivia यह है कि overlapping elements render करते समय यह Photoshop के सभी layer blend modes support करता है
दूसरी पसंदीदा बात यह है कि बाद में append किया गया content पहले वाले content को modify कर सकता है, इसलिए एक ही file में represent किए गए अलग-अलग versions को forensic तरीके से देखना पड़ता है
यह DRM की निरर्थकता दिखाने वाला उदाहरण भी है। specification में password-based encryption है, “owner” और “user” passwords अलग-अलग रखे जा सकते हैं, और “printing not allowed”, “text copying not allowed” जैसे bit fields भी हैं। लेकिन document पढ़ने के लिए आखिर decrypt करना ही पड़ता है, इसलिए “user” password से किसी non-compliant tool में encrypted PDF खोलकर unencrypted version के रूप में save कर दें, तो editable equivalent मिल जाता है
[1] “More than just transparency” section of 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] Page 61 of https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandard...
[4] उदाहरण के लिए pypdf library इस्तेमाल करने वाली script
उस समय के famous cracking tutorials में से एक तरीका official reader के DRM को हटाने के लिए permissions check करने वाले function को patch करना था
यह topic समय-समय पर आता रहता है, और ज्यादातर लोग PDF को crack करना मुश्किल binary format समझते हैं, लेकिन असल में ऐसा नहीं है
PDF अलग-अलग types का object graph है, और types खुद official specification में अच्छी तरह समझाए गए हैं। मुझे उसे मज़े के लिए पढ़ने जैसा एक painful taste है
मेरी हमेशा सलाह रहती है कि लेखक की तरह PDF को ऐसी version में convert करें जिसमें compressed data न हो। पसंदीदा tool mutool है, और
mutool clean -d in.pdf out.pdfइस्तेमाल कर सकते हैं। फिर उसमें खोजबीन करें तो हैरानी होगी कि उम्मीद से ज्यादा चीजें follow की जा सकती हैंलेख में page object देखकर resources check करने वाला step छूट गया है। content stream में इस्तेमाल होने वाला font name असली child object से जहां जुड़ता है, वह वही जगह है
एक और महत्वपूर्ण बात छूटी है कि ज्यादातर fonts PDF के अंदर subset के रूप में शामिल होते हैं। font में सिर्फ जरूरी glyphs रखे जाते हैं। re-encoding आम तौर पर शायद यहीं होती है, और ToUnicode text copying या PDF search enable करने के लिए रखा जाता है। यह users के लिए अच्छा तत्व है, और मेरे अनुभव में ज्यादातर मौजूद और सही होता है
शुरुआत से ही read-only format बनाने की design philosophy गलत थी। लोगों की सबसे पहली मांग कौन-सी feature होगी, यह साफ नहीं था क्या
cloud provider के बिना native तरीके से इसे अच्छी तरह handle करने पर कोई और insight है क्या? खासकर tables handle करते समय
यह इस तरह किया जा सकता है:
pdf2ps a.pdfसे PostScripta.psमें बदलेंvim a.psसे PostScript को सीधे edit करेंps2pdf a.psसे फिर से PDF में बदलेंजिन complex PDF में embedded JavaScript या animation जैसी चीज़ें होती हैं, वे इस round-trip के बाद कभी-कभी ठीक से काम नहीं करतीं। फिर भी साधारण documents के लिए यह काफी अच्छे से काम करता है। watermark हटाना, शब्द और नंबर बदलना आसान है, और spacing ठीक करना ज्यादा मुश्किल है। बेशक PostScript की कुछ समझ होनी चाहिए
output सही हो तब भी pages reorder करना, mailing machine processing और mail sorting के लिए barcode लगाना, और reports generate करना जरूरी होता था। आम तौर पर Perl और दूसरे tools से pages से text scrape करके address निकाले जाते थे, और PDF की तुलना में PS आम तौर पर बहुत आसान था, लेकिन बहुत unstable cases भी होते थे, जैसे जब “secure” PDF में सही glyph mapping नहीं होती थी
सबसे बुरे case में customers single-document PDFs भेजते थे, और इन्हें merge करने पर output में subset fonts की बाढ़ आ जाती थी, जिससे printer memory भरकर printer मर जाता था। जब मैंने वह काम छोड़ा, तब भी मुझे नहीं लगता कि उसी original font से आए subset fonts को consolidate/merge करने वाला कोई उपयोगी tool था। यह संभव होना चाहिए था और बहुत उपयोगी होता, लेकिन मेरे पास इसे देखने का समय या knowledge नहीं था
सच कहूँ तो PDF की complexity से फायदा उठाने वाले सिर्फ malware creators ही लगते हैं
लगता है एक अहम बात छूट गई है। PDF के अंत में file के अंदर कई objects के byte offsets store करने वाली table होती है, यानी cross-reference table
file के अंदर कुछ modify करने पर आम तौर पर ये offsets बदल जाते हैं और file टूट जाती है। लेख शायद सिर्फ एक number को दूसरे number से बदलने में interested था, इसलिए position शायद नहीं बदली होगी
लेकिन आम तौर पर file के बीच में add/delete/modify करने पर xref table को फिर से calculate करना पड़ता है, इसलिए direct text editing की तुलना में library इस्तेमाल करना कहीं आसान हो जाता है
qpdf लगता है original PDF structure को reconstruct करता है, और object numbers भी वैसे ही रखने की कोशिश करता है, लेकिन offsets पूरी तरह फिर से calculate होते हैं
अगर authors कभी इसके बारे में बताएं, तो मैं पढ़ना चाहूँगा कि format ऐसा क्यों बनाया गया। लगता है शुरुआत में इसे पूरी तरह text format के रूप में सोचा गया था, फिर बाद में binary को ज्यादा efficient माना गया। हालांकि xref table entries की length fixed रखनी पड़ती है, यह बात उस assumption के साथ भी थोड़ी अजीब तरह से जुड़ती है
mutool cleanजैसी चीज़ चलाना सबसे आसान है। चूँकि इसे content से पूरी तरह derive किया जा सकता है, इसलिए यह safe हैजब तक length preserve करें, binary में मनचाहे changes कर सकते हैं
पहले इस्तेमाल होने वाला एक software server पर authenticate करता था, लेकिन सारी processing client पर होती थी। client सीधे server पर SQL execute करता था, और server बस यह check करता था कि यह client खरीदी गई licenses की संख्या से ज्यादा तो नहीं जा रहा
disassembler में चलाकर check करने वाला हिस्सा ढूँढ सकते थे, उस हिस्से को सीधे JMP में बदल सकते थे, और बची हुई जगह NOP से भर सकते थे
qpdf के
--qdfmode का इस्तेमाल करते समय लगता है एक अहम step छूट गया है। editing खत्म होने के बाद file को fix-pdf utility से pass कराना चाहिए ताकि सभी object offsets फिर से calculate हों और file के अंत की cross-reference table फिर से बने। हाँ, अगर आपने bytes add या remove नहीं किए और सिर्फ inplace बदलाव किए, तो exception हैPDF के top 3 मजेदार facts ये हैं
[0] उदाहरण: https://lab6.com/2
PDF journey जारी रखते हुए अगर और सीखना चाहते हैं, तो हाल में तैयार किया गया file dissection document पढ़ सकते हैं:
https://pdfsyntax.dev/introduction_pdf_syntax.html
PDF के बारे में लोग अक्सर जो बात चूक जाते हैं, वह यह है कि कुछ मायनों में यह Word document से ज़्यादा image format के करीब है। document editing में Word document, PDF और image वैसे ही हैं जैसे music में DAW project, MIDI और MP3; और software में Java source code, JVM bytecode और pure x86 machine code
PDF file का मुख्य उद्देश्य यह है कि वास्तविक image की तुलना में बहुत कम bytes में पूरी स्पष्टता से बताया जाए कि क्या दिखाना या print करना है। यह इस बात का फायदा उठाता है कि document बनाने वाला document structure के patterns जानता है, ताकि सही ढंग से व्यक्त करने पर यह वास्तविक image compression algorithms से कहीं बेहतर compress हो सके। उदाहरण के लिए, अगर वास्तविक font तक access हो, तो हर अक्षर की उपस्थिति को image के हिस्से के रूप में डालकर compression algorithm से repetition कम करने की उम्मीद करने के बजाय, “इन characters को इन coordinates पर इस spacing के साथ रखो” कहना बेहतर है। कौन सा character किस word से जुड़ा है, या यहां तक कि कौन सा Unicode codepoint किस font glyph से मेल खाता है, अगर लक्ष्य सिर्फ document image को efficiently deliver करना है तो मूल रूप से महत्वपूर्ण नहीं है
editable document में representation के साथ-साथ content की semantic structure कहीं ज़्यादा महत्वपूर्ण हो जाती है। text में कोई खास break कई spaces है, table का अगला column है, या image की वजह से बना अजीब page layout—यह महत्वपूर्ण है। हर page के नीचे का text लेखक ने कई बार डाला है, या एक बार type करके footer के रूप में set किया है—यह भी महत्वपूर्ण है। अगर नया paragraph जोड़कर page layout बदलना है, तो यह बात महत्वपूर्ण है कि इस page का आखिरी paragraph footnote है और उसे अगले page पर नहीं जाना चाहिए। section title अगर दूसरे page पर चला जाए तो table of contents अपने-आप update होना चाहिए—यह महत्वपूर्ण है; यह सिर्फ लेखक द्वारा manually type किया गया text नहीं होना चाहिए
printer या screen के नज़रिए से इन बातों का कोई मतलब नहीं। उसे जैसा निर्देश मिला है, वैसा print या display करना है। PDF में footnote, section title, footer, table of contents का special होना ज़रूरी नहीं; वे अर्थहीन formatting वाला text भी हो सकते हैं। इसलिए display या printing के अलावा किसी उद्देश्य के लिए PDF इस्तेमाल करने की कोशिश करें तो यह 100% accurate नहीं हो सकता। बेशक, इसे सुधारने की कोशिशें हैं, और PDF generation programs मनचाहा metadata स्वतंत्र रूप से डाल सकते हैं, लेकिन यह अनिवार्य नहीं है
हो सकता है PDF लेखकों का intended mental model यह न रहा हो, लेकिन PDF वैसा क्यों है यह समझने के लिए यह उपयोगी दृष्टिकोण है
PostScript printer पर output करने पर यह बिल्कुल वैसा ही दिखता था, और Type 1 fonts इस्तेमाल करने पर कभी-कभी और बेहतर भी होता था
जो व्यक्ति यह करना चाहता है, वह PDF की मुख्य बात चूक रहा है। PDF एक page description format है, इसलिए यह document structure नहीं बल्कि page पर दिखने वाले marks को ही दर्शाता है
PDF को edit करने की कोशिश न करें; उस original document को edit करें जिससे PDF बना था
किसी तरह edit करने के लिए बने documents को सीधे भेजना “professional नहीं” माना जाने लगा, और आखिरकार यही स्थिति बन गई
यह optional है, लेकिन accessibility के लिए recommended है। उदाहरण के लिए PDF/UA है। [1] के sections 14.7–14.8 देखें
[1] https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandard...
PDF text को सीधे बदल नहीं सकते। क्योंकि typesetter वह change नहीं देखेगा। Acrobat के markup tools भयानक नहीं हैं, लेकिन वे कागज और लाल pencil वाले दिनों जितने अच्छे नहीं। जब तक आप Acrobat का “pencil” tool न इस्तेमाल करें। अच्छा होगा अगर यह हिस्सा बेहतर हो जाए
20 साल पहले मैं एक newspaper company में printing plate in-charge के तौर पर काम करता था। हमारे पास million-dollar वाली दो Kodak plate “printers” थीं, हालांकि printer कहना ठीक नहीं है। अगर मेरी याद सही है, तो plate की emulsion ultraviolet light पड़ने पर chemical bath में dissolve होती थी
Kodak equipment अक्सर fail हो जाता था, और मेरे boss PostScript या EPS files को सीधे खोलकर layout software द्वारा भेजे गए headers या गलत हिस्सों को ठीक करते थे। फिर यह फिर से ठीक चलने लगता था। वैसे, हमारी विशाल German offset web press Linux चलाती थी
शायद मेरे boss का नाम Bill था। वह अच्छा इंसान था, जिसने 17 साल के मुझे Sigur Ros concert में ले गया था। PDF से unrelated दो बातें हो गईं
अच्छा लेख है। पिछले करीब 5 वर्षों में DocSpring [1] बनाते हुए मैंने PDF specification काफी पढ़ी है, फिर भी लगता है कि अभी सिर्फ सतह ही खुरची है। qpdf शानदार tool है, और मेरा एक और पसंदीदा tool RUPS [2] है, जिससे PDF structure को गहराई से explore किया जा सकता है
[1] https://docspring.com
[2] https://github.com/itext/i7j-rups