5
5
import hashlib
6
6
import argparse
7
7
import logging
8
+ import typing
9
+ import uuid
10
+ import warnings
8
11
12
+ import case_utils .inherent_uuid
9
13
import case_utils .local_uuid
10
14
import exifread
11
15
import rdflib
23
27
ns_kb = rdflib .Namespace ("http://example.org/kb/" )
24
28
25
29
26
- def get_node_iri (ns : rdflib .Namespace , prefix : str ) -> rdflib .URIRef :
27
- node_id = rdflib .URIRef (f"{ prefix } { case_utils .local_uuid .demo_uuid ()} " , ns )
30
+ def get_node_iri (
31
+ ns : rdflib .Namespace ,
32
+ prefix : str ,
33
+ * args : typing .Any ,
34
+ facet_class : typing .Optional [rdflib .URIRef ] = None ,
35
+ uco_object_node : typing .Optional [rdflib .URIRef ] = None ,
36
+ use_deterministic_uuids : bool = False ,
37
+ ** kwargs : typing .Any
38
+ ) -> rdflib .URIRef :
39
+ node_id : typing .Optional [rdflib .URIRef ] = None
40
+ if use_deterministic_uuids :
41
+ if uco_object_node is None :
42
+ warnings .warn ("get_node_iri() called requesting deterministic UUIDs, but no UcoObject node was provided." )
43
+ else :
44
+ if uco_object_node is None :
45
+ warnings .warn ("get_node_iri() called requesting deterministic UUIDs, but no Facet class node was provided." )
46
+ else :
47
+ _node_id = case_utils .inherent_id .get_facet_uriref (uco_object_node , facet_class , namespace = ns )
48
+ # Swap in the requested prefix value.
49
+ _node_uuid = str (_node_id )[- 36 :]
50
+ node_id = ns [f"{ prefix } { _node_uuid } " ]
51
+
52
+ if node_id is None :
53
+ node_id = ns [f"{ prefix } { case_utils .local_uuid .demo_uuid ()} " ]
54
+
28
55
return node_id
29
56
30
57
@@ -72,17 +99,18 @@ def create_exif_dict(tags):
72
99
return exif
73
100
74
101
75
- def n_cyber_object_to_node (graph ):
102
+ def n_cyber_object_to_node (graph , * args : typing . Any , use_deterministic_uuids : bool = False , ** kwargs : typing . Any ):
76
103
"""
77
104
Initial function to create nodes for each of the file's facet nodes
78
105
:param graph: rdflib graph object for adding nodes to
79
106
:return: The four nodes for each fo the other functions to fill
80
107
"""
81
108
cyber_object = rdflib .URIRef (get_node_iri (ns = ns_kb , prefix = "observableobject-" ))
82
- n_raster_facet = rdflib .URIRef (get_node_iri (ns = ns_kb , prefix = "rasterpicture-" ))
83
- n_file_facet = rdflib .URIRef (get_node_iri (ns = ns_kb , prefix = "filefacet-" ))
84
- n_content_facet = rdflib .URIRef (get_node_iri (ns = ns_kb , prefix = "contentfacet-" ))
85
- n_exif_facet = rdflib .URIRef (get_node_iri (ns = ns_kb , prefix = "exiffacet-" ))
109
+
110
+ n_raster_facet = rdflib .URIRef (get_node_iri (ns = ns_kb , prefix = "rasterpicture-" , facet_class = NS_UCO_OBSERVABLE .RasterPictureFacet , uco_object_node = cyber_object_facet , use_deterministic_uuids = use_deterministic_uuids ))
111
+ n_file_facet = rdflib .URIRef (get_node_iri (ns = ns_kb , prefix = "filefacet-" , facet_class = NS_UCO_OBSERVABLE .FileFacet , uco_object_node = cyber_object_facet , use_deterministic_uuids = use_deterministic_uuids ))
112
+ n_content_facet = rdflib .URIRef (get_node_iri (ns = ns_kb , prefix = "contentfacet-" , facet_class = NS_UCO_OBSERVABLE .ContentDataFacet , uco_object_node = cyber_object_facet , use_deterministic_uuids = use_deterministic_uuids ))
113
+ n_exif_facet = rdflib .URIRef (get_node_iri (ns = ns_kb , prefix = "exiffacet-" , facet_class = NS_UCO_OBSERVABLE .EXIFFacet , uco_object_node = cyber_object_facet , use_deterministic_uuids = use_deterministic_uuids ))
86
114
graph .add ((
87
115
cyber_object ,
88
116
NS_RDF .type ,
@@ -111,15 +139,14 @@ def n_cyber_object_to_node(graph):
111
139
return n_exif_facet , n_raster_facet , n_file_facet , n_content_facet
112
140
113
141
114
- def filecontent_object_to_node (graph , n_content_facet , file_information ):
142
+ def filecontent_object_to_node (graph , n_content_facet , file_information , * args : typing . Any , use_deterministic_uuids : bool = False , ** kwargs : typing . Any ):
115
143
"""
116
144
Unused: Create a node that will add the file content facet node to the graph
117
145
:param graph: rdflib graph object for adding nodes to
118
- :param n_content_facet: Blank node to contain all content facet information
146
+ :param n_content_facet: Node to contain all content facet information
119
147
:param file_information: Dictionary containing information about file being analysed
120
148
:return: None
121
149
"""
122
- file_hash_facet = rdflib .URIRef (get_node_iri (ns = ns_kb , prefix = "hash-" ))
123
150
graph .add ((
124
151
n_content_facet ,
125
152
NS_RDF .type ,
@@ -143,16 +170,38 @@ def filecontent_object_to_node(graph, n_content_facet, file_information):
143
170
rdflib .term .Literal (file_information ["size" ],
144
171
datatype = NS_XSD .integer )
145
172
))
146
- graph .add ((
147
- n_content_facet ,
148
- NS_UCO_OBSERVABLE .hash ,
149
- file_hash_facet
150
- ))
151
- graph .add ((
152
- file_hash_facet ,
153
- NS_RDF .type ,
154
- NS_UCO_TYPES .Hash
155
- ))
173
+
174
+ if "SHA256" in file_information :
175
+ hash_method = rdflib .Literal ("SHA256" , datatype = NS_UCO_VOCABULARY .HashNameVocab )
176
+ hash_value = rdflib .Literal (file_information ["SHA256" ], datatype = NS_XSD .hexBinary )
177
+
178
+ file_hash : rdflib .URIRef
179
+ if use_deterministic_uuids :
180
+ file_hash_uuid : uuid .UUID = case_utils .inherent_uuid .hash_method_value_uuid (hash_method , hash_value , namespace = ns_kb )
181
+ file_hash = ns_kb ["hash-" + str (file_hash_uuid )]
182
+ else :
183
+ file_hash = get_node_iri (ns = ns_kb , prefix = "hash-" )
184
+
185
+ graph .add ((
186
+ n_content_facet ,
187
+ NS_UCO_OBSERVABLE .hash ,
188
+ file_hash
189
+ ))
190
+ graph .add ((
191
+ file_hash ,
192
+ NS_RDF .type ,
193
+ NS_UCO_TYPES .Hash
194
+ ))
195
+ graph .add ((
196
+ file_hash ,
197
+ NS_UCO_TYPES .hashMethod ,
198
+ hash_method
199
+ ))
200
+ graph .add ((
201
+ file_hash ,
202
+ NS_UCO_TYPES .hashValue ,
203
+ hash_value
204
+ ))
156
205
157
206
158
207
def filefacets_object_to_node (graph , n_file_facet , file_information ):
@@ -309,6 +358,11 @@ def main():
309
358
"""
310
359
parser = argparse .ArgumentParser ()
311
360
parser .add_argument ("file" , help = "file to extract exif data from" )
361
+ parser .add_argument (
362
+ "--use-deterministic-uuids" ,
363
+ action = "store_true" ,
364
+ help = "Use UUIDs computed using the case_utils.inherent_uuid module." ,
365
+ )
312
366
args = parser .parse_args ()
313
367
local_file = args .file
314
368
file_info = get_file_info (local_file )
0 commit comments