Received today from Timothy Stebbing:
gday,
I ported forge_fdf to python for work, I thought it might be useful to you to use/post along with forge_fdf.php on the website for others. I've attached it, it's a direct block-for-block port, it could probably be optimised a fair bit but it was the least amount of effort to port it directly :) It makes an interesting comparison between the languages, just look at the line count ;)
-tjs
This code was later updated by Thomas Heetderks at Frontline Processing:
See the full article for code. Thanks Timothy and Thomas!
Forge_fdf is a little PHP script I created for casting form data into the FDF syntax. This is handy for filling online PDF forms automatically, or for filling forms using pdftk.
Here are some examples of forge_fdf in action:
# This is a port of forge_fdf.php by Sid Steward (www.pdfhacks.com/forge_fdf/)
# Created by Timothy Stebbing in python.
# Updated by Thomas Heetderks (2006-01-11) and Sid Steward
def escapePDFString(string):
rv = ''
for c in string:
if c in ['(',')','\']:
rv += '\'+c # escape the character
elif ord(c) < 32 or 126 < ord(c):
rv += '\%s3o' % (ord(c),) # use an octal code
else:
rv += c # let it pass through
return rv
def escapePDFName(string):
rv = ''
for c in string:
if ord(c) < 33 or 126 < ord(c) or c == '#':
rv += '#%s2x' % (ord(c),) # use a hex code
else:
rv += c # let it pass through
return rv
def burstDotsIntoDicts(FDFData):
rv = {}
for k, v in FDFData.items():
if '.' in k:
lhs, rhs = k.split('.',2)
if not rv.has_key(lhs):
rv[lhs] = {}
if type(rv[lhs]) is dict:
rv[lhs] = {'' : lhs} #apparently this should not happen
rv[lhs][rhs] = v
else:
if rv.has_key(k) and type(rv[k]) is dict:
rv[k][''] = v
else:
rv[k] = v
for k, v in rv.items():
if type(v) is dict:
rv[k] = burstDotsIntoDicts(v)
return rv
def forgeFDFFieldFlags(fdf, fieldName, fieldsHidden, fieldsReadonly):
if fieldName in fieldsHidden:
fdf += '/SetF 2' #set
else:
fdf += '/ClrF 2' #clear
if fieldName in fieldsReadonly:
fdf += '/SetFf 1' #set
else:
fdf += '/ClrFf 1' #clear
return fdf
def forgeFDFFields(fdf, fdfData, fieldsHidden,
fieldsReadonly, accumulatedName, fdfDataIsStrings):
if len(accumulatedName) > 0:
accumulatedName += '.' #append period seperator
for k, v in fdfData.items():
fdf += '> x0d' #close dictionary
return fdf
def forgeFDFFieldsStrings(fdf, fdfDataStrings, fieldsHidden, fieldsReadonly):
return forgeFDFFields(fdf, fdfDataStrings, fieldsHidden, fieldsReadonly,
'', True)
def forgeFDFFieldsNames(fdf, fdfDataStrings, fieldsHidden, fieldsReadonly):
return forgeFDFFields(fdf, fdfDataStrings, fieldsHidden, fieldsReadonly,
'', False)
def forgeFDF(PDFFormURL, FDFDataStrings,
FDFDataNames, fieldsHidden, fieldsReadonly):
fdf = '%FDF-1.2x0d%xe2xe3xcfxd3x0dx0a' #header
fdf += '1 0 objx0d> x0d' #close the FDF dictionary
fdf += '>> x0dendobjx0d' #close the root dictionary
#trailer; note the "1 0 R" reference to "1 0 obj" above
fdf += 'trailerx0d>x0d'
fdf += '%%EOFx0dx0a'
return fdf