Skip to content

check for invalid header entity #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 14 additions & 13 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@

from lark import Lark, Transformer, Tree, Token
from lark.exceptions import UnexpectedToken, UnexpectedCharacters
from .mvd_info import MvdInfo, LARK_AVAILABLE
try:
from .mvd_info import MvdInfo, LARK_AVAILABLE
except ImportError: # in case of running module locally (e.g. test_parser.py)
from mvd_info import MvdInfo, LARK_AVAILABLE

class ValidationError(Exception):
pass
Expand Down Expand Up @@ -87,8 +90,10 @@ def build():
subsuper_record : "(" simple_record_list ")"
simple_record_list:simple_record simple_record*
simple_record: keyword "("parameter_list?")"
header_entity :keyword "(" parameter_list ")" ";"
header_entity_list: header_entity header_entity*
header_entity_list: file_description file_name file_schema
file_description: "FILE_DESCRIPTION" "(" parameter_list ")" ";"
file_name: "FILE_NAME" "(" parameter_list ")" ";"
file_schema: "FILE_SCHEMA" "(" parameter_list ")" ";"
id: /#[0-9]+/
keyword: /[A-Z][0-9A-Z_]*/
parameter: untyped_parameter|typed_parameter|omitted_parameter
Expand Down Expand Up @@ -285,17 +290,18 @@ def traverse(fn, x):
attributes,
(min(lines), max(lines)),
)

def make_header_ent(ast):
rule = ast.data
params = T(visit_tokens=True).transform(ast.children[0])
return rule.upper(), params



def process_tree(filecontent, file_tree, with_progress, with_header=False):
ents = defaultdict(list)
header, data = file_tree.children

def make_header_ent(ast):
kw, param_list = ast.children
kw = kw.children[0].value
return kw, T(visit_tokens=True).transform(param_list)

if with_header:
header = dict(map(make_header_ent, header.children[0].children))

Expand Down Expand Up @@ -366,11 +372,6 @@ def replace_fn(match):

header_tree = ast.children[0] # HEADER section

def make_header_ent(ast):
kw, param_list = ast.children
kw = kw.children[0].value
return kw, T(visit_tokens=True).transform(param_list)

header = dict(map(make_header_ent, header_tree.children[0].children))
return header

Expand Down
29 changes: 29 additions & 0 deletions fixtures/extended_mvd.ifc
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
ISO-10303-21;
HEADER;
FILE_DESCRIPTION(('ViewDefinition [ReferenceView_V1.2]', 'ViewDefinition [QuantityTakeOffAddOnView]', 'Option [ExcludedObjects: Stair, Ramp, Space; SplitLevel: On]', 'ExchangeRequirement [CustomRequirement: Value1, Value2]', 'Remark [SomeKey: SomeValue; AnotherKey: AnotherValue]', 'Comment [This is a free text comment, or a comma-separated list of items]'),'2;1');
FILE_NAME('','2022-05-04T08:08:30',(''),(''),'IfcOpenShell-0.7.0','IfcOpenShell-0.7.0','');
FILE_SCHEMA(('IFC4'));
ENDSEC;
DATA;
#1=IFCPERSON($,$,'',$,$,$,$);
#2=IFCORGANIZATION($,'',$,$,$);
#3=IFCPERSONANDORGANIZATION(#1,#2,$);
#4=IFCAPPLICATION(#2,'0.7.0','IfcOpenShell-0.7.0','');
#5=IFCOWNERHISTORY(#3,#4,$,.ADDED.,$,#3,#4,1651651710);
#6=IFCDIRECTION((1.,0.,0.));
#7=IFCDIRECTION((0.,0.,1.));
#8=IFCCARTESIANPOINT((0.,0.,0.));
#9=IFCAXIS2PLACEMENT3D(#8,#7,#6);
#10=IFCDIRECTION((0.,1.,0.));
#11=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-05,#9,#10);
#12=IFCDIMENSIONALEXPONENTS(0,0,0,0,0,0,0);
#13=IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);
#14=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.);
#15=IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.);
#16=IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.);
#17=IFCMEASUREWITHUNIT(IFCPLANEANGLEMEASURE(0.017453292519943295),#16);
#18=IFCCONVERSIONBASEDUNIT(#12,.PLANEANGLEUNIT.,'DEGREE',#17);
#19=IFCUNITASSIGNMENT((#13,#14,#15,#18));
#20=IFCPROJECT('2AyG2X0sb16Bjd4gQc07yZ',#5,'',$,$,$,$,(#11),#19);
ENDSEC;
END-ISO-10303-21;
46 changes: 46 additions & 0 deletions fixtures/fail_invalid_header_entity.ifc
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
ISO-10303-21;
HEADER;
FILE_DESCRIPTION(('ViewDefinition [Alignment-basedView]'),'2;1');
FILE_NAME('Header example2.ifc', '2022-09-16T10:35:07', ('Evandro Alfieri'), ('buildingSMART Int.'), 'IFC Motor 1.0', 'Company - Application - 26.0.0.0', 'none');
FILE_SCHEMA(('IFC4X3_ADD2'));
FILE_INFO(
'Report Date', '2025-04-21 18:16:37',
'IFC Schema', 'IFC2X3',
'MVD(s)', 'None',
'File Name in Header', 'generated (2).ifc',
'File Name', 'generated (2).ifc',
'File Size', '0.41 kB',
'File Date', '2025-04-21 18:16:37',
'Originating System', 'PHP Script',
'Preprocessor Version', '1.0.0',
'Company Name', 'Your Company Name',
'Application Name', 'IFC Generator PHP Script',
'Application Version', '1.0.0',
'Author', 'Your Name',
'Organization', 'Your Company Name'
);
ENDSEC;
DATA;
#1=IFCPERSON($,$,'',$,$,$,$,$);
#2=IFCORGANIZATION($,'',$,$,$);
#3=IFCPERSONANDORGANIZATION(#1,#2,$);
#4=IFCAPPLICATION(#2,'v0.7.0-6c9e130ca','IfcOpenShell-v0.7.0-6c9e130ca','');
#5=IFCOWNERHISTORY(#3,#4,$,.NOTDEFINED.,$,#3,#4,1700419055);
#6=IFCDIRECTION((1.,0.,0.));
#7=IFCDIRECTION((0.,0.,1.));
#8=IFCCARTESIANPOINT((0.,0.,0.));
#9=IFCAXIS2PLACEMENT3D(#8,#7,#6);
#10=IFCDIRECTION((0.,1.));
#11=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-05,#9,#10);
#12=IFCDIMENSIONALEXPONENTS(0,0,0,0,0,0,0);
#13=IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);
#14=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.);
#15=IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.);
#16=IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.);
#17=IFCMEASUREWITHUNIT(IFCPLANEANGLEMEASURE(0.017453292519943295),#16);
#18=IFCCONVERSIONBASEDUNIT(#12,.PLANEANGLEUNIT.,'DEGREE',#17);
#19=IFCUNITASSIGNMENT((#13,#14,#15,#18));
#20=IFCPROJECT('0iDmeiiLP3AOllitM2Favn',#5,'',$,$,$,$,(#11),#19);
#21=IFCSITE('3rg2jGkIH10RFhrQsGZKRk',#5,$,$,$,$,$,$,$,$,$,$,$,$);
ENDSEC;
END-ISO-10303-21;
2 changes: 2 additions & 0 deletions test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,5 @@ def test_file_mvd_attr():
assert 'Ramp' in f.mvd.options['ExcludedObjects']
assert f.mvd.Remark['SomeKey'] == 'SomeValue'
assert len(f.mvd.comments) == 2
assert all(v in vars(f.header).keys() for v in ['file_description', 'file_name', 'file_schema'])
assert len(f.header.file_name) == 7