1313
1414'''
1515
16- import json , struct
16+ import json , struct , os
1717
1818class JPKVolumeEntry :
1919 '''
2020 {
21- "filename": "vol0.jds",
22- "start": 0,
23- "end": 1000
21+ "filename": "vol0.jds"
2422 }
2523 '''
2624 filename = ""
2725 start = 0
2826 end = 0
2927
30- def __init__ (self , filename = "" , start = 0 , end = 0 ):
28+ def __init__ (self , filename = "" ):
3129 self .filename = filename
32- self .start = start
33- self .end = end
3430
3531 def toObject (self ):
36- return {"filename" :self .filename , "start" : self . start , "end" : self . end }
32+ return {"filename" :self .filename }
3733
3834 def fromObject (self , obj ):
3935 self .filename = obj ["filename" ] if "filename" in obj else ""
40- self .start = obj ["start" ] if "start" in obj else 0
41- self .end = obj ["end" ] if "end" in obj else 0
4236
4337class JPKFileEntry :
4438 '''
@@ -49,6 +43,7 @@ class JPKFileEntry:
4943 "size" : FILESIZE // The file size
5044 "aeskey" : AESKEY // File key if != false
5145 "zlib" : FALSE/TRUE // If file is compressed
46+ "volume" : VOLUMEID // ID from VolumeTable
5247 "md5" : MD5SUM // Uncompresssed/unencrypted file MD5SUM
5348 }
5449 '''
@@ -58,19 +53,21 @@ class JPKFileEntry:
5853 size = 0
5954 aeskey = ""
6055 zlib = False
56+ volume = ""
6157 md5 = ""
6258
63- def __init__ (self , name = "" , path = "" , offset = 0 , size = 0 , aeskey = "" , zlib = False , md5 = "" ):
59+ def __init__ (self , name = "" , path = "" , offset = 0 , size = 0 , aeskey = "" , zlib = False , volume = "" , md5 = "" ):
6460 self .name = name
6561 self .path = path
6662 self .offset = offset
6763 self .size = size
6864 self .aeskey = aeskey
6965 self .zlib = zlib
66+ self .volume = volume
7067 self .md5 = md5
7168
7269 def toObject (self ):
73- return {"name" :self .name , "path" :self .path , "offset" :self .offset , "size" :self .size , "aeskey" :self .aeskey , "zlib" :self .zlib , "md5" : self .md5 }
70+ return {"name" :self .name , "path" :self .path , "offset" :self .offset , "size" :self .size , "aeskey" :self .aeskey , "zlib" :self .zlib , "volume" : self . volume , " md5" : self .md5 }
7471
7572 def fromObject (self , obj ):
7673 self .name = obj ["name" ] if "name" in obj else ""
@@ -79,6 +76,7 @@ def fromObject(self, obj):
7976 self .size = obj ["size" ] if "size" in obj else ""
8077 self .aeskey = obj ["aeskey" ] if "aeskey" in obj else ""
8178 self .zlib = obj ["zlib" ] if "zlib" in obj else ""
79+ self .volume = obj ["volume" ] if "volume" in obj else ""
8280 self .md5 = obj ["md5" ] if "md5" in obj else ""
8381
8482class JPKDirectoryEntry :
@@ -110,6 +108,7 @@ def __init__(self, name="", path="", numfiles=0, directories={}, files={}, aeske
110108 def toObject (self ):
111109 dirs = {}
112110 fls = {}
111+
113112 for key , value in self .directories .iteritems ():
114113 dirs [key ] = value .toObject ()
115114
@@ -139,24 +138,53 @@ def fromObject(self, obj):
139138 def toJson (self ):
140139 return json .dumps (self .toObject ())
141140
142- def fromJson (self , json ):
143- obj = json .loads (json )
141+ def fromJson (self , json_ ):
142+ obj = json .loads (json_ )
144143 self .fromObject (obj )
145144
146- def JMS :
145+ def fromDirectory (self , folder , jds ):
146+ if os .path .isdir (folder ):
147+ print "Folder: %s" % folder
148+ dt = os .listdir (folder )
149+ for i in dt :
150+ print "File: %s" % i
151+ if os .path .isfile (folder + "/" + i ):
152+ offset , size = jds .addFromFile (folder + "/" + i )
153+ newfile = JPKFileEntry (name = os .path .basename (i ), path = folder + "/" + i , offset = offset , size = size , volume = jds .name )
154+ self .files = {}
155+ self .files [os .path .basename (i )] = newfile
156+ self .numfiles += 1
157+ print self .name
158+ else :
159+ newdir = JPKDirectoryEntry (directories = {},files = {})
160+ newdir .fromDirectory (folder + "/" + i , jds )
161+ self .directories [os .path .basename (i )] = newdir
162+
163+ else :
164+ print "File: %s" % folder
165+ offset , size = jds .addFromFile (folder )
166+ newfile = JPKFileEntry (name = os .path .basename (folder ), path = folder , offset = offset , size = size )
167+ self .files [os .path .basename (folder )] = newfile
168+ self .numfiles += 1
169+
170+ class JMS :
147171 MAGIC = "JMS1"
148- volumeTable = []
172+ volumeTable = {}
149173 fileTable = JPKDirectoryEntry ()
150174 producerId = 0
151175 flags = 0
152176 userflags = 0
153177
154- def __init__ (self , volumeTable = [] , fileTable = {} , producerId = 0 , flags = 0 , userflags = 0 ):
178+ def __init__ (self , volumeTable = {} , fileTable = JPKDirectoryEntry () , producerId = 0 , flags = 0 , userflags = 0 ):
155179 self .volumeTable = volumeTable
156180 self .fileTable = fileTable
157181 self .producerId = producerId
158182 self .flags = flags
159183 self .userflags = userflags
184+ self .fileTable .name = "ROOT"
185+
186+ def fromDirectory (self , directory , jds ):
187+ self .fileTable .fromDirectory (directory , jds )
160188
161189 def toObject (self ):
162190 vt = []
@@ -179,7 +207,7 @@ def fromObject(self, obj):
179207 if "fileTable" in obj :
180208 self .fileTable .fromObject (obj ["fileTable" ])
181209
182- self .volumeTable = []
210+ self .volumeTable = {}
183211
184212 if "volumeTable" in obj :
185213 for value in obj ["volumeTable" ]:
@@ -194,18 +222,96 @@ def fromBinary(self, data):
194222 self .MAGIC = "JMS1"
195223 return
196224
197- fileTableOffset = struct .unpack ("<I" , data [len (data )- 4 :len (data )])
225+ fileTableOffset = struct .unpack ("<I" , data [len (data )- 4 :len (data )])[ 0 ]
198226 volumeTableSize = fileTableOffset - 0xC
199227 fileTableSize = len (data ) - fileTableOffset - 12
200228
201- fileTableData = json .loads (data [fileTableOffset :fileTableOffset + fileTableSize ])
229+ fileTableData = json .loads (data [fileTableOffset :fileTableOffset + fileTableSize - 4 ])
202230 volumeTableData = json .loads (data [0xC :volumeTableSize + 0xC ])
203231
204232 self .fileTable = JPKDirectoryEntry ()
205- self .fileTable .fromJson (fileTableData )
233+ self .fileTable .fromObject (fileTableData )
206234
207- self .volumeTable = []
208- for value in volumeTableData :
235+ self .volumeTable = {}
236+ for key , value in volumeTableData . iteritems () :
209237 v = JPKVolumeEntry ()
210238 v .fromObject (value )
211- self .volumeTable .append (v )
239+ self .volumeTable [key ] = v
240+
241+ def toBinary (self ):
242+ data = self .MAGIC
243+ data += "\x00 " * 8
244+ vt = {}
245+
246+ for key , value in self .volumeTable .iteritems ():
247+ vt [key ] = value .toObject ()
248+ data += json .dumps (vt )
249+
250+ fileTableOffset = len (data )
251+ data += self .fileTable .toJson ()
252+ data += struct .pack ("<4I" , self .producerId , self .flags , self .userflags , fileTableOffset )
253+ return data
254+
255+ def addVolume (self , jds ):
256+ if jds .name in self .volumeTable :
257+ print "Volume already exists! %s" % jds .name
258+ return
259+
260+ print self .volumeTable
261+ volume = JPKVolumeEntry (jds .filename )
262+ self .volumeTable [jds .name ] = volume
263+
264+ def toFile (self , filename ):
265+ data = self .toBinary ()
266+ f = open (filename , "wb" )
267+ f .write (data )
268+ f .close ()
269+
270+ class JDS :
271+ MAGIC = "JDS1"
272+ name = ""
273+ filename = ""
274+ fd = None
275+ CHUNK = 4096
276+
277+ def __init__ (self , name , filename ):
278+ self .filename = filename
279+ self .name = name
280+ if os .path .isfile (filename ):
281+ self .fd = open (filename , "rb+" )
282+ else :
283+ self .fd = open (filename , "wb+" )
284+
285+ self .fd .seek (0 ,2 )
286+ if self .fd .tell () == 0 :
287+ self .__buildHeader ()
288+ self .fd .seek (0 )
289+
290+ def __buildHeader (self ):
291+ print "Creating Header"
292+ self .fd .write (self .MAGIC )
293+ self .fd .write ("\x00 " * 8 )
294+
295+ def add (self , data ):
296+ offset = fd .tell ()
297+ size = len (data )
298+ self .fd .write (data )
299+ return offset , size
300+
301+ def addFromFile (self , filename ):
302+ f = open (filename ,"rb" )
303+ offset = self .fd .tell ()
304+ f .seek (0 ,2 )
305+ size = f .tell ()
306+ f .seek (0 )
307+ c = 0
308+ while c < size :
309+ chunk = self .CHUNK if size - c > self .CHUNK else size - c
310+ data = f .read (chunk )
311+ self .fd .write (data )
312+ c += chunk
313+ return offset , size
314+
315+ def close (self ):
316+ self .fd .close ()
317+
0 commit comments