Het lijkt mij dat de oplossingen van @
m3gA en @
DukeBox wel kunnen wat jij zoekt. Mocht dat niet zo zijn, dan kun je overwegen om zelf een stukje software te bouwen. Zoals ik al zei, een PDF'je zit niet zo heel ingewikkeld in elkaar.
Om je een idee te geven... Een PDF-document bestaat ruwweg uit een verzameling objecten en een of meer indextabellen (xref). De Indextabellen kun je gebruiken, maar hoeft niet, je kunt ook zelf op objectheaders scannen. Minder efficient, maar voor kleine documenten prima te doen.
Een Indextabel heeft een header bestaande uit 2 nummers die het eerste indexnummer en het aantal entries aangeven. Elke entry bestaat uit 2 nummers, gevolgd door 'f' or 'n'. Een entry eindigend op 'f' is vrij/bestaat niet. Bij een entry eindigend op 'n' is het eerste nummer de lokatie in de file (bytewise vanaf de PDF-header) en het tweede de revisienummer van het object.
Elk object heeft een header, een body eventueel een stream en een trailer.
- de header bestaat uit 2 nummers en de tekst 'obj', bijvoorbeeld "23 0 obj".
- de body kan van alles zijn maar is meestal een dictionary met parameters.
- als er een stream in zit, dan begint die met 'stream', eindigt met 'endstream'. De lengte en encoding van de stream zit in de array van de body.
- de trailer is altijd 'endobj'
Referenties naar objecten kun je altijd herkennen aan 2 cijfers, gevolgd door de hoofdletter R. Dus '23 0 R" refereert naar '23 0 obj'.
Met de bovenstaande structuur in gedachten, kun je de PDF beginnen te ontcijferen. Zoek in de trailers naar de '/Root' entry, die wordt gevolgd door een referentie. Zoek dat object op en je krijgt een object met "/Type /Catalog" in de body. Ook vind je in de body een "/Pages" met een referentie. Daarmee kom je in de root van de pagina-btree. Je kunt hier referenties naar losse pagina's aantreffen (die hebben een "/Type/Page" in de body) en/of referenties naar andere btree-nodes (die hebben een "/Type/Pages" entry in de body). Elke pagina heeft een "/Contents" object of array en refereert naar een of meerdere objecten met de daadwerkelijke content.
Meestal is die content ingepakt met zlib (in PHP te decoderen met zlib_decode()). Als dat zo is, dan staat er in de body van het object een '/Filter /Deflate' entry. Maar soms heb je geluk en is het al plain text. Wanneer je de content kunt zien (eventueel na het decoderen) tref je de instructies aan die de pagina opbouwen. Die bestaan uit 0 tot 6 parameters gevolgd door een operator. De tekst-operators zijn TJ, Tj, ' en ". De laatste 3 zijn enkelvoudige strings, de eerste (TJ) is een array bestaande uit strings en spacing-correcties.
Strings heb je in 2 vormen: plain en encoded. Een plain-string herken je snel genoeg, dat is platte tekst tussen ( en ), of in geval van TJ: [ (dit)3( is)-5( een )1(string.)]. Een encoded string is lastiger. Die string bestaat overigens niet uit ASCII-hexcodes maar uit Glyph-ID's. Dus heb je informatie nodig uit de fontdescriptor om de mapping van GID naar Unicode te kunnen maken. Zoek dan de laatst gebruikte font-operator (Tf) en kijk naar de 1ste parameter. Dat is een die begint met /. Zoek die naam in de resources-dictionary van de pagina op en je vind het Font. Zoek in het font en alle gerefereerde objecten naar de 'ToUnicode' entry. Als die er is, kun je in dat object uitvinden hoeveel bytes 1 karakter heeft en welk Unicode teken die vertegenwoordigd. Wanneer de 'ToUnicode' entry ontbreekt, zul je het font moeten inlezen in een tool als
http://www.glyphrstudio.com/online/ en zelf je ToUnicode moeten maken. Een encoded string herken je aan de < en > markering, of in het geval van TJ: [ <0003>-8<02d34f1a73> ].
Dat is dus het onttrekken van strings uit een PDF in een vogelvlucht. Voor meer informatie over het PDF-formaat, kun je ook het 1300 pagina's tellend PDF-reference gebruiken:
http://www.adobe.com/cont...dfs/pdf_reference_1-7.pdf