Failed to add fdf with attachment annotation - annotations

I work on an application to add annotation from a fdf file to a Pdf file
With iText can do in this way
FdfReader aFdfReader = new FdfReader(new FileInputStream(args[0]));
PdfReader aReader = new PdfReader(new FileInputStream(args[1]));
PdfStamper aStamper = new PdfStamper(aReader, new FileOutputStream(args[2]));
aStamper.addComments(aFdfReader);
aStamper.close();
But when i load the fdf I have this exception. The fdf have an annotation with the type attachment file.
Exception in thread "main" com.itextpdf.text.exceptions.InvalidPdfException: Error reading string at file pointer 5106590
at com.itextpdf.text.pdf.PRTokeniser.throwError(PRTokeniser.java:220)
at com.itextpdf.text.pdf.PRTokeniser.nextToken(PRTokeniser.java:411)
at com.itextpdf.text.pdf.PRTokeniser.nextValidToken(PRTokeniser.java:282)
at com.itextpdf.text.pdf.PdfReader.readPRObject(PdfReader.java:1908)
at com.itextpdf.text.pdf.PdfReader.readArray(PdfReader.java:1891)
at com.itextpdf.text.pdf.PdfReader.readPRObject(PdfReader.java:1946)
at com.itextpdf.text.pdf.PdfReader.readDictionary(PdfReader.java:1877)
at com.itextpdf.text.pdf.PdfReader.readPRObject(PdfReader.java:1913)
at com.itextpdf.text.pdf.PdfReader.readDocObj(PdfReader.java:1411)
at com.itextpdf.text.pdf.FdfReader.readPdf(FdfReader.java:105)
at com.itextpdf.text.pdf.PdfReader.(PdfReader.java:181)
at com.itextpdf.text.pdf.PdfReader.(PdfReader.java:395)
at com.itextpdf.text.pdf.PdfReader.(PdfReader.java:415)
at com.itextpdf.text.pdf.FdfReader.(FdfReader.java:92)
at com.artesys.pdf.itext.pdf.AddFdf.main(AddFdf.java:18)
I do the test with itext_so.pdf to attach to the annotation
if i made the test with a helloword i works fine
I used the version 5.5.9
Thank in advance for your response
Regards
Fabien

The FDF is special as it contains a PDF in a stream; this PDF stream is partially uncompressed; thus, PDF syntax, in particular PDF indirect object starts are visible.
And the FdfReader works incorrectly: It assumes these starts of indirect objects in a stream content to be top level FDF object starts and fails when trying to read those objects.
One can quick-fix this by making the FdfReader object reading more forgiving.
The FDF
Your FDF looks like this:
%FDF-1.2
%âãÏÓ
1 0 obj
<</FDF<</Annots[2 0 R]/F(http://localhost:8780/PachaServer/downloadpacha?pathpdf=Rendition.pdf&edit=false&loginname=fhfgh)/ID[<2175D5400E41761374A2EB01E7026C68><5E9C3BFFF121CE737ED66FF7318CA58D>]/UF(http://localhost:8780/PachaServer/downloadpacha?pathpdf=Rendition.pdf&edit=false&loginname=fhfgh)>>/Type/Catalog/Version/1.6>>
endobj
2 0 obj
<</C[0.25 0.333328 1.0]/Contents(itext_so.pdf)/CreationDate(D:20160519150439+02'00')/F 28/FS 3 0 R/M(D:20160519150439+02'00')/NM(79bcf116-d9bd-4ade-a8cd-7575351271fd)/Name/Paperclip/Page 0/RC(<?xml version="1.0"?><body xmlns="http://www.w3.org/1999/xhtml" xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/" xfa:APIVersion="Acrobat:15.16.0" xfa:spec="2.0.2" ><p>itext_so.pdf</p></body>)/Rect[183.106 684.663 190.106 701.663]/Subj(Pièce jointe)/Subtype/FileAttachment/T(Fabien.Levalois)/Type/Annot>>
endobj
3 0 obj
<</EF<</F 4 0 R>>/F(itext_so.pdf)/Type/Filespec/UF(itext_so.pdf)>>
endobj
4 0 obj
<</DL 10536008/Filter/FlateDecode/Length 10207532/Params<</CheckSum("}þ¶îô/Óý‡†d’ÒÎ)/CreationDate(D:20160511112202+02'00')/ModDate(D:20160511112205+02'00')/Size 10536008>>/Subtype/application#2Fpdf>>stream
... [10207532 data bytes] ...
endstream
endobj
trailer
<</Root 1 0 R>>
%%EOF
This structure is correct. But the contents of the big stream, the 10207532 data bytes in object 4 are special: They constitute a PDF document, and as this document already is compressed, it partially could not be compressed any further when embedded into the FDF and the original PDF syntax becomes piecewise visible, e.g. some 660000 bytes into the stream there suddenly are byte sequences which represent an end of the current PDF stream and the start of another indirect PDF object:
endstream
endobj
10283 0 obj
<</Extends 10282 0 R/Filter/FlateDecode/First 1139/Length 4195/N 100/Type/ObjStm>>stream
...
endstream
endobj
10284 0 obj
<</Extends 10282 0 R/Filter/FlateDecode/First 1139/Length 4018/N 100/Type/ObjStm>>stream
...
endstream
endobj
10285 0 obj
<</Extends 10282 0 R/Filter/FlateDecode/First 190/Length 1001/N 18/Type/ObjStm>>stream
etc. etc. etc.
As these PDF objects only are piecewise visible, though, trying to read them as is can result in an error.
The FdfReader
As an FDF does not need to contain a cross reference section, the FdfReader as a first step tries to create one by searching the file for byte sequences which appear to be the start of indirect objects and deriving a cross reference section from that.
This is incorrect, though, because in cases like your FDF it creates many false cross reference entries, and while reading these false indirect objects, errors occur unless the false objects are syntactically correct.
In case of your PDF many false objects are syntactically correct until a location near the offset 5106590 mentioned in the exception where a false indirect object is partially re-compressed. And when trying to reading that, FdfReader throws the exception you observed.
But the problem are not only such syntax errors (these could be caught and ignored after all) but that false objects and true objects may have the same object number. Thus, FdfReader might use a false object instead of a true one!
A quick fix
While the cross reference reconstruction code for the FdfReader fundamentally has to be re-implemented for a true fix, there is a quick fix for it allowing it to properly process FDFs in which the "false FDF objects" do not collide with true ones, simply derive a class from FdfReader and override the method readPRObject() like this:
#Override
protected PdfObject readPRObject() throws IOException
{
try
{
return super.readPRObject();
}
catch (InvalidPdfException e)
{
return PdfNull.PDFNULL;
}
}
(ImprovedFdfReader.java)
While reading the provided FDF itext-SO.fdf using the ReadFdf.java test method testReadFdfFabienLevalois with a normal FdfReader fails, doing so using the test method testReadFdfFabienLevaloisImproved with an ImprovedFdfReader succeeds.

Related

Dynamic generation of signal spies in testbench

I have a .txt file that contains certain signals that I want to monitor in my testbench during the application of some stimulus.
I am creating an initial block in which I am reading the file and then I try to generate a init_signal_spy() for every one of the lines that I have read.
The code that I have written up until this point has the following format:
module testbench();
logic probes[];
initial begin : read_signals_to_dump_at
automatic int fd;
automatic string fname,line,line_stripped;
if ($value$plusargs("sigfile=%s",fname)) begin : read
fd = $fopen(fname,"r");
while($fgets(line,fd)) begin
//static logic net_to_be_probed;
automatic sig_and_spy entry = new();
// Trim away the '\n' from the line.
line_stripped = line.substr(0,line.len()-2);
// Resize the array
probes = new [probes.size() + 1] (probes);
// Link the extracted new line with the probe list
// - this raises an error "An invalid empty string was passed in as the Destination object."
// - expected since the last element is empty...
$init_signal_spy(line_stripped, probes[probes.size()-1] , 1);
end
end
end : read_signals_to_dump_at
endmodule
In the code above, just before I issue the generation for the spy, I get why the error
An invalid empty string was passed in as the Destination object.
is generated by the compiler. Although the array has been resized, it does not hold any element i.e., its empty. Thus, I tried creating locally a logic variable that then I assign to the signal spy within the loop in the following manner:
module testbench();
logic probes[];
initial begin : read_signals_to_dump_at
automatic int fd;
automatic string fname,line,line_stripped;
if ($value$plusargs("sigfile=%s",fname)) begin : read
fd = $fopen(fname,"r");
while($fgets(line,fd)) begin
logic new_probe;
// Trim away the '\n' from the line.
line_stripped = line.substr(0,line.len()-2);
// Resize the array and copy old values.
probes = new [probes.size() + 1] (probes);
// Add the new probe to the Testbenchs' probes array
probes[probes.size()-1] = new_probe;
// Again, An invalid empty string was passed in as the Destination object.
$init_signal_spy(line_stripped, probes[probes.size()-1] , 1);
end
end
end : read_signals_to_dump_at
endmodule
But then again, I see the same error at runtime during the simulation. So...Is there a way of achieving such a "dynamic" signal monitoring in the testbench somehow? As far as I understood the error concerns that the destination object is NOT a signal of the testbench. Thus the logic new_probe has no effect. Which is to be expected I mean, but is there a way of achieving the desired behavior in the Testbench via sysverilog?
You have at least two problems.
Both the source and destination arguments to init_signal_spy() need to be strings. Your destination argument is an integral variable with a 0 value, and that gets interpreted as a null string. init_signal_spy() was designed for mixed language simulation, and using strings was the only way to achieve that.
Your destination variable should be queue, not a dynamic array. Every time you re-size a dynamic array, the previous elements get relocated and that breaks the previous connection made by signal spy.
This example shows the proper syntax for string this up
module top;
int A[$];
int s1,s2;
initial begin
A.push_back(0);
$init_signal_spy("s1","A[0]");
A.push_back(0);
$init_signal_spy("s2","A[1]");
#1 s1 = 1;
#1 s2 = 2;
#1 $display("%p",A);
end
endmodule
A far better solution for performance is converting your .txt file into actual SystemVerilog code that can be compiled into your testbench.

getting the value from a checkbox in Matlab 2018

I am upgrading my Matlab from 2013b to 2018b and have found out that MathWorks have made quite a few changes to the GUI's.
One problem I am having is getting the value of checkbox. The line below is the code I used to use but now it doesn't work.
if get(handles.check_perf_attr,'Value') == 1
The error message is,
Undefined operator '==' for input arguments of type 'cell'.
So I tried the line below to just get the value that is being returned and then apply some logic.
tValue = get(handles.check_perf_attr,'Value');
However tValue is 2 x 1 cell which in (1, 1) = 0 & (2, 1) = 1. I don't really understand this as surely a checkbox can only be one value true (1) or false (0)?
get returns a cell array with values when applied to an array of handles.
Thus, I think your problem is that handles.check_perf_attr contains two handles, not one.
"Dot notation is a new syntax to access object properties starting in R2014b."
so try
if handles.check_perf_attr.Value == 1
or
tValue = handles.check_perf_attr.Value;

Saving data to .mat file in MATLAB

I'm new to MATLAB, and I can't manage to make my function work in order to save my data into a .mat file.
The input:
A structure, with 5 fields:
data: 3D matrix of 19x1000x143
labels: 1x143 matrix with 1 or -1 in it
subject_number: an integer
sampling_rate: an integer, 500 Hz
channel_names: 1x19 matrix with text in it
name: a string for the name of the file
clean: a matrix 1x143 with 1 or 0 in it.
The idea is to save only the clean data, marked as 1 in the clean matrix.
If clean(i) is equal to 1:
save data(:,:,i) and labels(:,i)
This is the code I've tried to implement in the saving.m file:
function saving(EEG_struct, clean, name)
subject_number = EEG_struct.subject_number;
fs = EEG_struct.sampling_rate;
chan_names = EEG_struct.channel_names;
nb_epoch = size(EEG_struct.data, 3);
for j=1:nb_epoch
if clean(j) == 1
% Keep the epoch and label
data = cat(3, data, EEG_struct.data(:,:,j));
labels = cat(2, labels, EEG_struct.labels(:,j));
end
end
save(name, data, labels, subject_number, fs, chan_names)
As you can see, I would like to save the data as a structure with the same shape as the EEG_struct input.
Moreover, I would like to use a parfor instead of a for, but it raised me an error I didn't quite get:
An UndefinedFunction error was thrown on the workers for 'data'. This might be because the file containing 'data' is not accessible on the workers. Use addAttachedFiles(pool, files) to specify the required files to be attached. See the documentation for 'parallel.Pool/addAttachedFiles' for more details. Caused by: Undefined function or variable 'data'.
Thanks for the help !
You can use your clean variable as a logical index and parse out your data and labels at once. So there is no need for a loop.
Also the save command needs the "names" of the vars to save not the variables themselves. So I just put ' ' around each one.
function saving(EEG_struct, clean, name)
subject_number = EEG_struct.subject_number;
fs = EEG_struct.sampling_rate;
chan_names = EEG_struct.channel_names;
nb_epoch = size(EEG_struct.data, 3);
%No need for a loop at all
data = EEG_struct.data(:,:,logical(clean));
labels = EEG_struct.labels(logical(clean)); %This is a 1xN so I removed the extra colon operator
save(name, 'data', 'labels', 'subject_number', 'fs', 'chan_names');
EDIT:
Per you comment if you want to just leave everything in the structure. I gave you 2 options for how to save it.
function saving(EEG_struct, clean, name)
%Crop out ~clead data
EEG_struct.data = EEG_struct.data(:,:,logical(clean));
EEG_struct.labels = EEG_struct.labels(logical(clean)); %This is a 1xN so I removed the extra colon operator
% Option 1
save(name, 'EEG_struct');
% Option2
save(name, '-struct', 'EEG_struct');
Option 1 will directly save the struct to the MAT file. So if you were to load the data back like this:
test = load(name);
test =
EEG_struct: [1x1 struct]
You would get your structure placed inside another structure ... which might not be ideal or require an extra line to de-nest it. On the other hand just loading the MAT file with no outputs load(name) would put EEG_struct into your current workspace. But if in a function then it sort of springs into existence without every being declared which makes code a bit harder to follow.
Option 2 uses the '-struct' option which breaks out each field automatically into separate vars in the MAT file. So loading like this:
EEG_struct = load(name);
Will put all the fields back together again. To me at least this looks cleaner when done within a function but is probably just my preference
So comment out which ever you prefer. Also, not I did not include clean in the save. You could either append it to the MAT or add it to your structure.
To get a structure the same as EEG_struct but with only the data/labels corresponding with the clean variable, you can simply make a copy of the existing structure and remove the rows where clean=0
function saving(EEG_struct, clean, name)
newstruct = EEG_struct;
newstruct.data(:,:,logical(~clean)) = '';
newstruct.labels(logical(~clean)) = '';
save(name,'newstruct');

Can pysnmp return octectstring values only

I am doing a small script to get SNMP traps with PySnmp.
I am able to get the oid = value pairs, but the value is too long with a small information in the end. How can I access the octectstring only which comes in the end of the value. Is there a way other than string manipulations? Please comment.
OID =_BindValue(componentType=NamedTypes(NamedType('value', ObjectSyntax------------------------------------------------(DELETED)-----------------(None, OctetString(b'New Alarm'))))
Is it possible to get the output like the following, as is available from another SNMP client:
.iso.org.dod.internet.private.enterprises.xxxx.1.1.2.2.14: CM_DAS Alarm Traps:
Edit - the codes are :
**for oid, val in varBinds:
print('%s = %s' % (oid.prettyPrint(), val.prettyPrint()))
target.write(str(val))**
On screen, it shows short, but on file, the val is so long.
Usage of target.write( str(val[0][1][2])) does not work for all (program stops with error), but the 1st oid(time tick) gets it fine.
How can I get the value from tail as the actual value is found there for all oids.
Thanks.
SNMP transfers information in form of a sequence of OID-value pairs called variable-bindings:
variable_bindings = [[oid1, value1], [oid2, value2], ...]
Once you get the variable-bindings sequence from SNMP PDU, to access value1, for example, you might do:
variable_binding1 = variable_bindings[0]
value1 = variable_binding1[1]
To access the tail part of value1 (assuming it's a string) you could simply subscribe it:
tail_of_value1 = value1[-10:]
I guess in your question you operate on a single variable_binding, not a sequence of them.
If you want pysnmp to translate oid-value pair into a human-friendly representation (of MIB object name, MIB object value), you'd have to pass original OID-value pair to the ObjectType class and run it through MIB resolver as explained in the documentation.
Thanks...
the following codes works like somwwhat I was looking for.
if str(oid)=="1.3.6.1.2.1.1.3.0":
target.write(" = str(val[0][1]['timeticks-value']) = " +str(val[0][1]['timeticks-value'])) # time ticks
else:
target.write("= val[0][0]['string-value']= " + str(val[0][0]['string-value']))

Read mongodump output with go and mgo

I'm trying to read a collection dump generated by mongodump. The file is a few gigabytes so I want to read it incrementally.
I can read the first object with something like this:
buf := make([]byte, 100000)
f, _ := os.Open(path)
f.Read(buf)
var m bson.M
bson.Unmarshal(buf, &m)
However I don't know how much of the buf was consumed, so I don't know how to read the next one.
Is this possible with mgo?
Using mgo's bson.Unmarshal() alone is not enough -- that function is designed to take a []byte representing a single document, and unmarshal it into a value.
You will need a function that can read the next whole document from the dump file, then you can pass the result to bson.Unmarshal().
Comparing this to encoding/json or encoding/gob, it would be convenient if mgo.bson had a Reader type that consumed documents from an io.Reader.
Anyway, from the source for mongodump, it looks like the dump file is just a series of bson documents, with no file header/footer or explicit record separators.
BSONTool::processFile shows how mongorestore reads the dump file. Their code reads 4 bytes to determine the length of the document, then uses that size to read the rest of the document. Confirmed that the size prefix is part of the bson spec.
Here is a playground example that shows how this could be done in Go: read the length field, read the rest of the document, unmarshal, repeat.
The method File.Read returns the number of bytes read.
File.Read
Read reads up to len(b) bytes from the File. It returns the number of bytes read and an error, if any. EOF is signaled by a zero count with err set to io.EOF.
So you can get the number of bytes read by simply storing the return parameters of you read:
n, err := f.Read(buf)
I managed to solve it with the following code:
for len(buf) > 0 {
var r bson.Raw
var m userObject
bson.Unmarshal(buf, &r)
r.Unmarshal(&m)
fmt.Println(m)
buf = buf[len(r.Data):]
}
Niks Keets' answer did not work for me. Somehow len(r.Data) was always the whole buffer length. So I came out with this other code:
for len(buff) > 0 {
messageSize := binary.LittleEndian.Uint32(buff)
err = bson.Unmarshal(buff, &myObject)
if err != nil {
panic(err)
}
// Do your stuff
buff = buff[messageSize:]
}
Of course you have to handle truncated strucs at the end of the buffer. In my case I could load the whole file into memory.