public void setJavascriptForObject( final FormObject formObject, final int parentType, final int actionType) { final String JSscript; final PdfObject actionObj; final PdfObject JSobj; final PdfObject additionalObject = formObject.getDictionary(parentType); final ObjectDecoder objectDecoder = new ObjectDecoder(this.objectReader); objectDecoder.checkResolved(additionalObject); if (additionalObject == null) { return; } if (actionType == parentType) { actionObj = additionalObject; } else { if (actionType == PdfDictionary.C2) // special case { actionObj = additionalObject.getDictionary(PdfDictionary.C); } else { actionObj = additionalObject.getDictionary(actionType); } } if (actionObj == null) { // throw new RuntimeException("Failed on actionType="+actionType+" // "+formObject.getPDFRef()+ // "\nformObject="+formObject+" parentObject="+additionalObject+ // "\nadditionalObject="+additionalObject.getTextStreamValue(PdfDictionary.T) // +"\nadditionalObject="+formObject.getTextStreamValue(PdfDictionary.T)); } else { objectDecoder.checkResolved(actionObj); JSobj = actionObj.getDictionary(PdfDictionary.JS); if (JSobj != null) { final byte[] data = JSobj.getDecodedStream(); JSscript = StringUtils.getTextString(data, true); } else { JSscript = actionObj.getTextStreamValue(PdfDictionary.JS); } // store if (JSscript != null) { // use name to reference Js if name is null use ref. seems to be slower, but better on // abacus/L295KantoonVaadt.pdf String name = formObject.getTextStreamValue(PdfDictionary.T); if (name == null) { name = formObject.getObjectRefAsString(); } javascript.storeJavascript(name, JSscript, actionType); // old version // // javascript.storeJavascript(formObject.getObjectRefAsString(),JSscript,actionType); } } }
public static int setNameStringValue( final PdfObject pdfObject, int i, final byte[] raw, final boolean isMap, final Object PDFkey, final int PDFkeyInt, final PdfFileReader objectReader) { byte[] stringBytes; // move cursor to end of last command if needed while (raw[i] != 10 && raw[i] != 13 && raw[i] != 32 && raw[i] != 47 && raw[i] != '(' && raw[i] != '<') { i++; } i = StreamReaderUtils.skipSpaces(raw, i); // work out if direct (ie /String or read ref 27 0 R int j2 = i; byte[] arrayData = raw; boolean isIndirect = raw[i] != 47 && raw[i] != 40 && raw[i] != 60; // Some /NAME values start ( final boolean startsWithBrace = raw[i] == 40; // delete // @speed - lose this code once Filters done properly /* * just check its not /Filter [/FlateDecode ] or [] or [ /ASCII85Decode /FlateDecode ] * by checking next valid char not / */ boolean isInsideArray = false; if (isIndirect) { int aa = i + 1; aa = StreamReaderUtils.skipSpaces(raw, aa); if (raw[aa] == 47 || raw[aa] == ']') { isIndirect = false; i = aa + 1; isInsideArray = true; } } if (isIndirect) { // its in another object so we need to fetch final int[] values = StreamReaderUtils.readRefFromStream(raw, i); final int ref = values[0]; final int generation = values[1]; i = values[2]; if (raw[i] != 82) { // we are expecting R to end ref throw new RuntimeException( padding + "2. Unexpected value in file - please send to IDRsolutions for analysis"); } // read the Dictionary data arrayData = objectReader.readObjectAsByteArray( pdfObject, objectReader.isCompressed(ref, generation), ref, generation); // allow for data in Linear object not yet loaded if (arrayData == null) { pdfObject.setFullyResolved(false); if (debugFastCode) { System.out.println(padding + "Data not yet loaded"); } return raw.length; } // lose obj at start and roll onto / if (arrayData[0] == 47) { j2 = 0; } else { j2 = 3; while (arrayData[j2] != 47) { j2++; } } } // lose / j2++; // allow for no value with /Intent//Filter if (arrayData[j2] == 47) { return j2 - 1; } int end = j2 + 1; if (isInsideArray) { // values inside [] // move cursor to start of text j2 = StreamReaderUtils.skipSpacesOrOtherCharacter(arrayData, j2, 47); int slashes = 0; // count chars byte lastChar = 0; while (true) { if (arrayData[end] == ']') { break; } if (arrayData[end] == 47 && (lastChar == 32 || lastChar == 10 || lastChar == 13)) // count the / if gap before { slashes++; } lastChar = arrayData[end]; end++; if (end == arrayData.length) { break; } } // set value and ensure space gap final int charCount = end - slashes; int ptr = 0; stringBytes = new byte[charCount - j2]; byte nextChar, previous = 0; for (int ii = j2; ii < charCount; ii++) { nextChar = arrayData[ii]; if (nextChar == 47) { if (previous != 32 && previous != 10 && previous != 13) { stringBytes[ptr] = 32; ptr++; } } else { stringBytes[ptr] = nextChar; ptr++; } previous = nextChar; } } else { // its in data stream directly or (string) // count chars while (true) { if (startsWithBrace) { if (arrayData[end] == ')' && !ObjectUtils.isEscaped(arrayData, end)) { break; } } else if (arrayData[end] == 32 || arrayData[end] == 10 || arrayData[end] == 13 || arrayData[end] == 47 || arrayData[end] == 62) { break; } end++; if (end == arrayData.length) { break; } } // set value final int charCount = end - j2; stringBytes = new byte[charCount]; System.arraycopy(arrayData, j2, stringBytes, 0, charCount); } if (isMap) { pdfObject.setName(PDFkey, StringUtils.getTextString(stringBytes, false)); } else { pdfObject.setName(PDFkeyInt, stringBytes); } if (debugFastCode) { System.out.println( padding + "String set as =" + new String(stringBytes) + "< written to " + pdfObject); } // put cursor in correct place (already there if ref) if (!isIndirect) { i = end - 1; } return i; }
/** for the use of the printf commend */ private static String convertToken(final String token, final String arg1) { if (!StringUtils.isNumber(arg1)) { return ""; } final byte[] bytes = StringUtils.toBytes(arg1); final double value = NumberUtils.parseDouble(0, bytes.length, bytes); // a seperator is used for dates, phone numbers, times, ete int decimalPoints = -1, minWidth = 0; char decimal = '.'; // seperator = ',', boolean padd = false, floatDecimal = false; final StringBuilder sValue = new StringBuilder(); // used to store the value in string form for each type of output final StringBuilder returnString = new StringBuilder(); // conversion token layout: %[,nDecSep][cFlags][nWidth][.nPrecision]cConvChar final char[] tokArray = token.toCharArray(); if (tokArray[0] == '%') { int i = 1; final int size = tokArray.length; loop: while (i < size) { switch (tokArray[i]) { case ',': // nDecSep - A comma character (,) followed by a digit that indicates the // decimal/separator format: switch (tokArray[++i]) { case '0': // 0 � Comma separated, period decimal point // seperator = ','; decimal = '.'; break; case '1': // 1 � No separator, period decimal point // seperator = 0; decimal = '.'; break; case '2': // 2 � Period separated, comma decimal point // seperator = '.'; decimal = ','; break; case '3': // 3 � No separator, comma decimal point // seperator = 0; decimal = ','; break; } break; // cFlags - Only valid for numeric conversions and consists of a number of characters // (in any order), // which will modify the specification: case '+': // cFlags // + � Specifies that the number will always be formatted with a sign. if (value > 0) { returnString.append('+'); } else { returnString.append('-'); } break; case ' ': // cFlags // space � If the first character is not a sign, a space will be prefixed. if (value > 0) { returnString.append(' '); } else { returnString.append('-'); } break; case '0': // cFlags // 0 � Specifies padding to the field with leading zeros. padd = true; break; case '#': // cFlags // # � Specifies an alternate output form. For f, the output will always have a // decimal point. floatDecimal = true; break; case '.': // nPrecision - A period character (.) followed by a number that specifies the // number of digits // after the decimal point for float conversions. decimalPoints = Integer.parseInt(String.valueOf(tokArray[++i])); break; case 'd': // cConvChar // d � Integer (truncating if necessary) sValue.append((int) value); if (padd) { final int stringlen = returnString.length() + sValue.length(); if (stringlen < minWidth) { for (int p = 0; p < minWidth - stringlen; p++) { returnString.append('0'); } } } returnString.append(sValue); break loop; case 'f': // cConvChar // f � Floating-point number if (decimalPoints != -1) { if (decimalPoints == 0) { sValue.append((int) value); } else { final NumberFormat nf = NumberFormat.getInstance(); nf.setMinimumFractionDigits(decimalPoints); nf.setMaximumFractionDigits(decimalPoints); sValue.append(nf.format(value)); } } else { sValue.append((float) value); } if (floatDecimal && sValue.indexOf(".") != -1) { sValue.append('.'); } if (padd) { final int stringlen = returnString.length() + sValue.length(); if (stringlen < minWidth) { for (int p = 0; p < minWidth - stringlen; p++) { returnString.append('0'); } } } String ssVal = sValue.toString(); ssVal = ssVal.replace('.', decimal); // replace the decimal point with the defined one returnString.append(ssVal); break loop; case 's': // cConvChar // s � String sValue.append(value); // amay need arg1 if (padd) { final int stringlen = returnString.length() + sValue.length(); if (stringlen < minWidth) { for (int p = 0; p < minWidth - stringlen; p++) { returnString.append('0'); } } } returnString.append(sValue); break loop; case 'x': // cConvChar // x � Integer (truncating if necessary) and formatted in unsigned hexadecimal // notation final int valI = (int) (value); final String retValS = Integer.toHexString(valI); sValue.append(retValS); if (padd) { final int stringlen = returnString.length() + sValue.length(); if (stringlen < minWidth) { for (int p = 0; p < minWidth - stringlen; p++) { returnString.append('0'); } } } returnString.append(sValue); break loop; default: // nWidth - A number specifying a minimum field width. The converted argument is // formatted to be at // least this many characters wide, including the sign and decimal point, and may be // wider // if necessary. If the converted argument has fewer characters than the field // width, it is // padded on the left to make up the field width. The padding character is normally // a space, // but is 0 if the zero padding flag is present (cFlags contains 0). minWidth = NumberUtils.parseInt(0, 1, new byte[] {(byte) tokArray[i]}); break; } i++; } // end while loop } return returnString.toString(); }